In this book, we demonstrated many ways to add features to the map, such as with the Reading features directly using AJAX recipe in Chapter 3, Working with Vector Layers. We also saw an example of exporting features from a vector layer in the GeoJSON format and displaying the result inside a textbox in the Exporting features as GeoJSON recipe in Chapter 3, Working with Vector Layers. For this recipe, we'll show you how to import a file containing GeoJSON to the map by dragging a file from your computer and dropping it in the web application.
Dragging and dropping is a part of the HTML5 API, an ability, which now has good cross browser support. To read more about the specifications, refer to https://html.spec.whatwg.org/multipage/interaction.html#dnd. For a quick run down of browser support, refer to http://caniuse.com/#search=drag.
Although there are alternative ways that you can import a file from the user's computer to the map, it's convenient to handle the file import client-side in the browser. For this recipe, the user will be able to drag a file from their computer to the map view. On doing this, they'll be prompted as to whether or not they'd like to proceed with the import, where they can decide to cancel or continue. They'll be shown some details of the import in a modal.
The source code can be found in ch07/ch07-drag-and-drop-import, and here's a screenshot of the stage when the user has dragged a file on the map:

For the modal effect in the screenshot, we used the Bootstrap CSS and JavaScript library. Please download a copy at http://getbootstrap.com/getting-started or view the accompanying source code for copies of the dependencies.
Bootstrap has its own dependency, jQuery. So, we'll need to pull this in the HTML file too.
div element to hold the map. As mentioned in the Getting ready section of this recipe, include the Bootstrap CSS and JavaScript dependencies. In particular, some of the markup for the modal is as follows:<div class="modal-body"> <p>You're about to import <code id="js-filename"></code> which contains <mark><strong id="js-count"></strong></mark> features.</p> <p>Would you like to proceed?</p> </div> <div class="modal-footer"> <button type="button" data-dismiss="modal">Cancel</button> <button id="js-confirmed" type="button" data-dismiss="modal">OK</button> </div>
map instance with a view instance and a raster layer:var map = new ol.Map({
view: new ol.View({
zoom: 6, center: [13484714, -266612]
}), target: 'js-map',
layers: [
new ol.layer.Tile({source: new ol.source.OSM()})
]
});map:var dragDrop = new ol.interaction.DragAndDrop({
formatConstructors: [ol.format.GeoJSON]
});
map.addInteraction(dragDrop);click event on the OK modal button and add the imported features to a new vector layer:$('#js-confirmed').on('click', function() {
var vectorSource = new ol.source.Vector({
features: featuresToImport
});
map.addLayer(new ol.layer.Vector({
source: vectorSource
}));
map.getView().fit(
vectorSource.getExtent(),
map.getSize()
);
});addfeatures event from the interaction, update some values for display in the modal, and then present the modal onscreen:var featuresToImport;
dragDrop.on('addfeatures', function(event) {
featuresToImport = event.features;
$('#js-filename').text(event.file.name);
$('#js-count').text(featuresToImport.length);
$('#js-modal').modal();
});Some of the HTML has been omitted for brevity, so please view the accompanying source code for full details of the implementation.
Let's take a look at the newly introduced OpenLayers interaction and the supporting logic:
var dragDrop = new ol.interaction.DragAndDrop({
formatConstructors: [ol.format.GeoJSON]
});
map.addInteraction(dragDrop);We've instantiated a new instance of the DragAndDrop interaction from OpenLayers. Behind the scenes, when the ol.interaction.DragAndDrop interaction is added to the map, OpenLayers uses the Google Closure library to construct a handler for drag and drop events detected from the map's viewport with the goog.events.FileDropHandler constructor. This constructor takes a single argument of the element to listen for drag and drop event types. OpenLayers passes in the map's div element to the constructor (map.getViewport()).
The formatConstructors property takes an array of file format types you wish to accept. Note that you're passing in the format constructor here without calling it. OpenLayers will call the format constructor for you as part of the underlying interaction code when it's processing the imported file.
$('#js-confirmed').on('click', function() {
var vectorSource = new ol.source.Vector({
features: featuresToImport
});
map.addLayer(new ol.layer.Vector({
source: vectorSource
}));
map.getView().fit(
vectorSource.getExtent(),
map.getSize()
);
});We subscribe to the click event on the modal OK button. Our handler creates a new vector source and assigns the featuresToImport value to the features property. The featuresToImport variable is populated in the addfeatures interaction event handler, which we'll discuss momentarily.
A new vector layer is then created with the new source from earlier and then added to the map.
For user convenience, we recenter the map to the extent of the newly imported features. The fit method from ol.View takes a first argument of extent, which we derive from the vector source. The second argument is the size (width, height) which we fit the extent into. We provide the total size of the map for these dimensions, as we want it to make use of all the available space.
dragDrop.on('addfeatures', function(event) {
featuresToImport = event.features;
$('#js-filename').text(event.file.name);
$('#js-count').text(featuresToImport.length);
$('#js-modal').modal();
});OpenLayers loops over the list of files that have been dropped on the map's viewport, creates an array of features from the file, and dispatches the ol.interaction.DragAndDropEventType.ADD_FEATURES event, which we subscribe to. The event object contains the list of features and also some other information, such as the name of the file.
We store the features in the featuresToImport variable, as it's referenced in the modal OK click handler. The name of the file (event.file.name) is inserted in the DOM, as well as the calculated length of the features to be imported. These values form a part of the modal content.
Finally, we trigger the Bootstrap modal to be displayed. If the user exits the modal without clicking on OK, the features are not imported. However, if they click on OK, the logic in the click event handler executes, adding the features to a new vector layer.