2014-01-27 14:10:53 +01:00

173 lines
5.4 KiB
JavaScript
Executable File

/*
* Load files *locally* (GeoJSON, KML, GPX) into the map
* using the HTML5 File API.
*
* Requires Pavel Shramov's GPX.js
* https://github.com/shramov/leaflet-plugins/blob/d74d67/layer/vector/GPX.js
*/
var FileLoader = L.Class.extend({
includes: L.Mixin.Events,
options: {
layerOptions: {}
},
initialize: function (map, options) {
this._map = map;
L.Util.setOptions(this, options);
this._parsers = {
'geojson': this._loadGeoJSON,
'gpx': this._convertToGeoJSON,
'kml': this._convertToGeoJSON
};
},
load: function (file /* File */) {
// Check file extension
var ext = file.name.split('.').pop(),
parser = this._parsers[ext];
if (!parser) {
window.alert("Unsupported file type " + file.type + '(' + ext + ')');
return;
}
// Read selected file using HTML5 File API
var reader = new FileReader();
reader.onload = L.Util.bind(function (e) {
this.fire('data:loading', {filename: file.name, format: ext});
var layer = parser.call(this, e.target.result, ext);
this.fire('data:loaded', {layer: layer, filename: file.name, format: ext});
}, this);
reader.readAsText(file);
},
_loadGeoJSON: function (content) {
if (typeof content == 'string') {
content = JSON.parse(content);
}
return L.geoJson(content, L.Util.extend({}, this.options.layerOptions, {
style: function (feature) {
return feature.properties && feature.properties.style;
}
})).addTo(this._map);
},
_convertToGeoJSON: function (content, format) {
// Format is either 'gpx' or 'kml'
if (typeof content == 'string') {
content = ( new window.DOMParser() ).parseFromString(content, "text/xml");
}
var geojson = toGeoJSON[format](content);
return this._loadGeoJSON(geojson);
}
});
L.Control.FileLayerLoad = L.Control.extend({
statics: {
TITLE: 'Load local file (GPX, KML, GeoJSON)',
LABEL: '⌅'
},
options: {
position: 'topleft',
fitBounds: true,
layerOptions: {}
},
initialize: function (options) {
L.Util.setOptions(this, options);
this.loader = null;
},
onAdd: function (map) {
this.loader = new FileLoader(map, {layerOptions: this.options.layerOptions});
this.loader.on('data:loaded', function (e) {
// Fit bounds after loading
if (this.options.fitBounds) {
window.setTimeout(function () {
map.fitBounds(e.layer.getBounds()).zoomOut();
}, 500);
}
}, this);
// Initialize Drag-and-drop
this._initDragAndDrop(map);
// Initialize map control
return this._initContainer();
},
_initDragAndDrop: function (map) {
var fileLoader = this.loader,
dropbox = map._container;
var callbacks = {
dragenter: function () {
map.scrollWheelZoom.disable();
},
dragleave: function () {
map.scrollWheelZoom.enable();
},
dragover: function (e) {
e.stopPropagation();
e.preventDefault();
},
drop: function (e) {
e.stopPropagation();
e.preventDefault();
var files = Array.prototype.slice.apply(e.dataTransfer.files),
i = files.length;
setTimeout(function(){
fileLoader.load(files.shift());
if (files.length > 0) {
setTimeout(arguments.callee, 25);
}
}, 25);
map.scrollWheelZoom.enable();
}
};
for (var name in callbacks)
dropbox.addEventListener(name, callbacks[name], false);
},
_initContainer: function () {
// Create an invisible file input
var fileInput = L.DomUtil.create('input', 'hidden', container);
fileInput.type = 'file';
fileInput.accept = '.gpx,.kml,.geojson';
fileInput.style.display = 'none';
// Load on file change
var fileLoader = this.loader;
fileInput.addEventListener("change", function (e) {
fileLoader.load(this.files[0]);
}, false);
// Create a button, and bind click on hidden file input
var zoomName = 'leaflet-control-filelayer leaflet-control-zoom',
barName = 'leaflet-bar',
partName = barName + '-part',
container = L.DomUtil.create('div', zoomName + ' ' + barName);
var link = L.DomUtil.create('a', zoomName + '-in ' + partName, container);
link.innerHTML = L.Control.FileLayerLoad.LABEL;
link.href = '#';
link.title = L.Control.FileLayerLoad.TITLE;
var stop = L.DomEvent.stopPropagation;
L.DomEvent
.on(link, 'click', stop)
.on(link, 'mousedown', stop)
.on(link, 'dblclick', stop)
.on(link, 'click', L.DomEvent.preventDefault)
.on(link, 'click', function (e) {
fileInput.click();
e.preventDefault();
});
return container;
}
});
L.Control.fileLayerLoad = function (options) {
return new L.Control.FileLayerLoad(options);
};