diff --git a/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/js/export.js b/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/js/export.js
index 1f19168d8..f453850a9 100644
--- a/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/js/export.js
+++ b/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/js/export.js
@@ -54,7 +54,7 @@ function showDocs(opts_){
} else if( layerId ) {
exportService.exportByLayerId({
layerId: layerId
- ,format: 'csv'
+ ,format: format
,onSuccess: function(csv){
$('.exportResult').empty();
var $textarea = $('');
@@ -82,17 +82,16 @@ function downloadDocs(opts_){
var schema = opts.schema;
var layerId = opts.layerId;
-
- var format = 'csv';
- var fileName = 'export.csv';
- if( opts.format ){
- format = opts.format;
-
- if( 'geojson' === format ){
- fileName = 'export.geojson';
- };
- };
+ const format = opts.format || 'csv';
+ let fileName = 'export.';
+ if ('csv' === format) fileName += 'csv';
+ else if ('geojson' === format) fileName += 'geojson';
+ else if ('turtle' === format) fileName += 'ttl';
+ else if ('jsonld' === format) fileName += 'jsonld';
+ else if ('rdfxml' === format) fileName += 'rdf';
+ else fileName = fileName.slice(0, -1);
+
var windowId = $n2.getUniqueId();
// Open a new iframe to get results
@@ -209,7 +208,7 @@ function showButtons(opts_){
.addClass('.exportControls_formatSelector')
.appendTo( $div );
var formatSelId = $n2.utils.getElementIdentifier($formatSel);
- var formats = ['csv','geojson'];
+ var formats = ['csv','geojson', 'turtle', 'jsonld', 'rdfxml'];
for(var i=0,e=formats.length; i')
diff --git a/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/test_leaflet.html b/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/test_leaflet.html
deleted file mode 100644
index 3b9923254..000000000
--- a/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/test_leaflet.html
+++ /dev/null
@@ -1,329 +0,0 @@
-
-
-
-
- Leaflet Test
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/tiles.html b/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/tiles.html
deleted file mode 100644
index 472a615f5..000000000
--- a/nunaliit2-couch-application/src/main/atlas_couchapp/_attachments/tools/tiles.html
+++ /dev/null
@@ -1,140 +0,0 @@
-
-
-
- Tiles Test
-
-
-
-
- Tiles Test
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/nunaliit2-couch-command/src/main/java/ca/carleton/gcrc/couch/command/servlet/ConfigServlet.java b/nunaliit2-couch-command/src/main/java/ca/carleton/gcrc/couch/command/servlet/ConfigServlet.java
index 0d921db13..b6aee8b35 100644
--- a/nunaliit2-couch-command/src/main/java/ca/carleton/gcrc/couch/command/servlet/ConfigServlet.java
+++ b/nunaliit2-couch-command/src/main/java/ca/carleton/gcrc/couch/command/servlet/ConfigServlet.java
@@ -15,6 +15,7 @@
import ca.carleton.gcrc.couch.command.impl.PathComputer;
import ca.carleton.gcrc.couch.date.DateServletConfiguration;
import ca.carleton.gcrc.couch.export.ExportConfiguration;
+import ca.carleton.gcrc.couch.export.ExportServlet;
import ca.carleton.gcrc.couch.fsentry.FSEntry;
import ca.carleton.gcrc.couch.fsentry.FSEntryFile;
import ca.carleton.gcrc.couch.metadata.IndexServlet;
@@ -763,6 +764,7 @@ private void initExport(ServletContext servletContext) throws ServletException {
CouchDesignDocument atlasDesign = couchDb.getDesignDocument("atlas");
config.setAtlasDesignDocument(atlasDesign);
servletContext.setAttribute(ExportConfiguration.CONFIGURATION_KEY, config);
+ servletContext.setAttribute(ExportServlet.ConfigAttributeName_AtlasName, atlasProperties.getAtlasName());
} catch(Exception e) {
logger.error("Error configuring export service",e);
diff --git a/nunaliit2-couch-export/pom.xml b/nunaliit2-couch-export/pom.xml
index 8ea796940..295cb15b7 100644
--- a/nunaliit2-couch-export/pom.xml
+++ b/nunaliit2-couch-export/pom.xml
@@ -63,5 +63,11 @@
nunaliit2-couch-utils
${project.version}
+
+ org.apache.jena
+ apache-jena-libs
+ pom
+ ${jena.version}
+
diff --git a/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/ExportServlet.java b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/ExportServlet.java
index 45dea456d..160ee3d75 100644
--- a/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/ExportServlet.java
+++ b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/ExportServlet.java
@@ -10,6 +10,7 @@
import java.util.Vector;
import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -33,28 +34,42 @@
import ca.carleton.gcrc.couch.export.impl.DocumentRetrievalSchema;
import ca.carleton.gcrc.couch.export.impl.ExportFormatCSV;
import ca.carleton.gcrc.couch.export.impl.ExportFormatGeoJson;
+import ca.carleton.gcrc.couch.export.impl.ExportFormatRDF;
import ca.carleton.gcrc.couch.export.impl.SchemaCacheCouchDb;
import ca.carleton.gcrc.couch.export.records.ExportRecordsCSV;
import ca.carleton.gcrc.couch.export.records.ExportRecordsGeoJson;
import ca.carleton.gcrc.couch.export.records.JSONArrayReaderIterator;
import ca.carleton.gcrc.json.servlet.JsonServlet;
-
@SuppressWarnings("serial")
public class ExportServlet extends JsonServlet {
final protected Logger logger = LoggerFactory.getLogger(this.getClass());
-
+ public static final String ConfigAttributeName_AtlasName = "ExportServlet_AtlasName";
+
private ExportConfiguration configuration;
-
+ private String atlasName = null;
+
public ExportServlet() {
-
+
}
public void init(ServletConfig config) throws ServletException {
super.init(config);
+ ServletContext context = config.getServletContext();
+
+ Object obj = context.getAttribute(ConfigAttributeName_AtlasName);
+ if (null == obj) {
+ throw new ServletException("Atlas name is not specified (" + ConfigAttributeName_AtlasName + ")");
+ }
+ if (obj instanceof String) {
+ atlasName = (String) obj;
+ } else {
+ throw new ServletException("Unexpected object for atlas name: " + obj.getClass().getName());
+ }
+
// Pick up configuration
- Object configurationObj = config.getServletContext().getAttribute(ExportConfiguration.CONFIGURATION_KEY);
+ Object configurationObj = context.getAttribute(ExportConfiguration.CONFIGURATION_KEY);
if( null == configurationObj ) {
throw new ServletException("Can not find configuration object");
}
@@ -77,12 +92,10 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
path = paths.get(0);
}
- if( "welcome".equalsIgnoreCase(path) ) {
+ if ("welcome".equalsIgnoreCase(path)) {
doGetWelcome(request, response);
-
- } else if( "test".equalsIgnoreCase(path) ) {
+ } else if ("test".equalsIgnoreCase(path)) {
doGetTest(request, response);
-
} else {
throw new Exception("Unknown request");
}
@@ -96,18 +109,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
try {
List paths = computeRequestPath(request);
String path = null;
- if( paths.size() > 0 ){
+ if (paths.size() > 0) {
path = paths.get(0);
}
-
- if( "definition".equalsIgnoreCase(path) ) {
- doPostDefinition(request, response);
- } else if( "records".equalsIgnoreCase(path) ) {
+ if ("definition".equalsIgnoreCase(path)) {
+ doPostDefinition(request, response);
+ } else if ("records".equalsIgnoreCase(path)) {
doPostRecords(request, response);
-
} else {
- throw new Exception("Unknown request: "+path);
+ throw new Exception("Unknown request: " + path);
}
} catch (Exception e) {
@@ -117,180 +128,181 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
protected void doPostDefinition(HttpServletRequest request, HttpServletResponse response) throws ServletException {
// Ignore final path. Allows client to set any download file name
-
+
try {
// Parse format
Format format = null;
{
String formatStr = request.getParameter("format");
- if( null == formatStr ) {
+ if (null == formatStr) {
format = Format.GEOJSON;
} else {
- for(Format f : Format.values()){
- if( f.matches(formatStr) ){
+ for (Format f : Format.values()) {
+ if (f.matches(formatStr)) {
format = f;
}
}
}
-
- if( null == format ) {
+ if (null == format) {
throw new Exception("Unknown format");
}
- logger.debug("Export Format: "+format.name());
+ logger.debug("Export Format: " + format.name());
}
-
+
// Parse filter
Filter filter = null;
{
String filterStr = request.getParameter("filter");
- if( null != filterStr ) {
- for(Filter f : Filter.values()){
- if( f.matches(filterStr) ){
+ if (null != filterStr) {
+ for (Filter f : Filter.values()) {
+ if (f.matches(filterStr)) {
filter = f;
}
}
}
-
- if( null != filter ) {
- logger.debug("Export Filter: "+filter.name());
+ if (null != filter) {
+ logger.debug("Export Filter: " + filter.name());
}
}
-
+
// Parse method
Method method = null;
{
String methodStr = request.getParameter("method");
- if( null != methodStr ) {
- for(Method m : Method.values()){
- if( m.matches(methodStr) ){
+ if (null != methodStr) {
+ for (Method m : Method.values()) {
+ if (m.matches(methodStr)) {
method = m;
}
}
}
-
- if( null == method ) {
+ if (null == method) {
throw new Exception("Unknown method");
}
- logger.debug("Export Method: "+method.name());
+ logger.debug("Export Method: " + method.name());
}
-
+
// Parse identifier
String identifier = null;
List identifiers = new Vector();
{
String[] ids = request.getParameterValues("name");
- if( null != ids ) {
- for(String id : ids){
+ if (null != ids) {
+ for (String id : ids) {
identifiers.add(id);
}
}
-
- if( identifiers.size() > 0 ) {
+ if (identifiers.size() > 0) {
identifier = identifiers.get(0);
}
-
- if( null == identifier ) {
+ if (null == identifier) {
throw new Exception("Unknown name");
}
- logger.debug("Export Name: "+identifier);
+ logger.debug("Export Name: " + identifier);
}
-
+
// Parse contentType
String contentType = null;
{
String[] contentTypes = request.getParameterValues("contentType");
- if( null != contentTypes ) {
- for(String t : contentTypes){
+ if (null != contentTypes) {
+ for (String t : contentTypes) {
contentType = t;
}
}
-
- if( null != contentType ) {
- logger.debug("Content-Type: "+contentType);
+ if (null != contentType) {
+ logger.debug("Content-Type: " + contentType);
}
}
-
+
// Build doc retrieval based on method
DocumentRetrieval docRetrieval = null;
- if( Method.LAYER == method ) {
+ if (Method.LAYER == method) {
try {
docRetrieval = DocumentRetrievalLayer.create(configuration.getCouchDb(), identifier);
} catch (Exception e) {
- throw new Exception("Problem retrieving documents from layer: "+identifier,e);
+ throw new Exception("Problem retrieving documents from layer: " + identifier, e);
}
-
- } else if( Method.SCHEMA == method ) {
+ } else if (Method.SCHEMA == method) {
try {
docRetrieval = DocumentRetrievalSchema.create(configuration.getCouchDb(), identifier);
} catch (Exception e) {
- throw new Exception("Problem retrieving documents from schema: "+identifier,e);
+ throw new Exception("Problem retrieving documents from schema: " + identifier, e);
}
-
- } else if( Method.DOC_ID == method ) {
+ } else if (Method.DOC_ID == method) {
try {
docRetrieval = DocumentRetrievalId.create(configuration.getCouchDb(), identifiers);
} catch (Exception e) {
- throw new Exception("Problem retrieving documents from doc ids: "+identifiers,e);
+ throw new Exception("Problem retrieving documents from doc ids: " + identifiers, e);
}
-
} else {
- throw new Exception("Do not know how to handle method: "+method.name());
+ throw new Exception("Do not know how to handle method: " + method.name());
}
-
+
// Build document filter based on filter type
- if( null != filter ){
+ if (null != filter) {
DocumentFilter docFilter = new DocumentFilterGeometryType(filter);
- DocumentRetrievalFiltered filteredRetrieval =
- new DocumentRetrievalFiltered(docRetrieval, docFilter);
+ DocumentRetrievalFiltered filteredRetrieval = new DocumentRetrievalFiltered(docRetrieval, docFilter);
docRetrieval = filteredRetrieval;
}
-
+
ExportFormat outputFormat = null;
- if( Format.GEOJSON == format ) {
+ if (Format.GEOJSON == format) {
try {
SchemaCache schemaCache = new SchemaCacheCouchDb(configuration.getCouchDb());
outputFormat = new ExportFormatGeoJson(schemaCache, docRetrieval);
} catch (Exception e) {
- throw new Exception("Problem setting up format: "+format.name(),e);
+ throw new Exception("Problem setting up format: " + format.name(), e);
}
-
- } else if( Format.CSV == format ) {
+ } else if (Format.CSV == format) {
try {
SchemaCache schemaCache = new SchemaCacheCouchDb(configuration.getCouchDb());
outputFormat = new ExportFormatCSV(schemaCache, docRetrieval);
} catch (Exception e) {
- throw new Exception("Problem setting up format: "+format.name(),e);
+ throw new Exception("Problem setting up format: " + format.name(), e);
+ }
+ } else if (Format.RDFXML == format ||
+ Format.TURTLE == format ||
+ Format.JSONLD == format) {
+ try {
+ SchemaCache schemaCache = new SchemaCacheCouchDb(configuration.getCouchDb());
+ outputFormat = new ExportFormatRDF(
+ schemaCache,
+ docRetrieval,
+ format.getLabel(),
+ atlasName);
+ } catch (Exception e) {
+ throw new Exception("Problem setting up format: " + format.name(), e);
}
-
} else {
- throw new Exception("Do not know how to handle format: "+format.name());
+ throw new Exception("Do not know how to handle format: " + format.name());
}
-
+
String charEncoding = outputFormat.getCharacterEncoding();
- if( null != charEncoding ) {
- response.setCharacterEncoding( charEncoding );
+ if (null != charEncoding) {
+ response.setCharacterEncoding(charEncoding);
}
- if( null == contentType ) {
+ if (null == contentType) {
contentType = outputFormat.getMimeType();
}
- if( null != contentType ) {
+ if (null != contentType) {
response.setContentType(contentType);
}
response.setHeader("Cache-Control", "no-cache,must-revalidate");
response.setDateHeader("Expires", (new Date()).getTime());
-
+
OutputStream os = response.getOutputStream();
-
+
try {
outputFormat.outputExport(os);
} catch (Exception e) {
- throw new Exception("Error during export process",e);
+ throw new Exception("Error during export process", e);
}
-
+
os.flush();
- } catch(Exception e) {
- reportError(e,response);
+ } catch (Exception e) {
+ reportError(e, response);
}
}
diff --git a/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/ExportUtils.java b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/ExportUtils.java
index 9150c9ec9..12533d083 100644
--- a/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/ExportUtils.java
+++ b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/ExportUtils.java
@@ -5,6 +5,9 @@ public class ExportUtils {
public enum Format {
GEOJSON("geojson")
,CSV("csv")
+ ,RDFXML("rdfxml")
+ ,TURTLE("turtle")
+ ,JSONLD("jsonld")
;
private String label;
diff --git a/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/impl/ExportFormatRDF.java b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/impl/ExportFormatRDF.java
new file mode 100644
index 000000000..1ce5035c3
--- /dev/null
+++ b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/impl/ExportFormatRDF.java
@@ -0,0 +1,147 @@
+package ca.carleton.gcrc.couch.export.impl;
+
+import java.io.OutputStream;
+
+import org.json.JSONObject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ca.carleton.gcrc.couch.app.Document;
+import ca.carleton.gcrc.couch.export.DocumentRetrieval;
+import ca.carleton.gcrc.couch.export.ExportFormat;
+import ca.carleton.gcrc.couch.export.rdf.GeoSPARQLDatatype;
+import ca.carleton.gcrc.couch.export.SchemaCache;
+import ca.carleton.gcrc.couch.export.SchemaExportInfo;
+import ca.carleton.gcrc.couch.export.SchemaExportProperty;
+import ca.carleton.gcrc.couch.utils.NunaliitDocument;
+
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdf.model.Property;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.apache.jena.vocabulary.RDF;
+import org.apache.jena.riot.RDFDataMgr;
+import org.apache.jena.riot.Lang;
+
+public class ExportFormatRDF implements ExportFormat {
+
+ final protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ private DocumentRetrieval retrieval = null;
+ private SchemaCache schemaCache = null;
+ private Lang language = null;
+ private String atlasName = null;
+ private String defaultNs = null;
+ private static final String geoSPARQLNs = "http://www.opengis.net/ont/geosparql#";
+ private boolean isGeoSPARQLNsSet = false;
+
+ public ExportFormatRDF(
+ SchemaCache schemaCache,
+ DocumentRetrieval retrieval,
+ String language,
+ String atlasName) throws Exception {
+ this.schemaCache = schemaCache;
+ this.retrieval = retrieval;
+ this.atlasName = atlasName;
+ this.defaultNs = "http://" + atlasName + "/ont/#";
+ setLanguageType(language);
+ }
+
+ private void setLanguageType(String langParam) {
+ if (langParam == null) {
+ this.language = Lang.TURTLE;
+ } else if (langParam.equals("turtle") || langParam.equals("ttl")) {
+ this.language = Lang.TURTLE;
+ } else if (langParam.equals("jsonld")) {
+ this.language = Lang.JSONLD;
+ } else if (langParam.equals("rdf") || langParam.equals("rdfxml")) {
+ this.language = Lang.RDFXML;
+ } else {
+ this.language = Lang.TURTLE;
+ }
+ }
+
+ @Override
+ public String getMimeType() {
+ if (Lang.TURTLE == language) {
+ return "text/turtle";
+ } else if (Lang.JSONLD == language) {
+ return "application/json+ld";
+ } else if (Lang.RDFXML == language) {
+ return "application/rdf+xml";
+ } else {
+ return "application/octet-stream";
+ }
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ return "utf-8";
+ }
+
+ @Override
+ public void outputExport(OutputStream os) throws Exception {
+ Model graph = ModelFactory.createDefaultModel();
+ outputExport(graph);
+ RDFDataMgr.write(os, graph, language);
+ }
+
+ public void outputExport(Model graph) throws Exception {
+ graph.setNsPrefix(atlasName, defaultNs);
+ while (retrieval.hasNext()) {
+ Document doc = retrieval.getNext();
+ if (doc == null)
+ break;
+ try {
+ outputDocument(graph, doc);
+ } catch (Exception e) {
+ throw new Exception("Failed to export document as RDF: " + doc.getId(), e);
+ }
+ }
+ }
+
+ private void outputDocument(Model graph, Document doc) throws Exception{
+ NunaliitDocument nunaliitDoc = new NunaliitDocument(doc);
+ JSONObject json = nunaliitDoc.getJSONObject();
+ String schemaName = json.optString("nunaliit_schema");
+ if (schemaName.equals(""))
+ return;
+ SchemaExportInfo exportInfo = null;
+ try {
+ exportInfo = schemaCache.getExportInfo(schemaName);
+ } catch (Exception e) {
+ throw new Exception("Failed to retrieve export info for schema: " + schemaName, e);
+ }
+ if (exportInfo == null)
+ return;
+
+ Resource type = graph.createResource(defaultNs + schemaName);
+ Resource blankInstance = graph.createResource();
+ graph.add(blankInstance, RDF.type, type);
+
+ JSONObject nunaliitGeom = json.optJSONObject("nunaliit_geom");
+ if (nunaliitGeom != null) {
+ String wkt = nunaliitGeom.optString("wkt");
+ if (!wkt.equals("")) {
+ if (!isGeoSPARQLNsSet) {
+ isGeoSPARQLNsSet = true;
+ graph.setNsPrefix("geo", geoSPARQLNs);
+ }
+ graph.add(blankInstance, RDF.type, graph.createResource(geoSPARQLNs + "Feature"));
+ Property hasGeometry = graph.createProperty(geoSPARQLNs + "hasGeometry");
+ Resource blankWKTNode = graph.createResource();
+ graph.add(blankInstance, hasGeometry, blankWKTNode);
+ Property asWKT = graph.createProperty(geoSPARQLNs + "asWKT");
+ graph.add(blankWKTNode, asWKT, graph.createTypedLiteral(wkt.toString(), GeoSPARQLDatatype.GeoSPARQLWKTLiteral));
+ }
+ }
+ for (SchemaExportProperty exportProperty : exportInfo.getProperties()) {
+ Object value = exportProperty.select(json);
+ if (null != value) {
+ Property schemaProperty = graph.createProperty(defaultNs + exportProperty.getLabel());
+ graph.add(blankInstance, schemaProperty, graph.createLiteral(value.toString(), false));
+ }
+ }
+ }
+}
diff --git a/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/rdf/GeoSPARQLDatatype.java b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/rdf/GeoSPARQLDatatype.java
new file mode 100644
index 000000000..399ac72fe
--- /dev/null
+++ b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/rdf/GeoSPARQLDatatype.java
@@ -0,0 +1,14 @@
+package ca.carleton.gcrc.couch.export.rdf;
+
+import org.apache.jena.datatypes.BaseDatatype;
+
+public class GeoSPARQLDatatype extends BaseDatatype {
+ public static final String GEOSPARQL = "http://www.opengis.net/ont/geosparql";
+
+ public static final GeoSPARQLDatatype GeoSPARQLWKTLiteral = new GeoSPARQLWKTLiteral("wktLiteral");
+
+ public GeoSPARQLDatatype(String typeName) {
+ super("");
+ this.uri = GEOSPARQL + "#" + typeName;
+ }
+}
diff --git a/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/rdf/GeoSPARQLWKTLiteral.java b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/rdf/GeoSPARQLWKTLiteral.java
new file mode 100644
index 000000000..ee4d722cd
--- /dev/null
+++ b/nunaliit2-couch-export/src/main/java/ca/carleton/gcrc/couch/export/rdf/GeoSPARQLWKTLiteral.java
@@ -0,0 +1,7 @@
+package ca.carleton.gcrc.couch.export.rdf;
+
+public class GeoSPARQLWKTLiteral extends GeoSPARQLDatatype {
+ public GeoSPARQLWKTLiteral(String typeName) {
+ super(typeName);
+ }
+}
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet.extra/Google.js b/nunaliit2-js-external/src/main/js/js-external/leaflet.extra/Google.js
deleted file mode 100644
index 277f68e46..000000000
--- a/nunaliit2-js-external/src/main/js/js-external/leaflet.extra/Google.js
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Google layer using Google Maps API
- */
-
-L.Google = L.Class.extend({
- includes: L.Mixin.Events,
-
- options: {
- minZoom: 0,
- maxZoom: 18,
- tileSize: 256,
- subdomains: 'abc',
- errorTileUrl: '',
- attribution: 'Google & data providers',
- opacity: 1,
- continuousWorld: false,
- noWrap: false,
- },
-
- // Possible types: SATELLITE, ROADMAP, HYBRID
- initialize: function(type, options) {
- L.Util.setOptions(this, options);
-
- this._ready = window.google.maps.Map != undefined;
- if (!this._ready) L.Google.asyncWait.push(this);
-
- this._type = type || 'SATELLITE';
- },
-
- onAdd: function(map, insertAtTheBottom) {
- this._map = map;
- this._insertAtTheBottom = insertAtTheBottom;
-
- // create a container div for tiles
- this._initContainer();
- this._initMapObject();
-
- // set up events
- map.on('viewreset', this._resetCallback, this);
-
- this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);
- map.on('move', this._update, this);
- //map.on('moveend', this._update, this);
-
- map._controlCorners['bottomright'].style.marginBottom = "1em";
-
- this._reset();
- this._update();
- },
-
- onRemove: function(map) {
- this._map._container.removeChild(this._container);
- //this._container = null;
-
- this._map.off('viewreset', this._resetCallback, this);
-
- this._map.off('move', this._update, this);
- map._controlCorners['bottomright'].style.marginBottom = "0em";
- //this._map.off('moveend', this._update, this);
- },
-
- getAttribution: function() {
- return this.options.attribution;
- },
-
- setOpacity: function(opacity) {
- this.options.opacity = opacity;
- if (opacity < 1) {
- L.DomUtil.setOpacity(this._container, opacity);
- }
- },
-
- _initContainer: function() {
- var tilePane = this._map._container,
- first = tilePane.firstChild;
-
- if (!this._container) {
- this._container = L.DomUtil.create('div', 'leaflet-google-layer leaflet-top leaflet-left');
- this._container.id = "_GMapContainer";
- }
-
- if (true) {
- tilePane.insertBefore(this._container, first);
-
- this.setOpacity(this.options.opacity);
- var size = this._map.getSize();
- this._container.style.width = size.x;
- this._container.style.height = size.y;
- }
- },
-
- _initMapObject: function() {
- if (!this._ready) return;
- this._google_center = new window.google.maps.LatLng(0, 0);
- var map = new window.google.maps.Map(this._container, {
- center: this._google_center,
- zoom: 0,
- mapTypeId: window.google.maps.MapTypeId[this._type],
- disableDefaultUI: true,
- keyboardShortcuts: false,
- draggable: false,
- disableDoubleClickZoom: true,
- scrollwheel: false,
- streetViewControl: false
- });
-
- var _this = this;
- this._reposition = window.google.maps.event.addListenerOnce(map, "center_changed",
- function() { _this.onReposition(); });
-
- map.backgroundColor = '#ff0000';
- this._google = map;
- },
-
- _resetCallback: function(e) {
- this._reset(e.hard);
- },
-
- _reset: function(clearOldContainer) {
- this._initContainer();
- },
-
- _update: function() {
- if (!this._google) return;
- this._resize();
-
- var bounds = this._map.getBounds();
- var ne = bounds.getNorthEast();
- var sw = bounds.getSouthWest();
- var google_bounds = new window.google.maps.LatLngBounds(
- new window.google.maps.LatLng(sw.lat, sw.lng),
- new window.google.maps.LatLng(ne.lat, ne.lng)
- );
- var center = this._map.getCenter();
- var _center = new window.google.maps.LatLng(center.lat, center.lng);
-
- this._google.setCenter(_center);
- this._google.setZoom(this._map.getZoom());
- //this._google.fitBounds(google_bounds);
- },
-
- _resize: function() {
- var size = this._map.getSize();
- if (this._container.style.width == size.x &&
- this._container.style.height == size.y)
- return;
- this._container.style.width = size.x;
- this._container.style.height = size.y;
- this.onReposition();
- },
-
- onReposition: function() {
- if (!this._google) return;
- window.google.maps.event.trigger(this._google, "resize");
- }
-});
-
-L.Google.asyncWait = [];
-L.Google.asyncInitialize = function() {
- var i;
- for (i = 0; i < L.Google.asyncWait.length; i++) {
- var o = L.Google.asyncWait[i];
- o._ready = true;
- if (o._container) {
- o._initMapObject();
- o._update();
- }
- }
- L.Google.asyncWait = [];
-}
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/layers.png b/nunaliit2-js-external/src/main/js/js-external/leaflet/images/layers.png
deleted file mode 100644
index 9be965fc8..000000000
Binary files a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/layers.png and /dev/null differ
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/marker-icon.png b/nunaliit2-js-external/src/main/js/js-external/leaflet/images/marker-icon.png
deleted file mode 100644
index bef032e62..000000000
Binary files a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/marker-icon.png and /dev/null differ
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/marker-shadow.png b/nunaliit2-js-external/src/main/js/js-external/leaflet/images/marker-shadow.png
deleted file mode 100644
index a64f6a672..000000000
Binary files a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/marker-shadow.png and /dev/null differ
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/popup-close.png b/nunaliit2-js-external/src/main/js/js-external/leaflet/images/popup-close.png
deleted file mode 100644
index c8faec5ea..000000000
Binary files a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/popup-close.png and /dev/null differ
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/zoom-in.png b/nunaliit2-js-external/src/main/js/js-external/leaflet/images/zoom-in.png
deleted file mode 100644
index 9f473d649..000000000
Binary files a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/zoom-in.png and /dev/null differ
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/zoom-out.png b/nunaliit2-js-external/src/main/js/js-external/leaflet/images/zoom-out.png
deleted file mode 100644
index f0a5b5d6e..000000000
Binary files a/nunaliit2-js-external/src/main/js/js-external/leaflet/images/zoom-out.png and /dev/null differ
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet-src.js b/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet-src.js
deleted file mode 100644
index 9c2e472d9..000000000
--- a/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet-src.js
+++ /dev/null
@@ -1,6513 +0,0 @@
-/*
- Copyright (c) 2010-2012, CloudMade, Vladimir Agafonkin
- Leaflet is a modern open-source JavaScript library for interactive maps.
- http://leaflet.cloudmade.com
-*/
-(function () {
-
-var L, originalL;
-
-if (typeof exports !== 'undefined') {
- L = exports;
-} else {
- L = {};
-
- originalL = window.L;
-
- L.noConflict = function () {
- window.L = originalL;
- return L;
- };
-
- window.L = L;
-}
-
-L.version = '0.4';
-
-
-/*
- * L.Util is a namespace for various utility functions.
- */
-
-L.Util = {
- extend: function (/*Object*/ dest) /*-> Object*/ { // merge src properties into dest
- var sources = Array.prototype.slice.call(arguments, 1);
- for (var j = 0, len = sources.length, src; j < len; j++) {
- src = sources[j] || {};
- for (var i in src) {
- if (src.hasOwnProperty(i)) {
- dest[i] = src[i];
- }
- }
- }
- return dest;
- },
-
- bind: function (fn, obj) { // (Function, Object) -> Function
- var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : null;
- return function () {
- return fn.apply(obj, args || arguments);
- };
- },
-
- stamp: (function () {
- var lastId = 0, key = '_leaflet_id';
- return function (/*Object*/ obj) {
- obj[key] = obj[key] || ++lastId;
- return obj[key];
- };
- }()),
-
-
- // TODO refactor: remove repetition
-
- requestAnimFrame: (function () {
- function timeoutDefer(callback) {
- window.setTimeout(callback, 1000 / 60);
- }
-
- var requestFn = window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- timeoutDefer;
-
- return function (callback, context, immediate, contextEl) {
- callback = context ? L.Util.bind(callback, context) : callback;
- if (immediate && requestFn === timeoutDefer) {
- callback();
- } else {
- return requestFn.call(window, callback, contextEl);
- }
- };
- }()),
-
- cancelAnimFrame: (function () {
- var requestFn = window.cancelAnimationFrame ||
- window.webkitCancelRequestAnimationFrame ||
- window.mozCancelRequestAnimationFrame ||
- window.oCancelRequestAnimationFrame ||
- window.msCancelRequestAnimationFrame ||
- clearTimeout;
-
- return function (handle) {
- if (!handle) { return; }
- return requestFn.call(window, handle);
- };
- }()),
-
- limitExecByInterval: function (fn, time, context) {
- var lock, execOnUnlock;
-
- return function wrapperFn() {
- var args = arguments;
-
- if (lock) {
- execOnUnlock = true;
- return;
- }
-
- lock = true;
-
- setTimeout(function () {
- lock = false;
-
- if (execOnUnlock) {
- wrapperFn.apply(context, args);
- execOnUnlock = false;
- }
- }, time);
-
- fn.apply(context, args);
- };
- },
-
- falseFn: function () {
- return false;
- },
-
- formatNum: function (num, digits) {
- var pow = Math.pow(10, digits || 5);
- return Math.round(num * pow) / pow;
- },
-
- setOptions: function (obj, options) {
- obj.options = L.Util.extend({}, obj.options, options);
- return obj.options;
- },
-
- getParamString: function (obj) {
- var params = [];
- for (var i in obj) {
- if (obj.hasOwnProperty(i)) {
- params.push(i + '=' + obj[i]);
- }
- }
- return '?' + params.join('&');
- },
-
- template: function (str, data) {
- return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) {
- var value = data[key];
- if (!data.hasOwnProperty(key)) {
- throw new Error('No value provided for variable ' + str);
- }
- return value;
- });
- },
-
- emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='
-};
-
-
-/*
- * Class powers the OOP facilities of the library. Thanks to John Resig and Dean Edwards for inspiration!
- */
-
-L.Class = function () {};
-
-L.Class.extend = function (/*Object*/ props) /*-> Class*/ {
-
- // extended class with the new prototype
- var NewClass = function () {
- if (this.initialize) {
- this.initialize.apply(this, arguments);
- }
- };
-
- // instantiate class without calling constructor
- var F = function () {};
- F.prototype = this.prototype;
-
- var proto = new F();
- proto.constructor = NewClass;
-
- NewClass.prototype = proto;
-
- //inherit parent's statics
- for (var i in this) {
- if (this.hasOwnProperty(i) && i !== 'prototype') {
- NewClass[i] = this[i];
- }
- }
-
- // mix static properties into the class
- if (props.statics) {
- L.Util.extend(NewClass, props.statics);
- delete props.statics;
- }
-
- // mix includes into the prototype
- if (props.includes) {
- L.Util.extend.apply(null, [proto].concat(props.includes));
- delete props.includes;
- }
-
- // merge options
- if (props.options && proto.options) {
- props.options = L.Util.extend({}, proto.options, props.options);
- }
-
- // mix given properties into the prototype
- L.Util.extend(proto, props);
-
- return NewClass;
-};
-
-
-// method for adding properties to prototype
-L.Class.include = function (props) {
- L.Util.extend(this.prototype, props);
-};
-
-L.Class.mergeOptions = function (options) {
- L.Util.extend(this.prototype.options, options);
-};
-
-/*
- * L.Mixin.Events adds custom events functionality to Leaflet classes
- */
-
-L.Mixin = {};
-
-L.Mixin.Events = {
- addEventListener: function (/*String*/ type, /*Function*/ fn, /*(optional) Object*/ context) {
- var events = this._leaflet_events = this._leaflet_events || {};
- events[type] = events[type] || [];
- events[type].push({
- action: fn,
- context: context || this
- });
- return this;
- },
-
- hasEventListeners: function (/*String*/ type) /*-> Boolean*/ {
- var k = '_leaflet_events';
- return (k in this) && (type in this[k]) && (this[k][type].length > 0);
- },
-
- removeEventListener: function (/*String*/ type, /*Function*/ fn, /*(optional) Object*/ context) {
- if (!this.hasEventListeners(type)) {
- return this;
- }
-
- for (var i = 0, events = this._leaflet_events, len = events[type].length; i < len; i++) {
- if (
- (events[type][i].action === fn) &&
- (!context || (events[type][i].context === context))
- ) {
- events[type].splice(i, 1);
- return this;
- }
- }
- return this;
- },
-
- fireEvent: function (/*String*/ type, /*(optional) Object*/ data) {
- if (!this.hasEventListeners(type)) {
- return this;
- }
-
- var event = L.Util.extend({
- type: type,
- target: this
- }, data);
-
- var listeners = this._leaflet_events[type].slice();
-
- for (var i = 0, len = listeners.length; i < len; i++) {
- listeners[i].action.call(listeners[i].context || this, event);
- }
-
- return this;
- }
-};
-
-L.Mixin.Events.on = L.Mixin.Events.addEventListener;
-L.Mixin.Events.off = L.Mixin.Events.removeEventListener;
-L.Mixin.Events.fire = L.Mixin.Events.fireEvent;
-
-
-(function () {
- var ua = navigator.userAgent.toLowerCase(),
- ie = !!window.ActiveXObject,
- webkit = ua.indexOf("webkit") !== -1,
- mobile = typeof orientation !== 'undefined' ? true : false,
- android = ua.indexOf("android") !== -1,
- opera = window.opera;
-
- L.Browser = {
- ie: ie,
- ie6: ie && !window.XMLHttpRequest,
-
- webkit: webkit,
- webkit3d: webkit && ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()),
-
- gecko: ua.indexOf("gecko") !== -1,
-
- opera: opera,
-
- android: android,
- mobileWebkit: mobile && webkit,
- mobileOpera: mobile && opera,
-
- mobile: mobile,
- touch: (function () {
- var touchSupported = false,
- startName = 'ontouchstart';
-
- // WebKit, etc
- if (startName in document.documentElement) {
- return true;
- }
-
- // Firefox/Gecko
- var e = document.createElement('div');
-
- // If no support for basic event stuff, unlikely to have touch support
- if (!e.setAttribute || !e.removeAttribute) {
- return false;
- }
-
- e.setAttribute(startName, 'return;');
- if (typeof e[startName] === 'function') {
- touchSupported = true;
- }
-
- e.removeAttribute(startName);
- e = null;
-
- return touchSupported;
- }())
- };
-}());
-
-
-/*
- * L.Point represents a point with x and y coordinates.
- */
-
-L.Point = function (/*Number*/ x, /*Number*/ y, /*Boolean*/ round) {
- this.x = (round ? Math.round(x) : x);
- this.y = (round ? Math.round(y) : y);
-};
-
-L.Point.prototype = {
- add: function (point) {
- return this.clone()._add(point);
- },
-
- _add: function (point) {
- this.x += point.x;
- this.y += point.y;
- return this;
- },
-
- subtract: function (point) {
- return this.clone()._subtract(point);
- },
-
- // destructive subtract (faster)
- _subtract: function (point) {
- this.x -= point.x;
- this.y -= point.y;
- return this;
- },
-
- divideBy: function (num, round) {
- return new L.Point(this.x / num, this.y / num, round);
- },
-
- multiplyBy: function (num) {
- return new L.Point(this.x * num, this.y * num);
- },
-
- distanceTo: function (point) {
- var x = point.x - this.x,
- y = point.y - this.y;
- return Math.sqrt(x * x + y * y);
- },
-
- round: function () {
- return this.clone()._round();
- },
-
- // destructive round
- _round: function () {
- this.x = Math.round(this.x);
- this.y = Math.round(this.y);
- return this;
- },
-
- clone: function () {
- return new L.Point(this.x, this.y);
- },
-
- toString: function () {
- return 'Point(' +
- L.Util.formatNum(this.x) + ', ' +
- L.Util.formatNum(this.y) + ')';
- }
-};
-
-
-/*
- * L.Bounds represents a rectangular area on the screen in pixel coordinates.
- */
-
-L.Bounds = L.Class.extend({
- initialize: function (min, max) { //(Point, Point) or Point[]
- if (!min) {
- return;
- }
- var points = (min instanceof Array ? min : [min, max]);
- for (var i = 0, len = points.length; i < len; i++) {
- this.extend(points[i]);
- }
- },
-
- // extend the bounds to contain the given point
- extend: function (/*Point*/ point) {
- if (!this.min && !this.max) {
- this.min = new L.Point(point.x, point.y);
- this.max = new L.Point(point.x, point.y);
- } else {
- this.min.x = Math.min(point.x, this.min.x);
- this.max.x = Math.max(point.x, this.max.x);
- this.min.y = Math.min(point.y, this.min.y);
- this.max.y = Math.max(point.y, this.max.y);
- }
- },
-
- getCenter: function (round)/*->Point*/ {
- return new L.Point(
- (this.min.x + this.max.x) / 2,
- (this.min.y + this.max.y) / 2, round);
- },
-
- contains: function (/*Bounds or Point*/ obj)/*->Boolean*/ {
- var min, max;
-
- if (obj instanceof L.Bounds) {
- min = obj.min;
- max = obj.max;
- } else {
- min = max = obj;
- }
-
- return (min.x >= this.min.x) &&
- (max.x <= this.max.x) &&
- (min.y >= this.min.y) &&
- (max.y <= this.max.y);
- },
-
- intersects: function (/*Bounds*/ bounds) {
- var min = this.min,
- max = this.max,
- min2 = bounds.min,
- max2 = bounds.max;
-
- var xIntersects = (max2.x >= min.x) && (min2.x <= max.x),
- yIntersects = (max2.y >= min.y) && (min2.y <= max.y);
-
- return xIntersects && yIntersects;
- }
-
-});
-
-
-/*
- * L.Transformation is an utility class to perform simple point transformations through a 2d-matrix.
- */
-
-L.Transformation = L.Class.extend({
- initialize: function (/*Number*/ a, /*Number*/ b, /*Number*/ c, /*Number*/ d) {
- this._a = a;
- this._b = b;
- this._c = c;
- this._d = d;
- },
-
- transform: function (point, scale) {
- return this._transform(point.clone(), scale);
- },
-
- // destructive transform (faster)
- _transform: function (/*Point*/ point, /*Number*/ scale) /*-> Point*/ {
- scale = scale || 1;
- point.x = scale * (this._a * point.x + this._b);
- point.y = scale * (this._c * point.y + this._d);
- return point;
- },
-
- untransform: function (/*Point*/ point, /*Number*/ scale) /*-> Point*/ {
- scale = scale || 1;
- return new L.Point(
- (point.x / scale - this._b) / this._a,
- (point.y / scale - this._d) / this._c);
- }
-});
-
-
-/*
- * L.DomUtil contains various utility functions for working with DOM
- */
-
-L.DomUtil = {
- get: function (id) {
- return (typeof id === 'string' ? document.getElementById(id) : id);
- },
-
- getStyle: function (el, style) {
- var value = el.style[style];
- if (!value && el.currentStyle) {
- value = el.currentStyle[style];
- }
- if (!value || value === 'auto') {
- var css = document.defaultView.getComputedStyle(el, null);
- value = css ? css[style] : null;
- }
- return (value === 'auto' ? null : value);
- },
-
- getViewportOffset: function (element) {
- var top = 0,
- left = 0,
- el = element,
- docBody = document.body;
-
- do {
- top += el.offsetTop || 0;
- left += el.offsetLeft || 0;
-
- if (el.offsetParent === docBody &&
- L.DomUtil.getStyle(el, 'position') === 'absolute') {
- break;
- }
- if (L.DomUtil.getStyle(el, 'position') === 'fixed') {
- top += docBody.scrollTop || 0;
- left += docBody.scrollLeft || 0;
- break;
- }
-
- el = el.offsetParent;
- } while (el);
-
- el = element;
-
- do {
- if (el === docBody) {
- break;
- }
-
- top -= el.scrollTop || 0;
- left -= el.scrollLeft || 0;
-
- el = el.parentNode;
- } while (el);
-
- return new L.Point(left, top);
- },
-
- create: function (tagName, className, container) {
- var el = document.createElement(tagName);
- el.className = className;
- if (container) {
- container.appendChild(el);
- }
- return el;
- },
-
- disableTextSelection: function () {
- if (document.selection && document.selection.empty) {
- document.selection.empty();
- }
- if (!this._onselectstart) {
- this._onselectstart = document.onselectstart;
- document.onselectstart = L.Util.falseFn;
- }
- },
-
- enableTextSelection: function () {
- document.onselectstart = this._onselectstart;
- this._onselectstart = null;
- },
-
- hasClass: function (el, name) {
- return (el.className.length > 0) &&
- new RegExp("(^|\\s)" + name + "(\\s|$)").test(el.className);
- },
-
- addClass: function (el, name) {
- if (!L.DomUtil.hasClass(el, name)) {
- el.className += (el.className ? ' ' : '') + name;
- }
- },
-
- removeClass: function (el, name) {
- el.className = el.className.replace(/(\S+)\s*/g, function (w, match) {
- if (match === name) {
- return '';
- }
- return w;
- }).replace(/^\s+/, '');
- },
-
- setOpacity: function (el, value) {
- if (L.Browser.ie) {
- el.style.filter += value !== 1 ? 'alpha(opacity=' + Math.round(value * 100) + ')' : '';
- } else {
- el.style.opacity = value;
- }
- },
-
- //TODO refactor away this ugly translate/position mess
-
- testProp: function (props) {
- var style = document.documentElement.style;
-
- for (var i = 0; i < props.length; i++) {
- if (props[i] in style) {
- return props[i];
- }
- }
- return false;
- },
-
- getTranslateString: function (point) {
- return L.DomUtil.TRANSLATE_OPEN +
- point.x + 'px,' + point.y + 'px' +
- L.DomUtil.TRANSLATE_CLOSE;
- },
-
- getScaleString: function (scale, origin) {
- var preTranslateStr = L.DomUtil.getTranslateString(origin),
- scaleStr = ' scale(' + scale + ') ',
- postTranslateStr = L.DomUtil.getTranslateString(origin.multiplyBy(-1));
-
- return preTranslateStr + scaleStr + postTranslateStr;
- },
-
- setPosition: function (el, point) {
- el._leaflet_pos = point;
- if (L.Browser.webkit3d) {
- el.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(point);
- el.style['-webkit-backface-visibility'] = 'hidden';
- } else {
- el.style.left = point.x + 'px';
- el.style.top = point.y + 'px';
- }
- },
-
- getPosition: function (el) {
- return el._leaflet_pos;
- }
-};
-
-L.Util.extend(L.DomUtil, {
- TRANSITION: L.DomUtil.testProp(['transition', 'webkitTransition', 'OTransition', 'MozTransition', 'msTransition']),
- TRANSFORM: L.DomUtil.testProp(['transformProperty', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']),
-
- TRANSLATE_OPEN: 'translate' + (L.Browser.webkit3d ? '3d(' : '('),
- TRANSLATE_CLOSE: L.Browser.webkit3d ? ',0)' : ')'
-});
-
-
-/*
- CM.LatLng represents a geographical point with latitude and longtitude coordinates.
-*/
-
-L.LatLng = function (/*Number*/ rawLat, /*Number*/ rawLng, /*Boolean*/ noWrap) {
- var lat = parseFloat(rawLat),
- lng = parseFloat(rawLng);
-
- if (isNaN(lat) || isNaN(lng)) {
- throw new Error('Invalid LatLng object: (' + rawLat + ', ' + rawLng + ')');
- }
-
- if (noWrap !== true) {
- lat = Math.max(Math.min(lat, 90), -90); // clamp latitude into -90..90
- lng = (lng + 180) % 360 + ((lng < -180 || lng === 180) ? 180 : -180); // wrap longtitude into -180..180
- }
-
- //TODO change to lat() & lng()
- this.lat = lat;
- this.lng = lng;
-};
-
-L.Util.extend(L.LatLng, {
- DEG_TO_RAD: Math.PI / 180,
- RAD_TO_DEG: 180 / Math.PI,
- MAX_MARGIN: 1.0E-9 // max margin of error for the "equals" check
-});
-
-L.LatLng.prototype = {
- equals: function (/*LatLng*/ obj) {
- if (!(obj instanceof L.LatLng)) {
- return false;
- }
-
- var margin = Math.max(Math.abs(this.lat - obj.lat), Math.abs(this.lng - obj.lng));
- return margin <= L.LatLng.MAX_MARGIN;
- },
-
- toString: function () {
- return 'LatLng(' +
- L.Util.formatNum(this.lat) + ', ' +
- L.Util.formatNum(this.lng) + ')';
- },
-
- // Haversine distance formula, see http://en.wikipedia.org/wiki/Haversine_formula
- distanceTo: function (/*LatLng*/ other)/*->Double*/ {
- var R = 6378137, // earth radius in meters
- d2r = L.LatLng.DEG_TO_RAD,
- dLat = (other.lat - this.lat) * d2r,
- dLon = (other.lng - this.lng) * d2r,
- lat1 = this.lat * d2r,
- lat2 = other.lat * d2r,
- sin1 = Math.sin(dLat / 2),
- sin2 = Math.sin(dLon / 2);
-
- var a = sin1 * sin1 + sin2 * sin2 * Math.cos(lat1) * Math.cos(lat2);
-
- return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
- }
-};
-
-
-/*
- * L.LatLngBounds represents a rectangular area on the map in geographical coordinates.
- */
-
-L.LatLngBounds = L.Class.extend({
- initialize: function (southWest, northEast) { // (LatLng, LatLng) or (LatLng[])
- if (!southWest) {
- return;
- }
- var latlngs = (southWest instanceof Array ? southWest : [southWest, northEast]);
- for (var i = 0, len = latlngs.length; i < len; i++) {
- this.extend(latlngs[i]);
- }
- },
-
- // extend the bounds to contain the given point or bounds
- extend: function (/*LatLng or LatLngBounds*/ obj) {
- if (obj instanceof L.LatLng) {
- if (!this._southWest && !this._northEast) {
- this._southWest = new L.LatLng(obj.lat, obj.lng, true);
- this._northEast = new L.LatLng(obj.lat, obj.lng, true);
- } else {
- this._southWest.lat = Math.min(obj.lat, this._southWest.lat);
- this._southWest.lng = Math.min(obj.lng, this._southWest.lng);
- this._northEast.lat = Math.max(obj.lat, this._northEast.lat);
- this._northEast.lng = Math.max(obj.lng, this._northEast.lng);
- }
- } else if (obj instanceof L.LatLngBounds) {
- this.extend(obj._southWest);
- this.extend(obj._northEast);
- }
- return this;
- },
-
- // extend the bounds by a percentage
- pad: function (bufferRatio) { // (Number) -> LatLngBounds
- var sw = this._southWest,
- ne = this._northEast,
- heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio,
- widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;
-
- return new L.LatLngBounds(
- new L.LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer),
- new L.LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer));
- },
-
- getCenter: function () /*-> LatLng*/ {
- return new L.LatLng(
- (this._southWest.lat + this._northEast.lat) / 2,
- (this._southWest.lng + this._northEast.lng) / 2);
- },
-
- getSouthWest: function () {
- return this._southWest;
- },
-
- getNorthEast: function () {
- return this._northEast;
- },
-
- getNorthWest: function () {
- return new L.LatLng(this._northEast.lat, this._southWest.lng, true);
- },
-
- getSouthEast: function () {
- return new L.LatLng(this._southWest.lat, this._northEast.lng, true);
- },
-
- contains: function (/*LatLngBounds or LatLng*/ obj) /*-> Boolean*/ {
- var sw = this._southWest,
- ne = this._northEast,
- sw2, ne2;
-
- if (obj instanceof L.LatLngBounds) {
- sw2 = obj.getSouthWest();
- ne2 = obj.getNorthEast();
- } else {
- sw2 = ne2 = obj;
- }
-
- return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) &&
- (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng);
- },
-
- intersects: function (/*LatLngBounds*/ bounds) {
- var sw = this._southWest,
- ne = this._northEast,
- sw2 = bounds.getSouthWest(),
- ne2 = bounds.getNorthEast();
-
- var latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat),
- lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng);
-
- return latIntersects && lngIntersects;
- },
-
- toBBoxString: function () {
- var sw = this._southWest,
- ne = this._northEast;
- return [sw.lng, sw.lat, ne.lng, ne.lat].join(',');
- },
-
- equals: function (/*LatLngBounds*/ bounds) {
- return bounds ? this._southWest.equals(bounds.getSouthWest()) &&
- this._northEast.equals(bounds.getNorthEast()) : false;
- }
-});
-
-//TODO International date line?
-
-
-/*
- * L.Projection contains various geographical projections used by CRS classes.
- */
-
-L.Projection = {};
-
-
-
-L.Projection.SphericalMercator = {
- MAX_LATITUDE: 85.0511287798,
-
- project: function (latlng) { // (LatLng) -> Point
- var d = L.LatLng.DEG_TO_RAD,
- max = this.MAX_LATITUDE,
- lat = Math.max(Math.min(max, latlng.lat), -max),
- x = latlng.lng * d,
- y = lat * d;
- y = Math.log(Math.tan((Math.PI / 4) + (y / 2)));
-
- return new L.Point(x, y);
- },
-
- unproject: function (point, unbounded) { // (Point, Boolean) -> LatLng
- var d = L.LatLng.RAD_TO_DEG,
- lng = point.x * d,
- lat = (2 * Math.atan(Math.exp(point.y)) - (Math.PI / 2)) * d;
-
- return new L.LatLng(lat, lng, unbounded);
- }
-};
-
-
-
-L.Projection.LonLat = {
- project: function (latlng) {
- return new L.Point(latlng.lng, latlng.lat);
- },
-
- unproject: function (point, unbounded) {
- return new L.LatLng(point.y, point.x, unbounded);
- }
-};
-
-
-
-L.CRS = {
- latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point
- var projectedPoint = this.projection.project(latlng),
- scale = this.scale(zoom);
-
- return this.transformation._transform(projectedPoint, scale);
- },
-
- pointToLatLng: function (point, zoom, unbounded) { // (Point, Number[, Boolean]) -> LatLng
- var scale = this.scale(zoom),
- untransformedPoint = this.transformation.untransform(point, scale);
-
- return this.projection.unproject(untransformedPoint, unbounded);
- //TODO get rid of 'unbounded' everywhere
- },
-
- project: function (latlng) {
- return this.projection.project(latlng);
- },
-
- scale: function (zoom) {
- return 256 * Math.pow(2, zoom);
- }
-};
-
-
-
-L.CRS.EPSG3857 = L.Util.extend({}, L.CRS, {
- code: 'EPSG:3857',
-
- projection: L.Projection.SphericalMercator,
- transformation: new L.Transformation(0.5 / Math.PI, 0.5, -0.5 / Math.PI, 0.5),
-
- project: function (latlng) { // (LatLng) -> Point
- var projectedPoint = this.projection.project(latlng),
- earthRadius = 6378137;
- return projectedPoint.multiplyBy(earthRadius);
- }
-});
-
-L.CRS.EPSG900913 = L.Util.extend({}, L.CRS.EPSG3857, {
- code: 'EPSG:900913'
-});
-
-
-
-L.CRS.EPSG4326 = L.Util.extend({}, L.CRS, {
- code: 'EPSG:4326',
-
- projection: L.Projection.LonLat,
- transformation: new L.Transformation(1 / 360, 0.5, -1 / 360, 0.5)
-});
-
-
-/*
- * L.Map is the central class of the API - it is used to create a map.
- */
-
-L.Map = L.Class.extend({
- includes: L.Mixin.Events,
-
- options: {
- crs: L.CRS.EPSG3857,
-
- /*
- center: LatLng,
- zoom: Number,
- layers: Array,
- */
-
- fadeAnimation: L.DomUtil.TRANSITION && !L.Browser.android,
- trackResize: true
- },
-
- initialize: function (id, options) { // (HTMLElement or String, Object)
- options = L.Util.setOptions(this, options);
-
- this._initContainer(id);
- this._initLayout();
- this._initHooks();
- this._initEvents();
-
- if (options.maxBounds) {
- this.setMaxBounds(options.maxBounds);
- }
-
- if (options.center && typeof options.zoom !== 'undefined') {
- this.setView(options.center, options.zoom, true);
- }
-
- this._initLayers(options.layers);
- },
-
-
- // public methods that modify map state
-
- // replaced by animation-powered implementation in Map.PanAnimation.js
- setView: function (center, zoom) {
- this._resetView(center, this._limitZoom(zoom));
- return this;
- },
-
- setZoom: function (zoom) { // (Number)
- return this.setView(this.getCenter(), zoom);
- },
-
- zoomIn: function () {
- return this.setZoom(this._zoom + 1);
- },
-
- zoomOut: function () {
- return this.setZoom(this._zoom - 1);
- },
-
- fitBounds: function (bounds) { // (LatLngBounds)
- var zoom = this.getBoundsZoom(bounds);
- return this.setView(bounds.getCenter(), zoom);
- },
-
- fitWorld: function () {
- var sw = new L.LatLng(-60, -170),
- ne = new L.LatLng(85, 179);
-
- return this.fitBounds(new L.LatLngBounds(sw, ne));
- },
-
- panTo: function (center) { // (LatLng)
- return this.setView(center, this._zoom);
- },
-
- panBy: function (offset) { // (Point)
- // replaced with animated panBy in Map.Animation.js
- this.fire('movestart');
-
- this._rawPanBy(offset);
-
- this.fire('move');
- return this.fire('moveend');
- },
-
- setMaxBounds: function (bounds) {
- this.options.maxBounds = bounds;
-
- if (!bounds) {
- this._boundsMinZoom = null;
- return this;
- }
-
- var minZoom = this.getBoundsZoom(bounds, true);
-
- this._boundsMinZoom = minZoom;
-
- if (this._loaded) {
- if (this._zoom < minZoom) {
- this.setView(bounds.getCenter(), minZoom);
- } else {
- this.panInsideBounds(bounds);
- }
- }
-
- return this;
- },
-
- panInsideBounds: function (bounds) {
- var viewBounds = this.getBounds(),
- viewSw = this.project(viewBounds.getSouthWest()),
- viewNe = this.project(viewBounds.getNorthEast()),
- sw = this.project(bounds.getSouthWest()),
- ne = this.project(bounds.getNorthEast()),
- dx = 0,
- dy = 0;
-
- if (viewNe.y < ne.y) { // north
- dy = ne.y - viewNe.y;
- }
- if (viewNe.x > ne.x) { // east
- dx = ne.x - viewNe.x;
- }
- if (viewSw.y > sw.y) { // south
- dy = sw.y - viewSw.y;
- }
- if (viewSw.x < sw.x) { // west
- dx = sw.x - viewSw.x;
- }
-
- return this.panBy(new L.Point(dx, dy, true));
- },
-
- addLayer: function (layer, insertAtTheBottom) {
- // TODO method is too big, refactor
-
- var id = L.Util.stamp(layer);
-
- if (this._layers[id]) { return this; }
-
- this._layers[id] = layer;
-
- // TODO getMaxZoom, getMinZoom in ILayer (instead of options)
- if (layer.options && !isNaN(layer.options.maxZoom)) {
- this._layersMaxZoom = Math.max(this._layersMaxZoom || 0, layer.options.maxZoom);
- }
- if (layer.options && !isNaN(layer.options.minZoom)) {
- this._layersMinZoom = Math.min(this._layersMinZoom || Infinity, layer.options.minZoom);
- }
-
- // TODO looks ugly, refactor!!!
- if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) {
- this._tileLayersNum++;
- layer.on('load', this._onTileLayerLoad, this);
- }
-
- var onMapLoad = function () {
- layer.onAdd(this, insertAtTheBottom);
- this.fire('layeradd', {layer: layer});
- };
-
- if (this._loaded) {
- onMapLoad.call(this);
- } else {
- this.on('load', onMapLoad, this);
- }
-
- return this;
- },
-
- removeLayer: function (layer) {
- var id = L.Util.stamp(layer);
-
- if (!this._layers[id]) { return; }
-
- layer.onRemove(this);
-
- delete this._layers[id];
-
- // TODO looks ugly, refactor
- if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) {
- this._tileLayersNum--;
- layer.off('load', this._onTileLayerLoad, this);
- }
-
- return this.fire('layerremove', {layer: layer});
- },
-
- hasLayer: function (layer) {
- var id = L.Util.stamp(layer);
- return this._layers.hasOwnProperty(id);
- },
-
- invalidateSize: function () {
- var oldSize = this.getSize();
-
- this._sizeChanged = true;
-
- if (this.options.maxBounds) {
- this.setMaxBounds(this.options.maxBounds);
- }
-
- if (!this._loaded) { return this; }
-
- var offset = oldSize.subtract(this.getSize()).divideBy(2, true);
- this._rawPanBy(offset);
-
- this.fire('move');
-
- clearTimeout(this._sizeTimer);
- this._sizeTimer = setTimeout(L.Util.bind(this.fire, this, 'moveend'), 200);
-
- return this;
- },
-
- // TODO handler.addTo
- addHandler: function (name, HandlerClass) {
- if (!HandlerClass) { return; }
-
- this[name] = new HandlerClass(this);
-
- if (this.options[name]) {
- this[name].enable();
- }
-
- return this;
- },
-
-
- // public methods for getting map state
-
- getCenter: function (unbounded) { // (Boolean) -> LatLng
- var viewHalf = this.getSize().divideBy(2),
- centerPoint = this._getTopLeftPoint().add(viewHalf);
-
- return this.unproject(centerPoint, this._zoom, unbounded);
- },
-
- getZoom: function () {
- return this._zoom;
- },
-
- getBounds: function () {
- var bounds = this.getPixelBounds(),
- sw = this.unproject(new L.Point(bounds.min.x, bounds.max.y), this._zoom, true),
- ne = this.unproject(new L.Point(bounds.max.x, bounds.min.y), this._zoom, true);
-
- return new L.LatLngBounds(sw, ne);
- },
-
- getMinZoom: function () {
- var z1 = this.options.minZoom || 0,
- z2 = this._layersMinZoom || 0,
- z3 = this._boundsMinZoom || 0;
-
- return Math.max(z1, z2, z3);
- },
-
- getMaxZoom: function () {
- var z1 = typeof this.options.maxZoom === 'undefined' ? Infinity : this.options.maxZoom,
- z2 = typeof this._layersMaxZoom === 'undefined' ? Infinity : this._layersMaxZoom;
-
- return Math.min(z1, z2);
- },
-
- getBoundsZoom: function (bounds, inside) { // (LatLngBounds, Boolean) -> Number
- var size = this.getSize(),
- zoom = this.options.minZoom || 0,
- maxZoom = this.getMaxZoom(),
- ne = bounds.getNorthEast(),
- sw = bounds.getSouthWest(),
- boundsSize,
- nePoint,
- swPoint,
- zoomNotFound = true;
-
- if (inside) {
- zoom--;
- }
-
- do {
- zoom++;
- nePoint = this.project(ne, zoom);
- swPoint = this.project(sw, zoom);
- boundsSize = new L.Point(nePoint.x - swPoint.x, swPoint.y - nePoint.y);
-
- if (!inside) {
- zoomNotFound = boundsSize.x <= size.x && boundsSize.y <= size.y;
- } else {
- zoomNotFound = boundsSize.x < size.x || boundsSize.y < size.y;
- }
- } while (zoomNotFound && zoom <= maxZoom);
-
- if (zoomNotFound && inside) {
- return null;
- }
-
- return inside ? zoom : zoom - 1;
- },
-
- getSize: function () {
- if (!this._size || this._sizeChanged) {
- this._size = new L.Point(
- this._container.clientWidth,
- this._container.clientHeight);
-
- this._sizeChanged = false;
- }
- return this._size;
- },
-
- getPixelBounds: function () {
- var topLeftPoint = this._getTopLeftPoint();
- return new L.Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));
- },
-
- getPixelOrigin: function () {
- return this._initialTopLeftPoint;
- },
-
- getPanes: function () {
- return this._panes;
- },
-
- getContainer: function () {
- return this._container;
- },
-
-
- // conversion methods
-
- mouseEventToContainerPoint: function (e) { // (MouseEvent)
- return L.DomEvent.getMousePosition(e, this._container);
- },
-
- mouseEventToLayerPoint: function (e) { // (MouseEvent)
- return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e));
- },
-
- mouseEventToLatLng: function (e) { // (MouseEvent)
- return this.layerPointToLatLng(this.mouseEventToLayerPoint(e));
- },
-
- containerPointToLayerPoint: function (point) { // (Point)
- return point.subtract(L.DomUtil.getPosition(this._mapPane));
- },
-
- layerPointToContainerPoint: function (point) { // (Point)
- return point.add(L.DomUtil.getPosition(this._mapPane));
- },
-
- layerPointToLatLng: function (point) { // (Point)
- return this.unproject(point.add(this._initialTopLeftPoint));
- },
-
- latLngToLayerPoint: function (latlng) { // (LatLng)
- return this.project(latlng)._round()._subtract(this._initialTopLeftPoint);
- },
-
- containerPointToLatLng: function (point) {
- return this.layerPointToLatLng(this.containerPointToLayerPoint(point));
- },
-
- latLngToContainerPoint: function (latlng) {
- return this.layerPointToContainerPoint(this.latLngToLayerPoint(latlng));
- },
-
- project: function (latlng, zoom) { // (LatLng[, Number]) -> Point
- zoom = typeof zoom === 'undefined' ? this._zoom : zoom;
- return this.options.crs.latLngToPoint(latlng, zoom);
- },
-
- unproject: function (point, zoom, unbounded) { // (Point[, Number, Boolean]) -> LatLng
- // TODO remove unbounded, making it true all the time?
- zoom = typeof zoom === 'undefined' ? this._zoom : zoom;
- return this.options.crs.pointToLatLng(point, zoom, unbounded);
- },
-
-
- // private methods that modify map state
-
- _initContainer: function (id) {
- var container = this._container = L.DomUtil.get(id);
-
- if (container._leaflet) {
- throw new Error("Map container is already initialized.");
- }
-
- container._leaflet = true;
- },
-
- _initLayout: function () {
- var container = this._container;
-
- container.innerHTML = '';
- container.className += ' leaflet-container';
-
- if (L.Browser.touch) {
- container.className += ' leaflet-touch';
- }
-
- if (this.options.fadeAnimation) {
- container.className += ' leaflet-fade-anim';
- }
-
- var position = L.DomUtil.getStyle(container, 'position');
-
- if (position !== 'absolute' && position !== 'relative') {
- container.style.position = 'relative';
- }
-
- this._initPanes();
-
- if (this._initControlPos) {
- this._initControlPos();
- }
- },
-
- _initPanes: function () {
- var panes = this._panes = {};
-
- this._mapPane = panes.mapPane = this._createPane('leaflet-map-pane', this._container);
-
- this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane', this._mapPane);
- this._objectsPane = panes.objectsPane = this._createPane('leaflet-objects-pane', this._mapPane);
-
- panes.shadowPane = this._createPane('leaflet-shadow-pane');
- panes.overlayPane = this._createPane('leaflet-overlay-pane');
- panes.markerPane = this._createPane('leaflet-marker-pane');
- panes.popupPane = this._createPane('leaflet-popup-pane');
- },
-
- _createPane: function (className, container) {
- return L.DomUtil.create('div', className, container || this._objectsPane);
- },
-
- _initializers: [],
-
- _initHooks: function () {
- var i, len;
- for (i = 0, len = this._initializers.length; i < len; i++) {
- this._initializers[i].call(this);
- }
- },
-
- _resetView: function (center, zoom, preserveMapOffset, afterZoomAnim) {
-
- var zoomChanged = (this._zoom !== zoom);
-
- if (!afterZoomAnim) {
- this.fire('movestart');
-
- if (zoomChanged) {
- this.fire('zoomstart');
- }
- }
-
- this._zoom = zoom;
-
- this._initialTopLeftPoint = this._getNewTopLeftPoint(center);
-
- if (!preserveMapOffset) {
- L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0));
- } else {
- this._initialTopLeftPoint._add(L.DomUtil.getPosition(this._mapPane));
- }
-
- this._tileLayersToLoad = this._tileLayersNum;
-
- this.fire('viewreset', {hard: !preserveMapOffset});
-
- this.fire('move');
-
- if (zoomChanged || afterZoomAnim) {
- this.fire('zoomend');
- }
-
- this.fire('moveend');
-
- if (!this._loaded) {
- this._loaded = true;
- this.fire('load');
- }
- },
-
- _initLayers: function (layers) {
- layers = layers ? (layers instanceof Array ? layers : [layers]) : [];
-
- this._layers = {};
- this._tileLayersNum = 0;
-
- var i, len;
-
- for (i = 0, len = layers.length; i < len; i++) {
- this.addLayer(layers[i]);
- }
- },
-
- _rawPanBy: function (offset) {
- var newPos = L.DomUtil.getPosition(this._mapPane).subtract(offset);
- L.DomUtil.setPosition(this._mapPane, newPos);
- },
-
-
- // map events
-
- _initEvents: function () {
- if (!L.DomEvent) { return; }
-
- L.DomEvent.addListener(this._container, 'click', this._onMouseClick, this);
-
- var events = ['dblclick', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'contextmenu'];
-
- var i, len;
-
- for (i = 0, len = events.length; i < len; i++) {
- L.DomEvent.addListener(this._container, events[i], this._fireMouseEvent, this);
- }
-
- if (this.options.trackResize) {
- L.DomEvent.addListener(window, 'resize', this._onResize, this);
- }
- },
-
- _onResize: function () {
- L.Util.requestAnimFrame(this.invalidateSize, this, false, this._container);
- },
-
- _onMouseClick: function (e) {
- if (!this._loaded || (this.dragging && this.dragging.moved())) { return; }
-
- this.fire('pre' + e.type);
- this._fireMouseEvent(e);
- },
-
- _fireMouseEvent: function (e) {
- if (!this._loaded) { return; }
-
- var type = e.type;
-
- type = (type === 'mouseenter' ? 'mouseover' : (type === 'mouseleave' ? 'mouseout' : type));
-
- if (!this.hasEventListeners(type)) { return; }
-
- if (type === 'contextmenu') {
- L.DomEvent.preventDefault(e);
- }
-
- var containerPoint = this.mouseEventToContainerPoint(e),
- layerPoint = this.containerPointToLayerPoint(containerPoint),
- latlng = this.layerPointToLatLng(layerPoint);
-
- this.fire(type, {
- latlng: latlng,
- layerPoint: layerPoint,
- containerPoint: containerPoint,
- originalEvent: e
- });
- },
-
- _onTileLayerLoad: function () {
- // TODO super-ugly, refactor!!!
- // clear scaled tiles after all new tiles are loaded (for performance)
- this._tileLayersToLoad--;
- if (this._tileLayersNum && !this._tileLayersToLoad && this._tileBg) {
- clearTimeout(this._clearTileBgTimer);
- this._clearTileBgTimer = setTimeout(L.Util.bind(this._clearTileBg, this), 500);
- }
- },
-
-
- // private methods for getting map state
-
- _getTopLeftPoint: function () {
- if (!this._loaded) {
- throw new Error('Set map center and zoom first.');
- }
-
- var mapPanePos = L.DomUtil.getPosition(this._mapPane);
- return this._initialTopLeftPoint.subtract(mapPanePos);
- },
-
- _getNewTopLeftPoint: function (center) {
- var viewHalf = this.getSize().divideBy(2);
- // TODO round on display, not calculation to increase precision?
- return this.project(center)._subtract(viewHalf)._round();
- },
-
- _limitZoom: function (zoom) {
- var min = this.getMinZoom(),
- max = this.getMaxZoom();
-
- return Math.max(min, Math.min(max, zoom));
- }
-});
-
-L.Map.addInitHook = function (fn) {
- var args = Array.prototype.slice.call(arguments, 1);
-
- var init = typeof fn === 'function' ? fn : function () {
- this[fn].apply(this, args);
- };
-
- this.prototype._initializers.push(init);
-};
-
-
-L.Projection.Mercator = {
- MAX_LATITUDE: 85.0840591556,
-
- R_MINOR: 6356752.3142,
- R_MAJOR: 6378137,
-
- project: function (latlng) { // (LatLng) -> Point
- var d = L.LatLng.DEG_TO_RAD,
- max = this.MAX_LATITUDE,
- lat = Math.max(Math.min(max, latlng.lat), -max),
- r = this.R_MAJOR,
- r2 = this.R_MINOR,
- x = latlng.lng * d * r,
- y = lat * d,
- tmp = r2 / r,
- eccent = Math.sqrt(1.0 - tmp * tmp),
- con = eccent * Math.sin(y);
-
- con = Math.pow((1 - con) / (1 + con), eccent * 0.5);
-
- var ts = Math.tan(0.5 * ((Math.PI * 0.5) - y)) / con;
- y = -r2 * Math.log(ts);
-
- return new L.Point(x, y);
- },
-
- unproject: function (point, unbounded) { // (Point, Boolean) -> LatLng
- var d = L.LatLng.RAD_TO_DEG,
- r = this.R_MAJOR,
- r2 = this.R_MINOR,
- lng = point.x * d / r,
- tmp = r2 / r,
- eccent = Math.sqrt(1 - (tmp * tmp)),
- ts = Math.exp(- point.y / r2),
- phi = (Math.PI / 2) - 2 * Math.atan(ts),
- numIter = 15,
- tol = 1e-7,
- i = numIter,
- dphi = 0.1,
- con;
-
- while ((Math.abs(dphi) > tol) && (--i > 0)) {
- con = eccent * Math.sin(phi);
- dphi = (Math.PI / 2) - 2 * Math.atan(ts * Math.pow((1.0 - con) / (1.0 + con), 0.5 * eccent)) - phi;
- phi += dphi;
- }
-
- return new L.LatLng(phi * d, lng, unbounded);
- }
-};
-
-
-
-L.CRS.EPSG3395 = L.Util.extend({}, L.CRS, {
- code: 'EPSG:3395',
-
- projection: L.Projection.Mercator,
-
- transformation: (function () {
- var m = L.Projection.Mercator,
- r = m.R_MAJOR,
- r2 = m.R_MINOR;
-
- return new L.Transformation(0.5 / (Math.PI * r), 0.5, -0.5 / (Math.PI * r2), 0.5);
- }())
-});
-
-
-/*
- * L.TileLayer is used for standard xyz-numbered tile layers.
- */
-
-L.TileLayer = L.Class.extend({
- includes: L.Mixin.Events,
-
- options: {
- minZoom: 0,
- maxZoom: 18,
- tileSize: 256,
- subdomains: 'abc',
- errorTileUrl: '',
- attribution: '',
- opacity: 1,
- scheme: 'xyz',
- continuousWorld: false,
- noWrap: false,
- zoomOffset: 0,
- zoomReverse: false,
- detectRetina: false,
-
- unloadInvisibleTiles: L.Browser.mobile,
- updateWhenIdle: L.Browser.mobile,
- reuseTiles: false
- },
-
- initialize: function (url, options) {
- options = L.Util.setOptions(this, options);
-
- // detecting retina displays, adjusting tileSize and zoom levels
- if (options.detectRetina && window.devicePixelRatio > 1 && options.maxZoom > 0) {
-
- options.tileSize = Math.floor(options.tileSize / 2);
- options.zoomOffset++;
-
- if (options.minZoom > 0) {
- options.minZoom--;
- }
- this.options.maxZoom--;
- }
-
- this._url = url;
-
- var subdomains = this.options.subdomains;
-
- if (typeof subdomains === 'string') {
- this.options.subdomains = subdomains.split('');
- }
- },
-
- onAdd: function (map, insertAtTheBottom) {
- this._map = map;
- this._insertAtTheBottom = insertAtTheBottom;
-
- // create a container div for tiles
- this._initContainer();
-
- // create an image to clone for tiles
- this._createTileProto();
-
- // set up events
- map.on('viewreset', this._resetCallback, this);
- map.on('moveend', this._update, this);
-
- if (!this.options.updateWhenIdle) {
- this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);
- map.on('move', this._limitedUpdate, this);
- }
-
- this._reset();
- this._update();
- },
-
- onRemove: function (map) {
- map._panes.tilePane.removeChild(this._container);
-
- map.off('viewreset', this._resetCallback, this);
- map.off('moveend', this._update, this);
-
- if (!this.options.updateWhenIdle) {
- map.off('move', this._limitedUpdate, this);
- }
-
- this._container = null;
- this._map = null;
- },
-
- getAttribution: function () {
- return this.options.attribution;
- },
-
- setOpacity: function (opacity) {
- this.options.opacity = opacity;
-
- if (this._map) {
- this._updateOpacity();
- }
-
- // stupid webkit hack to force redrawing of tiles
- var i,
- tiles = this._tiles;
-
- if (L.Browser.webkit) {
- for (i in tiles) {
- if (tiles.hasOwnProperty(i)) {
- tiles[i].style.webkitTransform += ' translate(0,0)';
- }
- }
- }
- },
-
- _updateOpacity: function () {
- L.DomUtil.setOpacity(this._container, this.options.opacity);
- },
-
- _initContainer: function () {
- var tilePane = this._map._panes.tilePane,
- first = tilePane.firstChild;
-
- if (!this._container || tilePane.empty) {
- this._container = L.DomUtil.create('div', 'leaflet-layer');
-
- if (this._insertAtTheBottom && first) {
- tilePane.insertBefore(this._container, first);
- } else {
- tilePane.appendChild(this._container);
- }
-
- if (this.options.opacity < 1) {
- this._updateOpacity();
- }
- }
- },
-
- _resetCallback: function (e) {
- this._reset(e.hard);
- },
-
- _reset: function (clearOldContainer) {
- var key,
- tiles = this._tiles;
-
- for (key in tiles) {
- if (tiles.hasOwnProperty(key)) {
- this.fire('tileunload', {tile: tiles[key]});
- }
- }
-
- this._tiles = {};
-
- if (this.options.reuseTiles) {
- this._unusedTiles = [];
- }
-
- if (clearOldContainer && this._container) {
- this._container.innerHTML = "";
- }
-
- this._initContainer();
- },
-
- _update: function (e) {
- if (this._map._panTransition && this._map._panTransition._inProgress) { return; }
-
- var bounds = this._map.getPixelBounds(),
- zoom = this._map.getZoom(),
- tileSize = this.options.tileSize;
-
- if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
- return;
- }
-
- var nwTilePoint = new L.Point(
- Math.floor(bounds.min.x / tileSize),
- Math.floor(bounds.min.y / tileSize)),
- seTilePoint = new L.Point(
- Math.floor(bounds.max.x / tileSize),
- Math.floor(bounds.max.y / tileSize)),
- tileBounds = new L.Bounds(nwTilePoint, seTilePoint);
-
- this._addTilesFromCenterOut(tileBounds);
-
- if (this.options.unloadInvisibleTiles || this.options.reuseTiles) {
- this._removeOtherTiles(tileBounds);
- }
- },
-
- _addTilesFromCenterOut: function (bounds) {
- var queue = [],
- center = bounds.getCenter();
-
- var j, i;
- for (j = bounds.min.y; j <= bounds.max.y; j++) {
- for (i = bounds.min.x; i <= bounds.max.x; i++) {
- if (!((i + ':' + j) in this._tiles)) {
- queue.push(new L.Point(i, j));
- }
- }
- }
-
- // load tiles in order of their distance to center
- queue.sort(function (a, b) {
- return a.distanceTo(center) - b.distanceTo(center);
- });
-
- var fragment = document.createDocumentFragment();
-
- this._tilesToLoad = queue.length;
-
- var k, len;
- for (k = 0, len = this._tilesToLoad; k < len; k++) {
- this._addTile(queue[k], fragment);
- }
-
- this._container.appendChild(fragment);
- },
-
- _removeOtherTiles: function (bounds) {
- var kArr, x, y, key, tile;
-
- for (key in this._tiles) {
- if (this._tiles.hasOwnProperty(key)) {
- kArr = key.split(':');
- x = parseInt(kArr[0], 10);
- y = parseInt(kArr[1], 10);
-
- // remove tile if it's out of bounds
- if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) {
- this._removeTile(key);
- }
- }
- }
- },
-
- _removeTile: function (key) {
- var tile = this._tiles[key];
-
- this.fire("tileunload", {tile: tile, url: tile.src});
-
- if (tile.parentNode === this._container) {
- this._container.removeChild(tile);
- }
- if (this.options.reuseTiles) {
- this._unusedTiles.push(tile);
- }
-
- tile.src = L.Util.emptyImageUrl;
-
- delete this._tiles[key];
- },
-
- _addTile: function (tilePoint, container) {
- var tilePos = this._getTilePos(tilePoint),
- zoom = this._map.getZoom(),
- key = tilePoint.x + ':' + tilePoint.y,
- limit = Math.pow(2, this._getOffsetZoom(zoom));
-
- // wrap tile coordinates
- if (!this.options.continuousWorld) {
- if (!this.options.noWrap) {
- tilePoint.x = ((tilePoint.x % limit) + limit) % limit;
- } else if (tilePoint.x < 0 || tilePoint.x >= limit) {
- this._tilesToLoad--;
- return;
- }
-
- if (tilePoint.y < 0 || tilePoint.y >= limit) {
- this._tilesToLoad--;
- return;
- }
- }
-
- // get unused tile - or create a new tile
- var tile = this._getTile();
- L.DomUtil.setPosition(tile, tilePos);
-
- this._tiles[key] = tile;
-
- if (this.options.scheme === 'tms') {
- tilePoint.y = limit - tilePoint.y - 1;
- }
-
- this._loadTile(tile, tilePoint, zoom);
-
- container.appendChild(tile);
- },
-
- _getOffsetZoom: function (zoom) {
- var options = this.options;
- zoom = options.zoomReverse ? options.maxZoom - zoom : zoom;
- return zoom + options.zoomOffset;
- },
-
- _getTilePos: function (tilePoint) {
- var origin = this._map.getPixelOrigin(),
- tileSize = this.options.tileSize;
-
- return tilePoint.multiplyBy(tileSize).subtract(origin);
- },
-
- // image-specific code (override to implement e.g. Canvas or SVG tile layer)
-
- getTileUrl: function (tilePoint, zoom) {
- var subdomains = this.options.subdomains,
- index = (tilePoint.x + tilePoint.y) % subdomains.length,
- s = this.options.subdomains[index];
-
- return L.Util.template(this._url, L.Util.extend({
- s: s,
- z: this._getOffsetZoom(zoom),
- x: tilePoint.x,
- y: tilePoint.y
- }, this.options));
- },
-
- _createTileProto: function () {
- var img = this._tileImg = L.DomUtil.create('img', 'leaflet-tile');
- img.galleryimg = 'no';
-
- var tileSize = this.options.tileSize;
- img.style.width = tileSize + 'px';
- img.style.height = tileSize + 'px';
- },
-
- _getTile: function () {
- if (this.options.reuseTiles && this._unusedTiles.length > 0) {
- var tile = this._unusedTiles.pop();
- this._resetTile(tile);
- return tile;
- }
- return this._createTile();
- },
-
- _resetTile: function (tile) {
- // Override if data stored on a tile needs to be cleaned up before reuse
- },
-
- _createTile: function () {
- var tile = this._tileImg.cloneNode(false);
- tile.onselectstart = tile.onmousemove = L.Util.falseFn;
- return tile;
- },
-
- _loadTile: function (tile, tilePoint, zoom) {
- tile._layer = this;
- tile.onload = this._tileOnLoad;
- tile.onerror = this._tileOnError;
-
- tile.src = this.getTileUrl(tilePoint, zoom);
- },
-
- _tileOnLoad: function (e) {
- var layer = this._layer;
-
- this.className += ' leaflet-tile-loaded';
-
- layer.fire('tileload', {
- tile: this,
- url: this.src
- });
-
- layer._tilesToLoad--;
- if (!layer._tilesToLoad) {
- layer.fire('load');
- }
- },
-
- _tileOnError: function (e) {
- var layer = this._layer;
-
- layer.fire('tileerror', {
- tile: this,
- url: this.src
- });
-
- var newUrl = layer.options.errorTileUrl;
- if (newUrl) {
- this.src = newUrl;
- }
- }
-});
-
-
-L.TileLayer.WMS = L.TileLayer.extend({
- defaultWmsParams: {
- service: 'WMS',
- request: 'GetMap',
- version: '1.1.1',
- layers: '',
- styles: '',
- format: 'image/jpeg',
- transparent: false
- },
-
- initialize: function (url, options) { // (String, Object)
- this._url = url;
-
- var wmsParams = L.Util.extend({}, this.defaultWmsParams);
- wmsParams.width = wmsParams.height = this.options.tileSize;
-
- for (var i in options) {
- // all keys that are not TileLayer options go to WMS params
- if (!this.options.hasOwnProperty(i)) {
- wmsParams[i] = options[i];
- }
- }
-
- this.wmsParams = wmsParams;
-
- L.Util.setOptions(this, options);
- },
-
- onAdd: function (map, insertAtTheBottom) {
- var projectionKey = parseFloat(this.wmsParams.version) >= 1.3 ? 'crs' : 'srs';
- this.wmsParams[projectionKey] = map.options.crs.code;
-
- L.TileLayer.prototype.onAdd.call(this, map, insertAtTheBottom);
- },
-
- getTileUrl: function (tilePoint, zoom) { // (Point, Number) -> String
- var map = this._map,
- crs = map.options.crs,
-
- tileSize = this.options.tileSize,
-
- nwPoint = tilePoint.multiplyBy(tileSize),
- sePoint = nwPoint.add(new L.Point(tileSize, tileSize)),
-
- nwMap = map.unproject(nwPoint, zoom, true),
- seMap = map.unproject(sePoint, zoom, true),
-
- nw = crs.project(nwMap),
- se = crs.project(seMap),
-
- bbox = [nw.x, se.y, se.x, nw.y].join(',');
-
- return this._url + L.Util.getParamString(this.wmsParams) + "&bbox=" + bbox;
- }
-});
-
-
-L.TileLayer.Canvas = L.TileLayer.extend({
- options: {
- async: false
- },
-
- initialize: function (options) {
- L.Util.setOptions(this, options);
- },
-
- redraw: function () {
- var i,
- tiles = this._tiles;
-
- for (i in tiles) {
- if (tiles.hasOwnProperty(i)) {
- this._redrawTile(tiles[i]);
- }
- }
- },
-
- _redrawTile: function (tile) {
- this.drawTile(tile, tile._tilePoint, tile._zoom);
- },
-
- _createTileProto: function () {
- var proto = this._canvasProto = L.DomUtil.create('canvas', 'leaflet-tile');
-
- var tileSize = this.options.tileSize;
- proto.width = tileSize;
- proto.height = tileSize;
- },
-
- _createTile: function () {
- var tile = this._canvasProto.cloneNode(false);
- tile.onselectstart = tile.onmousemove = L.Util.falseFn;
- return tile;
- },
-
- _loadTile: function (tile, tilePoint, zoom) {
- tile._layer = this;
- tile._tilePoint = tilePoint;
- tile._zoom = zoom;
-
- this.drawTile(tile, tilePoint, zoom);
-
- if (!this.options.async) {
- this.tileDrawn(tile);
- }
- },
-
- drawTile: function (tile, tilePoint, zoom) {
- // override with rendering code
- },
-
- tileDrawn: function (tile) {
- this._tileOnLoad.call(tile);
- }
-});
-
-
-L.ImageOverlay = L.Class.extend({
- includes: L.Mixin.Events,
-
- initialize: function (/*String*/ url, /*LatLngBounds*/ bounds) {
- this._url = url;
- this._bounds = bounds;
- },
-
- onAdd: function (map) {
- this._map = map;
-
- if (!this._image) {
- this._initImage();
- }
-
- map._panes.overlayPane.appendChild(this._image);
-
- map.on('viewreset', this._reset, this);
- this._reset();
- },
-
- onRemove: function (map) {
- map.getPanes().overlayPane.removeChild(this._image);
- map.off('viewreset', this._reset, this);
- },
-
- _initImage: function () {
- this._image = L.DomUtil.create('img', 'leaflet-image-layer');
-
- this._image.style.visibility = 'hidden';
- //TODO opacity option
-
- //TODO createImage util method to remove duplication
- L.Util.extend(this._image, {
- galleryimg: 'no',
- onselectstart: L.Util.falseFn,
- onmousemove: L.Util.falseFn,
- onload: L.Util.bind(this._onImageLoad, this),
- src: this._url
- });
- },
-
- _reset: function () {
- var image = this._image,
- topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
- size = this._map.latLngToLayerPoint(this._bounds.getSouthEast()).subtract(topLeft);
-
- L.DomUtil.setPosition(image, topLeft);
-
- image.style.width = size.x + 'px';
- image.style.height = size.y + 'px';
- },
-
- _onImageLoad: function () {
- this._image.style.visibility = '';
- this.fire('load');
- }
-});
-
-
-L.Icon = L.Class.extend({
- options: {
- /*
- iconUrl: (String) (required)
- iconSize: (Point) (can be set through CSS)
- iconAnchor: (Point) (centered by default if size is specified, can be set in CSS with negative margins)
- popupAnchor: (Point) (if not specified, popup opens in the anchor point)
- shadowUrl: (Point) (no shadow by default)
- shadowSize: (Point)
- */
- className: ''
- },
-
- initialize: function (options) {
- L.Util.setOptions(this, options);
- },
-
- createIcon: function () {
- return this._createIcon('icon');
- },
-
- createShadow: function () {
- return this._createIcon('shadow');
- },
-
- _createIcon: function (name) {
- var src = this._getIconUrl(name);
-
- if (!src) { return null; }
-
- var img = this._createImg(src);
- this._setIconStyles(img, name);
-
- return img;
- },
-
- _setIconStyles: function (img, name) {
- var options = this.options,
- size = options[name + 'Size'],
- anchor = options.iconAnchor;
-
- if (!anchor && size) {
- anchor = size.divideBy(2, true);
- }
-
- if (name === 'shadow' && anchor && options.shadowOffset) {
- anchor._add(options.shadowOffset);
- }
-
- img.className = 'leaflet-marker-' + name + ' ' + options.className;
-
- if (anchor) {
- img.style.marginLeft = (-anchor.x) + 'px';
- img.style.marginTop = (-anchor.y) + 'px';
- }
-
- if (size) {
- img.style.width = size.x + 'px';
- img.style.height = size.y + 'px';
- }
- },
-
- _createImg: function (src) {
- var el;
-
- if (!L.Browser.ie6) {
- el = document.createElement('img');
- el.src = src;
- } else {
- el = document.createElement('div');
- el.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + src + '")';
- }
- return el;
- },
-
- _getIconUrl: function (name) {
- return this.options[name + 'Url'];
- }
-});
-
-
-// TODO move to a separate file
-
-L.Icon.Default = L.Icon.extend({
- options: {
- iconSize: new L.Point(25, 41),
- iconAnchor: new L.Point(13, 41),
- popupAnchor: new L.Point(0, -33),
-
- shadowSize: new L.Point(41, 41)
- },
-
- _getIconUrl: function (name) {
- var path = L.Icon.Default.imagePath;
- if (!path) {
- throw new Error("Couldn't autodetect L.Icon.Default.imagePath, set it manually.");
- }
-
- return path + '/marker-' + name + '.png';
- }
-});
-
-L.Icon.Default.imagePath = (function () {
- var scripts = document.getElementsByTagName('script'),
- leafletRe = /\/?leaflet[\-\._]?([\w\-\._]*)\.js\??/;
-
- var i, len, src, matches;
-
- for (i = 0, len = scripts.length; i < len; i++) {
- src = scripts[i].src;
- matches = src.match(leafletRe);
-
- if (matches) {
- return src.split(leafletRe)[0] + '/images';
- }
- }
-}());
-
-/*
- * L.Marker is used to display clickable/draggable icons on the map.
- */
-
-L.Marker = L.Class.extend({
-
- includes: L.Mixin.Events,
-
- options: {
- icon: new L.Icon.Default(),
- title: '',
- clickable: true,
- draggable: false,
- zIndexOffset: 0,
- opacity: 1
- },
-
- initialize: function (latlng, options) {
- L.Util.setOptions(this, options);
- this._latlng = latlng;
- },
-
- onAdd: function (map) {
- this._map = map;
-
- map.on('viewreset', this._reset, this);
-
- this._initIcon();
- this._reset();
- },
-
- onRemove: function (map) {
- this._removeIcon();
-
- // TODO move to Marker.Popup.js
- if (this.closePopup) {
- this.closePopup();
- }
-
- map.off('viewreset', this._reset, this);
-
- this._map = null;
- },
-
- getLatLng: function () {
- return this._latlng;
- },
-
- setLatLng: function (latlng) {
- this._latlng = latlng;
-
- this._reset();
-
- if (this._popup) {
- this._popup.setLatLng(latlng);
- }
- },
-
- setZIndexOffset: function (offset) {
- this.options.zIndexOffset = offset;
- this._reset();
- },
-
- setIcon: function (icon) {
- if (this._map) {
- this._removeIcon();
- }
-
- this.options.icon = icon;
-
- if (this._map) {
- this._initIcon();
- this._reset();
- }
- },
-
- _initIcon: function () {
- var options = this.options;
-
- if (!this._icon) {
- this._icon = options.icon.createIcon();
-
- if (options.title) {
- this._icon.title = options.title;
- }
-
- this._initInteraction();
- this._updateOpacity();
- }
- if (!this._shadow) {
- this._shadow = options.icon.createShadow();
- }
-
- var panes = this._map._panes;
-
- panes.markerPane.appendChild(this._icon);
-
- if (this._shadow) {
- panes.shadowPane.appendChild(this._shadow);
- }
- },
-
- _removeIcon: function () {
- var panes = this._map._panes;
-
- panes.markerPane.removeChild(this._icon);
-
- if (this._shadow) {
- panes.shadowPane.removeChild(this._shadow);
- }
-
- this._icon = this._shadow = null;
- },
-
- _reset: function () {
- var icon = this._icon;
-
- if (!icon) {
- return;
- }
-
- var pos = this._map.latLngToLayerPoint(this._latlng).round();
-
- L.DomUtil.setPosition(icon, pos);
-
- if (this._shadow) {
- L.DomUtil.setPosition(this._shadow, pos);
- }
-
- icon.style.zIndex = pos.y + this.options.zIndexOffset;
- },
-
- _initInteraction: function () {
- if (!this.options.clickable) {
- return;
- }
-
- var icon = this._icon,
- events = ['dblclick', 'mousedown', 'mouseover', 'mouseout'];
-
- icon.className += ' leaflet-clickable';
- L.DomEvent.addListener(icon, 'click', this._onMouseClick, this);
-
- for (var i = 0; i < events.length; i++) {
- L.DomEvent.addListener(icon, events[i], this._fireMouseEvent, this);
- }
-
- if (L.Handler.MarkerDrag) {
- this.dragging = new L.Handler.MarkerDrag(this);
-
- if (this.options.draggable) {
- this.dragging.enable();
- }
- }
- },
-
- _onMouseClick: function (e) {
- L.DomEvent.stopPropagation(e);
- if (this.dragging && this.dragging.moved()) { return; }
- if (this._map.dragging && this._map.dragging.moved()) { return; }
- this.fire(e.type, {
- originalEvent: e
- });
- },
-
- _fireMouseEvent: function (e) {
- this.fire(e.type, {
- originalEvent: e
- });
- if (e.type !== 'mousedown') {
- L.DomEvent.stopPropagation(e);
- }
- },
-
- setOpacity: function (opacity) {
- this.options.opacity = opacity;
- if (this._map) {
- this._updateOpacity();
- }
- },
-
- _updateOpacity: function (opacity) {
- L.DomUtil.setOpacity(this._icon, this.options.opacity);
- }
-});
-
-
-L.DivIcon = L.Icon.extend({
- options: {
- iconSize: new L.Point(12, 12), // also can be set through CSS
- /*
- iconAnchor: (Point)
- popupAnchor: (Point)
- */
- className: 'leaflet-div-icon'
- },
-
- createIcon: function () {
- var div = document.createElement('div');
- this._setIconStyles(div, 'icon');
- return div;
- },
-
- createShadow: function () {
- return null;
- }
-});
-
-
-
-L.Map.mergeOptions({
- closePopupOnClick: true
-});
-
-L.Popup = L.Class.extend({
- includes: L.Mixin.Events,
-
- options: {
- minWidth: 50,
- maxWidth: 300,
- maxHeight: null,
- autoPan: true,
- closeButton: true,
- offset: new L.Point(0, 2),
- autoPanPadding: new L.Point(5, 5),
- className: ''
- },
-
- initialize: function (options, source) {
- L.Util.setOptions(this, options);
-
- this._source = source;
- },
-
- onAdd: function (map) {
- this._map = map;
-
- if (!this._container) {
- this._initLayout();
- }
- this._updateContent();
-
- this._container.style.opacity = '0';
- map._panes.popupPane.appendChild(this._container);
-
- map.on('viewreset', this._updatePosition, this);
-
- if (map.options.closePopupOnClick) {
- map.on('preclick', this._close, this);
- }
-
- this._update();
-
- this._container.style.opacity = '1'; //TODO fix ugly opacity hack
- },
-
- onRemove: function (map) {
- map._panes.popupPane.removeChild(this._container);
-
- L.Util.falseFn(this._container.offsetWidth);
-
- map.off('viewreset', this._updatePosition, this)
- .off('preclick', this._close, this);
-
- this._container.style.opacity = '0';
-
- this._map = null;
- },
-
- setLatLng: function (latlng) {
- this._latlng = latlng;
- this._update();
- return this;
- },
-
- setContent: function (content) {
- this._content = content;
- this._update();
- return this;
- },
-
- _close: function () {
- var map = this._map;
-
- if (map) {
- map._popup = null;
-
- map
- .removeLayer(this)
- .fire('popupclose', {popup: this});
- }
- },
-
- _initLayout: function () {
- var prefix = 'leaflet-popup',
- container = this._container = L.DomUtil.create('div', prefix + ' ' + this.options.className),
- closeButton;
-
- if (this.options.closeButton) {
- closeButton = this._closeButton = L.DomUtil.create('a', prefix + '-close-button', container);
- closeButton.href = '#close';
-
- L.DomEvent.addListener(closeButton, 'click', this._onCloseButtonClick, this);
- }
-
- var wrapper = this._wrapper = L.DomUtil.create('div', prefix + '-content-wrapper', container);
- L.DomEvent.disableClickPropagation(wrapper);
-
- this._contentNode = L.DomUtil.create('div', prefix + '-content', wrapper);
- L.DomEvent.addListener(this._contentNode, 'mousewheel', L.DomEvent.stopPropagation);
-
- this._tipContainer = L.DomUtil.create('div', prefix + '-tip-container', container);
- this._tip = L.DomUtil.create('div', prefix + '-tip', this._tipContainer);
- },
-
- _update: function () {
- if (!this._map) { return; }
-
- this._container.style.visibility = 'hidden';
-
- this._updateContent();
- this._updateLayout();
- this._updatePosition();
-
- this._container.style.visibility = '';
-
- this._adjustPan();
- },
-
- _updateContent: function () {
- if (!this._content) { return; }
-
- if (typeof this._content === 'string') {
- this._contentNode.innerHTML = this._content;
- } else {
- this._contentNode.innerHTML = '';
- this._contentNode.appendChild(this._content);
- }
- this.fire('contentupdate');
- },
-
- _updateLayout: function () {
- var container = this._contentNode;
-
- container.style.width = '';
- container.style.whiteSpace = 'nowrap';
-
- var width = container.offsetWidth;
- width = Math.min(width, this.options.maxWidth);
- width = Math.max(width, this.options.minWidth);
-
- container.style.width = (width + 1) + 'px';
- container.style.whiteSpace = '';
-
- container.style.height = '';
-
- var height = container.offsetHeight,
- maxHeight = this.options.maxHeight,
- scrolledClass = ' leaflet-popup-scrolled';
-
- if (maxHeight && height > maxHeight) {
- container.style.height = maxHeight + 'px';
- container.className += scrolledClass;
- } else {
- container.className = container.className.replace(scrolledClass, '');
- }
-
- this._containerWidth = this._container.offsetWidth;
- },
-
- _updatePosition: function () {
- var pos = this._map.latLngToLayerPoint(this._latlng);
-
- this._containerBottom = -pos.y - this.options.offset.y;
- this._containerLeft = pos.x - Math.round(this._containerWidth / 2) + this.options.offset.x;
-
- this._container.style.bottom = this._containerBottom + 'px';
- this._container.style.left = this._containerLeft + 'px';
- },
-
- _adjustPan: function () {
- if (!this.options.autoPan) { return; }
-
- var map = this._map,
- containerHeight = this._container.offsetHeight,
- containerWidth = this._containerWidth,
-
- layerPos = new L.Point(
- this._containerLeft,
- -containerHeight - this._containerBottom),
-
- containerPos = map.layerPointToContainerPoint(layerPos),
- adjustOffset = new L.Point(0, 0),
- padding = this.options.autoPanPadding,
- size = map.getSize();
-
- if (containerPos.x < 0) {
- adjustOffset.x = containerPos.x - padding.x;
- }
- if (containerPos.x + containerWidth > size.x) {
- adjustOffset.x = containerPos.x + containerWidth - size.x + padding.x;
- }
- if (containerPos.y < 0) {
- adjustOffset.y = containerPos.y - padding.y;
- }
- if (containerPos.y + containerHeight > size.y) {
- adjustOffset.y = containerPos.y + containerHeight - size.y + padding.y;
- }
-
- if (adjustOffset.x || adjustOffset.y) {
- map.panBy(adjustOffset);
- }
- },
-
- _onCloseButtonClick: function (e) {
- this._close();
- L.DomEvent.stop(e);
- }
-});
-
-
-/*
- * Popup extension to L.Marker, adding openPopup & bindPopup methods.
- */
-
-L.Marker.include({
- openPopup: function () {
- if (this._popup && this._map) {
- this._popup.setLatLng(this._latlng);
- this._map.openPopup(this._popup);
- }
-
- return this;
- },
-
- closePopup: function () {
- if (this._popup) {
- this._popup._close();
- }
- return this;
- },
-
- bindPopup: function (content, options) {
- var anchor = this.options.icon.options.popupAnchor || new L.Point(0, 0);
-
- if (options && options.offset) {
- anchor = anchor.add(options.offset);
- }
-
- options = L.Util.extend({offset: anchor}, options);
-
- if (!this._popup) {
- this.on('click', this.openPopup, this);
- }
-
- this._popup = new L.Popup(options, this)
- .setContent(content);
-
- return this;
- },
-
- unbindPopup: function () {
- if (this._popup) {
- this._popup = null;
- this.off('click', this.openPopup);
- }
- return this;
- }
-});
-
-
-
-L.Map.include({
- openPopup: function (popup) {
- this.closePopup();
-
- this._popup = popup;
-
- return this
- .addLayer(popup)
- .fire('popupopen', {popup: this._popup});
- },
-
- closePopup: function () {
- if (this._popup) {
- this._popup._close();
- }
- return this;
- }
-});
-
-/*
- * L.LayerGroup is a class to combine several layers so you can manipulate the group (e.g. add/remove it) as one layer.
- */
-
-L.LayerGroup = L.Class.extend({
- initialize: function (layers) {
- this._layers = {};
-
- var i, len;
-
- if (layers) {
- for (i = 0, len = layers.length; i < len; i++) {
- this.addLayer(layers[i]);
- }
- }
- },
-
- addLayer: function (layer) {
- var id = L.Util.stamp(layer);
-
- this._layers[id] = layer;
-
- if (this._map) {
- this._map.addLayer(layer);
- }
-
- return this;
- },
-
- removeLayer: function (layer) {
- var id = L.Util.stamp(layer);
-
- delete this._layers[id];
-
- if (this._map) {
- this._map.removeLayer(layer);
- }
-
- return this;
- },
-
- clearLayers: function () {
- this._iterateLayers(this.removeLayer, this);
- return this;
- },
-
- invoke: function (methodName) {
- var args = Array.prototype.slice.call(arguments, 1),
- i, layer;
-
- for (i in this._layers) {
- if (this._layers.hasOwnProperty(i)) {
- layer = this._layers[i];
-
- if (layer[methodName]) {
- layer[methodName].apply(layer, args);
- }
- }
- }
-
- return this;
- },
-
- onAdd: function (map) {
- this._map = map;
- this._iterateLayers(map.addLayer, map);
- },
-
- onRemove: function (map) {
- this._iterateLayers(map.removeLayer, map);
- this._map = null;
- },
-
- _iterateLayers: function (method, context) {
- for (var i in this._layers) {
- if (this._layers.hasOwnProperty(i)) {
- method.call(context, this._layers[i]);
- }
- }
- }
-});
-
-
-/*
- * L.FeatureGroup extends L.LayerGroup by introducing mouse events and bindPopup method shared between a group of layers.
- */
-
-L.FeatureGroup = L.LayerGroup.extend({
- includes: L.Mixin.Events,
-
- addLayer: function (layer) {
- this._initEvents(layer);
-
- L.LayerGroup.prototype.addLayer.call(this, layer);
-
- if (this._popupContent && layer.bindPopup) {
- layer.bindPopup(this._popupContent);
- }
- },
-
- bindPopup: function (content) {
- this._popupContent = content;
- return this.invoke('bindPopup', content);
- },
-
- setStyle: function (style) {
- return this.invoke('setStyle', style);
- },
-
- getBounds: function () {
- var bounds = new L.LatLngBounds();
- this._iterateLayers(function (layer) {
- bounds.extend(layer instanceof L.Marker ? layer.getLatLng() : layer.getBounds());
- }, this);
- return bounds;
- },
-
- _initEvents: function (layer) {
- var events = ['click', 'dblclick', 'mouseover', 'mouseout'],
- i, len;
-
- for (i = 0, len = events.length; i < len; i++) {
- layer.on(events[i], this._propagateEvent, this);
- }
- },
-
- _propagateEvent: function (e) {
- e.layer = e.target;
- e.target = this;
-
- this.fire(e.type, e);
- }
-});
-
-
-/*
- * L.Path is a base class for rendering vector paths on a map. It's inherited by Polyline, Circle, etc.
- */
-
-L.Path = L.Class.extend({
- includes: [L.Mixin.Events],
-
- statics: {
- // how much to extend the clip area around the map view
- // (relative to its size, e.g. 0.5 is half the screen in each direction)
- CLIP_PADDING: 0.5
- },
-
- options: {
- stroke: true,
- color: '#0033ff',
- weight: 5,
- opacity: 0.5,
-
- fill: false,
- fillColor: null, //same as color by default
- fillOpacity: 0.2,
-
- clickable: true
- },
-
- initialize: function (options) {
- L.Util.setOptions(this, options);
- },
-
- onAdd: function (map) {
- this._map = map;
-
- this._initElements();
- this._initEvents();
- this.projectLatlngs();
- this._updatePath();
-
- map
- .on('viewreset', this.projectLatlngs, this)
- .on('moveend', this._updatePath, this);
- },
-
- onRemove: function (map) {
- this._map = null;
-
- map._pathRoot.removeChild(this._container);
-
- map
- .off('viewreset', this.projectLatlngs, this)
- .off('moveend', this._updatePath, this);
- },
-
- projectLatlngs: function () {
- // do all projection stuff here
- },
-
- setStyle: function (style) {
- L.Util.setOptions(this, style);
-
- if (this._container) {
- this._updateStyle();
- }
-
- return this;
- },
-
- redraw: function () {
- if (this._map) {
- this.projectLatlngs();
- this._updatePath();
- }
- return this;
- }
-});
-
-L.Map.include({
- _updatePathViewport: function () {
- var p = L.Path.CLIP_PADDING,
- size = this.getSize(),
- panePos = L.DomUtil.getPosition(this._mapPane),
- min = panePos.multiplyBy(-1)._subtract(size.multiplyBy(p)),
- max = min.add(size.multiplyBy(1 + p * 2));
-
- this._pathViewport = new L.Bounds(min, max);
- }
-});
-
-
-L.Path.SVG_NS = 'http://www.w3.org/2000/svg';
-
-L.Browser.svg = !!(document.createElementNS && document.createElementNS(L.Path.SVG_NS, 'svg').createSVGRect);
-
-L.Path = L.Path.extend({
- statics: {
- SVG: L.Browser.svg
- },
-
- getPathString: function () {
- // form path string here
- },
-
- _createElement: function (name) {
- return document.createElementNS(L.Path.SVG_NS, name);
- },
-
- _initElements: function () {
- this._map._initPathRoot();
- this._initPath();
- this._initStyle();
- },
-
- _initPath: function () {
- this._container = this._createElement('g');
-
- this._path = this._createElement('path');
- this._container.appendChild(this._path);
-
- this._map._pathRoot.appendChild(this._container);
- },
-
- _initStyle: function () {
- if (this.options.stroke) {
- this._path.setAttribute('stroke-linejoin', 'round');
- this._path.setAttribute('stroke-linecap', 'round');
- }
- if (this.options.fill) {
- this._path.setAttribute('fill-rule', 'evenodd');
- }
- this._updateStyle();
- },
-
- _updateStyle: function () {
- if (this.options.stroke) {
- this._path.setAttribute('stroke', this.options.color);
- this._path.setAttribute('stroke-opacity', this.options.opacity);
- this._path.setAttribute('stroke-width', this.options.weight);
- } else {
- this._path.setAttribute('stroke', 'none');
- }
- if (this.options.fill) {
- this._path.setAttribute('fill', this.options.fillColor || this.options.color);
- this._path.setAttribute('fill-opacity', this.options.fillOpacity);
- } else {
- this._path.setAttribute('fill', 'none');
- }
- },
-
- _updatePath: function () {
- var str = this.getPathString();
- if (!str) {
- // fix webkit empty string parsing bug
- str = 'M0 0';
- }
- this._path.setAttribute('d', str);
- },
-
- // TODO remove duplication with L.Map
- _initEvents: function () {
- if (this.options.clickable) {
- if (L.Browser.svg || !L.Browser.vml) {
- this._path.setAttribute('class', 'leaflet-clickable');
- }
-
- L.DomEvent.addListener(this._container, 'click', this._onMouseClick, this);
-
- var events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'mousemove', 'contextmenu'];
- for (var i = 0; i < events.length; i++) {
- L.DomEvent.addListener(this._container, events[i], this._fireMouseEvent, this);
- }
- }
- },
-
- _onMouseClick: function (e) {
- if (this._map.dragging && this._map.dragging.moved()) {
- return;
- }
-
- if (e.type === 'contextmenu') {
- L.DomEvent.preventDefault(e);
- }
-
- this._fireMouseEvent(e);
- },
-
- _fireMouseEvent: function (e) {
- if (!this.hasEventListeners(e.type)) {
- return;
- }
- var map = this._map,
- containerPoint = map.mouseEventToContainerPoint(e),
- layerPoint = map.containerPointToLayerPoint(containerPoint),
- latlng = map.layerPointToLatLng(layerPoint);
-
- this.fire(e.type, {
- latlng: latlng,
- layerPoint: layerPoint,
- containerPoint: containerPoint,
- originalEvent: e
- });
-
- L.DomEvent.stopPropagation(e);
- }
-});
-
-L.Map.include({
- _initPathRoot: function () {
- if (!this._pathRoot) {
- this._pathRoot = L.Path.prototype._createElement('svg');
- this._panes.overlayPane.appendChild(this._pathRoot);
-
- this.on('moveend', this._updateSvgViewport);
- this._updateSvgViewport();
- }
- },
-
- _updateSvgViewport: function () {
- this._updatePathViewport();
-
- var vp = this._pathViewport,
- min = vp.min,
- max = vp.max,
- width = max.x - min.x,
- height = max.y - min.y,
- root = this._pathRoot,
- pane = this._panes.overlayPane;
-
- // Hack to make flicker on drag end on mobile webkit less irritating
- // Unfortunately I haven't found a good workaround for this yet
- if (L.Browser.webkit) {
- pane.removeChild(root);
- }
-
- L.DomUtil.setPosition(root, min);
- root.setAttribute('width', width);
- root.setAttribute('height', height);
- root.setAttribute('viewBox', [min.x, min.y, width, height].join(' '));
-
- if (L.Browser.webkit) {
- pane.appendChild(root);
- }
- }
-});
-
-
-/*
- * Popup extension to L.Path (polylines, polygons, circles), adding bindPopup method.
- */
-
-L.Path.include({
- bindPopup: function (content, options) {
- if (!this._popup || this._popup.options !== options) {
- this._popup = new L.Popup(options, this);
- }
- this._popup.setContent(content);
-
- if (!this._openPopupAdded) {
- this.on('click', this._openPopup, this);
- this._openPopupAdded = true;
- }
-
- return this;
- },
-
- _openPopup: function (e) {
- this._popup.setLatLng(e.latlng);
- this._map.openPopup(this._popup);
- }
-});
-
-
-/*
- * Vector rendering for IE6-8 through VML.
- * Thanks to Dmitry Baranovsky and his Raphael library for inspiration!
- */
-
-L.Browser.vml = (function () {
- var div = document.createElement('div');
- div.innerHTML = '';
-
- var shape = div.firstChild;
- shape.style.behavior = 'url(#default#VML)';
-
- return shape && (typeof shape.adj === 'object');
-}());
-
-L.Path = L.Browser.svg || !L.Browser.vml ? L.Path : L.Path.extend({
- statics: {
- VML: true,
- CLIP_PADDING: 0.02
- },
-
- _createElement: (function () {
- try {
- document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml');
- return function (name) {
- return document.createElement('');
- };
- } catch (e) {
- return function (name) {
- return document.createElement('<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">');
- };
- }
- }()),
-
- _initPath: function () {
- var container = this._container = this._createElement('shape');
- container.className += ' leaflet-vml-shape' +
- (this.options.clickable ? ' leaflet-clickable' : '');
- container.coordsize = '1 1';
-
- this._path = this._createElement('path');
- container.appendChild(this._path);
-
- this._map._pathRoot.appendChild(container);
- },
-
- _initStyle: function () {
- var container = this._container,
- stroke,
- fill;
-
- if (this.options.stroke) {
- stroke = this._stroke = this._createElement('stroke');
- stroke.endcap = 'round';
- container.appendChild(stroke);
- }
-
- if (this.options.fill) {
- fill = this._fill = this._createElement('fill');
- container.appendChild(fill);
- }
-
- this._updateStyle();
- },
-
- _updateStyle: function () {
- var stroke = this._stroke,
- fill = this._fill,
- options = this.options,
- container = this._container;
-
- container.stroked = options.stroke;
- container.filled = options.fill;
-
- if (options.stroke) {
- stroke.weight = options.weight + 'px';
- stroke.color = options.color;
- stroke.opacity = options.opacity;
- }
-
- if (options.fill) {
- fill.color = options.fillColor || options.color;
- fill.opacity = options.fillOpacity;
- }
- },
-
- _updatePath: function () {
- var style = this._container.style;
-
- style.display = 'none';
- this._path.v = this.getPathString() + ' '; // the space fixes IE empty path string bug
- style.display = '';
- }
-});
-
-L.Map.include(L.Browser.svg || !L.Browser.vml ? {} : {
- _initPathRoot: function () {
- if (this._pathRoot) { return; }
-
- var root = this._pathRoot = document.createElement('div');
- root.className = 'leaflet-vml-container';
- this._panes.overlayPane.appendChild(root);
-
- this.on('moveend', this._updatePathViewport);
- this._updatePathViewport();
- }
-});
-
-
-/*
- * Vector rendering for all browsers that support canvas.
- */
-
-L.Browser.canvas = (function () {
- return !!document.createElement('canvas').getContext;
-}());
-
-L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({
- statics: {
- //CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value
- CANVAS: true,
- SVG: false
- },
-
- _initElements: function () {
- this._map._initPathRoot();
- this._ctx = this._map._canvasCtx;
- },
-
- _updateStyle: function () {
- var options = this.options;
-
- if (options.stroke) {
- this._ctx.lineWidth = options.weight;
- this._ctx.strokeStyle = options.color;
- }
- if (options.fill) {
- this._ctx.fillStyle = options.fillColor || options.color;
- }
- },
-
- _drawPath: function () {
- var i, j, len, len2, point, drawMethod;
-
- this._ctx.beginPath();
-
- for (i = 0, len = this._parts.length; i < len; i++) {
- for (j = 0, len2 = this._parts[i].length; j < len2; j++) {
- point = this._parts[i][j];
- drawMethod = (j === 0 ? 'move' : 'line') + 'To';
-
- this._ctx[drawMethod](point.x, point.y);
- }
- // TODO refactor ugly hack
- if (this instanceof L.Polygon) {
- this._ctx.closePath();
- }
- }
- },
-
- _checkIfEmpty: function () {
- return !this._parts.length;
- },
-
- _updatePath: function () {
- if (this._checkIfEmpty()) { return; }
-
- var ctx = this._ctx,
- options = this.options;
-
- this._drawPath();
- ctx.save();
- this._updateStyle();
-
- if (options.fill) {
- if (options.fillOpacity < 1) {
- ctx.globalAlpha = options.fillOpacity;
- }
- ctx.fill();
- }
-
- if (options.stroke) {
- if (options.opacity < 1) {
- ctx.globalAlpha = options.opacity;
- }
- ctx.stroke();
- }
-
- ctx.restore();
-
- // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature
- },
-
- _initEvents: function () {
- if (this.options.clickable) {
- // TODO hand cursor
- // TODO mouseover, mouseout, dblclick
- this._map.on('click', this._onClick, this);
- }
- },
-
- _onClick: function (e) {
- if (this._containsPoint(e.layerPoint)) {
- this.fire('click', e);
- }
- },
-
- onRemove: function (map) {
- map
- .off('viewreset', this._projectLatlngs, this)
- .off('moveend', this._updatePath, this)
- .fire('moveend');
- }
-});
-
-L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : {
- _initPathRoot: function () {
- var root = this._pathRoot,
- ctx;
-
- if (!root) {
- root = this._pathRoot = document.createElement("canvas");
- root.style.position = 'absolute';
- ctx = this._canvasCtx = root.getContext('2d');
-
- ctx.lineCap = "round";
- ctx.lineJoin = "round";
-
- this._panes.overlayPane.appendChild(root);
-
- this.on('moveend', this._updateCanvasViewport);
- this._updateCanvasViewport();
- }
- },
-
- _updateCanvasViewport: function () {
- this._updatePathViewport();
-
- var vp = this._pathViewport,
- min = vp.min,
- size = vp.max.subtract(min),
- root = this._pathRoot;
-
- //TODO check if this works properly on mobile webkit
- L.DomUtil.setPosition(root, min);
- root.width = size.x;
- root.height = size.y;
- root.getContext('2d').translate(-min.x, -min.y);
- }
-});
-
-
-/*
- * L.LineUtil contains different utility functions for line segments
- * and polylines (clipping, simplification, distances, etc.)
- */
-
-L.LineUtil = {
-
- // Simplify polyline with vertex reduction and Douglas-Peucker simplification.
- // Improves rendering performance dramatically by lessening the number of points to draw.
-
- simplify: function (/*Point[]*/ points, /*Number*/ tolerance) {
- if (!tolerance || !points.length) {
- return points.slice();
- }
-
- var sqTolerance = tolerance * tolerance;
-
- // stage 1: vertex reduction
- points = this._reducePoints(points, sqTolerance);
-
- // stage 2: Douglas-Peucker simplification
- points = this._simplifyDP(points, sqTolerance);
-
- return points;
- },
-
- // distance from a point to a segment between two points
- pointToSegmentDistance: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
- return Math.sqrt(this._sqClosestPointOnSegment(p, p1, p2, true));
- },
-
- closestPointOnSegment: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
- return this._sqClosestPointOnSegment(p, p1, p2);
- },
-
- // Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm
- _simplifyDP: function (points, sqTolerance) {
-
- var len = points.length,
- ArrayConstructor = typeof Uint8Array !== 'undefined' ? Uint8Array : Array,
- markers = new ArrayConstructor(len);
-
- markers[0] = markers[len - 1] = 1;
-
- this._simplifyDPStep(points, markers, sqTolerance, 0, len - 1);
-
- var i,
- newPoints = [];
-
- for (i = 0; i < len; i++) {
- if (markers[i]) {
- newPoints.push(points[i]);
- }
- }
-
- return newPoints;
- },
-
- _simplifyDPStep: function (points, markers, sqTolerance, first, last) {
-
- var maxSqDist = 0,
- index, i, sqDist;
-
- for (i = first + 1; i <= last - 1; i++) {
- sqDist = this._sqClosestPointOnSegment(points[i], points[first], points[last], true);
-
- if (sqDist > maxSqDist) {
- index = i;
- maxSqDist = sqDist;
- }
- }
-
- if (maxSqDist > sqTolerance) {
- markers[index] = 1;
-
- this._simplifyDPStep(points, markers, sqTolerance, first, index);
- this._simplifyDPStep(points, markers, sqTolerance, index, last);
- }
- },
-
- // reduce points that are too close to each other to a single point
- _reducePoints: function (points, sqTolerance) {
- var reducedPoints = [points[0]];
-
- for (var i = 1, prev = 0, len = points.length; i < len; i++) {
- if (this._sqDist(points[i], points[prev]) > sqTolerance) {
- reducedPoints.push(points[i]);
- prev = i;
- }
- }
- if (prev < len - 1) {
- reducedPoints.push(points[len - 1]);
- }
- return reducedPoints;
- },
-
- /*jshint bitwise:false */ // temporarily allow bitwise oprations
-
- // Cohen-Sutherland line clipping algorithm.
- // Used to avoid rendering parts of a polyline that are not currently visible.
-
- clipSegment: function (a, b, bounds, useLastCode) {
- var min = bounds.min,
- max = bounds.max;
-
- var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds),
- codeB = this._getBitCode(b, bounds);
-
- // save 2nd code to avoid calculating it on the next segment
- this._lastCode = codeB;
-
- while (true) {
- // if a,b is inside the clip window (trivial accept)
- if (!(codeA | codeB)) {
- return [a, b];
- // if a,b is outside the clip window (trivial reject)
- } else if (codeA & codeB) {
- return false;
- // other cases
- } else {
- var codeOut = codeA || codeB,
- p = this._getEdgeIntersection(a, b, codeOut, bounds),
- newCode = this._getBitCode(p, bounds);
-
- if (codeOut === codeA) {
- a = p;
- codeA = newCode;
- } else {
- b = p;
- codeB = newCode;
- }
- }
- }
- },
-
- _getEdgeIntersection: function (a, b, code, bounds) {
- var dx = b.x - a.x,
- dy = b.y - a.y,
- min = bounds.min,
- max = bounds.max;
-
- if (code & 8) { // top
- return new L.Point(a.x + dx * (max.y - a.y) / dy, max.y);
- } else if (code & 4) { // bottom
- return new L.Point(a.x + dx * (min.y - a.y) / dy, min.y);
- } else if (code & 2) { // right
- return new L.Point(max.x, a.y + dy * (max.x - a.x) / dx);
- } else if (code & 1) { // left
- return new L.Point(min.x, a.y + dy * (min.x - a.x) / dx);
- }
- },
-
- _getBitCode: function (/*Point*/ p, bounds) {
- var code = 0;
-
- if (p.x < bounds.min.x) { // left
- code |= 1;
- } else if (p.x > bounds.max.x) { // right
- code |= 2;
- }
- if (p.y < bounds.min.y) { // bottom
- code |= 4;
- } else if (p.y > bounds.max.y) { // top
- code |= 8;
- }
-
- return code;
- },
-
- /*jshint bitwise:true */
-
- // square distance (to avoid unnecessary Math.sqrt calls)
- _sqDist: function (p1, p2) {
- var dx = p2.x - p1.x,
- dy = p2.y - p1.y;
- return dx * dx + dy * dy;
- },
-
- // return closest point on segment or distance to that point
- _sqClosestPointOnSegment: function (p, p1, p2, sqDist) {
- var x = p1.x,
- y = p1.y,
- dx = p2.x - x,
- dy = p2.y - y,
- dot = dx * dx + dy * dy,
- t;
-
- if (dot > 0) {
- t = ((p.x - x) * dx + (p.y - y) * dy) / dot;
-
- if (t > 1) {
- x = p2.x;
- y = p2.y;
- } else if (t > 0) {
- x += dx * t;
- y += dy * t;
- }
- }
-
- dx = p.x - x;
- dy = p.y - y;
-
- return sqDist ? dx * dx + dy * dy : new L.Point(x, y);
- }
-};
-
-
-
-L.Polyline = L.Path.extend({
- initialize: function (latlngs, options) {
- L.Path.prototype.initialize.call(this, options);
- this._latlngs = latlngs;
-
- // TODO refactor: move to Polyline.Edit.js
- if (L.Handler.PolyEdit) {
- this.editing = new L.Handler.PolyEdit(this);
-
- if (this.options.editable) {
- this.editing.enable();
- }
- }
- },
-
- options: {
- // how much to simplify the polyline on each zoom level
- // more = better performance and smoother look, less = more accurate
- smoothFactor: 1.0,
- noClip: false
- },
-
- projectLatlngs: function () {
- this._originalPoints = [];
-
- for (var i = 0, len = this._latlngs.length; i < len; i++) {
- this._originalPoints[i] = this._map.latLngToLayerPoint(this._latlngs[i]);
- }
- },
-
- getPathString: function () {
- for (var i = 0, len = this._parts.length, str = ''; i < len; i++) {
- str += this._getPathPartStr(this._parts[i]);
- }
- return str;
- },
-
- getLatLngs: function () {
- return this._latlngs;
- },
-
- setLatLngs: function (latlngs) {
- this._latlngs = latlngs;
- return this.redraw();
- },
-
- addLatLng: function (latlng) {
- this._latlngs.push(latlng);
- return this.redraw();
- },
-
- spliceLatLngs: function (index, howMany) {
- var removed = [].splice.apply(this._latlngs, arguments);
- this.redraw();
- return removed;
- },
-
- closestLayerPoint: function (p) {
- var minDistance = Infinity, parts = this._parts, p1, p2, minPoint = null;
-
- for (var j = 0, jLen = parts.length; j < jLen; j++) {
- var points = parts[j];
- for (var i = 1, len = points.length; i < len; i++) {
- p1 = points[i - 1];
- p2 = points[i];
- var point = L.LineUtil._sqClosestPointOnSegment(p, p1, p2);
- if (point._sqDist < minDistance) {
- minDistance = point._sqDist;
- minPoint = point;
- }
- }
- }
- if (minPoint) {
- minPoint.distance = Math.sqrt(minDistance);
- }
- return minPoint;
- },
-
- getBounds: function () {
- var b = new L.LatLngBounds();
- var latLngs = this.getLatLngs();
- for (var i = 0, len = latLngs.length; i < len; i++) {
- b.extend(latLngs[i]);
- }
- return b;
- },
-
- // TODO refactor: move to Polyline.Edit.js
- onAdd: function (map) {
- L.Path.prototype.onAdd.call(this, map);
-
- if (this.editing && this.editing.enabled()) {
- this.editing.addHooks();
- }
- },
-
- onRemove: function (map) {
- if (this.editing.enabled()) {
- this.editing.removeHooks();
- }
-
- L.Path.prototype.onRemove.call(this, map);
- },
-
- _initEvents: function () {
- L.Path.prototype._initEvents.call(this);
- },
-
- _getPathPartStr: function (points) {
- var round = L.Path.VML;
-
- for (var j = 0, len2 = points.length, str = '', p; j < len2; j++) {
- p = points[j];
- if (round) {
- p._round();
- }
- str += (j ? 'L' : 'M') + p.x + ' ' + p.y;
- }
- return str;
- },
-
- _clipPoints: function () {
- var points = this._originalPoints,
- len = points.length,
- i, k, segment;
-
- if (this.options.noClip) {
- this._parts = [points];
- return;
- }
-
- this._parts = [];
-
- var parts = this._parts,
- vp = this._map._pathViewport,
- lu = L.LineUtil;
-
- for (i = 0, k = 0; i < len - 1; i++) {
- segment = lu.clipSegment(points[i], points[i + 1], vp, i);
- if (!segment) {
- continue;
- }
-
- parts[k] = parts[k] || [];
- parts[k].push(segment[0]);
-
- // if segment goes out of screen, or it's the last one, it's the end of the line part
- if ((segment[1] !== points[i + 1]) || (i === len - 2)) {
- parts[k].push(segment[1]);
- k++;
- }
- }
- },
-
- // simplify each clipped part of the polyline
- _simplifyPoints: function () {
- var parts = this._parts,
- lu = L.LineUtil;
-
- for (var i = 0, len = parts.length; i < len; i++) {
- parts[i] = lu.simplify(parts[i], this.options.smoothFactor);
- }
- },
-
- _updatePath: function () {
- this._clipPoints();
- this._simplifyPoints();
-
- L.Path.prototype._updatePath.call(this);
- }
-});
-
-
-/*
- * L.PolyUtil contains utilify functions for polygons (clipping, etc.).
- */
-
-/*jshint bitwise:false */ // allow bitwise oprations here
-
-L.PolyUtil = {};
-
-/*
- * Sutherland-Hodgeman polygon clipping algorithm.
- * Used to avoid rendering parts of a polygon that are not currently visible.
- */
-L.PolyUtil.clipPolygon = function (points, bounds) {
- var min = bounds.min,
- max = bounds.max,
- clippedPoints,
- edges = [1, 4, 2, 8],
- i, j, k,
- a, b,
- len, edge, p,
- lu = L.LineUtil;
-
- for (i = 0, len = points.length; i < len; i++) {
- points[i]._code = lu._getBitCode(points[i], bounds);
- }
-
- // for each edge (left, bottom, right, top)
- for (k = 0; k < 4; k++) {
- edge = edges[k];
- clippedPoints = [];
-
- for (i = 0, len = points.length, j = len - 1; i < len; j = i++) {
- a = points[i];
- b = points[j];
-
- // if a is inside the clip window
- if (!(a._code & edge)) {
- // if b is outside the clip window (a->b goes out of screen)
- if (b._code & edge) {
- p = lu._getEdgeIntersection(b, a, edge, bounds);
- p._code = lu._getBitCode(p, bounds);
- clippedPoints.push(p);
- }
- clippedPoints.push(a);
-
- // else if b is inside the clip window (a->b enters the screen)
- } else if (!(b._code & edge)) {
- p = lu._getEdgeIntersection(b, a, edge, bounds);
- p._code = lu._getBitCode(p, bounds);
- clippedPoints.push(p);
- }
- }
- points = clippedPoints;
- }
-
- return points;
-};
-
-/*jshint bitwise:true */
-
-
-/*
- * L.Polygon is used to display polygons on a map.
- */
-
-L.Polygon = L.Polyline.extend({
- options: {
- fill: true
- },
-
- initialize: function (latlngs, options) {
- L.Polyline.prototype.initialize.call(this, latlngs, options);
-
- if (latlngs && (latlngs[0] instanceof Array)) {
- this._latlngs = latlngs[0];
- this._holes = latlngs.slice(1);
- }
- },
-
- projectLatlngs: function () {
- L.Polyline.prototype.projectLatlngs.call(this);
-
- // project polygon holes points
- // TODO move this logic to Polyline to get rid of duplication
- this._holePoints = [];
-
- if (!this._holes) {
- return;
- }
-
- for (var i = 0, len = this._holes.length, hole; i < len; i++) {
- this._holePoints[i] = [];
-
- for (var j = 0, len2 = this._holes[i].length; j < len2; j++) {
- this._holePoints[i][j] = this._map.latLngToLayerPoint(this._holes[i][j]);
- }
- }
- },
-
- _clipPoints: function () {
- var points = this._originalPoints,
- newParts = [];
-
- this._parts = [points].concat(this._holePoints);
-
- if (this.options.noClip) {
- return;
- }
-
- for (var i = 0, len = this._parts.length; i < len; i++) {
- var clipped = L.PolyUtil.clipPolygon(this._parts[i], this._map._pathViewport);
- if (!clipped.length) {
- continue;
- }
- newParts.push(clipped);
- }
-
- this._parts = newParts;
- },
-
- _getPathPartStr: function (points) {
- var str = L.Polyline.prototype._getPathPartStr.call(this, points);
- return str + (L.Browser.svg ? 'z' : 'x');
- }
-});
-
-
-/*
- * Contains L.MultiPolyline and L.MultiPolygon layers.
- */
-
-(function () {
- function createMulti(Klass) {
- return L.FeatureGroup.extend({
- initialize: function (latlngs, options) {
- this._layers = {};
- this._options = options;
- this.setLatLngs(latlngs);
- },
-
- setLatLngs: function (latlngs) {
- var i = 0, len = latlngs.length;
-
- this._iterateLayers(function (layer) {
- if (i < len) {
- layer.setLatLngs(latlngs[i++]);
- } else {
- this.removeLayer(layer);
- }
- }, this);
-
- while (i < len) {
- this.addLayer(new Klass(latlngs[i++], this._options));
- }
-
- return this;
- }
- });
- }
-
- L.MultiPolyline = createMulti(L.Polyline);
- L.MultiPolygon = createMulti(L.Polygon);
-}());
-
-
-/*
- * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds
- */
-
-L.Rectangle = L.Polygon.extend({
- initialize: function (latLngBounds, options) {
- L.Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options);
- },
-
- setBounds: function (latLngBounds) {
- this.setLatLngs(this._boundsToLatLngs(latLngBounds));
- },
-
- _boundsToLatLngs: function (latLngBounds) {
- return [
- latLngBounds.getSouthWest(),
- latLngBounds.getNorthWest(),
- latLngBounds.getNorthEast(),
- latLngBounds.getSouthEast(),
- latLngBounds.getSouthWest()
- ];
- }
-});
-
-
-/*
- * L.Circle is a circle overlay (with a certain radius in meters).
- */
-
-L.Circle = L.Path.extend({
- initialize: function (latlng, radius, options) {
- L.Path.prototype.initialize.call(this, options);
-
- this._latlng = latlng;
- this._mRadius = radius;
- },
-
- options: {
- fill: true
- },
-
- setLatLng: function (latlng) {
- this._latlng = latlng;
- return this.redraw();
- },
-
- setRadius: function (radius) {
- this._mRadius = radius;
- return this.redraw();
- },
-
- projectLatlngs: function () {
- var lngRadius = this._getLngRadius(),
- latlng2 = new L.LatLng(this._latlng.lat, this._latlng.lng - lngRadius, true),
- point2 = this._map.latLngToLayerPoint(latlng2);
-
- this._point = this._map.latLngToLayerPoint(this._latlng);
- this._radius = Math.max(Math.round(this._point.x - point2.x), 1);
- },
-
- getBounds: function () {
- var map = this._map,
- delta = this._radius * Math.cos(Math.PI / 4),
- point = map.project(this._latlng),
- swPoint = new L.Point(point.x - delta, point.y + delta),
- nePoint = new L.Point(point.x + delta, point.y - delta),
- zoom = map.getZoom(),
- sw = map.unproject(swPoint, zoom, true),
- ne = map.unproject(nePoint, zoom, true);
-
- return new L.LatLngBounds(sw, ne);
- },
-
- getLatLng: function () {
- return this._latlng;
- },
-
- getPathString: function () {
- var p = this._point,
- r = this._radius;
-
- if (this._checkIfEmpty()) {
- return '';
- }
-
- if (L.Browser.svg) {
- return "M" + p.x + "," + (p.y - r) +
- "A" + r + "," + r + ",0,1,1," +
- (p.x - 0.1) + "," + (p.y - r) + " z";
- } else {
- p._round();
- r = Math.round(r);
- return "AL " + p.x + "," + p.y + " " + r + "," + r + " 0," + (65535 * 360);
- }
- },
-
- getRadius: function () {
- return this._mRadius;
- },
-
- _getLngRadius: function () {
- var equatorLength = 40075017,
- hLength = equatorLength * Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat);
-
- return (this._mRadius / hLength) * 360;
- },
-
- _checkIfEmpty: function () {
- if (!this._map) {
- return false;
- }
- var vp = this._map._pathViewport,
- r = this._radius,
- p = this._point;
-
- return p.x - r > vp.max.x || p.y - r > vp.max.y ||
- p.x + r < vp.min.x || p.y + r < vp.min.y;
- }
-});
-
-
-/*
- * L.CircleMarker is a circle overlay with a permanent pixel radius.
- */
-
-L.CircleMarker = L.Circle.extend({
- options: {
- radius: 10,
- weight: 2
- },
-
- initialize: function (latlng, options) {
- L.Circle.prototype.initialize.call(this, latlng, null, options);
- this._radius = this.options.radius;
- },
-
- projectLatlngs: function () {
- this._point = this._map.latLngToLayerPoint(this._latlng);
- },
-
- setRadius: function (radius) {
- this._radius = radius;
- return this.redraw();
- }
-});
-
-
-
-L.Polyline.include(!L.Path.CANVAS ? {} : {
- _containsPoint: function (p, closed) {
- var i, j, k, len, len2, dist, part,
- w = this.options.weight / 2;
-
- if (L.Browser.touch) {
- w += 10; // polyline click tolerance on touch devices
- }
-
- for (i = 0, len = this._parts.length; i < len; i++) {
- part = this._parts[i];
- for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
- if (!closed && (j === 0)) {
- continue;
- }
-
- dist = L.LineUtil.pointToSegmentDistance(p, part[k], part[j]);
-
- if (dist <= w) {
- return true;
- }
- }
- }
- return false;
- }
-});
-
-
-
-L.Polygon.include(!L.Path.CANVAS ? {} : {
- _containsPoint: function (p) {
- var inside = false,
- part, p1, p2,
- i, j, k,
- len, len2;
-
- // TODO optimization: check if within bounds first
-
- if (L.Polyline.prototype._containsPoint.call(this, p, true)) {
- // click on polygon border
- return true;
- }
-
- // ray casting algorithm for detecting if point is in polygon
-
- for (i = 0, len = this._parts.length; i < len; i++) {
- part = this._parts[i];
-
- for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
- p1 = part[j];
- p2 = part[k];
-
- 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)) {
- inside = !inside;
- }
- }
- }
-
- return inside;
- }
-});
-
-
-/*
- * Circle canvas specific drawing parts.
- */
-
-L.Circle.include(!L.Path.CANVAS ? {} : {
- _drawPath: function () {
- var p = this._point;
- this._ctx.beginPath();
- this._ctx.arc(p.x, p.y, this._radius, 0, Math.PI * 2, false);
- },
-
- _containsPoint: function (p) {
- var center = this._point,
- w2 = this.options.stroke ? this.options.weight / 2 : 0;
-
- return (p.distanceTo(center) <= this._radius + w2);
- }
-});
-
-
-
-L.GeoJSON = L.FeatureGroup.extend({
- initialize: function (geojson, options) {
- L.Util.setOptions(this, options);
-
- this._geojson = geojson;
- this._layers = {};
-
- if (geojson) {
- this.addGeoJSON(geojson);
- }
- },
-
- addGeoJSON: function (geojson) {
- var features = geojson.features,
- i, len;
-
- if (features) {
- for (i = 0, len = features.length; i < len; i++) {
- this.addGeoJSON(features[i]);
- }
- return;
- }
-
- var isFeature = (geojson.type === 'Feature'),
- geometry = isFeature ? geojson.geometry : geojson,
- layer = L.GeoJSON.geometryToLayer(geometry, this.options.pointToLayer);
-
- this.fire('featureparse', {
- layer: layer,
- properties: geojson.properties,
- geometryType: geometry.type,
- bbox: geojson.bbox,
- id: geojson.id
- });
-
- this.addLayer(layer);
- }
-});
-
-L.Util.extend(L.GeoJSON, {
- geometryToLayer: function (geometry, pointToLayer) {
- var coords = geometry.coordinates,
- layers = [],
- latlng, latlngs, i, len, layer;
-
- switch (geometry.type) {
- case 'Point':
- latlng = this.coordsToLatLng(coords);
- return pointToLayer ? pointToLayer(latlng) : new L.Marker(latlng);
-
- case 'MultiPoint':
- for (i = 0, len = coords.length; i < len; i++) {
- latlng = this.coordsToLatLng(coords[i]);
- layer = pointToLayer ? pointToLayer(latlng) : new L.Marker(latlng);
- layers.push(layer);
- }
- return new L.FeatureGroup(layers);
-
- case 'LineString':
- latlngs = this.coordsToLatLngs(coords);
- return new L.Polyline(latlngs);
-
- case 'Polygon':
- latlngs = this.coordsToLatLngs(coords, 1);
- return new L.Polygon(latlngs);
-
- case 'MultiLineString':
- latlngs = this.coordsToLatLngs(coords, 1);
- return new L.MultiPolyline(latlngs);
-
- case "MultiPolygon":
- latlngs = this.coordsToLatLngs(coords, 2);
- return new L.MultiPolygon(latlngs);
-
- case "GeometryCollection":
- for (i = 0, len = geometry.geometries.length; i < len; i++) {
- layer = this.geometryToLayer(geometry.geometries[i], pointToLayer);
- layers.push(layer);
- }
- return new L.FeatureGroup(layers);
-
- default:
- throw new Error('Invalid GeoJSON object.');
- }
- },
-
- coordsToLatLng: function (coords, reverse) { // (Array, Boolean) -> LatLng
- var lat = parseFloat(coords[reverse ? 0 : 1]),
- lng = parseFloat(coords[reverse ? 1 : 0]);
-
- return new L.LatLng(lat, lng, true);
- },
-
- coordsToLatLngs: function (coords, levelsDeep, reverse) { // (Array, Number, Boolean) -> Array
- var latlng,
- latlngs = [],
- i, len;
-
- for (i = 0, len = coords.length; i < len; i++) {
- latlng = levelsDeep ?
- this.coordsToLatLngs(coords[i], levelsDeep - 1, reverse) :
- this.coordsToLatLng(coords[i], reverse);
- latlngs.push(latlng);
- }
-
- return latlngs;
- }
-});
-
-
-/*
- * L.DomEvent contains functions for working with DOM events.
- */
-
-L.DomEvent = {
- /* inpired by John Resig, Dean Edwards and YUI addEvent implementations */
- addListener: function (/*HTMLElement*/ obj, /*String*/ type, /*Function*/ fn, /*Object*/ context) {
- var id = L.Util.stamp(fn),
- key = '_leaflet_' + type + id;
-
- if (obj[key]) {
- return this;
- }
-
- var handler = function (e) {
- return fn.call(context || obj, e || L.DomEvent._getEvent());
- };
-
- if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) {
- this.addDoubleTapListener(obj, handler, id);
- } else if ('addEventListener' in obj) {
- if (type === 'mousewheel') {
- obj.addEventListener('DOMMouseScroll', handler, false);
- obj.addEventListener(type, handler, false);
- } else if ((type === 'mouseenter') || (type === 'mouseleave')) {
- var originalHandler = handler,
- newType = (type === 'mouseenter' ? 'mouseover' : 'mouseout');
- handler = function (e) {
- if (!L.DomEvent._checkMouse(obj, e)) {
- return;
- }
- return originalHandler(e);
- };
- obj.addEventListener(newType, handler, false);
- } else {
- obj.addEventListener(type, handler, false);
- }
- } else if ('attachEvent' in obj) {
- obj.attachEvent("on" + type, handler);
- }
-
- obj[key] = handler;
-
- return this;
- },
-
- removeListener: function (/*HTMLElement*/ obj, /*String*/ type, /*Function*/ fn) {
- var id = L.Util.stamp(fn),
- key = '_leaflet_' + type + id,
- handler = obj[key];
-
- if (!handler) {
- return;
- }
-
- if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) {
- this.removeDoubleTapListener(obj, id);
- } else if ('removeEventListener' in obj) {
- if (type === 'mousewheel') {
- obj.removeEventListener('DOMMouseScroll', handler, false);
- obj.removeEventListener(type, handler, false);
- } else if ((type === 'mouseenter') || (type === 'mouseleave')) {
- obj.removeEventListener((type === 'mouseenter' ? 'mouseover' : 'mouseout'), handler, false);
- } else {
- obj.removeEventListener(type, handler, false);
- }
- } else if ('detachEvent' in obj) {
- obj.detachEvent("on" + type, handler);
- }
- obj[key] = null;
-
- return this;
- },
-
- _checkMouse: function (el, e) {
- var related = e.relatedTarget;
-
- if (!related) {
- return true;
- }
-
- try {
- while (related && (related !== el)) {
- related = related.parentNode;
- }
- } catch (err) {
- return false;
- }
-
- return (related !== el);
- },
-
- /*jshint noarg:false */ // evil magic for IE
- _getEvent: function () {
- var e = window.event;
- if (!e) {
- var caller = arguments.callee.caller;
- while (caller) {
- e = caller['arguments'][0];
- if (e && window.Event === e.constructor) {
- break;
- }
- caller = caller.caller;
- }
- }
- return e;
- },
- /*jshint noarg:false */
-
- stopPropagation: function (/*Event*/ e) {
- if (e.stopPropagation) {
- e.stopPropagation();
- } else {
- e.cancelBubble = true;
- }
- return this;
- },
-
- disableClickPropagation: function (/*HTMLElement*/ el) {
- return L.DomEvent
- .addListener(el, L.Draggable.START, L.DomEvent.stopPropagation)
- .addListener(el, 'click', L.DomEvent.stopPropagation)
- .addListener(el, 'dblclick', L.DomEvent.stopPropagation);
- },
-
- preventDefault: function (/*Event*/ e) {
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- return this;
- },
-
- stop: function (e) {
- return L.DomEvent
- .preventDefault(e)
- .stopPropagation(e);
- },
-
- getMousePosition: function (e, container) {
- var x = e.pageX ? e.pageX : e.clientX +
- document.body.scrollLeft + document.documentElement.scrollLeft,
- y = e.pageY ? e.pageY : e.clientY +
- document.body.scrollTop + document.documentElement.scrollTop,
- pos = new L.Point(x, y);
-
- return (container ?
- pos.subtract(L.DomUtil.getViewportOffset(container)) : pos);
- },
-
- getWheelDelta: function (e) {
- var delta = 0;
- if (e.wheelDelta) {
- delta = e.wheelDelta / 120;
- }
- if (e.detail) {
- delta = -e.detail / 3;
- }
- return delta;
- }
-};
-
-
-
-/*
- * L.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too.
- */
-
-L.Draggable = L.Class.extend({
- includes: L.Mixin.Events,
-
- statics: {
- START: L.Browser.touch ? 'touchstart' : 'mousedown',
- END: L.Browser.touch ? 'touchend' : 'mouseup',
- MOVE: L.Browser.touch ? 'touchmove' : 'mousemove',
- TAP_TOLERANCE: 15
- },
-
- initialize: function (element, dragStartTarget) {
- this._element = element;
- this._dragStartTarget = dragStartTarget || element;
- },
-
- enable: function () {
- if (this._enabled) {
- return;
- }
- L.DomEvent.addListener(this._dragStartTarget, L.Draggable.START, this._onDown, this);
- this._enabled = true;
- },
-
- disable: function () {
- if (!this._enabled) {
- return;
- }
- L.DomEvent.removeListener(this._dragStartTarget, L.Draggable.START, this._onDown);
- this._enabled = false;
- this._moved = false;
- },
-
- _onDown: function (e) {
- if ((!L.Browser.touch && e.shiftKey) || ((e.which !== 1) && (e.button !== 1) && !e.touches)) {
- return;
- }
-
- this._simulateClick = true;
-
- if (e.touches && e.touches.length > 1) {
- this._simulateClick = false;
- return;
- }
-
- var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
- el = first.target;
-
- L.DomEvent.preventDefault(e);
-
- if (L.Browser.touch && el.tagName.toLowerCase() === 'a') {
- el.className += ' leaflet-active';
- }
-
- this._moved = false;
- if (this._moving) {
- return;
- }
-
- if (!L.Browser.touch) {
- L.DomUtil.disableTextSelection();
- this._setMovingCursor();
- }
-
- this._startPos = this._newPos = L.DomUtil.getPosition(this._element);
- this._startPoint = new L.Point(first.clientX, first.clientY);
-
- L.DomEvent.addListener(document, L.Draggable.MOVE, this._onMove, this);
- L.DomEvent.addListener(document, L.Draggable.END, this._onUp, this);
- },
-
- _onMove: function (e) {
- if (e.touches && e.touches.length > 1) {
- return;
- }
-
- L.DomEvent.preventDefault(e);
-
- var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e);
-
- if (!this._moved) {
- this.fire('dragstart');
- this._moved = true;
- }
- this._moving = true;
-
- var newPoint = new L.Point(first.clientX, first.clientY);
- this._newPos = this._startPos.add(newPoint).subtract(this._startPoint);
-
- L.Util.cancelAnimFrame(this._animRequest);
- this._animRequest = L.Util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget);
- },
-
- _updatePosition: function () {
- this.fire('predrag');
- L.DomUtil.setPosition(this._element, this._newPos);
- this.fire('drag');
- },
-
- _onUp: function (e) {
- if (this._simulateClick && e.changedTouches) {
- var first = e.changedTouches[0],
- el = first.target,
- dist = (this._newPos && this._newPos.distanceTo(this._startPos)) || 0;
-
- if (el.tagName.toLowerCase() === 'a') {
- el.className = el.className.replace(' leaflet-active', '');
- }
-
- if (dist < L.Draggable.TAP_TOLERANCE) {
- this._simulateEvent('click', first);
- }
- }
-
- if (!L.Browser.touch) {
- L.DomUtil.enableTextSelection();
- this._restoreCursor();
- }
-
- L.DomEvent.removeListener(document, L.Draggable.MOVE, this._onMove);
- L.DomEvent.removeListener(document, L.Draggable.END, this._onUp);
-
- if (this._moved) {
- this.fire('dragend');
- }
- this._moving = false;
- },
-
- _setMovingCursor: function () {
- document.body.className += ' leaflet-dragging';
- },
-
- _restoreCursor: function () {
- document.body.className = document.body.className.replace(/ leaflet-dragging/g, '');
- },
-
- _simulateEvent: function (type, e) {
- var simulatedEvent = document.createEvent('MouseEvents');
-
- simulatedEvent.initMouseEvent(
- type, true, true, window, 1,
- e.screenX, e.screenY,
- e.clientX, e.clientY,
- false, false, false, false, 0, null);
-
- e.target.dispatchEvent(simulatedEvent);
- }
-});
-
-
-/*
- * L.Handler classes are used internally to inject interaction features to classes like Map and Marker.
- */
-
-L.Handler = L.Class.extend({
- initialize: function (map) {
- this._map = map;
- },
-
- enable: function () {
- if (this._enabled) {
- return;
- }
- this._enabled = true;
- this.addHooks();
- },
-
- disable: function () {
- if (!this._enabled) {
- return;
- }
- this._enabled = false;
- this.removeHooks();
- },
-
- enabled: function () {
- return !!this._enabled;
- }
-});
-
-
-/*
- * L.Handler.MapDrag is used internally by L.Map to make the map draggable.
- */
-
-L.Map.mergeOptions({
- dragging: true,
-
- inertia: !L.Browser.android,
- inertiaDeceleration: L.Browser.touch ? 3000 : 2000, // px/s^2
- inertiaMaxSpeed: L.Browser.touch ? 1500 : 1000, // px/s
- inertiaThreshold: L.Browser.touch ? 32 : 16, // ms
-
- // TODO refactor, move to CRS
- worldCopyJump: true,
- continuousWorld: false
-});
-
-L.Map.Drag = L.Handler.extend({
- addHooks: function () {
- if (!this._draggable) {
- this._draggable = new L.Draggable(this._map._mapPane, this._map._container);
-
- this._draggable
- .on('dragstart', this._onDragStart, this)
- .on('drag', this._onDrag, this)
- .on('dragend', this._onDragEnd, this);
-
- var options = this._map.options;
-
- if (options.worldCopyJump && !options.continuousWorld) {
- this._draggable.on('predrag', this._onPreDrag, this);
- this._map.on('viewreset', this._onViewReset, this);
- }
- }
- this._draggable.enable();
- },
-
- removeHooks: function () {
- this._draggable.disable();
- },
-
- moved: function () {
- return this._draggable && this._draggable._moved;
- },
-
- _onDragStart: function () {
- var map = this._map;
-
- map
- .fire('movestart')
- .fire('dragstart');
-
- if (map._panTransition) {
- map._panTransition._onTransitionEnd(true);
- }
-
- if (map.options.inertia) {
- this._positions = [];
- this._times = [];
- }
- },
-
- _onDrag: function () {
- if (this._map.options.inertia) {
- var time = this._lastTime = +new Date(),
- pos = this._lastPos = this._draggable._newPos;
-
- this._positions.push(pos);
- this._times.push(time);
-
- if (time - this._times[0] > 200) {
- this._positions.shift();
- this._times.shift();
- }
- }
-
- this._map
- .fire('move')
- .fire('drag');
- },
-
- _onViewReset: function () {
- var pxCenter = this._map.getSize().divideBy(2),
- pxWorldCenter = this._map.latLngToLayerPoint(new L.LatLng(0, 0));
-
- this._initialWorldOffset = pxWorldCenter.subtract(pxCenter);
- },
-
- _onPreDrag: function () {
- var map = this._map,
- worldWidth = map.options.crs.scale(map.getZoom()),
- halfWidth = Math.round(worldWidth / 2),
- dx = this._initialWorldOffset.x,
- x = this._draggable._newPos.x,
- newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx,
- newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx,
- newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2;
-
- this._draggable._newPos.x = newX;
- },
-
- _onDragEnd: function () {
- var map = this._map,
- options = map.options,
- delay = +new Date() - this._lastTime,
-
- noInertia = !options.inertia ||
- delay > options.inertiaThreshold ||
- typeof this._positions[0] === 'undefined';
-
- if (noInertia) {
- map.fire('moveend');
-
- } else {
-
- var direction = this._lastPos.subtract(this._positions[0]),
- duration = (this._lastTime + delay - this._times[0]) / 1000,
-
- speedVector = direction.multiplyBy(0.58 / duration),
- speed = speedVector.distanceTo(new L.Point(0, 0)),
-
- limitedSpeed = Math.min(options.inertiaMaxSpeed, speed),
- limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed),
-
- decelerationDuration = limitedSpeed / options.inertiaDeceleration,
- offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round();
-
- var panOptions = {
- duration: decelerationDuration,
- easing: 'ease-out'
- };
-
- L.Util.requestAnimFrame(L.Util.bind(function () {
- this._map.panBy(offset, panOptions);
- }, this));
- }
-
- map.fire('dragend');
-
- if (options.maxBounds) {
- // TODO predrag validation instead of animation
- L.Util.requestAnimFrame(this._panInsideMaxBounds, map, true, map._container);
- }
- },
-
- _panInsideMaxBounds: function () {
- this.panInsideBounds(this.options.maxBounds);
- }
-});
-
-L.Map.addInitHook('addHandler', 'dragging', L.Map.Drag);
-
-/*
- * L.Handler.DoubleClickZoom is used internally by L.Map to add double-click zooming.
- */
-
-L.Map.mergeOptions({
- doubleClickZoom: true
-});
-
-L.Map.DoubleClickZoom = L.Handler.extend({
- addHooks: function () {
- this._map.on('dblclick', this._onDoubleClick);
- },
-
- removeHooks: function () {
- this._map.off('dblclick', this._onDoubleClick);
- },
-
- _onDoubleClick: function (e) {
- this.setView(e.latlng, this._zoom + 1);
- }
-});
-
-L.Map.addInitHook('addHandler', 'doubleClickZoom', L.Map.DoubleClickZoom);
-
-/*
- * L.Handler.ScrollWheelZoom is used internally by L.Map to enable mouse scroll wheel zooming on the map.
- */
-
-L.Map.mergeOptions({
- scrollWheelZoom: !L.Browser.touch
-});
-
-L.Map.ScrollWheelZoom = L.Handler.extend({
- addHooks: function () {
- L.DomEvent.addListener(this._map._container, 'mousewheel', this._onWheelScroll, this);
- this._delta = 0;
- },
-
- removeHooks: function () {
- L.DomEvent.removeListener(this._map._container, 'mousewheel', this._onWheelScroll);
- },
-
- _onWheelScroll: function (e) {
- var delta = L.DomEvent.getWheelDelta(e);
-
- this._delta += delta;
- this._lastMousePos = this._map.mouseEventToContainerPoint(e);
-
- clearTimeout(this._timer);
- this._timer = setTimeout(L.Util.bind(this._performZoom, this), 50);
-
- L.DomEvent.preventDefault(e);
- },
-
- _performZoom: function () {
- var map = this._map,
- delta = Math.round(this._delta),
- zoom = map.getZoom();
-
- delta = Math.max(Math.min(delta, 4), -4);
- delta = map._limitZoom(zoom + delta) - zoom;
-
- this._delta = 0;
-
- if (!delta) { return; }
-
- var newCenter = this._getCenterForScrollWheelZoom(this._lastMousePos, delta),
- newZoom = zoom + delta;
-
- map.setView(newCenter, newZoom);
- },
-
- _getCenterForScrollWheelZoom: function (mousePos, delta) {
- var map = this._map,
- centerPoint = map.getPixelBounds().getCenter(),
- viewHalf = map.getSize().divideBy(2),
- centerOffset = mousePos.subtract(viewHalf).multiplyBy(1 - Math.pow(2, -delta)),
- newCenterPoint = centerPoint.add(centerOffset);
-
- return map.unproject(newCenterPoint, map._zoom, true);
- }
-});
-
-L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom);
-
-L.Util.extend(L.DomEvent, {
- // inspired by Zepto touch code by Thomas Fuchs
- addDoubleTapListener: function (obj, handler, id) {
- var last,
- doubleTap = false,
- delay = 250,
- touch,
- pre = '_leaflet_',
- touchstart = 'touchstart',
- touchend = 'touchend';
-
- function onTouchStart(e) {
- if (e.touches.length !== 1) {
- return;
- }
-
- var now = Date.now(),
- delta = now - (last || now);
-
- touch = e.touches[0];
- doubleTap = (delta > 0 && delta <= delay);
- last = now;
- }
- function onTouchEnd(e) {
- if (doubleTap) {
- touch.type = 'dblclick';
- handler(touch);
- last = null;
- }
- }
- obj[pre + touchstart + id] = onTouchStart;
- obj[pre + touchend + id] = onTouchEnd;
-
- obj.addEventListener(touchstart, onTouchStart, false);
- obj.addEventListener(touchend, onTouchEnd, false);
- },
-
- removeDoubleTapListener: function (obj, id) {
- var pre = '_leaflet_';
- obj.removeEventListener(obj, obj[pre + 'touchstart' + id], false);
- obj.removeEventListener(obj, obj[pre + 'touchend' + id], false);
- }
-});
-
-
-/*
- * L.Handler.TouchZoom is used internally by L.Map to add touch-zooming on Webkit-powered mobile browsers.
- */
-
-L.Map.mergeOptions({
- touchZoom: L.Browser.touch && !L.Browser.android
-});
-
-L.Map.TouchZoom = L.Handler.extend({
- addHooks: function () {
- L.DomEvent.addListener(this._map._container, 'touchstart', this._onTouchStart, this);
- },
-
- removeHooks: function () {
- L.DomEvent.removeListener(this._map._container, 'touchstart', this._onTouchStart, this);
- },
-
- _onTouchStart: function (e) {
- var map = this._map;
-
- if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; }
-
- var p1 = map.mouseEventToLayerPoint(e.touches[0]),
- p2 = map.mouseEventToLayerPoint(e.touches[1]),
- viewCenter = map.containerPointToLayerPoint(map.getSize().divideBy(2));
-
- this._startCenter = p1.add(p2).divideBy(2, true);
- this._startDist = p1.distanceTo(p2);
-
- this._moved = false;
- this._zooming = true;
-
- this._centerOffset = viewCenter.subtract(this._startCenter);
-
- L.DomEvent
- .addListener(document, 'touchmove', this._onTouchMove, this)
- .addListener(document, 'touchend', this._onTouchEnd, this);
-
- L.DomEvent.preventDefault(e);
- },
-
- _onTouchMove: function (e) {
- if (!e.touches || e.touches.length !== 2) { return; }
-
- var map = this._map;
-
- var p1 = map.mouseEventToLayerPoint(e.touches[0]),
- p2 = map.mouseEventToLayerPoint(e.touches[1]);
-
- this._scale = p1.distanceTo(p2) / this._startDist;
- this._delta = p1.add(p2).divideBy(2, true).subtract(this._startCenter);
-
- if (this._scale === 1) { return; }
-
- if (!this._moved) {
- map._mapPane.className += ' leaflet-zoom-anim';
-
- map
- .fire('zoomstart')
- .fire('movestart')
- ._prepareTileBg();
-
- this._moved = true;
- }
-
- // Used 2 translates instead of transform-origin because of a very strange bug -
- // it didn't count the origin on the first touch-zoom but worked correctly afterwards
-
- map._tileBg.style.webkitTransform =
- L.DomUtil.getTranslateString(this._delta) + ' ' +
- L.DomUtil.getScaleString(this._scale, this._startCenter);
-
- L.DomEvent.preventDefault(e);
- },
-
- _onTouchEnd: function (e) {
- if (!this._moved || !this._zooming) { return; }
-
- this._zooming = false;
-
- L.DomEvent
- .removeListener(document, 'touchmove', this._onTouchMove)
- .removeListener(document, 'touchend', this._onTouchEnd);
-
- var centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale),
- centerPoint = this._map.getPixelOrigin().add(this._startCenter).add(centerOffset),
- center = this._map.unproject(centerPoint),
-
- oldZoom = this._map.getZoom(),
- floatZoomDelta = Math.log(this._scale) / Math.LN2,
- roundZoomDelta = (floatZoomDelta > 0 ? Math.ceil(floatZoomDelta) : Math.floor(floatZoomDelta)),
- zoom = this._map._limitZoom(oldZoom + roundZoomDelta),
- finalScale = Math.pow(2, zoom - oldZoom);
-
- this._map._runAnimation(center, zoom, finalScale / this._scale, this._startCenter.add(centerOffset));
- }
-});
-
-L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom);
-
-/*
- * L.Handler.ShiftDragZoom is used internally by L.Map to add shift-drag zoom (zoom to a selected bounding box).
- */
-
-L.Map.mergeOptions({
- boxZoom: true
-});
-
-L.Map.BoxZoom = L.Handler.extend({
- initialize: function (map) {
- this._map = map;
- this._container = map._container;
- this._pane = map._panes.overlayPane;
- },
-
- addHooks: function () {
- L.DomEvent.addListener(this._container, 'mousedown', this._onMouseDown, this);
- },
-
- removeHooks: function () {
- L.DomEvent.removeListener(this._container, 'mousedown', this._onMouseDown);
- },
-
- _onMouseDown: function (e) {
- if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }
-
- L.DomUtil.disableTextSelection();
-
- this._startLayerPoint = this._map.mouseEventToLayerPoint(e);
-
- this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane);
- L.DomUtil.setPosition(this._box, this._startLayerPoint);
-
- //TODO refactor: move cursor to styles
- this._container.style.cursor = 'crosshair';
-
- L.DomEvent
- .addListener(document, 'mousemove', this._onMouseMove, this)
- .addListener(document, 'mouseup', this._onMouseUp, this)
- .preventDefault(e);
-
- this._map.fire("boxzoomstart");
- },
-
- _onMouseMove: function (e) {
- var startPoint = this._startLayerPoint,
- box = this._box,
-
- layerPoint = this._map.mouseEventToLayerPoint(e),
- offset = layerPoint.subtract(startPoint),
-
- newPos = new L.Point(
- Math.min(layerPoint.x, startPoint.x),
- Math.min(layerPoint.y, startPoint.y));
-
- L.DomUtil.setPosition(box, newPos);
-
- // TODO refactor: remove hardcoded 4 pixels
- box.style.width = (Math.abs(offset.x) - 4) + 'px';
- box.style.height = (Math.abs(offset.y) - 4) + 'px';
- },
-
- _onMouseUp: function (e) {
- this._pane.removeChild(this._box);
- this._container.style.cursor = '';
-
- L.DomUtil.enableTextSelection();
-
- L.DomEvent
- .removeListener(document, 'mousemove', this._onMouseMove)
- .removeListener(document, 'mouseup', this._onMouseUp);
-
- var map = this._map,
- layerPoint = map.mouseEventToLayerPoint(e);
-
- var bounds = new L.LatLngBounds(
- map.layerPointToLatLng(this._startLayerPoint),
- map.layerPointToLatLng(layerPoint));
-
- map.fitBounds(bounds);
-
- map.fire("boxzoomend", {
- boxZoomBounds: bounds
- });
- }
-});
-
-L.Map.addInitHook('addHandler', 'boxZoom', L.Map.BoxZoom);
-
-
-/*
- * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable.
- */
-
-L.Handler.MarkerDrag = L.Handler.extend({
- initialize: function (marker) {
- this._marker = marker;
- },
-
- addHooks: function () {
- var icon = this._marker._icon;
- if (!this._draggable) {
- this._draggable = new L.Draggable(icon, icon)
- .on('dragstart', this._onDragStart, this)
- .on('drag', this._onDrag, this)
- .on('dragend', this._onDragEnd, this);
- }
- this._draggable.enable();
- },
-
- removeHooks: function () {
- this._draggable.disable();
- },
-
- moved: function () {
- return this._draggable && this._draggable._moved;
- },
-
- _onDragStart: function (e) {
- this._marker
- .closePopup()
- .fire('movestart')
- .fire('dragstart');
- },
-
- _onDrag: function (e) {
- // update shadow position
- var iconPos = L.DomUtil.getPosition(this._marker._icon);
- if (this._marker._shadow) {
- L.DomUtil.setPosition(this._marker._shadow, iconPos);
- }
-
- this._marker._latlng = this._marker._map.layerPointToLatLng(iconPos);
-
- this._marker
- .fire('move')
- .fire('drag');
- },
-
- _onDragEnd: function () {
- this._marker
- .fire('moveend')
- .fire('dragend');
- }
-});
-
-
-L.Handler.PolyEdit = L.Handler.extend({
- options: {
- icon: new L.DivIcon({
- iconSize: new L.Point(8, 8),
- className: 'leaflet-div-icon leaflet-editing-icon'
- })
- },
-
- initialize: function (poly, options) {
- this._poly = poly;
- L.Util.setOptions(this, options);
- },
-
- addHooks: function () {
- if (this._poly._map) {
- if (!this._markerGroup) {
- this._initMarkers();
- }
- this._poly._map.addLayer(this._markerGroup);
- }
- },
-
- removeHooks: function () {
- if (this._poly._map) {
- this._poly._map.removeLayer(this._markerGroup);
- delete this._markerGroup;
- delete this._markers;
- }
- },
-
- updateMarkers: function () {
- this._markerGroup.clearLayers();
- this._initMarkers();
- },
-
- _initMarkers: function () {
- this._markerGroup = new L.LayerGroup();
- this._markers = [];
-
- var latlngs = this._poly._latlngs,
- i, j, len, marker;
-
- // TODO refactor holes implementation in Polygon to support it here
-
- for (i = 0, len = latlngs.length; i < len; i++) {
-
- marker = this._createMarker(latlngs[i], i);
- marker.on('click', this._onMarkerClick, this);
- this._markers.push(marker);
- }
-
- var markerLeft, markerRight;
-
- for (i = 0, j = len - 1; i < len; j = i++) {
- if (i === 0 && !(L.Polygon && (this._poly instanceof L.Polygon))) {
- continue;
- }
-
- markerLeft = this._markers[j];
- markerRight = this._markers[i];
-
- this._createMiddleMarker(markerLeft, markerRight);
- this._updatePrevNext(markerLeft, markerRight);
- }
- },
-
- _createMarker: function (latlng, index) {
- var marker = new L.Marker(latlng, {
- draggable: true,
- icon: this.options.icon
- });
-
- marker._origLatLng = latlng;
- marker._index = index;
-
- marker.on('drag', this._onMarkerDrag, this);
- marker.on('dragend', this._fireEdit, this);
-
- this._markerGroup.addLayer(marker);
-
- return marker;
- },
-
- _fireEdit: function () {
- this._poly.fire('edit');
- },
-
- _onMarkerDrag: function (e) {
- var marker = e.target;
-
- L.Util.extend(marker._origLatLng, marker._latlng);
-
- if (marker._middleLeft) {
- marker._middleLeft.setLatLng(this._getMiddleLatLng(marker._prev, marker));
- }
- if (marker._middleRight) {
- marker._middleRight.setLatLng(this._getMiddleLatLng(marker, marker._next));
- }
-
- this._poly.redraw();
- },
-
- _onMarkerClick: function (e) {
- // Default action on marker click is to remove that marker, but if we remove the marker when latlng count < 3, we don't have a valid polyline anymore
- if (this._poly._latlngs.length < 3) {
- return;
- }
-
- var marker = e.target,
- i = marker._index;
-
- // Check existence of previous and next markers since they wouldn't exist for edge points on the polyline
- if (marker._prev && marker._next) {
- this._createMiddleMarker(marker._prev, marker._next);
- this._updatePrevNext(marker._prev, marker._next);
- }
-
- // The marker itself is guaranteed to exist and present in the layer, since we managed to click on it
- this._markerGroup.removeLayer(marker);
- // Check for the existence of middle left or middle right
- if (marker._middleLeft) {
- this._markerGroup.removeLayer(marker._middleLeft);
- }
- if (marker._middleRight) {
- this._markerGroup.removeLayer(marker._middleRight);
- }
- this._poly.spliceLatLngs(i, 1);
- this._updateIndexes(i, -1);
- this._poly.fire('edit');
- },
-
- _updateIndexes: function (index, delta) {
- this._markerGroup._iterateLayers(function (marker) {
- if (marker._index > index) {
- marker._index += delta;
- }
- });
- },
-
- _createMiddleMarker: function (marker1, marker2) {
- var latlng = this._getMiddleLatLng(marker1, marker2),
- marker = this._createMarker(latlng),
- onClick,
- onDragStart,
- onDragEnd;
-
- marker.setOpacity(0.6);
-
- marker1._middleRight = marker2._middleLeft = marker;
-
- onDragStart = function () {
- var i = marker2._index;
-
- marker._index = i;
-
- marker
- .off('click', onClick)
- .on('click', this._onMarkerClick, this);
-
- this._poly.spliceLatLngs(i, 0, latlng);
- this._markers.splice(i, 0, marker);
-
- marker.setOpacity(1);
-
- this._updateIndexes(i, 1);
- marker2._index++;
- this._updatePrevNext(marker1, marker);
- this._updatePrevNext(marker, marker2);
- };
-
- onDragEnd = function () {
- marker.off('dragstart', onDragStart, this);
- marker.off('dragend', onDragEnd, this);
-
- this._createMiddleMarker(marker1, marker);
- this._createMiddleMarker(marker, marker2);
- };
-
- onClick = function () {
- onDragStart.call(this);
- onDragEnd.call(this);
- this._poly.fire('edit');
- };
-
- marker
- .on('click', onClick, this)
- .on('dragstart', onDragStart, this)
- .on('dragend', onDragEnd, this);
-
- this._markerGroup.addLayer(marker);
- },
-
- _updatePrevNext: function (marker1, marker2) {
- marker1._next = marker2;
- marker2._prev = marker1;
- },
-
- _getMiddleLatLng: function (marker1, marker2) {
- var map = this._poly._map,
- p1 = map.latLngToLayerPoint(marker1.getLatLng()),
- p2 = map.latLngToLayerPoint(marker2.getLatLng());
-
- return map.layerPointToLatLng(p1._add(p2).divideBy(2));
- }
-});
-
-
-
-L.Control = L.Class.extend({
- options: {
- position: 'topright'
- },
-
- initialize: function (options) {
- L.Util.setOptions(this, options);
- },
-
- getPosition: function () {
- return this.options.position;
- },
-
- setPosition: function (position) {
- var map = this._map;
-
- if (map) {
- map.removeControl(this);
- }
-
- this.options.position = position;
-
- if (map) {
- map.addControl(this);
- }
- },
-
- addTo: function (map) {
- this._map = map;
-
- var container = this._container = this.onAdd(map),
- pos = this.getPosition(),
- corner = map._controlCorners[pos];
-
- L.DomUtil.addClass(container, 'leaflet-control');
-
- if (pos.indexOf('bottom') !== -1) {
- corner.insertBefore(container, corner.firstChild);
- } else {
- corner.appendChild(container);
- }
-
- return this;
- },
-
- removeFrom: function (map) {
- var pos = this.getPosition(),
- corner = map._controlCorners[pos];
-
- corner.removeChild(this._container);
- this._map = null;
-
- if (this.onRemove) {
- this.onRemove(map);
- }
-
- return this;
- }
-});
-
-
-
-L.Map.include({
- addControl: function (control) {
- control.addTo(this);
- return this;
- },
-
- removeControl: function (control) {
- control.removeFrom(this);
- return this;
- },
-
- _initControlPos: function () {
- var corners = this._controlCorners = {},
- l = 'leaflet-',
- container = this._controlContainer =
- L.DomUtil.create('div', l + 'control-container', this._container);
-
- function createCorner(vSide, hSide) {
- var className = l + vSide + ' ' + l + hSide;
-
- corners[vSide + hSide] =
- L.DomUtil.create('div', className, container);
- }
-
- createCorner('top', 'left');
- createCorner('top', 'right');
- createCorner('bottom', 'left');
- createCorner('bottom', 'right');
- }
-});
-
-
-L.Control.Zoom = L.Control.extend({
- options: {
- position: 'topleft'
- },
-
- onAdd: function (map) {
- var className = 'leaflet-control-zoom',
- container = L.DomUtil.create('div', className);
-
- this._createButton('Zoom in', className + '-in', container, map.zoomIn, map);
- this._createButton('Zoom out', className + '-out', container, map.zoomOut, map);
-
- return container;
- },
-
- _createButton: function (title, className, container, fn, context) {
- var link = L.DomUtil.create('a', className, container);
- link.href = '#';
- link.title = title;
-
- L.DomEvent
- .addListener(link, 'click', L.DomEvent.stopPropagation)
- .addListener(link, 'click', L.DomEvent.preventDefault)
- .addListener(link, 'click', fn, context);
-
- return link;
- }
-});
-
-L.Map.mergeOptions({
- zoomControl: true
-});
-
-L.Map.addInitHook(function () {
- if (this.options.zoomControl) {
- this.zoomControl = new L.Control.Zoom();
- this.addControl(this.zoomControl);
- }
-});
-
-L.Control.Attribution = L.Control.extend({
- options: {
- position: 'bottomright',
- prefix: 'Powered by Leaflet'
- },
-
- initialize: function (options) {
- L.Util.setOptions(this, options);
-
- this._attributions = {};
- },
-
- onAdd: function (map) {
- this._container = L.DomUtil.create('div', 'leaflet-control-attribution');
- L.DomEvent.disableClickPropagation(this._container);
-
- map
- .on('layeradd', this._onLayerAdd, this)
- .on('layerremove', this._onLayerRemove, this);
-
- this._update();
-
- return this._container;
- },
-
- onRemove: function (map) {
- map
- .off('layeradd', this._onLayerAdd)
- .off('layerremove', this._onLayerRemove);
-
- },
-
- setPrefix: function (prefix) {
- this.options.prefix = prefix;
- this._update();
- },
-
- addAttribution: function (text) {
- if (!text) { return; }
-
- if (!this._attributions[text]) {
- this._attributions[text] = 0;
- }
- this._attributions[text]++;
-
- this._update();
- },
-
- removeAttribution: function (text) {
- if (!text) { return; }
-
- this._attributions[text]--;
- this._update();
- },
-
- _update: function () {
- if (!this._map) { return; }
-
- var attribs = [];
-
- for (var i in this._attributions) {
- if (this._attributions.hasOwnProperty(i) && this._attributions[i]) {
- attribs.push(i);
- }
- }
-
- var prefixAndAttribs = [];
-
- if (this.options.prefix) {
- prefixAndAttribs.push(this.options.prefix);
- }
- if (attribs.length) {
- prefixAndAttribs.push(attribs.join(', '));
- }
-
- this._container.innerHTML = prefixAndAttribs.join(' — ');
- },
-
- _onLayerAdd: function (e) {
- if (e.layer.getAttribution) {
- this.addAttribution(e.layer.getAttribution());
- }
- },
-
- _onLayerRemove: function (e) {
- if (e.layer.getAttribution) {
- this.removeAttribution(e.layer.getAttribution());
- }
- }
-});
-
-L.Map.mergeOptions({
- attributionControl: true
-});
-
-L.Map.addInitHook(function () {
- if (this.options.attributionControl) {
- this.attributionControl = (new L.Control.Attribution()).addTo(this);
- }
-});
-
-L.Control.Scale = L.Control.extend({
- options: {
- position: 'bottomleft',
- maxWidth: 100,
- metric: true,
- imperial: true,
- updateWhenIdle: false
- },
-
- onAdd: function (map) {
- this._map = map;
-
- var className = 'leaflet-control-scale',
- container = L.DomUtil.create('div', className),
- options = this.options;
-
- if (options.metric) {
- this._mScale = L.DomUtil.create('div', className + '-line', container);
- }
- if (options.imperial) {
- this._iScale = L.DomUtil.create('div', className + '-line', container);
- }
-
- map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
- this._update();
-
- return container;
- },
-
- onRemove: function (map) {
- map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
- },
-
- _update: function () {
- var bounds = this._map.getBounds(),
- centerLat = bounds.getCenter().lat,
-
- left = new L.LatLng(centerLat, bounds.getSouthWest().lng),
- right = new L.LatLng(centerLat, bounds.getNorthEast().lng),
-
- size = this._map.getSize(),
- options = this.options,
-
- maxMeters = left.distanceTo(right) * (options.maxWidth / size.x);
-
- if (options.metric) {
- this._updateMetric(maxMeters);
- }
-
- if (options.imperial) {
- this._updateImperial(maxMeters);
- }
- },
-
- _updateMetric: function (maxMeters) {
- var meters = this._getRoundNum(maxMeters);
-
- this._mScale.style.width = this._getScaleWidth(meters / maxMeters) + 'px';
- this._mScale.innerHTML = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';
- },
-
- _updateImperial: function (maxMeters) {
- var maxFeet = maxMeters * 3.2808399,
- scale = this._iScale,
- maxMiles, miles, feet;
-
- if (maxFeet > 5280) {
- maxMiles = maxFeet / 5280;
- miles = this._getRoundNum(maxMiles);
-
- scale.style.width = this._getScaleWidth(miles / maxMiles) + 'px';
- scale.innerHTML = miles + ' mi';
-
- } else {
- feet = this._getRoundNum(maxFeet);
-
- scale.style.width = this._getScaleWidth(feet / maxFeet) + 'px';
- scale.innerHTML = feet + ' ft';
- }
- },
-
- _getScaleWidth: function (ratio) {
- return Math.round(this.options.maxWidth * ratio) - 10;
- },
-
- _getRoundNum: function (num) {
- var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),
- d = num / pow10;
-
- d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 2 ? 2 : 1;
-
- return pow10 * d;
- }
-});
-
-
-L.Control.Layers = L.Control.extend({
- options: {
- collapsed: true,
- position: 'topright'
- },
-
- initialize: function (baseLayers, overlays, options) {
- L.Util.setOptions(this, options);
-
- this._layers = {};
-
- for (var i in baseLayers) {
- if (baseLayers.hasOwnProperty(i)) {
- this._addLayer(baseLayers[i], i);
- }
- }
-
- for (i in overlays) {
- if (overlays.hasOwnProperty(i)) {
- this._addLayer(overlays[i], i, true);
- }
- }
- },
-
- onAdd: function (map) {
- this._initLayout();
- this._update();
-
- return this._container;
- },
-
- addBaseLayer: function (layer, name) {
- this._addLayer(layer, name);
- this._update();
- return this;
- },
-
- addOverlay: function (layer, name) {
- this._addLayer(layer, name, true);
- this._update();
- return this;
- },
-
- removeLayer: function (layer) {
- var id = L.Util.stamp(layer);
- delete this._layers[id];
- this._update();
- return this;
- },
-
- _initLayout: function () {
- var className = 'leaflet-control-layers',
- container = this._container = L.DomUtil.create('div', className);
-
- if (!L.Browser.touch) {
- L.DomEvent.disableClickPropagation(container);
- } else {
- L.DomEvent.addListener(container, 'click', L.DomEvent.stopPropagation);
- }
-
- var form = this._form = L.DomUtil.create('form', className + '-list');
-
- if (this.options.collapsed) {
- L.DomEvent
- .addListener(container, 'mouseover', this._expand, this)
- .addListener(container, 'mouseout', this._collapse, this);
-
- var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container);
- link.href = '#';
- link.title = 'Layers';
-
- L.DomEvent.addListener(link, L.Browser.touch ? 'click' : 'focus', this._expand, this);
-
- this._map.on('movestart', this._collapse, this);
- // TODO keyboard accessibility
- } else {
- this._expand();
- }
-
- this._baseLayersList = L.DomUtil.create('div', className + '-base', form);
- this._separator = L.DomUtil.create('div', className + '-separator', form);
- this._overlaysList = L.DomUtil.create('div', className + '-overlays', form);
-
- container.appendChild(form);
- },
-
- _addLayer: function (layer, name, overlay) {
- var id = L.Util.stamp(layer);
- this._layers[id] = {
- layer: layer,
- name: name,
- overlay: overlay
- };
- },
-
- _update: function () {
- if (!this._container) {
- return;
- }
-
- this._baseLayersList.innerHTML = '';
- this._overlaysList.innerHTML = '';
-
- var baseLayersPresent = false,
- overlaysPresent = false;
-
- for (var i in this._layers) {
- if (this._layers.hasOwnProperty(i)) {
- var obj = this._layers[i];
- this._addItem(obj);
- overlaysPresent = overlaysPresent || obj.overlay;
- baseLayersPresent = baseLayersPresent || !obj.overlay;
- }
- }
-
- this._separator.style.display = (overlaysPresent && baseLayersPresent ? '' : 'none');
- },
-
- _addItem: function (obj, onclick) {
- var label = document.createElement('label');
-
- var input = document.createElement('input');
- if (!obj.overlay) {
- input.name = 'leaflet-base-layers';
- }
- input.type = obj.overlay ? 'checkbox' : 'radio';
- input.checked = this._map.hasLayer(obj.layer);
- input.layerId = L.Util.stamp(obj.layer);
-
- L.DomEvent.addListener(input, 'click', this._onInputClick, this);
-
- var name = document.createTextNode(' ' + obj.name);
-
- label.appendChild(input);
- label.appendChild(name);
-
- var container = obj.overlay ? this._overlaysList : this._baseLayersList;
- container.appendChild(label);
- },
-
- _onInputClick: function () {
- var i, input, obj,
- inputs = this._form.getElementsByTagName('input'),
- inputsLen = inputs.length;
-
- for (i = 0; i < inputsLen; i++) {
- input = inputs[i];
- obj = this._layers[input.layerId];
-
- if (input.checked) {
- this._map.addLayer(obj.layer, !obj.overlay);
- } else {
- this._map.removeLayer(obj.layer);
- }
- }
- },
-
- _expand: function () {
- L.DomUtil.addClass(this._container, 'leaflet-control-layers-expanded');
- },
-
- _collapse: function () {
- this._container.className = this._container.className.replace(' leaflet-control-layers-expanded', '');
- }
-});
-
-
-L.Transition = L.Class.extend({
- includes: L.Mixin.Events,
-
- statics: {
- CUSTOM_PROPS_SETTERS: {
- position: L.DomUtil.setPosition
- //TODO transform custom attr
- },
-
- implemented: function () {
- return L.Transition.NATIVE || L.Transition.TIMER;
- }
- },
-
- options: {
- easing: 'ease',
- duration: 0.5
- },
-
- _setProperty: function (prop, value) {
- var setters = L.Transition.CUSTOM_PROPS_SETTERS;
- if (prop in setters) {
- setters[prop](this._el, value);
- } else {
- this._el.style[prop] = value;
- }
- }
-});
-
-
-/*
- * L.Transition native implementation that powers Leaflet animation
- * in browsers that support CSS3 Transitions
- */
-
-L.Transition = L.Transition.extend({
- statics: (function () {
- var transition = L.DomUtil.TRANSITION,
- transitionEnd = (transition === 'webkitTransition' || transition === 'OTransition' ?
- transition + 'End' : 'transitionend');
-
- return {
- NATIVE: !!transition,
-
- TRANSITION: transition,
- PROPERTY: transition + 'Property',
- DURATION: transition + 'Duration',
- EASING: transition + 'TimingFunction',
- END: transitionEnd,
-
- // transition-property value to use with each particular custom property
- CUSTOM_PROPS_PROPERTIES: {
- position: L.Browser.webkit ? L.DomUtil.TRANSFORM : 'top, left'
- }
- };
- }()),
-
- options: {
- fakeStepInterval: 100
- },
-
- initialize: function (/*HTMLElement*/ el, /*Object*/ options) {
- this._el = el;
- L.Util.setOptions(this, options);
-
- L.DomEvent.addListener(el, L.Transition.END, this._onTransitionEnd, this);
- this._onFakeStep = L.Util.bind(this._onFakeStep, this);
- },
-
- run: function (/*Object*/ props) {
- var prop,
- propsList = [],
- customProp = L.Transition.CUSTOM_PROPS_PROPERTIES;
-
- for (prop in props) {
- if (props.hasOwnProperty(prop)) {
- prop = customProp[prop] ? customProp[prop] : prop;
- prop = this._dasherize(prop);
- propsList.push(prop);
- }
- }
-
- this._el.style[L.Transition.DURATION] = this.options.duration + 's';
- this._el.style[L.Transition.EASING] = this.options.easing;
- this._el.style[L.Transition.PROPERTY] = propsList.join(', ');
-
- for (prop in props) {
- if (props.hasOwnProperty(prop)) {
- this._setProperty(prop, props[prop]);
- }
- }
-
- this._inProgress = true;
-
- this.fire('start');
-
- if (L.Transition.NATIVE) {
- clearInterval(this._timer);
- this._timer = setInterval(this._onFakeStep, this.options.fakeStepInterval);
- } else {
- this._onTransitionEnd();
- }
- },
-
- _dasherize: (function () {
- var re = /([A-Z])/g;
-
- function replaceFn(w) {
- return '-' + w.toLowerCase();
- }
-
- return function (str) {
- return str.replace(re, replaceFn);
- };
- }()),
-
- _onFakeStep: function () {
- this.fire('step');
- },
-
- _onTransitionEnd: function (e) {
- if (this._inProgress) {
- this._inProgress = false;
- clearInterval(this._timer);
-
- this._el.style[L.Transition.PROPERTY] = 'none';
-
- this.fire('step');
-
- if (e && e.type) {
- this.fire('end');
- }
- }
- }
-});
-
-
-/*
- * L.Transition fallback implementation that powers Leaflet animation
- * in browsers that don't support CSS3 Transitions
- */
-
-L.Transition = L.Transition.NATIVE ? L.Transition : L.Transition.extend({
- statics: {
- getTime: Date.now || function () {
- return +new Date();
- },
-
- TIMER: true,
-
- EASINGS: {
- 'ease': [0.25, 0.1, 0.25, 1.0],
- 'linear': [0.0, 0.0, 1.0, 1.0],
- 'ease-in': [0.42, 0, 1.0, 1.0],
- 'ease-out': [0, 0, 0.58, 1.0],
- 'ease-in-out': [0.42, 0, 0.58, 1.0]
- },
-
- CUSTOM_PROPS_GETTERS: {
- position: L.DomUtil.getPosition
- },
-
- //used to get units from strings like "10.5px" (->px)
- UNIT_RE: /^[\d\.]+(\D*)$/
- },
-
- options: {
- fps: 50
- },
-
- initialize: function (el, options) {
- this._el = el;
- L.Util.extend(this.options, options);
-
- var easings = L.Transition.EASINGS[this.options.easing] || L.Transition.EASINGS.ease;
-
- this._p1 = new L.Point(0, 0);
- this._p2 = new L.Point(easings[0], easings[1]);
- this._p3 = new L.Point(easings[2], easings[3]);
- this._p4 = new L.Point(1, 1);
-
- this._step = L.Util.bind(this._step, this);
- this._interval = Math.round(1000 / this.options.fps);
- },
-
- run: function (props) {
- this._props = {};
-
- var getters = L.Transition.CUSTOM_PROPS_GETTERS,
- re = L.Transition.UNIT_RE;
-
- this.fire('start');
-
- for (var prop in props) {
- if (props.hasOwnProperty(prop)) {
- var p = {};
- if (prop in getters) {
- p.from = getters[prop](this._el);
- } else {
- var matches = this._el.style[prop].match(re);
- p.from = parseFloat(matches[0]);
- p.unit = matches[1];
- }
- p.to = props[prop];
- this._props[prop] = p;
- }
- }
-
- clearInterval(this._timer);
- this._timer = setInterval(this._step, this._interval);
- this._startTime = L.Transition.getTime();
- },
-
- _step: function () {
- var time = L.Transition.getTime(),
- elapsed = time - this._startTime,
- duration = this.options.duration * 1000;
-
- if (elapsed < duration) {
- this._runFrame(this._cubicBezier(elapsed / duration));
- } else {
- this._runFrame(1);
- this._complete();
- }
- },
-
- _runFrame: function (percentComplete) {
- var setters = L.Transition.CUSTOM_PROPS_SETTERS,
- prop, p, value;
-
- for (prop in this._props) {
- if (this._props.hasOwnProperty(prop)) {
- p = this._props[prop];
- if (prop in setters) {
- value = p.to.subtract(p.from).multiplyBy(percentComplete).add(p.from);
- setters[prop](this._el, value);
- } else {
- this._el.style[prop] =
- ((p.to - p.from) * percentComplete + p.from) + p.unit;
- }
- }
- }
- this.fire('step');
- },
-
- _complete: function () {
- clearInterval(this._timer);
- this.fire('end');
- },
-
- _cubicBezier: function (t) {
- var a = Math.pow(1 - t, 3),
- b = 3 * Math.pow(1 - t, 2) * t,
- c = 3 * (1 - t) * Math.pow(t, 2),
- d = Math.pow(t, 3),
- p1 = this._p1.multiplyBy(a),
- p2 = this._p2.multiplyBy(b),
- p3 = this._p3.multiplyBy(c),
- p4 = this._p4.multiplyBy(d);
-
- return p1.add(p2).add(p3).add(p4).y;
- }
-});
-
-
-
-L.Map.include(!(L.Transition && L.Transition.implemented()) ? {} : {
- setView: function (center, zoom, forceReset) {
- zoom = this._limitZoom(zoom);
-
- var zoomChanged = (this._zoom !== zoom);
-
- if (this._loaded && !forceReset && this._layers) {
- // difference between the new and current centers in pixels
- var offset = this._getNewTopLeftPoint(center).subtract(this._getTopLeftPoint());
-
- center = new L.LatLng(center.lat, center.lng);
-
- var done = (zoomChanged ?
- this._zoomToIfCenterInView && this._zoomToIfCenterInView(center, zoom, offset) :
- this._panByIfClose(offset));
-
- // exit if animated pan or zoom started
- if (done) {
- return this;
- }
- }
-
- // reset the map view
- this._resetView(center, zoom);
-
- return this;
- },
-
- panBy: function (offset, options) {
- if (!(offset.x || offset.y)) {
- return this;
- }
-
- if (!this._panTransition) {
- this._panTransition = new L.Transition(this._mapPane);
-
- this._panTransition.on('step', this._onPanTransitionStep, this);
- this._panTransition.on('end', this._onPanTransitionEnd, this);
- }
-
- L.Util.setOptions(this._panTransition, L.Util.extend({duration: 0.25}, options));
-
- this.fire('movestart');
-
- this._mapPane.className += ' leaflet-pan-anim';
-
- this._panTransition.run({
- position: L.DomUtil.getPosition(this._mapPane).subtract(offset)
- });
-
- return this;
- },
-
- _onPanTransitionStep: function () {
- this.fire('move');
- },
-
- _onPanTransitionEnd: function () {
- this._mapPane.className = this._mapPane.className.replace(/ leaflet-pan-anim/g, '');
- this.fire('moveend');
- },
-
- _panByIfClose: function (offset) {
- if (this._offsetIsWithinView(offset)) {
- this.panBy(offset);
- return true;
- }
- return false;
- },
-
- _offsetIsWithinView: function (offset, multiplyFactor) {
- var m = multiplyFactor || 1,
- size = this.getSize();
-
- return (Math.abs(offset.x) <= size.x * m) &&
- (Math.abs(offset.y) <= size.y * m);
- }
-});
-
-
-L.Map.mergeOptions({
- zoomAnimation: L.DomUtil.TRANSITION && !L.Browser.android && !L.Browser.mobileOpera
-});
-
-L.Map.include(!L.DomUtil.TRANSITION ? {} : {
- _zoomToIfCenterInView: function (center, zoom, centerOffset) {
-
- if (this._animatingZoom) {
- return true;
- }
- if (!this.options.zoomAnimation) {
- return false;
- }
-
- var scale = Math.pow(2, zoom - this._zoom),
- offset = centerOffset.divideBy(1 - 1 / scale);
-
- // if offset does not exceed half of the view
- if (!this._offsetIsWithinView(offset, 1)) {
- return false;
- }
-
- this._mapPane.className += ' leaflet-zoom-anim';
-
- this
- .fire('movestart')
- .fire('zoomstart');
-
- this._prepareTileBg();
-
- var centerPoint = this.containerPointToLayerPoint(this.getSize().divideBy(2)),
- origin = centerPoint.add(offset);
-
- this._runAnimation(center, zoom, scale, origin);
-
- return true;
- },
-
-
- _runAnimation: function (center, zoom, scale, origin) {
- this._animatingZoom = true;
-
- this._animateToCenter = center;
- this._animateToZoom = zoom;
-
- var transform = L.DomUtil.TRANSFORM,
- tileBg = this._tileBg;
-
- clearTimeout(this._clearTileBgTimer);
-
- //dumb FireFox hack, I have no idea why this magic zero translate fixes the scale transition problem
- if (L.Browser.gecko || window.opera) {
- tileBg.style[transform] += ' translate(0,0)';
- }
-
- var scaleStr;
-
- // Android 2.* doesn't like translate/scale chains, transformOrigin + scale works better but
- // it breaks touch zoom which Anroid doesn't support anyway, so that's a really ugly hack
-
- // TODO work around this prettier
- if (L.Browser.android) {
- tileBg.style[transform + 'Origin'] = origin.x + 'px ' + origin.y + 'px';
- scaleStr = 'scale(' + scale + ')';
- } else {
- scaleStr = L.DomUtil.getScaleString(scale, origin);
- }
-
- L.Util.falseFn(tileBg.offsetWidth); //hack to make sure transform is updated before running animation
-
- var options = {};
- options[transform] = tileBg.style[transform] + ' ' + scaleStr;
-
- tileBg.transition.run(options);
- },
-
- _prepareTileBg: function () {
- var tilePane = this._tilePane,
- tileBg = this._tileBg;
-
- if (!tileBg) {
- tileBg = this._tileBg = this._createPane('leaflet-tile-pane', this._mapPane);
- tileBg.style.zIndex = 1;
- }
-
- // prepare the background pane to become the main tile pane
- tileBg.style[L.DomUtil.TRANSFORM] = '';
- tileBg.style.visibility = 'hidden';
-
- // tells tile layers to reinitialize their containers
- tileBg.empty = true;
- tilePane.empty = false;
-
- this._tilePane = this._panes.tilePane = tileBg;
- var newTileBg = this._tileBg = tilePane;
-
- if (!newTileBg.transition) {
- // TODO move to Map options
- newTileBg.transition = new L.Transition(newTileBg, {
- duration: 0.25,
- easing: 'cubic-bezier(0.25,0.1,0.25,0.75)'
- });
- newTileBg.transition.on('end', this._onZoomTransitionEnd, this);
- }
-
- this._stopLoadingImages(newTileBg);
- },
-
- // stops loading all tiles in the background layer
- _stopLoadingImages: function (container) {
- var tiles = Array.prototype.slice.call(container.getElementsByTagName('img')),
- i, len, tile;
-
- for (i = 0, len = tiles.length; i < len; i++) {
- tile = tiles[i];
-
- if (!tile.complete) {
- tile.onload = L.Util.falseFn;
- tile.onerror = L.Util.falseFn;
- tile.src = L.Util.emptyImageUrl;
-
- tile.parentNode.removeChild(tile);
- }
- }
- },
-
- _onZoomTransitionEnd: function () {
- this._restoreTileFront();
-
- L.Util.falseFn(this._tileBg.offsetWidth);
- this._resetView(this._animateToCenter, this._animateToZoom, true, true);
-
- this._mapPane.className = this._mapPane.className.replace(' leaflet-zoom-anim', ''); //TODO toggleClass util
- this._animatingZoom = false;
- },
-
- _restoreTileFront: function () {
- this._tilePane.innerHTML = '';
- this._tilePane.style.visibility = '';
- this._tilePane.style.zIndex = 2;
- this._tileBg.style.zIndex = 1;
- },
-
- _clearTileBg: function () {
- if (!this._animatingZoom && !this.touchZoom._zooming) {
- this._tileBg.innerHTML = '';
- }
- }
-});
-
-
-/*
- * Provides L.Map with convenient shortcuts for W3C geolocation.
- */
-
-L.Map.include({
- _defaultLocateOptions: {
- watch: false,
- setView: false,
- maxZoom: Infinity,
- timeout: 10000,
- maximumAge: 0,
- enableHighAccuracy: false
- },
-
- locate: function (/*Object*/ options) {
-
- options = this._locationOptions = L.Util.extend(this._defaultLocateOptions, options);
-
- if (!navigator.geolocation) {
- return this.fire('locationerror', {
- code: 0,
- message: "Geolocation not supported."
- });
- }
-
- var onResponse = L.Util.bind(this._handleGeolocationResponse, this),
- onError = L.Util.bind(this._handleGeolocationError, this);
-
- if (options.watch) {
- this._locationWatchId = navigator.geolocation.watchPosition(onResponse, onError, options);
- } else {
- navigator.geolocation.getCurrentPosition(onResponse, onError, options);
- }
- return this;
- },
-
- stopLocate: function () {
- if (navigator.geolocation) {
- navigator.geolocation.clearWatch(this._locationWatchId);
- }
- return this;
- },
-
- _handleGeolocationError: function (error) {
- var c = error.code,
- message =
- (c === 1 ? "permission denied" :
- (c === 2 ? "position unavailable" : "timeout"));
-
- if (this._locationOptions.setView && !this._loaded) {
- this.fitWorld();
- }
-
- this.fire('locationerror', {
- code: c,
- message: "Geolocation error: " + message + "."
- });
- },
-
- _handleGeolocationResponse: function (pos) {
- var latAccuracy = 180 * pos.coords.accuracy / 4e7,
- lngAccuracy = latAccuracy * 2,
-
- lat = pos.coords.latitude,
- lng = pos.coords.longitude,
- latlng = new L.LatLng(lat, lng),
-
- sw = new L.LatLng(lat - latAccuracy, lng - lngAccuracy),
- ne = new L.LatLng(lat + latAccuracy, lng + lngAccuracy),
- bounds = new L.LatLngBounds(sw, ne),
-
- options = this._locationOptions;
-
- if (options.setView) {
- var zoom = Math.min(this.getBoundsZoom(bounds), options.maxZoom);
- this.setView(latlng, zoom);
- }
-
- this.fire('locationfound', {
- latlng: latlng,
- bounds: bounds,
- accuracy: pos.coords.accuracy
- });
- }
-});
-
-
-
-
-}());
\ No newline at end of file
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet.css b/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet.css
deleted file mode 100644
index 2ecd85526..000000000
--- a/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet.css
+++ /dev/null
@@ -1,366 +0,0 @@
-/* required styles */
-
-.leaflet-map-pane,
-.leaflet-tile,
-.leaflet-marker-icon,
-.leaflet-marker-shadow,
-.leaflet-tile-pane,
-.leaflet-overlay-pane,
-.leaflet-shadow-pane,
-.leaflet-marker-pane,
-.leaflet-popup-pane,
-.leaflet-overlay-pane svg,
-.leaflet-zoom-box,
-.leaflet-image-layer { /* TODO optimize classes */
- position: absolute;
- }
-.leaflet-container {
- overflow: hidden;
- }
-.leaflet-tile-pane,
-.leaflet-container,
-.leaflet-corner,
-.leaflet-popup {
- /* TODO make this configurable */
- -webkit-transform: translate3d(0,0,0);
- }
-.leaflet-tile,
-.leaflet-marker-icon,
-.leaflet-marker-shadow {
- -moz-user-select: none;
- -webkit-user-select: none;
- user-select: none;
- }
-.leaflet-marker-icon,
-.leaflet-marker-shadow {
- display: block;
- }
-.leaflet-clickable {
- cursor: pointer;
- }
-.leaflet-dragging {
- cursor: move;
- }
-.leaflet-dragging .leaflet-clickable {
- cursor: move;
- }
-.leaflet-container img {
- max-width: none !important;
- }
-.leaflet-div-icon {
- background: #fff;
- border: 1px solid #666;
-}
-.leaflet-editing-icon {
- border-radius: 2px;
-}
-
-.leaflet-tile-pane { z-index: 2; }
-
-.leaflet-objects-pane { z-index: 3; }
-.leaflet-overlay-pane { z-index: 4; }
-.leaflet-shadow-pane { z-index: 5; }
-.leaflet-marker-pane { z-index: 6; }
-.leaflet-popup-pane { z-index: 7; }
-
-.leaflet-zoom-box {
- width: 0;
- height: 0;
- }
-
-.leaflet-tile {
- visibility: hidden;
- }
-.leaflet-tile-loaded {
- visibility: inherit;
- }
-
-a.leaflet-active {
- outline: 2px solid orange;
- }
-
-
-/* Leaflet controls */
-
-.leaflet-control {
- position: relative;
- z-index: 7;
- }
-.leaflet-top,
-.leaflet-bottom {
- position: absolute;
- }
-.leaflet-top {
- top: 0;
- }
-.leaflet-right {
- right: 0;
- }
-.leaflet-bottom {
- bottom: 0;
- }
-.leaflet-left {
- left: 0;
- }
-.leaflet-control {
- float: left;
- clear: both;
- }
-.leaflet-right .leaflet-control {
- float: right;
- }
-.leaflet-top .leaflet-control {
- margin-top: 10px;
- }
-.leaflet-bottom .leaflet-control {
- margin-bottom: 10px;
- }
-.leaflet-left .leaflet-control {
- margin-left: 10px;
- }
-.leaflet-right .leaflet-control {
- margin-right: 10px;
- }
-
-.leaflet-control-zoom {
- -moz-border-radius: 7px;
- -webkit-border-radius: 7px;
- border-radius: 7px;
- }
-.leaflet-control-zoom {
- padding: 5px;
- background: rgba(0, 0, 0, 0.25);
- }
-.leaflet-control-zoom a {
- background-color: rgba(255, 255, 255, 0.75);
- }
-.leaflet-control-zoom a, .leaflet-control-layers a {
- background-position: 50% 50%;
- background-repeat: no-repeat;
- display: block;
- }
-.leaflet-control-zoom a {
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
- width: 19px;
- height: 19px;
- }
-.leaflet-control-zoom a:hover {
- background-color: #fff;
- }
-.leaflet-touch .leaflet-control-zoom a {
- width: 27px;
- height: 27px;
- }
-.leaflet-control-zoom-in {
- background-image: url(images/zoom-in.png);
- margin-bottom: 5px;
- }
-.leaflet-control-zoom-out {
- background-image: url(images/zoom-out.png);
- }
-
-.leaflet-control-layers {
- box-shadow: 0 1px 7px #999;
- background: #f8f8f9;
- -moz-border-radius: 8px;
- -webkit-border-radius: 8px;
- border-radius: 8px;
- }
-.leaflet-control-layers a {
- background-image: url(images/layers.png);
- width: 36px;
- height: 36px;
- }
-.leaflet-touch .leaflet-control-layers a {
- width: 44px;
- height: 44px;
- }
-.leaflet-control-layers .leaflet-control-layers-list,
-.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
- display: none;
- }
-.leaflet-control-layers-expanded .leaflet-control-layers-list {
- display: block;
- position: relative;
- }
-.leaflet-control-layers-expanded {
- padding: 6px 10px 6px 6px;
- font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
- color: #333;
- background: #fff;
- }
-.leaflet-control-layers input {
- margin-top: 2px;
- position: relative;
- top: 1px;
- }
-.leaflet-control-layers label {
- display: block;
- }
-.leaflet-control-layers-separator {
- height: 0;
- border-top: 1px solid #ddd;
- margin: 5px -10px 5px -6px;
- }
-
-.leaflet-container .leaflet-control-attribution {
- background-color: rgba(255, 255, 255, 0.7);
- box-shadow: 0 0 5px #bbb;
- margin: 0;
-}
-
-.leaflet-control-attribution,
-.leaflet-control-scale-line {
- padding: 0 5px;
- color: #333;
- }
-
-.leaflet-container .leaflet-control-attribution,
-.leaflet-container .leaflet-control-scale {
- font: 11px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
- }
-
-.leaflet-left .leaflet-control-scale {
- margin-left: 5px;
- }
-.leaflet-bottom .leaflet-control-scale {
- margin-bottom: 5px;
- }
-
-.leaflet-control-scale-line {
- border: 2px solid #777;
- border-top: none;
- color: black;
- line-height: 1;
- font-size: 10px;
- padding-bottom: 2px;
- text-shadow: 1px 1px 1px #fff;
- background-color: rgba(255, 255, 255, 0.5);
- }
-.leaflet-control-scale-line:nth-child(2) {
- border-top: 2px solid #777;
- padding-top: 1px;
- border-bottom: none;
- margin-top: -2px;
- }
-
-.leaflet-touch .leaflet-control-attribution, .leaflet-touch .leaflet-control-layers {
- box-shadow: none;
- }
-.leaflet-touch .leaflet-control-layers {
- border: 5px solid #bbb;
- }
-
-
-/* Fade animations */
-
-.leaflet-fade-anim .leaflet-tile, .leaflet-fade-anim .leaflet-popup {
- opacity: 0;
-
- -webkit-transition: opacity 0.2s linear;
- -moz-transition: opacity 0.2s linear;
- -o-transition: opacity 0.2s linear;
- transition: opacity 0.2s linear;
- }
-.leaflet-fade-anim .leaflet-tile-loaded, .leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
- opacity: 1;
- }
-
-.leaflet-zoom-anim .leaflet-tile, .leaflet-pan-anim .leaflet-tile {
- -webkit-transition: none;
- -moz-transition: none;
- -o-transition: none;
- transition: none;
- }
-
-.leaflet-zoom-anim .leaflet-objects-pane {
- visibility: hidden;
- }
-
-
-/* Popup layout */
-
-.leaflet-popup {
- position: absolute;
- text-align: center;
- }
-.leaflet-popup-content-wrapper {
- padding: 1px;
- text-align: left;
- }
-.leaflet-popup-content {
- margin: 14px 20px;
- }
-.leaflet-popup-tip-container {
- margin: 0 auto;
- width: 40px;
- height: 16px;
- position: relative;
- overflow: hidden;
- }
-.leaflet-popup-tip {
- width: 15px;
- height: 15px;
- padding: 1px;
-
- margin: -8px auto 0;
-
- -moz-transform: rotate(45deg);
- -webkit-transform: rotate(45deg);
- -ms-transform: rotate(45deg);
- -o-transform: rotate(45deg);
- transform: rotate(45deg);
- }
-.leaflet-popup-close-button {
- position: absolute;
- top: 8px;
- right: 8px;
-
- width: 10px;
- height: 10px;
-
- overflow: hidden;
- }
-.leaflet-popup-content p {
- margin: 18px 0;
- }
-.leaflet-popup-scrolled {
- overflow: auto;
- border-bottom: 1px solid #ddd;
- border-top: 1px solid #ddd;
- }
-
-
-/* Visual appearance */
-
-.leaflet-container {
- background: #ddd;
- }
-.leaflet-container a {
- color: #0078A8;
- }
-.leaflet-zoom-box {
- border: 2px dotted #05f;
- background: white;
- opacity: 0.5;
- }
-.leaflet-popup-content-wrapper, .leaflet-popup-tip {
- background: white;
-
- box-shadow: 0 3px 10px #888;
- -moz-box-shadow: 0 3px 10px #888;
- -webkit-box-shadow: 0 3px 14px #999;
- }
-.leaflet-popup-content-wrapper {
- -moz-border-radius: 20px;
- -webkit-border-radius: 20px;
- border-radius: 20px;
- }
-.leaflet-popup-content {
- font: 12px/1.4 "Helvetica Neue", Arial, Helvetica, sans-serif;
- }
-.leaflet-popup-close-button {
- background: white url(images/popup-close.png);
- }
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet.ie.css b/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet.ie.css
deleted file mode 100644
index 24a48eb1c..000000000
--- a/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet.ie.css
+++ /dev/null
@@ -1,48 +0,0 @@
-.leaflet-tile {
- filter: inherit;
- }
-
-.leaflet-vml-shape {
- width: 1px;
- height: 1px;
- }
-.lvml {
- behavior: url(#default#VML);
- display: inline-block;
- position: absolute;
- }
-
-.leaflet-control {
- display: inline;
- }
-
-.leaflet-popup-tip {
- width: 21px;
- _width: 27px;
- margin: 0 auto;
- _margin-top: -3px;
-
- filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
- -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
- }
-.leaflet-popup-tip-container {
- margin-top: -1px;
- }
-.leaflet-popup-content-wrapper, .leaflet-popup-tip {
- border: 1px solid #bbb;
- }
-
-.leaflet-control-zoom {
- filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#3F000000',EndColorStr='#3F000000');
- }
-.leaflet-control-zoom a {
- background-color: #eee;
- }
-.leaflet-control-zoom a:hover {
- background-color: #fff;
- }
-.leaflet-control-layers-toggle {
- }
-.leaflet-control-attribution, .leaflet-control-layers {
- background: white;
- }
\ No newline at end of file
diff --git a/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet.js b/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet.js
deleted file mode 100644
index 2bd896b7c..000000000
--- a/nunaliit2-js-external/src/main/js/js-external/leaflet/leaflet.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- Copyright (c) 2010-2012, CloudMade, Vladimir Agafonkin
- Leaflet is a modern open-source JavaScript library for interactive maps.
- http://leaflet.cloudmade.com
-*/
-(function(){var a,b;typeof exports!="undefined"?a=exports:(a={},b=window.L,a.noConflict=function(){return window.L=b,a},window.L=a),a.version="0.4",a.Util={extend:function(a){var b=Array.prototype.slice.call(arguments,1);for(var c=0,d=b.length,e;c2?Array.prototype.slice.call(arguments,2):null;return function(){return a.apply(b,c||arguments)}},stamp:function(){var a=0,b="_leaflet_id";return function(c){return c[b]=c[b]||++a,c[b]}}(),requestAnimFrame:function(){function b(a){window.setTimeout(a,1e3/60)}var c=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||b;return function(d,e,f,g){d=e?a.Util.bind(d,e):d;if(!f||c!==b)return c.call(window,d,g);d()}}(),cancelAnimFrame:function(){var a=window.cancelAnimationFrame||window.webkitCancelRequestAnimationFrame||window.mozCancelRequestAnimationFrame||window.oCancelRequestAnimationFrame||window.msCancelRequestAnimationFrame||clearTimeout;return function(b){if(!b)return;return a.call(window,b)}}(),limitExecByInterval:function(a,b,c){var d,e;return function f(){var g=arguments;if(d){e=!0;return}d=!0,setTimeout(function(){d=!1,e&&(f.apply(c,g),e=!1)},b),a.apply(c,g)}},falseFn:function(){return!1},formatNum:function(a,b){var c=Math.pow(10,b||5);return Math.round(a*c)/c},setOptions:function(b,c){return b.options=a.Util.extend({},b.options,c),b.options},getParamString:function(a){var b=[];for(var c in a)a.hasOwnProperty(c)&&b.push(c+"="+a[c]);return"?"+b.join("&")},template:function(a,b){return a.replace(/\{ *([\w_]+) *\}/g,function(a,c){var d=b[c];if(!b.hasOwnProperty(c))throw Error("No value provided for variable "+a);return d})},emptyImageUrl:"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="},a.Class=function(){},a.Class.extend=function(b){var c=function(){this.initialize&&this.initialize.apply(this,arguments)},d=function(){};d.prototype=this.prototype;var e=new d;e.constructor=c,c.prototype=e;for(var f in this)this.hasOwnProperty(f)&&f!=="prototype"&&(c[f]=this[f]);return b.statics&&(a.Util.extend(c,b.statics),delete b.statics),b.includes&&(a.Util.extend.apply(null,[e].concat(b.includes)),delete b.includes),b.options&&e.options&&(b.options=a.Util.extend({},e.options,b.options)),a.Util.extend(e,b),c},a.Class.include=function(b){a.Util.extend(this.prototype,b)},a.Class.mergeOptions=function(b){a.Util.extend(this.prototype.options,b)},a.Mixin={},a.Mixin.Events={addEventListener:function(a,b,c){var d=this._leaflet_events=this._leaflet_events||{};return d[a]=d[a]||[],d[a].push({action:b,context:c||this}),this},hasEventListeners:function(a){var b="_leaflet_events";return b in this&&a in this[b]&&this[b][a].length>0},removeEventListener:function(a,b,c){if(!this.hasEventListeners(a))return this;for(var d=0,e=this._leaflet_events,f=e[a].length;d=this.min.x&&d.x<=this.max.x&&c.y>=this.min.y&&d.y<=this.max.y},intersects:function(a){var b=this.min,c=this.max,d=a.min,e=a.max,f=e.x>=b.x&&d.x<=c.x,g=e.y>=b.y&&d.y<=c.y;return f&&g}}),a.Transformation=a.Class.extend({initialize:function(a,b,c,d){this._a=a,this._b=b,this._c=c,this._d=d},transform:function(a,b){return this._transform(a.clone(),b)},_transform:function(a,b){return b=b||1,a.x=b*(this._a*a.x+this._b),a.y=b*(this._c*a.y+this._d),a},untransform:function(b,c){return c=c||1,new a.Point((b.x/c-this._b)/this._a,(b.y/c-this._d)/this._c)}}),a.DomUtil={get:function(a){return typeof a=="string"?document.getElementById(a):a},getStyle:function(a,b){var c=a.style[b];!c&&a.currentStyle&&(c=a.currentStyle[b]);if(!c||c==="auto"){var d=document.defaultView.getComputedStyle(a,null);c=d?d[b]:null}return c==="auto"?null:c},getViewportOffset:function(b){var c=0,d=0,e=b,f=document.body;do{c+=e.offsetTop||0,d+=e.offsetLeft||0;if(e.offsetParent===f&&a.DomUtil.getStyle(e,"position")==="absolute")break;if(a.DomUtil.getStyle(e,"position")==="fixed"){c+=f.scrollTop||0,d+=f.scrollLeft||0;break}e=e.offsetParent}while(e);e=b;do{if(e===f)break;c-=e.scrollTop||0,d-=e.scrollLeft||0,e=e.parentNode}while(e);return new a.Point(d,c)},create:function(a,b,c){var d=document.createElement(a);return d.className=b,c&&c.appendChild(d),d},disableTextSelection:function(){document.selection&&document.selection.empty&&document.selection.empty(),this._onselectstart||(this._onselectstart=document.onselectstart,document.onselectstart=a.Util.falseFn)},enableTextSelection:function(){document.onselectstart=this._onselectstart,this._onselectstart=null},hasClass:function(a,b){return a.className.length>0&&RegExp("(^|\\s)"+b+"(\\s|$)").test(a.className)},addClass:function(b,c){a.DomUtil.hasClass(b,c)||(b.className+=(b.className?" ":"")+c)},removeClass:function(a,b){a.className=a.className.replace(/(\S+)\s*/g,function(a,c){return c===b?"":a}).replace(/^\s+/,"")},setOpacity:function(b,c){a.Browser.ie?b.style.filter+=c!==1?"alpha(opacity="+Math.round(c*100)+")":"":b.style.opacity=c},testProp:function(a){var b=document.documentElement.style;for(var c=0;c=c.lat&&f.lat<=d.lat&&e.lng>=c.lng&&f.lng<=d.lng},intersects:function(a){var b=this._southWest,c=this._northEast,d=a.getSouthWest(),e=a.getNorthEast(),f=e.lat>=b.lat&&d.lat<=c.lat,g=e.lng>=b.lng&&d.lng<=c.lng;return f&&g},toBBoxString:function(){var a=this._southWest,b=this._northEast;return[a.lng,a.lat,b.lng,b.lat].join(",")},equals:function(a){return a?this._southWest.equals(a.getSouthWest())&&this._northEast.equals(a.getNorthEast()):!1}}),a.Projection={},a.Projection.SphericalMercator={MAX_LATITUDE:85.0511287798,project:function(b){var c=a.LatLng.DEG_TO_RAD,d=this.MAX_LATITUDE,e=Math.max(Math.min(d,b.lat),-d),f=b.lng*c,g=e*c;return g=Math.log(Math.tan(Math.PI/4+g/2)),new a.Point(f,g)},unproject:function(b,c){var d=a.LatLng.RAD_TO_DEG,e=b.x*d,f=(2*Math.atan(Math.exp(b.y))-Math.PI/2)*d;return new a.LatLng(f,e,c)}},a.Projection.LonLat={project:function(b){return new a.Point(b.lng,b.lat)},unproject:function(b,c){return new a.LatLng(b.y,b.x,c)}},a.CRS={latLngToPoint:function(a,b){var c=this.projection.project(a),d=this.scale(b);return this.transformation._transform(c,d)},pointToLatLng:function(a,b,c){var d=this.scale(b),e=this.transformation.untransform(a,d);return this.projection.unproject(e,c)},project:function(a){return this.projection.project(a)},scale:function(a){return 256*Math.pow(2,a)}},a.CRS.EPSG3857=a.Util.extend({},a.CRS,{code:"EPSG:3857",projection:a.Projection.SphericalMercator,transformation:new a.Transformation(.5/Math.PI,.5,-0.5/Math.PI,.5),project:function(a){var b=this.projection.project(a),c=6378137;return b.multiplyBy(c)}}),a.CRS.EPSG900913=a.Util.extend({},a.CRS.EPSG3857,{code:"EPSG:900913"}),a.CRS.EPSG4326=a.Util.extend({},a.CRS,{code:"EPSG:4326",projection:a.Projection.LonLat,transformation:new a.Transformation(1/360,.5,-1/360,.5)}),a.Map=a.Class.extend({includes:a.Mixin.Events,options:{crs:a.CRS.EPSG3857,fadeAnimation:a.DomUtil.TRANSITION&&!a.Browser.android,trackResize:!0},initialize:function(b,c){c=a.Util.setOptions(this,c),this._initContainer(b),this._initLayout(),this._initHooks(),this._initEvents(),c.maxBounds&&this.setMaxBounds(c.maxBounds),c.center&&typeof c.zoom!="undefined"&&this.setView(c.center,c.zoom,!0),this._initLayers(c.layers)},setView:function(a,b){return this._resetView(a,this._limitZoom(b)),this},setZoom:function(a){return this.setView(this.getCenter(),a)},zoomIn:function(){return this.setZoom(this._zoom+1)},zoomOut:function(){return this.setZoom(this._zoom-1)},fitBounds:function(a){var b=this.getBoundsZoom(a);return this.setView(a.getCenter(),b)},fitWorld:function(){var b=new a.LatLng(-60,-170),c=new a.LatLng(85,179);return this.fitBounds(new a.LatLngBounds(b,c))},panTo:function(a){return this.setView(a,this._zoom)},panBy:function(a){return this.fire("movestart"),this._rawPanBy(a),this.fire("move"),this.fire("moveend")},setMaxBounds:function(a){this.options.maxBounds=a;if(!a)return this._boundsMinZoom=null,this;var b=this.getBoundsZoom(a,!0);return this._boundsMinZoom=b,this._loaded&&(this._zoomg.x&&(h=g.x-e.x),d.y>f.y&&(i=f.y-d.y),d.xm&&--n>0)p=i*Math.sin(k),o=Math.PI/2-2*Math.atan(j*Math.pow((1-p)/(1+p),.5*i))-k,k+=o;return new a.LatLng(k*d,g,c)}},a.CRS.EPSG3395=a.Util.extend({},a.CRS,{code:"EPSG:3395",projection:a.Projection.Mercator,transformation:function(){var b=a.Projection.Mercator,c=b.R_MAJOR,d=b.R_MINOR;return new a.Transformation(.5/(Math.PI*c),.5,-0.5/(Math.PI*d),.5)}()}),a.TileLayer=a.Class.extend({includes:a.Mixin.Events,options:{minZoom:0,maxZoom:18,tileSize:256,subdomains:"abc",errorTileUrl:"",attribution:"",opacity:1,scheme:"xyz",continuousWorld:!1,noWrap:!1,zoomOffset:0,zoomReverse:!1,detectRetina:!1,unloadInvisibleTiles:a.Browser.mobile,updateWhenIdle:a.Browser.mobile,reuseTiles:!1},initialize:function(b,c){c=a.Util.setOptions(this,c),c.detectRetina&&window.devicePixelRatio>1&&c.maxZoom>0&&(c.tileSize=Math.floor(c.tileSize/2),c.zoomOffset++,c.minZoom>0&&c.minZoom--,this.options.maxZoom--),this._url=b;var d=this.options.subdomains;typeof d=="string"&&(this.options.subdomains=d.split(""))},onAdd:function(b,c){this._map=b,this._insertAtTheBottom=c,this._initContainer(),this._createTileProto(),b.on("viewreset",this._resetCallback,this),b.on("moveend",this._update,this),this.options.updateWhenIdle||(this._limitedUpdate=a.Util.limitExecByInterval(this._update,150,this),b.on("move",this._limitedUpdate,this)),this._reset(),this._update()},onRemove:function(a){a._panes.tilePane.removeChild(this._container),a.off("viewreset",this._resetCallback,this),a.off("moveend",this._update,this),this.options.updateWhenIdle||a.off("move",this._limitedUpdate,this),this._container=null,this._map=null},getAttribution:function(){return this.options.attribution},setOpacity:function(b){this.options.opacity=b,this._map&&this._updateOpacity();var c,d=this._tiles;if(a.Browser.webkit)for(c in d)d.hasOwnProperty(c)&&(d[c].style.webkitTransform+=" translate(0,0)")},_updateOpacity:function(){a.DomUtil.setOpacity(this._container,this.options.opacity)},_initContainer:function(){var b=this._map._panes.tilePane,c=b.firstChild;if(!this._container||b.empty)this._container=a.DomUtil.create("div","leaflet-layer"),this._insertAtTheBottom&&c?b.insertBefore(this._container,c):b.appendChild(this._container),this.options.opacity<1&&this._updateOpacity()},_resetCallback:function(a){this._reset(a.hard)},_reset:function(a){var b,c=this._tiles;for(b in c)c.hasOwnProperty(b)&&this.fire("tileunload",{tile:c[b]});this._tiles={},this.options.reuseTiles&&(this._unusedTiles=[]),a&&this._container&&(this._container.innerHTML=""),this._initContainer()},_update:function(b){if(this._map._panTransition&&this._map._panTransition._inProgress)return;var c=this._map.getPixelBounds(),d=this._map.getZoom(),e=this.options.tileSize;if(d>this.options.maxZoom||da.max.x||da.max.y)&&this._removeTile(e))},_removeTile:function(b){var c=this._tiles[b];this.fire("tileunload",{tile:c,url:c.src}),c.parentNode===this._container&&this._container.removeChild(c),this.options.reuseTiles&&this._unusedTiles.push(c),c.src=a.Util.emptyImageUrl,delete this._tiles[b]},_addTile:function(b,c){var d=this._getTilePos(b),e=this._map.getZoom(),f=b.x+":"+b.y,g=Math.pow(2,this._getOffsetZoom(e));if(!this.options.continuousWorld){if(!this.options.noWrap)b.x=(b.x%g+g)%g;else if(b.x<0||b.x>=g){this._tilesToLoad--;return}if(b.y<0||b.y>=g){this._tilesToLoad--;return}}var h=this._getTile();a.DomUtil.setPosition(h,d),this._tiles[f]=h,this.options.scheme==="tms"&&(b.y=g-b.y-1),this._loadTile(h,b,e),c.appendChild(h)},_getOffsetZoom:function(a){var b=this.options;return a=b.zoomReverse?b.maxZoom-a:a,a+b.zoomOffset},_getTilePos:function(a){var b=this._map.getPixelOrigin(),c=this.options.tileSize;return a.multiplyBy(c).subtract(b)},getTileUrl:function(b,c){var d=this.options.subdomains,e=(b.x+b.y)%d.length,f=this.options.subdomains[e];return a.Util.template(this._url,a.Util.extend({s:f,z:this._getOffsetZoom(c),x:b.x,y:b.y},this.options))},_createTileProto:function(){var b=this._tileImg=a.DomUtil.create("img","leaflet-tile");b.galleryimg="no";var c=this.options.tileSize;b.style.width=c+"px",b.style.height=c+"px"},_getTile:function(){if(this.options.reuseTiles&&this._unusedTiles.length>0){var a=this._unusedTiles.pop();return this._resetTile(a),a}return this._createTile()},_resetTile:function(a){},_createTile:function(){var b=this._tileImg.cloneNode(!1);return b.onselectstart=b.onmousemove=a.Util.falseFn,b},_loadTile:function(a,b,c){a._layer=this,a.onload=this._tileOnLoad,a.onerror=this._tileOnError,a.src=this.getTileUrl(b,c)},_tileOnLoad:function(a){var b=this._layer;this.className+=" leaflet-tile-loaded",b.fire("tileload",{tile:this,url:this.src}),b._tilesToLoad--,b._tilesToLoad||b.fire("load")},_tileOnError:function(a){var b=this._layer;b.fire("tileerror",{tile:this,url:this.src});var c=b.options.errorTileUrl;c&&(this.src=c)}}),a.TileLayer.WMS=a.TileLayer.extend({defaultWmsParams:{service:"WMS",request:"GetMap",version:"1.1.1",layers:"",styles:"",format:"image/jpeg",transparent:!1},initialize:function(b,c){this._url=b;var d=a.Util.extend({},this.defaultWmsParams);d.width=d.height=this.options.tileSize;for(var e in c)this.options.hasOwnProperty(e)||(d[e]=c[e]);this.wmsParams=d,a.Util.setOptions(this,c)},onAdd:function(b,c){var d=parseFloat(this.wmsParams.version)<1.3?"srs":"crs";this.wmsParams[d]=b.options.crs.code,a.TileLayer.prototype.onAdd.call(this,b,c)},getTileUrl:function(b,c){var d=this._map,e=d.options.crs,f=this.options.tileSize,g=b.multiplyBy(f),h=g.add(new a.Point(f,f)),i=d.unproject(g,c,!0),j=d.unproject(h,c,!0),k=e.project(i),l=e.project(j),m=[k.x,l.y,l.x,k.y].join(",");return this._url+a.Util.getParamString(this.wmsParams)+"&bbox="+m}}),a.TileLayer.Canvas=a.TileLayer.extend({options:{async:!1},initialize:function(b){a.Util.setOptions(this,b)},redraw:function(){var a,b=this._tiles;for(a in b)b.hasOwnProperty(a)&&this._redrawTile(b[a])},_redrawTile:function(a){this.drawTile(a,a._tilePoint,a._zoom)},_createTileProto:function(){var b=this._canvasProto=a.DomUtil.create("canvas","leaflet-tile"),c=this.options.tileSize;b.width=c,b.height=c},_createTile:function(){var b=this._canvasProto.cloneNode(!1);return b.onselectstart=b.onmousemove=a.Util.falseFn,b},_loadTile:function(a,b,c){a._layer=this,a._tilePoint=b,a._zoom=c,this.drawTile(a,b,c),this.options.async||this.tileDrawn(a)},drawTile:function(a,b,c){},tileDrawn:function(a){this._tileOnLoad.call(a)}}),a.ImageOverlay=a.Class.extend({includes:a.Mixin.Events,initialize:function(a,b){this._url=a,this._bounds=b},onAdd:function(a){this._map=a,this._image||this._initImage(),a._panes.overlayPane.appendChild(this._image),a.on("viewreset",this._reset,this),this._reset()},onRemove:function(a){a.getPanes().overlayPane.removeChild(this._image),a.off("viewreset",this._reset,this)},_initImage:function(){this._image=a.DomUtil.create("img","leaflet-image-layer"),this._image.style.visibility="hidden",a.Util.extend(this._image,{galleryimg:"no",onselectstart:a.Util.falseFn,onmousemove:a.Util.falseFn,onload:a.Util.bind(this._onImageLoad,this),src:this._url})},_reset:function(){var b=this._image,c=this._map.latLngToLayerPoint(this._bounds.getNorthWest()),d=this._map.latLngToLayerPoint(this._bounds.getSouthEast()).subtract(c);a.DomUtil.setPosition(b,c),b.style.width=d.x+"px",b.style.height=d.y+"px"},_onImageLoad:function(){this._image.style.visibility="",this.fire("load")}}),a.Icon=a.Class.extend({options:{className:""},initialize:function(b){a.Util.setOptions(this,b)},createIcon:function(){return this._createIcon("icon")},createShadow:function(){return this._createIcon("shadow")},_createIcon:function(a){var b=this._getIconUrl(a);if(!b)return null;var c=this._createImg(b);return this._setIconStyles(c,a),c},_setIconStyles:function(a,b){var c=this.options,d=c[b+"Size"],e=c.iconAnchor;!e&&d&&(e=d.divideBy(2,!0)),b==="shadow"&&e&&c.shadowOffset&&e._add(c.shadowOffset),a.className="leaflet-marker-"+b+" "+c.className,e&&(a.style.marginLeft=-e.x+"px",a.style.marginTop=-e.y+"px"),d&&(a.style.width=d.x+"px",a.style.height=d.y+"px")},_createImg:function(b){var c;return a.Browser.ie6?(c=document.createElement("div"),c.style.filter='progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+b+'")'):(c=document.createElement("img"),c.src=b),c},_getIconUrl:function(a){return this.options[a+"Url"]}}),a.Icon.Default=a.Icon.extend({options:{iconSize:new a.Point(25,41),iconAnchor:new a.Point(13,41),popupAnchor:new a.Point(0,-33),shadowSize:new a.Point(41,41)},_getIconUrl:function(b){var c=a.Icon.Default.imagePath;if(!c)throw Error("Couldn't autodetect L.Icon.Default.imagePath, set it manually.");return c+"/marker-"+b+".png"}}),a.Icon.Default.imagePath=function(){var a=document.getElementsByTagName("script"),b=/\/?leaflet[\-\._]?([\w\-\._]*)\.js\??/,c,d,e,f;for(c=0,d=a.length;cd?(a.style.height=d+"px",a.className+=e):a.className=a.className.replace(e,""),this._containerWidth=this._container.offsetWidth},_updatePosition:function(){var a=this._map.latLngToLayerPoint(this._latlng);this._containerBottom=-a.y-this.options.offset.y,this._containerLeft=a.x-Math.round(this._containerWidth/2)+this.options.offset.x,this._container.style.bottom=this._containerBottom+"px",this._container.style.left=this._containerLeft+"px"},_adjustPan:function(){if(!this.options.autoPan)return;var b=this._map,c=this._container.offsetHeight,d=this._containerWidth,e=new a.Point(this._containerLeft,-c-this._containerBottom),f=b.layerPointToContainerPoint(e),g=new a.Point(0,0),h=this.options.autoPanPadding,i=b.getSize();f.x<0&&(g.x=f.x-h.x),f.x+d>i.x&&(g.x=f.x+d-i.x+h.x),f.y<0&&(g.y=f.y-h.y),f.y+c>i.y&&(g.y=f.y+c-i.y+h.y),(g.x||g.y)&&b.panBy(g)},_onCloseButtonClick:function(b){this._close(),a.DomEvent.stop(b)}}),a.Marker.include({openPopup:function(){return this._popup&&this._map&&(this._popup.setLatLng(this._latlng),this._map.openPopup(this._popup)),this},closePopup:function(){return this._popup&&this._popup._close(),this},bindPopup:function(b,c){var d=this.options.icon.options.popupAnchor||new a.Point(0,0);return c&&c.offset&&(d=d.add(c.offset)),c=a.Util.extend({offset:d},c),this._popup||this.on("click",this.openPopup,this),this._popup=(new a.Popup(c,this)).setContent(b),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this.openPopup)),this}}),a.Map.include({openPopup:function(a){return this.closePopup(),this._popup=a,this.addLayer(a).fire("popupopen",{popup:this._popup})},closePopup:function(){return this._popup&&this._popup._close(),this}}),a.LayerGroup=a.Class.extend({initialize:function(a){this._layers={};var b,c;if(a)for(b=0,c=a.length;b';var b=a.firstChild;return b.style.behavior="url(#default#VML)",b&&typeof b.adj=="object"}(),a.Path=a.Browser.svg||!a.Browser.vml?a.Path:a.Path.extend({statics:{VML:!0,CLIP_PADDING:.02},_createElement:function(){try{return document.namespaces.add("lvml","urn:schemas-microsoft-com:vml"),function(a){return document.createElement("')}}catch(a){return function(a){return document.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),_initPath:function(){var a=this._container=this._createElement("shape");a.className+=" leaflet-vml-shape"+(this.options.clickable?" leaflet-clickable":""),a.coordsize="1 1",this._path=this._createElement("path"),a.appendChild(this._path),this._map._pathRoot.appendChild(a)},_initStyle:function(){var a=this._container,b,c;this.options.stroke&&(b=this._stroke=this._createElement("stroke"),b.endcap="round",a.appendChild(b)),this.options.fill&&(c=this._fill=this._createElement("fill"),a.appendChild(c)),this._updateStyle()},_updateStyle:function(){var a=this._stroke,b=this._fill,c=this.options,d=this._container;d.stroked=c.stroke,d.filled=c.fill,c.stroke&&(a.weight=c.weight+"px",a.color=c.color,a.opacity=c.opacity),c.fill&&(b.color=c.fillColor||c.color,b.opacity=c.fillOpacity)},_updatePath:function(){var a=this._container.style;a.display="none",this._path.v=this.getPathString()+" ",a.display=""}}),a.Map.include(a.Browser.svg||!a.Browser.vml?{}:{_initPathRoot:function(){if(this._pathRoot)return;var a=this._pathRoot=document.createElement("div");a.className="leaflet-vml-container",this._panes.overlayPane.appendChild(a),this.on("moveend",this._updatePathViewport),this._updatePathViewport()}}),a.Browser.canvas=function(){return!!document.createElement("canvas").getContext}(),a.Path=a.Path.SVG&&!window.L_PREFER_CANVAS||!a.Browser.canvas?a.Path:a.Path.extend({statics:{CANVAS:!0,SVG:!1},_initElements:function(){this._map._initPathRoot(),this._ctx=this._map._canvasCtx},_updateStyle:function(){var a=this.options;a.stroke&&(this._ctx.lineWidth=a.weight,this._ctx.strokeStyle=a.color),a.fill&&(this._ctx.fillStyle=a.fillColor||a.color)},_drawPath:function(){var b,c,d,e,f,g;this._ctx.beginPath();for(b=0,d=this._parts.length;bf&&(g=h,f=i);f>c&&(b[g]=1,this._simplifyDPStep(a,b,c,d,g),this._simplifyDPStep(a,b,c,g,e))},_reducePoints:function(a,b){var c=[a[0]];for(var d=1,e=0,f=a.length;db&&(c.push(a[d]),e=d);return eb.max.x&&(c|=2),a.yb.max.y&&(c|=8),c},_sqDist:function(a,b){var c=b.x-a.x,d=b.y-a.y;return c*c+d*d},_sqClosestPointOnSegment:function(b,c,d,e){var f=c.x,g=c.y,h=d.x-f,i=d.y-g,j=h*h+i*i,k;return j>0&&(k=((b.x-f)*h+(b.y-g)*i)/j,k>1?(f=d.x,g=d.y):k>0&&(f+=h*k,g+=i*k)),h=b.x-f,i=b.y-g,e?h*h+i*i:new a.Point(f,g)}},a.Polyline=a.Path.extend({initialize:function(b,c){a.Path.prototype.initialize.call(this,c),this._latlngs=b,a.Handler.PolyEdit&&(this.editing=new a.Handler.PolyEdit(this),this.options.editable&&this.editing.enable())},options:{smoothFactor:1,noClip:!1},projectLatlngs:function(){this._originalPoints=[];for(var a=0,b=this._latlngs.length;aa.max.x||c.y-b>a.max.y||c.x+bb.y!=f.y>b.y&&b.x<(f.x-e.x)*(b.y-e.y)/(f.y-e.y)+e.x&&(c=!c)}return c}}:{}),a.Circle.include(a.Path.CANVAS?{_drawPath:function(){var a=this._point;this._ctx.beginPath(),this._ctx.arc(a.x,a.y,this._radius,0,Math.PI*2,!1)},_containsPoint:function(a){var b=this._point,c=this.options.stroke?this.options.weight/2:0;return a.distanceTo(b)<=this._radius+c}}:{}),a.GeoJSON=a.FeatureGroup.extend({initialize:function(b,c){a.Util.setOptions(this,c),this._geojson=b,this._layers={},b&&this.addGeoJSON(b)},addGeoJSON:function(b){var c=b.features,d,e;if(c){for(d=0,e=c.length;d1){this._simulateClick=!1;return}var c=b.touches&&b.touches.length===1?b.touches[0]:b,d=c.target;a.DomEvent.preventDefault(b),a.Browser.touch&&d.tagName.toLowerCase()==="a"&&(d.className+=" leaflet-active"),this._moved=!1;if(this._moving)return;a.Browser.touch||(a.DomUtil.disableTextSelection(),this._setMovingCursor()),this._startPos=this._newPos=a.DomUtil.getPosition(this._element),this._startPoint=new a.Point(c.clientX,c.clientY),a.DomEvent.addListener(document,a.Draggable.MOVE,this._onMove,this),a.DomEvent.addListener(document,a.Draggable.END,this._onUp,this)},_onMove:function(b){if(b.touches&&b.touches.length>1)return;a.DomEvent.preventDefault(b);var c=b.touches&&b.touches.length===1?b.touches[0]:b;this._moved||(this.fire("dragstart"),this._moved=!0),this._moving=!0;var d=new a.Point(c.clientX,c.clientY);this._newPos=this._startPos.add(d).subtract(this._startPoint),a.Util.cancelAnimFrame(this._animRequest),this._animRequest=a.Util.requestAnimFrame(this._updatePosition,this,!0,this._dragStartTarget)},_updatePosition:function(){this.fire("predrag"),a.DomUtil.setPosition(this._element,this._newPos),this.fire("drag")},_onUp:function(b){if(this._simulateClick&&b.changedTouches){var c=b.changedTouches[0],d=c.target,e=this._newPos&&this._newPos.distanceTo(this._startPos)||0;d.tagName.toLowerCase()==="a"&&(d.className=d.className.replace(" leaflet-active","")),e200&&(this._positions.shift(),this._times.shift())}this._map.fire("move").fire("drag")},_onViewReset:function(){var b=this._map.getSize().divideBy(2),c=this._map.latLngToLayerPoint(new a.LatLng(0,0));this._initialWorldOffset=c.subtract(b)},_onPreDrag:function(){var a=this._map,b=a.options.crs.scale(a.getZoom()),c=Math.round(b/2),d=this._initialWorldOffset.x,e=this._draggable._newPos.x,f=(e-c+d)%b+c-d,g=(e+c+d)%b-c-d,h=Math.abs(f+d)c.inertiaThreshold||typeof this._positions[0]=="undefined";if(e)b.fire("moveend");else{var f=this._lastPos.subtract(this._positions[0]),g=(this._lastTime+d-this._times[0])/1e3,h=f.multiplyBy(.58/g),i=h.distanceTo(new a.Point(0,0)),j=Math.min(c.inertiaMaxSpeed,i),k=h.multiplyBy(j/i),l=j/c.inertiaDeceleration,m=k.multiplyBy(-l/2).round(),n={duration:l,easing:"ease-out"};a.Util.requestAnimFrame(a.Util.bind(function(){this._map.panBy(m,n)},this))}b.fire("dragend"),c.maxBounds&&a.Util.requestAnimFrame(this._panInsideMaxBounds,b,!0,b._container)},_panInsideMaxBounds:function(){this.panInsideBounds(this.options.maxBounds)}}),a.Map.addInitHook("addHandler","dragging",a.Map.Drag),a.Map.mergeOptions({doubleClickZoom:!0}),a.Map.DoubleClickZoom=a.Handler.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick)},_onDoubleClick:function(a){this.setView(a.latlng,this._zoom+1)}}),a.Map.addInitHook("addHandler","doubleClickZoom",a.Map.DoubleClickZoom),a.Map.mergeOptions({scrollWheelZoom:!a.Browser.touch}),a.Map.ScrollWheelZoom=a.Handler.extend({addHooks:function(){a.DomEvent.addListener(this._map._container,"mousewheel",this._onWheelScroll,this),this._delta=0},removeHooks:function(){a.DomEvent.removeListener(this._map._container,"mousewheel",this._onWheelScroll)},_onWheelScroll:function(b){var c=a.DomEvent.getWheelDelta(b);this._delta+=c,this._lastMousePos=this._map.mouseEventToContainerPoint(b),clearTimeout(this._timer),this._timer=setTimeout(a.Util.bind(this._performZoom,this),50),a.DomEvent.preventDefault(b)},_performZoom:function(){var a=this._map,b=Math.round(this._delta),c=a.getZoom();b=Math.max(Math.min(b,4),-4),b=a._limitZoom(c+b)-c,this._delta=0;if(!b)return;var d=this._getCenterForScrollWheelZoom(this._lastMousePos,b),e=c+b;a.setView(d,e)},_getCenterForScrollWheelZoom:function(a,b){var c=this._map,d=c.getPixelBounds().getCenter(),e=c.getSize().divideBy(2),f=a.subtract(e).multiplyBy(1-Math.pow(2,-b)),g=d.add(f);return c.unproject(g,c._zoom,!0)}}),a.Map.addInitHook("addHandler","scrollWheelZoom",a.Map.ScrollWheelZoom),a.Util.extend(a.DomEvent,{addDoubleTapListener:function(a,b,c){function k(a){if(a.touches.length!==1)return;var b=Date.now(),c=b-(d||b);g=a.touches[0],e=c>0&&c<=f,d=b}function l(a){e&&(g.type="dblclick",b(g),d=null)}var d,e=!1,f=250,g,h="_leaflet_",i="touchstart",j="touchend";a[h+i+c]=k,a[h+j+c]=l,a.addEventListener(i,k,!1),a.addEventListener(j,l,!1)},removeDoubleTapListener:function(a,b){var c="_leaflet_";a.removeEventListener(a,a[c+"touchstart"+b],!1),a.removeEventListener(a,a[c+"touchend"+b],!1)}}),a.Map.mergeOptions({touchZoom:a.Browser.touch&&!a.Browser.android}),a.Map.TouchZoom=a.Handler.extend({addHooks:function(){a.DomEvent.addListener(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){a.DomEvent.removeListener(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(b){var c=this._map;if(!b.touches||b.touches.length!==2||c._animatingZoom||this._zooming)return;var d=c.mouseEventToLayerPoint(b.touches[0]),e=c.mouseEventToLayerPoint(b.touches[1]),f=c.containerPointToLayerPoint(c.getSize().divideBy(2));this._startCenter=d.add(e).divideBy(2,!0),this._startDist=d.distanceTo(e),this._moved=!1,this._zooming=!0,this._centerOffset=f.subtract(this._startCenter),a.DomEvent.addListener(document,"touchmove",this._onTouchMove,this).addListener(document,"touchend",this._onTouchEnd,this),a.DomEvent.preventDefault(b)},_onTouchMove:function(b){if(!b.touches||b.touches.length!==2)return;var c=this._map,d=c.mouseEventToLayerPoint(b.touches[0]),e=c.mouseEventToLayerPoint(b.touches[1]);this._scale=d.distanceTo(e)/this._startDist,this._delta=d.add(e).divideBy(2,!0).subtract(this._startCenter);if(this._scale===1)return;this._moved||(c._mapPane.className+=" leaflet-zoom-anim",c.fire("zoomstart").fire("movestart")._prepareTileBg(),this._moved=!0),c._tileBg.style.webkitTransform=a.DomUtil.getTranslateString(this._delta)+" "+a.DomUtil.getScaleString(this._scale,this._startCenter),a.DomEvent.preventDefault(b)},_onTouchEnd:function(b){if(!this._moved||!this._zooming)return;this._zooming=!1,a.DomEvent.removeListener(document,"touchmove",this._onTouchMove).removeListener(document,"touchend",this._onTouchEnd);var c=this._centerOffset.subtract(this._delta).divideBy(this._scale),d=this._map.getPixelOrigin().add(this._startCenter).add(c),e=this._map.unproject(d),f=this._map.getZoom(),g=Math.log(this._scale)/Math.LN2,h=g>0?Math.ceil(g):Math.floor(g),i=this._map._limitZoom(f+h),j=Math.pow(2,i-f);this._map._runAnimation(e,i,j/this._scale,this._startCenter.add(c))}}),a.Map.addInitHook("addHandler","touchZoom",a.Map.TouchZoom),a.Map.mergeOptions({boxZoom:!0}),a.Map.BoxZoom=a.Handler.extend({initialize:function(a){this._map=a,this._container=a._container,this._pane=a._panes.overlayPane},addHooks:function(){a.DomEvent.addListener(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){a.DomEvent.removeListener(this._container,"mousedown",this._onMouseDown)},_onMouseDown:function(b){if(!b.shiftKey||b.which!==1&&b.button!==1)return!1;a.DomUtil.disableTextSelection(),this._startLayerPoint=this._map.mouseEventToLayerPoint(b),this._box=a.DomUtil.create("div","leaflet-zoom-box",this._pane),a.DomUtil.setPosition(this._box,this._startLayerPoint),this._container.style.cursor="crosshair",a.DomEvent.addListener(document,"mousemove",this._onMouseMove,this).addListener(document,"mouseup",this._onMouseUp,this).preventDefault(b),this._map.fire("boxzoomstart")},_onMouseMove:function(b){var c=this._startLayerPoint,d=this._box,e=this._map.mouseEventToLayerPoint(b),f=e.subtract(c),g=new a.Point(Math.min(e.x,c.x),Math.min(e.y,c.y));a.DomUtil.setPosition(d,g),d.style.width=Math.abs(f.x)-4+"px",d.style.height=Math.abs(f.y)-4+"px"},_onMouseUp:function(b){this._pane.removeChild(this._box),this._container.style.cursor="",a.DomUtil.enableTextSelection(),a.DomEvent.removeListener(document,"mousemove",this._onMouseMove).removeListener(document,"mouseup",this._onMouseUp);var c=this._map,d=c.mouseEventToLayerPoint(b),e=new a.LatLngBounds(c.layerPointToLatLng(this._startLayerPoint),c.layerPointToLatLng(d));c.fitBounds(e),c.fire("boxzoomend",{boxZoomBounds:e})}}),a.Map.addInitHook("addHandler","boxZoom",a.Map.BoxZoom),a.Handler.MarkerDrag=a.Handler.extend({initialize:function(a){this._marker=a},addHooks:function(){var b=this._marker._icon;this._draggable||(this._draggable=(new a.Draggable(b,b)).on("dragstart",this._onDragStart,this).on("drag",this._onDrag,this).on("dragend",this._onDragEnd,this)),this._draggable.enable()},removeHooks:function(){this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(a){this._marker.closePopup().fire("movestart").fire("dragstart")},_onDrag:function(b){var c=a.DomUtil.getPosition(this._marker._icon);this._marker._shadow&&a.DomUtil.setPosition(this._marker._shadow,c),this._marker._latlng=this._marker._map.layerPointToLatLng(c),this._marker.fire("move").fire("drag")},_onDragEnd:function(){this._marker.fire("moveend").fire("dragend")}}),a.Handler.PolyEdit=a.Handler.extend({options:{icon:new a.DivIcon({iconSize:new a.Point(8,8),className:"leaflet-div-icon leaflet-editing-icon"})},initialize:function(b,c){this._poly=b,a.Util.setOptions(this,c)},addHooks:function(){this._poly._map&&(this._markerGroup||this._initMarkers(),this._poly._map.addLayer(this._markerGroup))},removeHooks:function(){this._poly._map&&(this._poly._map.removeLayer(this._markerGroup),delete this._markerGroup,delete this._markers)},updateMarkers:function(){this._markerGroup.clearLayers(),this._initMarkers()},_initMarkers:function(){this._markerGroup=new a.LayerGroup,this._markers=[];var b=this._poly._latlngs,c,d,e,f;for(c=0,e=b.length;ca&&(c._index+=b)})},_createMiddleMarker:function(a,b){var c=this._getMiddleLatLng(a,b),d=this._createMarker(c),e,f,g;d.setOpacity(.6),a._middleRight=b._middleLeft=d,f=function(){var f=b._index;d._index=f,d.off("click",e).on("click",this._onMarkerClick,this),this._poly.spliceLatLngs(f,0,c),this._markers.splice(f,0,d),d.setOpacity(1),this._updateIndexes(f,1),b._index++,this._updatePrevNext(a,d),this._updatePrevNext(d,b)},g=function(){d.off("dragstart",f,this),d.off("dragend",g,this),this._createMiddleMarker(a,d),this._createMiddleMarker(d,b)},e=function(){f.call(this),g.call(this),this._poly.fire("edit")},d.on("click",e,this).on("dragstart",f,this).on("dragend",g,this),this._markerGroup.addLayer(d)},_updatePrevNext:function(a,b){a._next=b,b._prev=a},_getMiddleLatLng:function(a,b){var c=this._poly._map,d=c.latLngToLayerPoint(a.getLatLng()),e=c.latLngToLayerPoint(b.getLatLng());return c.layerPointToLatLng(d._add(e).divideBy(2))}}),a.Control=a.Class.extend({options:{position:"topright"},initialize:function(b){a.Util.setOptions(this,b)},getPosition:function(){return this.options.position},setPosition:function(a){var b=this._map;b&&b.removeControl(this),this.options.position=a,b&&b.addControl(this)},addTo:function(b){this._map=b;var c=this._container=this.onAdd(b),d=this.getPosition(),e=b._controlCorners[d];return a.DomUtil.addClass(c,"leaflet-control"),d.indexOf("bottom")!==-1?e.insertBefore(c,e.firstChild):e.appendChild(c),this},removeFrom:function(a){var b=this.getPosition(),c=a._controlCorners[b];return c.removeChild(this._container),this._map=null,this.onRemove&&this.onRemove(a),this}}),a.Map.include({addControl:function(a){return a.addTo(this),this},removeControl:function(a){return a.removeFrom(this),this},_initControlPos:function(){function e(e,f){var g=c+e+" "+c+f;b[e+f]=a.DomUtil.create("div",g,d)}var b=this._controlCorners={},c="leaflet-",d=this._controlContainer=a.DomUtil.create("div",c+"control-container",this._container);e("top","left"),e("top","right"),e("bottom","left"),e("bottom","right")}}),a.Control.Zoom=a.Control.extend({options:{position:"topleft"},onAdd:function(b){var c="leaflet-control-zoom",d=a.DomUtil.create("div",c);return this._createButton("Zoom in",c+"-in",d,b.zoomIn,b),this._createButton("Zoom out",c+"-out",d,b.zoomOut,b),d},_createButton:function(b,c,d,e,f){var g=a.DomUtil.create("a",c,d);return g.href="#",g.title=b,a.DomEvent.addListener(g,"click",a.DomEvent.stopPropagation).addListener(g,"click",a.DomEvent.preventDefault).addListener(g,"click",e,f),g}}),a.Map.mergeOptions({zoomControl:!0}),a.Map.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new a.Control.Zoom,this.addControl(this.zoomControl))}),a.Control.Attribution=a.Control.extend({options:{position:"bottomright",prefix:'Powered by Leaflet'},initialize:function(b){a.Util.setOptions(this,b),this._attributions={}},onAdd:function(b){return this._container=a.DomUtil.create("div","leaflet-control-attribution"),a.DomEvent.disableClickPropagation(this._container),b.on("layeradd",this._onLayerAdd,this).on("layerremove",this._onLayerRemove,this),this._update(),this._container},onRemove:function(a){a.off("layeradd",this._onLayerAdd).off("layerremove",this._onLayerRemove)},setPrefix:function(a){this.options.prefix=a,this._update()},addAttribution:function(a){if(!a)return;this._attributions[a]||(this._attributions[a]=0),this._attributions[a]++,this._update()},removeAttribution:function(a){if(!a)return;this._attributions[a]--,this._update()},_update:function(){if(!this._map)return;var a=[];for(var b in this._attributions)this._attributions.hasOwnProperty(b)&&this._attributions[b]&&a.push(b);var c=[];this.options.prefix&&c.push(this.options.prefix),a.length&&c.push(a.join(", ")),this._container.innerHTML=c.join(" — ")},_onLayerAdd:function(a){a.layer.getAttribution&&this.addAttribution(a.layer.getAttribution())},_onLayerRemove:function(a){a.layer.getAttribution&&this.removeAttribution(a.layer.getAttribution())}}),a.Map.mergeOptions({attributionControl:!0}),a.Map.addInitHook(function(){this.options.attributionControl&&(this.attributionControl=(new a.Control.Attribution).addTo(this))}),a.Control.Scale=a.Control.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0,updateWhenIdle:!1},onAdd:function(b){this._map=b;var c="leaflet-control-scale",d=a.DomUtil.create("div",c),e=this.options;return e.metric&&(this._mScale=a.DomUtil.create("div",c+"-line",d)),e.imperial&&(this._iScale=a.DomUtil.create("div",c+"-line",d)),b.on(e.updateWhenIdle?"moveend":"move",this._update,this),this._update(),d},onRemove:function(a){a.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_update:function(){var b=this._map.getBounds(),c=b.getCenter().lat,d=new a.LatLng(c,b.getSouthWest().lng),e=new a.LatLng(c,b.getNorthEast().lng),f=this._map.getSize(),g=this.options,h=d.distanceTo(e)*(g.maxWidth/f.x);g.metric&&this._updateMetric(h),g.imperial&&this._updateImperial(h)},_updateMetric:function(a){var b=this._getRoundNum(a);this._mScale.style.width=this._getScaleWidth(b/a)+"px",this._mScale.innerHTML=b<1e3?b+" m":b/1e3+" km"},_updateImperial:function(a){var b=a*3.2808399,c=this._iScale,d,e,f;b>5280?(d=b/5280,e=this._getRoundNum(d),c.style.width=this._getScaleWidth(e/d)+"px",c.innerHTML=e+" mi"):(f=this._getRoundNum(b),c.style.width=this._getScaleWidth(f/b)+"px",c.innerHTML=f+" ft")},_getScaleWidth:function(a){return Math.round(this.options.maxWidth*a)-10},_getRoundNum:function(a){var b=Math.pow(10,(Math.floor(a)+"").length-1),c=a/b;return c=c<10?c<5?c<2?1:2:5:10,b*c}}),a.Control.Layers=a.Control.extend({options:{collapsed:!0,position:"topright"},initialize:function(b,c,d){a.Util.setOptions(this,d),this._layers={};for(var e in b)b.hasOwnProperty(e)&&this._addLayer(b[e],e);for(e in c)c.hasOwnProperty(e)&&this._addLayer(c[e],e,!0)},onAdd:function(a){return this._initLayout(),this._update(),this._container},addBaseLayer:function(a,b){return this._addLayer(a,b),this._update(),this},addOverlay:function(a,b){return this._addLayer(a,b,!0),this._update(),this},removeLayer:function(b){var c=a.Util.stamp(b);return delete this._layers[c],this._update(),this},_initLayout:function(){var b="leaflet-control-layers",c=this._container=a.DomUtil.create("div",b);a.Browser.touch?a.DomEvent.addListener(c,"click",a.DomEvent.stopPropagation):a.DomEvent.disableClickPropagation(c);var d=this._form=a.DomUtil.create("form",b+"-list");if(this.options.collapsed){a.DomEvent.addListener(c,"mouseover",this._expand,this).addListener(c,"mouseout",this._collapse,this);var e=this._layersLink=a.DomUtil.create("a",b+"-toggle",c);e.href="#",e.title="Layers",a.DomEvent.addListener(e,a.Browser.touch?"click":"focus",this._expand,this),this._map.on("movestart",this._collapse,this)}else this._expand();this._baseLayersList=a.DomUtil.create("div",b+"-base",d),this._separator=a.DomUtil.create("div",b+"-separator",d),this._overlaysList=a.DomUtil.create("div",b+"-overlays",d),c.appendChild(d)},_addLayer:function(b,c,d){var e=a.Util.stamp(b);this._layers[e]={layer:b,name:c,overlay:d}},_update:function(){if(!this._container)return;this._baseLayersList.innerHTML="",this._overlaysList.innerHTML="";var a=!1,b=!1;for(var c in this._layers)if(this._layers.hasOwnProperty(c)){var d=this._layers[c];this._addItem(d),b=b||d.overlay,a=a||!d.overlay}this._separator.style.display=b&&a?"":"none"},_addItem:function(b,c){var d=document.createElement("label"),e=document.createElement("input");b.overlay||(e.name="leaflet-base-layers"),e.type=b.overlay?"checkbox":"radio",e.checked=this._map.hasLayer(b.layer),e.layerId=a.Util.stamp(b.layer),a.DomEvent.addListener(e,"click",this._onInputClick,this);var f=document.createTextNode(" "+b.name);d.appendChild(e),d.appendChild(f);var g=b.overlay?this._overlaysList:this._baseLayersList;g.appendChild(d)},_onInputClick:function(){var a,b,c,d=this._form.getElementsByTagName("input"),e=d.length;for(a=0;a3.1.0
1.7.13
1.12.1
+ 3.17.0
nunaliit2-jdbc