Skip to content

Commit

Permalink
"data" event revamp (#3590)
Browse files Browse the repository at this point in the history
* Add *data and *dataloading events

* Remove "tile" data events, make them all "source" data events

* Add MapDataEvent#isSourceLoaded and MapDataEvent#source properties

* Restore the tile data type

* Update map.js

* Refactored to reduce diff size
  • Loading branch information
Lucas Wojciechowski committed Nov 23, 2016
1 parent 95b440d commit 25950e6
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 27 deletions.
1 change: 0 additions & 1 deletion js/source/image_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ class ImageSource extends Evented {
}

_finishLoading() {
this.fire('data', {dataType: 'source'});
this.fire('source.load');

if (this.map) {
Expand Down
6 changes: 3 additions & 3 deletions js/source/source_cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class SourceCache extends Evented {

tile.sourceCache = this;
tile.timeAdded = new Date().getTime();
this._source.fire('data', {tile: tile, dataType: 'tile'});
this._source.fire('data', {tile: tile, coord: tile.coord, dataType: 'tile'});

// HACK this is nescessary to fix https://github.com/mapbox/mapbox-gl-js/issues/2986
if (this.map) this.map.painter.tileExtentVAO.vao = null;
Expand Down Expand Up @@ -403,7 +403,7 @@ class SourceCache extends Evented {

tile.uses++;
this._tiles[coord.id] = tile;
this._source.fire('dataloading', {tile: tile, dataType: 'tile'});
this._source.fire('dataloading', {tile: tile, coord: tile.coord, dataType: 'tile'});

return tile;
}
Expand All @@ -421,7 +421,7 @@ class SourceCache extends Evented {

tile.uses--;
delete this._tiles[id];
this._source.fire('data', { tile: tile, dataType: 'tile' });
this._source.fire('data', { tile: tile, coord: tile.coord, dataType: 'tile' });

if (tile.uses > 0)
return;
Expand Down
2 changes: 1 addition & 1 deletion js/source/tile.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class Tile {

function done(_, data) {
this.reloadSymbolData(data, source.map.style);
source.fire('data', {tile: this, dataType: 'tile'});
source.fire('data', {tile: this, coord: this.coord, dataType: 'tile'});

// HACK this is nescessary to fix https://github.com/mapbox/mapbox-gl-js/issues/2986
if (source.map) source.map.painter.tileExtentVAO.vao = null;
Expand Down
10 changes: 7 additions & 3 deletions js/style/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class Style extends Evented {
}

this.on('source.load', (event) => {
const source = event.source;
const source = this.sourceCaches[event.sourceId].getSource();
if (source && source.vectorLayerIds) {
for (const layerId in this._layers) {
const layer = this._layers[layerId];
Expand Down Expand Up @@ -375,9 +375,13 @@ class Style extends Evented {

const sourceCache = this.sourceCaches[id] = new SourceCache(id, source, this.dispatcher);
sourceCache.style = this;
sourceCache.setEventedParent(this, {source: sourceCache.getSource()});
sourceCache.setEventedParent(this, () => ({
isSourceLoaded: sourceCache.loaded(),
source: sourceCache.serialize(),
sourceId: id
}));

if (sourceCache.onAdd) sourceCache.onAdd(this.map);
sourceCache.onAdd(this.map);
this._changed = true;
}

Expand Down
105 changes: 90 additions & 15 deletions js/ui/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ class Map extends Camera {
'_contextLost',
'_contextRestored',
'_update',
'_render'
'_render',
'_onData',
'_onDataLoading'
], this);

this._setupContainer();
Expand Down Expand Up @@ -202,13 +204,8 @@ class Map extends Camera {
this.style.update(this._classes, {transition: false});
});

this.on('data', function(event) {
if (event.dataType === 'style') {
this._update(true);
} else {
this._update();
}
});
this.on('data', this._onData);
this.on('dataloading', this._onDataLoading);
}

/**
Expand Down Expand Up @@ -1274,6 +1271,15 @@ class Map extends Camera {
// show vertices
get vertices() { return !!this._vertices; }
set vertices(value) { this._vertices = value; this._update(); }

_onData(event) {
this._update(event.dataType === 'style');
this.fire(`${event.dataType}data`, event);
}

_onDataLoading(event) {
this.fire(`${event.dataType}dataloading`, event);
}
}

module.exports = Map;
Expand Down Expand Up @@ -1596,26 +1602,92 @@ function removeNode(node) {
*/

/**
* Fired when any map data (style, source, tile, etc) loads or changes. See
* [`MapDataEvent`](#MapDataEvent) for more information.
* Fired when any map data loads or changes. See [`MapDataEvent`](#MapDataEvent)
* for more information.
*
* @event data
* @memberof Map
* @instance
* @property {MapDataEvent} data
*/

/**
* Fired when the map's style loads or changes. See
* [`MapDataEvent`](#MapDataEvent) for more information.
*
* @event styledata
* @memberof Map
* @instance
* @property {MapDataEvent} data
*/

/**
* Fired when one of the map's sources loads or changes. This event is not fired
* if a tile belonging to a source loads or changes (that is handled by
* `tiledata`). See [`MapDataEvent`](#MapDataEvent) for more information.
*
* @event sourcedata
* @memberof Map
* @instance
* @property {MapDataEvent} data
*/

/**
* Fired when any map data (style, source, tile, etc) begins loading or
* changing asyncronously. All `dataloading` events are followed by a `data`
* or `error` event. See [`MapDataEvent`](#MapDataEvent) for more information.
* Fired when one of the map's sources' tiles loads or changes. See
* [`MapDataEvent`](#MapDataEvent) for more information.
*
* @event dataloading
* @event tiledata
* @memberof Map
* @instance
* @property {MapDataEvent} data
*/

/**
* Fired when any map data (style, source, tile, etc) begins loading or
* changing asyncronously. All `dataloading` events are followed by a `data`
* or `error` event. See [`MapDataEvent`](#MapDataEvent) for more information.
*
* @event dataloading
* @memberof Map
* @instance
* @property {MapDataEvent} data
*/

/**
* Fired when the map's style begins loading or changing asyncronously.
* All `styledataloading` events are followed by a `styledata`
* or `error` event. See [`MapDataEvent`](#MapDataEvent) for more information.
*
* @event styledataloading
* @memberof Map
* @instance
* @property {MapDataEvent} data
*/

/**
* Fired when one of the map's sources begins loading or changing asyncronously.
* This event is not fired if a tile belonging to a source begins loading or
* changing (that is handled by `tiledataloading`). All `sourcedataloading`
* events are followed by a `sourcedata` or `error` event. See
* [`MapDataEvent`](#MapDataEvent) for more information.
*
* @event sourcedataloading
* @memberof Map
* @instance
* @property {MapDataEvent} data
*/

/**
* Fired when one of the map's sources' tiles begins loading or changing
* asyncronously. All `tiledataloading` events are followed by a `tiledata`
* or `error` event. See [`MapDataEvent`](#MapDataEvent) for more information.
*
* @event tiledataloading
* @memberof Map
* @instance
* @property {MapDataEvent} data
*/

/**
* A `MapDataEvent` object is emitted with the [`Map#data`](#Map.event:data)
* and [`Map#dataloading`](#Map.event:dataloading) events. Possible values for
Expand All @@ -1627,7 +1699,10 @@ function removeNode(node) {
*
* @typedef {Object} MapDataEvent
* @property {string} type The event type.
* @property {string} dataType The type of data that has changed. One of `'source'`, `'style'`, or `'tile'`.
* @property {string} dataType The type of data that has changed. One of `'source'`, `'style'`.
* @property {boolean} [isSourceLoaded] True if the event has a `dataType` of `source` and the source has no outstanding network requests.
* @property {Object} [source] The [style spec representation of the source](https://www.mapbox.com/mapbox-gl-style-spec/#sources) if the event has a `dataType` of `source`.
* @property {Coordinate} [coord] The coordinate of the tile if the event has a `dataType` of `tile`.
*/

/**
Expand Down
2 changes: 1 addition & 1 deletion js/util/evented.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class Evented {
*/
setEventedParent(parent, data) {
this._eventedParent = parent;
this._eventedParentData = data;
this._eventedParentData = typeof data === 'function' ? data() : data;

return this;
}
Expand Down
37 changes: 34 additions & 3 deletions test/js/ui/map.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,15 @@ test('Map', (t) => {
function recordEvent(event) { events.push(event.type); }

map.on('error', recordEvent);
map.on('source.load', recordEvent);
map.on('data', recordEvent);
map.on('dataloading', recordEvent);

map.style.fire('error');
map.style.fire('source.load');
map.style.fire('data');
map.style.fire('dataloading');

t.deepEqual(events, [
'error',
'source.load',
'data',
'dataloading',
]);
Expand All @@ -153,6 +150,40 @@ test('Map', (t) => {
});
});

t.test('fires *data and *dataloading events', (t) => {
createMap({}, (error, map) => {
t.error(error);

const events = [];
function recordEvent(event) { events.push(event.type); }

map.on('styledata', recordEvent);
map.on('styledataloading', recordEvent);
map.on('sourcedata', recordEvent);
map.on('sourcedataloading', recordEvent);
map.on('tiledata', recordEvent);
map.on('tiledataloading', recordEvent);

map.style.fire('data', {dataType: 'style'});
map.style.fire('dataloading', {dataType: 'style'});
map.style.fire('data', {dataType: 'source'});
map.style.fire('dataloading', {dataType: 'source'});
map.style.fire('data', {dataType: 'tile'});
map.style.fire('dataloading', {dataType: 'tile'});

t.deepEqual(events, [
'styledata',
'styledataloading',
'sourcedata',
'sourcedataloading',
'tiledata',
'tiledataloading'
]);

t.end();
});
});

t.test('can be called more than once', (t) => {
const map = createMap();

Expand Down
11 changes: 11 additions & 0 deletions test/js/util/evented.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,17 @@ test('Evented', (t) => {
t.end();
});

t.test('attaches parent data from a function to parent listeners', (t) => {
const eventedSource = new Evented();
const eventedSink = new Evented();
eventedSource.setEventedParent(eventedSink, () => ({foz: 'baz'}));
eventedSink.on('a', (data) => {
t.equal(data.foz, 'baz');
});
eventedSource.fire('a', {foo: 'bar'});
t.end();
});

t.test('passes original "target" to parent listeners', (t) => {
const eventedSource = new Evented();
const eventedSink = new Evented();
Expand Down

0 comments on commit 25950e6

Please sign in to comment.