Support formats that read ArrayBuffer sources

Drag-and-Drop support for formats that read arraybuffer sources
Add TextDecoder to polyfills
Add custom Drag-and-Drop examples for KMZ and MVT
Add sample download and KML styles option to existing example
Test arraybuffer and constructed formats
This commit is contained in:
mike-000
2020-11-06 16:22:34 +00:00
parent bdd343e87b
commit a6860118c7
17 changed files with 5280 additions and 34 deletions

View File

@@ -2,6 +2,7 @@ import DragAndDrop from '../../../../src/ol/interaction/DragAndDrop.js';
import Event from '../../../../src/ol/events/Event.js';
import EventTarget from '../../../../src/ol/events/Target.js';
import GeoJSON from '../../../../src/ol/format/GeoJSON.js';
import MVT from '../../../../src/ol/format/MVT.js';
import VectorSource from '../../../../src/ol/source/Vector.js';
import View from '../../../../src/ol/View.js';
@@ -29,8 +30,8 @@ where('FileReader').describe('ol.interaction.DragAndDrop', function () {
expect(interaction).to.be.an(DragAndDrop);
});
it('sets formatConstructors on the instance', function () {
expect(interaction.formatConstructors_).to.have.length(1);
it('sets formats on the instance', function () {
expect(interaction.formats_).to.have.length(1);
});
it('accepts a source option', function () {
@@ -88,18 +89,28 @@ where('FileReader').describe('ol.interaction.DragAndDrop', function () {
describe('#handleDrop_', function () {
let OrigFileReader;
let mockReadAsText;
let mockReadAsArrayBuffer;
beforeEach(function () {
OrigFileReader = FileReader;
mockReadAsText = false;
mockReadAsArrayBuffer = false;
class MockFileReader extends EventTarget {
constructor() {
super(...arguments);
}
readAsText(file) {
mockReadAsText = true;
this.result = file;
this.dispatchEvent('load');
}
readAsArrayBuffer(file) {
mockReadAsArrayBuffer = true;
this.result = new TextEncoder().encode(file).buffer;
this.dispatchEvent('load');
}
}
FileReader = MockFileReader;
});
@@ -108,9 +119,11 @@ where('FileReader').describe('ol.interaction.DragAndDrop', function () {
FileReader = OrigFileReader;
});
it('reads dropped files', function (done) {
it('reads dropped files as text', function (done) {
interaction.on('addfeatures', function (evt) {
expect(evt.features.length).to.be(1);
expect(mockReadAsText).to.be(true);
expect(mockReadAsArrayBuffer).to.be(false);
done();
});
interaction.setMap(map);
@@ -135,6 +148,121 @@ where('FileReader').describe('ol.interaction.DragAndDrop', function () {
expect(event.propagationStopped).to.be(true);
});
it('reads dropped files as arraybuffer', function (done) {
const drop = new DragAndDrop({
formatConstructors: [GeoJSON, MVT],
});
drop.setMap(map);
drop.on('addfeatures', function (evt) {
expect(evt.features.length).to.be(1);
expect(mockReadAsText).to.be(false);
expect(mockReadAsArrayBuffer).to.be(true);
done();
});
const event = new Event();
event.dataTransfer = {};
event.type = 'dragenter';
viewport.dispatchEvent(event);
event.type = 'dragover';
viewport.dispatchEvent(event);
event.type = 'drop';
event.dataTransfer.files = {
length: 1,
item: function () {
return JSON.stringify({
type: 'FeatureCollection',
features: [{type: 'Feature', id: '1'}],
});
},
};
viewport.dispatchEvent(event);
expect(event.dataTransfer.dropEffect).to.be('copy');
expect(event.propagationStopped).to.be(true);
});
it('reads using constructed formats', function (done) {
const drop = new DragAndDrop({
formatConstructors: [new GeoJSON()],
});
drop.setMap(map);
drop.on('addfeatures', function (evt) {
expect(evt.features.length).to.be(1);
expect(mockReadAsText).to.be(true);
expect(mockReadAsArrayBuffer).to.be(false);
done();
});
const event = new Event();
event.dataTransfer = {};
event.type = 'dragenter';
viewport.dispatchEvent(event);
event.type = 'dragover';
viewport.dispatchEvent(event);
event.type = 'drop';
event.dataTransfer.files = {
length: 1,
item: function () {
return JSON.stringify({
type: 'FeatureCollection',
features: [{type: 'Feature', id: '1'}],
});
},
};
viewport.dispatchEvent(event);
expect(event.dataTransfer.dropEffect).to.be('copy');
expect(event.propagationStopped).to.be(true);
});
it('reads using arraybuffer formats', function (done) {
class binaryGeoJSON extends GeoJSON {
constructor(options) {
super(options);
}
getType() {
return 'arraybuffer';
}
readFeatures(source, options) {
const data = new TextDecoder().decode(source);
return super.readFeatures(data, options);
}
}
const drop = new DragAndDrop({
formatConstructors: [binaryGeoJSON],
});
drop.setMap(map);
drop.on('addfeatures', function (evt) {
expect(evt.features.length).to.be(1);
expect(mockReadAsText).to.be(false);
expect(mockReadAsArrayBuffer).to.be(true);
done();
});
const event = new Event();
event.dataTransfer = {};
event.type = 'dragenter';
viewport.dispatchEvent(event);
event.type = 'dragover';
viewport.dispatchEvent(event);
event.type = 'drop';
event.dataTransfer.files = {
length: 1,
item: function () {
return JSON.stringify({
type: 'FeatureCollection',
features: [{type: 'Feature', id: '1'}],
});
},
};
viewport.dispatchEvent(event);
expect(event.dataTransfer.dropEffect).to.be('copy');
expect(event.propagationStopped).to.be(true);
});
it('adds dropped features to a source', function (done) {
const source = new VectorSource();
const drop = new DragAndDrop({