Skip to content

Commit 25950e6

Browse files
authored
"data" event revamp (#3590)
* 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
1 parent 95b440d commit 25950e6

File tree

8 files changed

+147
-27
lines changed

8 files changed

+147
-27
lines changed

js/source/image_source.js

-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ class ImageSource extends Evented {
7373
}
7474

7575
_finishLoading() {
76-
this.fire('data', {dataType: 'source'});
7776
this.fire('source.load');
7877

7978
if (this.map) {

js/source/source_cache.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class SourceCache extends Evented {
157157

158158
tile.sourceCache = this;
159159
tile.timeAdded = new Date().getTime();
160-
this._source.fire('data', {tile: tile, dataType: 'tile'});
160+
this._source.fire('data', {tile: tile, coord: tile.coord, dataType: 'tile'});
161161

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

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

408408
return tile;
409409
}
@@ -421,7 +421,7 @@ class SourceCache extends Evented {
421421

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

426426
if (tile.uses > 0)
427427
return;

js/source/tile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class Tile {
150150

151151
function done(_, data) {
152152
this.reloadSymbolData(data, source.map.style);
153-
source.fire('data', {tile: this, dataType: 'tile'});
153+
source.fire('data', {tile: this, coord: this.coord, dataType: 'tile'});
154154

155155
// HACK this is nescessary to fix https://github.com/mapbox/mapbox-gl-js/issues/2986
156156
if (source.map) source.map.painter.tileExtentVAO.vao = null;

js/style/style.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class Style extends Evented {
111111
}
112112

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

376376
const sourceCache = this.sourceCaches[id] = new SourceCache(id, source, this.dispatcher);
377377
sourceCache.style = this;
378-
sourceCache.setEventedParent(this, {source: sourceCache.getSource()});
378+
sourceCache.setEventedParent(this, () => ({
379+
isSourceLoaded: sourceCache.loaded(),
380+
source: sourceCache.serialize(),
381+
sourceId: id
382+
}));
379383

380-
if (sourceCache.onAdd) sourceCache.onAdd(this.map);
384+
sourceCache.onAdd(this.map);
381385
this._changed = true;
382386
}
383387

js/ui/map.js

+90-15
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ class Map extends Camera {
155155
'_contextLost',
156156
'_contextRestored',
157157
'_update',
158-
'_render'
158+
'_render',
159+
'_onData',
160+
'_onDataLoading'
159161
], this);
160162

161163
this._setupContainer();
@@ -202,13 +204,8 @@ class Map extends Camera {
202204
this.style.update(this._classes, {transition: false});
203205
});
204206

205-
this.on('data', function(event) {
206-
if (event.dataType === 'style') {
207-
this._update(true);
208-
} else {
209-
this._update();
210-
}
211-
});
207+
this.on('data', this._onData);
208+
this.on('dataloading', this._onDataLoading);
212209
}
213210

214211
/**
@@ -1274,6 +1271,15 @@ class Map extends Camera {
12741271
// show vertices
12751272
get vertices() { return !!this._vertices; }
12761273
set vertices(value) { this._vertices = value; this._update(); }
1274+
1275+
_onData(event) {
1276+
this._update(event.dataType === 'style');
1277+
this.fire(`${event.dataType}data`, event);
1278+
}
1279+
1280+
_onDataLoading(event) {
1281+
this.fire(`${event.dataType}dataloading`, event);
1282+
}
12771283
}
12781284

12791285
module.exports = Map;
@@ -1596,26 +1602,92 @@ function removeNode(node) {
15961602
*/
15971603

15981604
/**
1599-
* Fired when any map data (style, source, tile, etc) loads or changes. See
1600-
* [`MapDataEvent`](#MapDataEvent) for more information.
1605+
* Fired when any map data loads or changes. See [`MapDataEvent`](#MapDataEvent)
1606+
* for more information.
16011607
*
16021608
* @event data
16031609
* @memberof Map
16041610
* @instance
16051611
* @property {MapDataEvent} data
16061612
*/
16071613

1614+
/**
1615+
* Fired when the map's style loads or changes. See
1616+
* [`MapDataEvent`](#MapDataEvent) for more information.
1617+
*
1618+
* @event styledata
1619+
* @memberof Map
1620+
* @instance
1621+
* @property {MapDataEvent} data
1622+
*/
1623+
1624+
/**
1625+
* Fired when one of the map's sources loads or changes. This event is not fired
1626+
* if a tile belonging to a source loads or changes (that is handled by
1627+
* `tiledata`). See [`MapDataEvent`](#MapDataEvent) for more information.
1628+
*
1629+
* @event sourcedata
1630+
* @memberof Map
1631+
* @instance
1632+
* @property {MapDataEvent} data
1633+
*/
1634+
16081635
/**
1609-
* Fired when any map data (style, source, tile, etc) begins loading or
1610-
* changing asyncronously. All `dataloading` events are followed by a `data`
1611-
* or `error` event. See [`MapDataEvent`](#MapDataEvent) for more information.
1636+
* Fired when one of the map's sources' tiles loads or changes. See
1637+
* [`MapDataEvent`](#MapDataEvent) for more information.
16121638
*
1613-
* @event dataloading
1639+
* @event tiledata
16141640
* @memberof Map
16151641
* @instance
16161642
* @property {MapDataEvent} data
16171643
*/
16181644

1645+
/**
1646+
* Fired when any map data (style, source, tile, etc) begins loading or
1647+
* changing asyncronously. All `dataloading` events are followed by a `data`
1648+
* or `error` event. See [`MapDataEvent`](#MapDataEvent) for more information.
1649+
*
1650+
* @event dataloading
1651+
* @memberof Map
1652+
* @instance
1653+
* @property {MapDataEvent} data
1654+
*/
1655+
1656+
/**
1657+
* Fired when the map's style begins loading or changing asyncronously.
1658+
* All `styledataloading` events are followed by a `styledata`
1659+
* or `error` event. See [`MapDataEvent`](#MapDataEvent) for more information.
1660+
*
1661+
* @event styledataloading
1662+
* @memberof Map
1663+
* @instance
1664+
* @property {MapDataEvent} data
1665+
*/
1666+
1667+
/**
1668+
* Fired when one of the map's sources begins loading or changing asyncronously.
1669+
* This event is not fired if a tile belonging to a source begins loading or
1670+
* changing (that is handled by `tiledataloading`). All `sourcedataloading`
1671+
* events are followed by a `sourcedata` or `error` event. See
1672+
* [`MapDataEvent`](#MapDataEvent) for more information.
1673+
*
1674+
* @event sourcedataloading
1675+
* @memberof Map
1676+
* @instance
1677+
* @property {MapDataEvent} data
1678+
*/
1679+
1680+
/**
1681+
* Fired when one of the map's sources' tiles begins loading or changing
1682+
* asyncronously. All `tiledataloading` events are followed by a `tiledata`
1683+
* or `error` event. See [`MapDataEvent`](#MapDataEvent) for more information.
1684+
*
1685+
* @event tiledataloading
1686+
* @memberof Map
1687+
* @instance
1688+
* @property {MapDataEvent} data
1689+
*/
1690+
16191691
/**
16201692
* A `MapDataEvent` object is emitted with the [`Map#data`](#Map.event:data)
16211693
* and [`Map#dataloading`](#Map.event:dataloading) events. Possible values for
@@ -1627,7 +1699,10 @@ function removeNode(node) {
16271699
*
16281700
* @typedef {Object} MapDataEvent
16291701
* @property {string} type The event type.
1630-
* @property {string} dataType The type of data that has changed. One of `'source'`, `'style'`, or `'tile'`.
1702+
* @property {string} dataType The type of data that has changed. One of `'source'`, `'style'`.
1703+
* @property {boolean} [isSourceLoaded] True if the event has a `dataType` of `source` and the source has no outstanding network requests.
1704+
* @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`.
1705+
* @property {Coordinate} [coord] The coordinate of the tile if the event has a `dataType` of `tile`.
16311706
*/
16321707

16331708
/**

js/util/evented.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class Evented {
117117
*/
118118
setEventedParent(parent, data) {
119119
this._eventedParent = parent;
120-
this._eventedParentData = data;
120+
this._eventedParentData = typeof data === 'function' ? data() : data;
121121

122122
return this;
123123
}

test/js/ui/map.test.js

+34-3
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,15 @@ test('Map', (t) => {
133133
function recordEvent(event) { events.push(event.type); }
134134

135135
map.on('error', recordEvent);
136-
map.on('source.load', recordEvent);
137136
map.on('data', recordEvent);
138137
map.on('dataloading', recordEvent);
139138

140139
map.style.fire('error');
141-
map.style.fire('source.load');
142140
map.style.fire('data');
143141
map.style.fire('dataloading');
144142

145143
t.deepEqual(events, [
146144
'error',
147-
'source.load',
148145
'data',
149146
'dataloading',
150147
]);
@@ -153,6 +150,40 @@ test('Map', (t) => {
153150
});
154151
});
155152

153+
t.test('fires *data and *dataloading events', (t) => {
154+
createMap({}, (error, map) => {
155+
t.error(error);
156+
157+
const events = [];
158+
function recordEvent(event) { events.push(event.type); }
159+
160+
map.on('styledata', recordEvent);
161+
map.on('styledataloading', recordEvent);
162+
map.on('sourcedata', recordEvent);
163+
map.on('sourcedataloading', recordEvent);
164+
map.on('tiledata', recordEvent);
165+
map.on('tiledataloading', recordEvent);
166+
167+
map.style.fire('data', {dataType: 'style'});
168+
map.style.fire('dataloading', {dataType: 'style'});
169+
map.style.fire('data', {dataType: 'source'});
170+
map.style.fire('dataloading', {dataType: 'source'});
171+
map.style.fire('data', {dataType: 'tile'});
172+
map.style.fire('dataloading', {dataType: 'tile'});
173+
174+
t.deepEqual(events, [
175+
'styledata',
176+
'styledataloading',
177+
'sourcedata',
178+
'sourcedataloading',
179+
'tiledata',
180+
'tiledataloading'
181+
]);
182+
183+
t.end();
184+
});
185+
});
186+
156187
t.test('can be called more than once', (t) => {
157188
const map = createMap();
158189

test/js/util/evented.test.js

+11
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,17 @@ test('Evented', (t) => {
115115
t.end();
116116
});
117117

118+
t.test('attaches parent data from a function to parent listeners', (t) => {
119+
const eventedSource = new Evented();
120+
const eventedSink = new Evented();
121+
eventedSource.setEventedParent(eventedSink, () => ({foz: 'baz'}));
122+
eventedSink.on('a', (data) => {
123+
t.equal(data.foz, 'baz');
124+
});
125+
eventedSource.fire('a', {foo: 'bar'});
126+
t.end();
127+
});
128+
118129
t.test('passes original "target" to parent listeners', (t) => {
119130
const eventedSource = new Evented();
120131
const eventedSink = new Evented();

0 commit comments

Comments
 (0)