Refactor background in preparation for multiple overlays

This commit is contained in:
John Firebaugh
2013-07-15 12:31:26 -07:00
parent ab566c8fa7
commit 734d53e08b
12 changed files with 362 additions and 327 deletions

View File

@@ -46,7 +46,8 @@
<script src='js/id/renderer/background.js'></script>
<script src='js/id/renderer/background_source.js'></script>
<script src='js/id/renderer/localgpx.js'></script>
<script src='js/id/renderer/gpx_layer.js'></script>
<script src='js/id/renderer/tile_layer.js'></script>
<script src='js/id/renderer/map.js'></script>
<script src="js/id/svg.js"></script>

View File

@@ -21,7 +21,6 @@ window.iD = function () {
mode,
container,
ui = iD.ui(context),
map = iD.Map(context),
connection = iD.Connection(),
locale = iD.detect().locale,
localePath;
@@ -62,7 +61,6 @@ window.iD = function () {
context.ui = function() { return ui; };
context.connection = function() { return connection; };
context.history = function() { return history; };
context.map = function() { return map; };
/* History */
context.graph = history.graph;
@@ -77,7 +75,6 @@ window.iD = function () {
context.flush = function() {
history.reset();
connection.flush();
map.redraw();
return context;
};
@@ -131,32 +128,26 @@ window.iD = function () {
context.surface().call(behavior.off);
};
/* Projection */
context.projection = d3.geo.mercator()
.scale(512 / Math.PI)
.precision(0);
/* Background */
var background = iD.Background(context);
context.background = function() { return background; };
/* Map */
var map = iD.Map(context);
context.map = function() { return map; };
context.layers = function() { return map.layers; };
context.background = function() { return map.layers[0]; };
context.surface = function() { return map.surface; };
context.mouse = map.mouse;
context.projection = map.projection;
context.extent = map.extent;
context.redraw = map.redraw;
context.pan = map.pan;
context.zoomIn = map.zoomIn;
context.zoomOut = map.zoomOut;
/* Background */
var backgroundSources = iD.data.imagery.map(function(source) {
if (source.sourcetag === 'Bing') {
return iD.BackgroundSource.Bing(source, context.background().dispatch);
} else {
return iD.BackgroundSource.template(source);
}
});
backgroundSources.push(iD.BackgroundSource.Custom);
context.backgroundSources = function() {
return backgroundSources;
};
/* Presets */
var presets = iD.presets()
.load(iD.data.presets);
@@ -172,34 +163,6 @@ window.iD = function () {
return context;
};
var q = iD.util.stringQs(location.hash.substring(1)),
detected = false,
background = q.background || q.layer;
if (background && background.indexOf('custom:') === 0) {
context.layers()[0]
.source(iD.BackgroundSource.template({
template: background.replace(/^custom:/, ''),
name: 'Custom'
}));
detected = true;
} else if (background) {
context.layers()[0]
.source(_.find(backgroundSources, function(l) {
if (l.data.sourcetag === background) {
detected = true;
return true;
}
}));
}
if (!detected) {
context.background()
.source(_.find(backgroundSources, function(l) {
return l.data.name === 'Bing aerial imagery';
}));
}
var embed = false;
context.embed = function(_) {
if (!arguments.length) return embed;

View File

@@ -1,210 +1,125 @@
iD.Background = function(backgroundType) {
iD.Background = function(context) {
var dispatch = d3.dispatch('change'),
baseLayer = iD.TileLayer()
.projection(context.projection),
gpxLayer = iD.GpxLayer(context, dispatch)
.projection(context.projection),
overlayLayer = iD.TileLayer('overlay')
.projection(context.projection),
layers = [baseLayer, gpxLayer, overlayLayer];
backgroundType = backgroundType || 'background';
var tileSize = 256,
tile = d3.geo.tile(),
projection,
cache = {},
offset = [0, 0],
offsets = {},
tileOrigin,
z,
transformProp = iD.util.prefixCSSProperty('Transform'),
source = d3.functor('');
function tileSizeAtZoom(d, z) {
return Math.ceil(tileSize * Math.pow(2, z - d[2])) / tileSize;
}
function atZoom(t, distance) {
var power = Math.pow(2, distance);
return [
Math.floor(t[0] * power),
Math.floor(t[1] * power),
t[2] + distance];
}
function lookUp(d) {
for (var up = -1; up > -d[2]; up--) {
var tile = atZoom(d, up);
if (cache[source(tile)] !== false) {
return tile;
}
var backgroundSources = iD.data.imagery.map(function(source) {
if (source.sourcetag === 'Bing') {
return iD.BackgroundSource.Bing(source, dispatch);
} else {
return iD.BackgroundSource.template(source);
}
});
backgroundSources.push(iD.BackgroundSource.Custom);
function findSource(sourcetag) {
return _.find(backgroundSources, function(d) {
return d.data.sourcetag && d.data.sourcetag === sourcetag;
});
}
function uniqueBy(a, n) {
var o = [], seen = {};
for (var i = 0; i < a.length; i++) {
if (seen[a[i][n]] === undefined) {
o.push(a[i]);
seen[a[i][n]] = true;
}
}
return o;
function background(supersurface) {
layers.forEach(function(layer) {
supersurface.call(layer);
});
}
function addSource(d) {
d.push(source(d));
return d;
}
// Update tiles based on current state of `projection`.
function background(selection) {
var layer = selection.selectAll('.' + backgroundType + '-layer')
.data([background]);
layer.enter().append('div')
.attr('class', 'layer-layer ' + backgroundType + '-layer', true);
tile.scale(projection.scale() * 2 * Math.PI)
.translate(projection.translate());
tileOrigin = [
projection.scale() * Math.PI - projection.translate()[0],
projection.scale() * Math.PI - projection.translate()[1]];
z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
render(layer);
}
// Derive the tiles onscreen, remove those offscreen and position them.
// Important that this part not depend on `projection` because it's
// rentered when tiles load/error (see #644).
function render(selection) {
var requests = [];
if (tile.scaleExtent()[0] <= z) {
tile().forEach(function(d) {
addSource(d);
requests.push(d);
if (cache[d[3]] === false && lookUp(d)) {
requests.push(addSource(lookUp(d)));
}
});
requests = uniqueBy(requests, 3).filter(function(r) {
// don't re-request tiles which have failed in the past
return cache[r[3]] !== false;
});
}
var pixelOffset = [
Math.round(offset[0] * Math.pow(2, z)),
Math.round(offset[1] * Math.pow(2, z))
];
function load(d) {
cache[d[3]] = true;
d3.select(this)
.on('error', null)
.on('load', null)
.classed('tile-loaded', true);
render(selection);
}
function error(d) {
cache[d[3]] = false;
d3.select(this)
.on('error', null)
.on('load', null)
.remove();
render(selection);
}
function imageTransform(d) {
var _ts = tileSize * Math.pow(2, z - d[2]);
var scale = tileSizeAtZoom(d, z);
return 'translate(' +
(Math.round((d[0] * _ts) - tileOrigin[0]) + pixelOffset[0]) + 'px,' +
(Math.round((d[1] * _ts) - tileOrigin[1]) + pixelOffset[1]) + 'px)' +
'scale(' + scale + ',' + scale + ')';
}
var image = selection
.selectAll('img')
.data(requests, function(d) { return d[3]; });
image.exit()
.style(transformProp, imageTransform)
.classed('tile-removing', true)
.each(function() {
var tile = d3.select(this);
window.setTimeout(function() {
if (tile.classed('tile-removing')) {
tile.remove();
}
}, 300);
});
image.enter().append('img')
.attr('class', 'tile')
.attr('src', function(d) { return d[3]; })
.on('error', error)
.on('load', load);
image
.style(transformProp, imageTransform)
.classed('tile-removing', false);
}
background.offset = function(_) {
if (!arguments.length) return offset;
offset = _;
if (source.data) offsets[source.data.name] = offset;
return background;
};
background.nudge = function(_, zoomlevel) {
offset[0] += _[0] / Math.pow(2, zoomlevel);
offset[1] += _[1] / Math.pow(2, zoomlevel);
return background;
};
background.projection = function(_) {
if (!arguments.length) return projection;
projection = _;
return background;
background.sources = function(extent) {
return backgroundSources.filter(function(layer) {
return !layer.data.extent ||
iD.geo.Extent(layer.data.extent).intersects(extent);
});
};
background.dimensions = function(_) {
if (!arguments.length) return tile.size();
tile.size(_);
layers.forEach(function(layer) {
layer.dimensions(_);
});
};
background.baseLayerSource = function(d) {
if (!arguments.length) return baseLayer.source();
baseLayer.source(d);
dispatch.change();
if (d.data.name === 'Custom (customized)') {
context.history()
.imagery_used('Custom (' + d.data.template + ')');
} else {
context.history()
.imagery_used(d.data.sourcetag || d.data.name);
}
return background;
};
function setHash(source) {
var tag = source.data && source.data.sourcetag;
if (!tag && source.data && source.data.name === 'Custom') {
tag = 'custom:' + source.data.template;
background.bing = function() {
background.baseLayerSource(findSource("Bing"));
};
background.hasGpxLayer = function() {
return !_.isEmpty(gpxLayer.geojson());
};
background.showsGpxLayer = function() {
return background.hasGpxLayer() && gpxLayer.enable();
};
background.zoomToGpxLayer = function() {
if (background.hasGpxLayer()) {
context.map()
.extent(d3.geo.bounds(gpxLayer.geojson()));
}
var q = iD.util.stringQs(location.hash.substring(1));
if (tag) {
q[backgroundType] = tag;
location.replace('#' + iD.util.qsString(q, true));
};
background.toggleGpxLayer = function() {
gpxLayer.enable(!gpxLayer.enable());
dispatch.change();
};
background.showsLayer = function(d) {
var overlay = overlayLayer.source();
return d.data.name === baseLayer.source().data.name ||
(overlay.data && overlay.data.name === d.data.name);
};
background.toggleOverlayLayer = function(d) {
if (overlayLayer.source() === d) {
overlayLayer.source(d3.functor(''));
} else {
location.replace('#' + iD.util.qsString(_.omit(q, backgroundType), true));
overlayLayer.source(d);
}
dispatch.change();
};
background.nudge = function(d, zoom) {
baseLayer.nudge(d, zoom);
dispatch.change();
return background;
};
background.offset = function(d) {
if (!arguments.length) return baseLayer.offset();
baseLayer.offset(d);
dispatch.change();
return background;
};
var q = iD.util.stringQs(location.hash.substring(1)),
chosen = q.background || q.layer;
if (chosen && chosen.indexOf('custom:') === 0) {
background.baseLayerSource(iD.BackgroundSource.template({
template: chosen.replace(/^custom:/, ''),
name: 'Custom'
}));
} else {
background.baseLayerSource(findSource(chosen) || findSource("Bing"));
}
background.dispatch = d3.dispatch('change');
background.source = function(_) {
if (!arguments.length) return source;
source = _;
if (source.data) {
offset = offsets[source.data.name] = offsets[source.data.name] || [0, 0];
} else {
offset = [0, 0];
}
cache = {};
tile.scaleExtent((source.data && source.data.scaleExtent) || [1, 20]);
setHash(source);
background.dispatch.change();
return background;
};
return d3.rebind(background, background.dispatch, 'on');
return d3.rebind(background, dispatch, 'on');
};

View File

@@ -1,4 +1,4 @@
iD.LocalGpx = function(context) {
iD.GpxLayer = function(context, dispatch) {
var projection,
gj = {},
enable = true,
@@ -74,7 +74,7 @@ iD.LocalGpx = function(context) {
reader.onload = function(e) {
render.geojson(toGeoJSON.gpx(toDom(e.target.result)));
context.redraw();
dispatch.change();
context.map().pan([0, 0]);
};

View File

@@ -1,9 +1,7 @@
iD.Map = function(context) {
var dimensions = [1, 1],
dispatch = d3.dispatch('move', 'drawn'),
projection = d3.geo.mercator()
.scale(512 / Math.PI)
.precision(0),
projection = context.projection,
roundedProjection = iD.svg.RoundProjection(projection),
zoom = d3.behavior.zoom()
.translate(projection.translate())
@@ -14,11 +12,6 @@ iD.Map = function(context) {
transformStart,
transformed = false,
minzoom = 0,
layers = [
iD.Background().projection(projection),
iD.LocalGpx(context).projection(projection),
iD.Background('overlay').projection(projection)
],
transformProp = iD.util.prefixCSSProperty('Transform'),
points = iD.svg.Points(roundedProjection, context),
vertices = iD.svg.Vertices(roundedProjection, context),
@@ -32,15 +25,15 @@ iD.Map = function(context) {
function map(selection) {
context.history()
.on('change.map', redraw);
context.background()
.on('change.map', redraw);
selection.call(zoom);
supersurface = selection.append('div')
.attr('id', 'supersurface');
layers.forEach(function(layer) {
supersurface.call(layer);
});
supersurface.call(context.background());
// Need a wrapper div because Opera can't cope with an absolutely positioned
// SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
@@ -221,9 +214,7 @@ iD.Map = function(context) {
}
if (!difference) {
layers.forEach(function(layer) {
supersurface.call(layer);
});
supersurface.call(context.background());
}
if (map.editable()) {
@@ -320,9 +311,7 @@ iD.Map = function(context) {
var center = map.center();
dimensions = _;
surface.dimensions(dimensions);
layers.forEach(function(layer) {
layer.dimensions(dimensions);
});
context.background().dimensions(dimensions);
projection.clipExtent([[0, 0], dimensions]);
setCenter(center);
return redraw();
@@ -425,9 +414,5 @@ iD.Map = function(context) {
return map;
};
map.layers = layers;
map.projection = projection;
map.redraw = redraw;
return d3.rebind(map, dispatch, 'on');
};

View File

@@ -0,0 +1,207 @@
iD.TileLayer = function(backgroundType) {
backgroundType = backgroundType || 'background';
var tileSize = 256,
tile = d3.geo.tile(),
projection,
cache = {},
offset = [0, 0],
offsets = {},
tileOrigin,
z,
transformProp = iD.util.prefixCSSProperty('Transform'),
source = d3.functor('');
function tileSizeAtZoom(d, z) {
return Math.ceil(tileSize * Math.pow(2, z - d[2])) / tileSize;
}
function atZoom(t, distance) {
var power = Math.pow(2, distance);
return [
Math.floor(t[0] * power),
Math.floor(t[1] * power),
t[2] + distance];
}
function lookUp(d) {
for (var up = -1; up > -d[2]; up--) {
var tile = atZoom(d, up);
if (cache[source(tile)] !== false) {
return tile;
}
}
}
function uniqueBy(a, n) {
var o = [], seen = {};
for (var i = 0; i < a.length; i++) {
if (seen[a[i][n]] === undefined) {
o.push(a[i]);
seen[a[i][n]] = true;
}
}
return o;
}
function addSource(d) {
d.push(source(d));
return d;
}
// Update tiles based on current state of `projection`.
function background(selection) {
var layer = selection.selectAll('.' + backgroundType + '-layer')
.data([background]);
layer.enter().append('div')
.attr('class', 'layer-layer ' + backgroundType + '-layer', true);
tile.scale(projection.scale() * 2 * Math.PI)
.translate(projection.translate());
tileOrigin = [
projection.scale() * Math.PI - projection.translate()[0],
projection.scale() * Math.PI - projection.translate()[1]];
z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
render(layer);
}
// Derive the tiles onscreen, remove those offscreen and position them.
// Important that this part not depend on `projection` because it's
// rentered when tiles load/error (see #644).
function render(selection) {
var requests = [];
if (tile.scaleExtent()[0] <= z) {
tile().forEach(function(d) {
addSource(d);
requests.push(d);
if (cache[d[3]] === false && lookUp(d)) {
requests.push(addSource(lookUp(d)));
}
});
requests = uniqueBy(requests, 3).filter(function(r) {
// don't re-request tiles which have failed in the past
return cache[r[3]] !== false;
});
}
var pixelOffset = [
Math.round(offset[0] * Math.pow(2, z)),
Math.round(offset[1] * Math.pow(2, z))
];
function load(d) {
cache[d[3]] = true;
d3.select(this)
.on('error', null)
.on('load', null)
.classed('tile-loaded', true);
render(selection);
}
function error(d) {
cache[d[3]] = false;
d3.select(this)
.on('error', null)
.on('load', null)
.remove();
render(selection);
}
function imageTransform(d) {
var _ts = tileSize * Math.pow(2, z - d[2]);
var scale = tileSizeAtZoom(d, z);
return 'translate(' +
(Math.round((d[0] * _ts) - tileOrigin[0]) + pixelOffset[0]) + 'px,' +
(Math.round((d[1] * _ts) - tileOrigin[1]) + pixelOffset[1]) + 'px)' +
'scale(' + scale + ',' + scale + ')';
}
var image = selection
.selectAll('img')
.data(requests, function(d) { return d[3]; });
image.exit()
.style(transformProp, imageTransform)
.classed('tile-removing', true)
.each(function() {
var tile = d3.select(this);
window.setTimeout(function() {
if (tile.classed('tile-removing')) {
tile.remove();
}
}, 300);
});
image.enter().append('img')
.attr('class', 'tile')
.attr('src', function(d) { return d[3]; })
.on('error', error)
.on('load', load);
image
.style(transformProp, imageTransform)
.classed('tile-removing', false);
}
background.offset = function(_) {
if (!arguments.length) return offset;
offset = _;
if (source.data) offsets[source.data.name] = offset;
return background;
};
background.nudge = function(_, zoomlevel) {
offset[0] += _[0] / Math.pow(2, zoomlevel);
offset[1] += _[1] / Math.pow(2, zoomlevel);
return background;
};
background.projection = function(_) {
if (!arguments.length) return projection;
projection = _;
return background;
};
background.dimensions = function(_) {
if (!arguments.length) return tile.size();
tile.size(_);
return background;
};
function setHash(source) {
var tag = source.data && source.data.sourcetag;
if (!tag && source.data && source.data.name === 'Custom') {
tag = 'custom:' + source.data.template;
}
var q = iD.util.stringQs(location.hash.substring(1));
if (tag) {
q[backgroundType] = tag;
location.replace('#' + iD.util.qsString(q, true));
} else {
location.replace('#' + iD.util.qsString(_.omit(q, backgroundType), true));
}
}
background.source = function(_) {
if (!arguments.length) return source;
source = _;
if (source.data) {
offset = offsets[source.data.name] = offsets[source.data.name] || [0, 0];
} else {
offset = [0, 0];
}
cache = {};
tile.scaleExtent((source.data && source.data.scaleExtent) || [1, 20]);
setHash(source);
return background;
};
return background;
};

View File

@@ -2,13 +2,13 @@ iD.ui.Attribution = function(context) {
var selection;
function update() {
if (!context.background().source()) {
if (!context.background().baseLayerSource()) {
selection.html('');
return;
}
var attribution = selection.selectAll('.provided-by')
.data([context.background().source()], function(d) { return d.data.name; });
.data([context.background().baseLayerSource()], function(d) { return d.data.name; });
attribution.enter()
.append('span')

View File

@@ -6,18 +6,9 @@ iD.ui.Background = function(context) {
['top', [0, -1]],
['right', [-1, 0]],
['bottom', [0, 1]]],
layers = context.backgroundSources(),
opacityDefault = (context.storage('background-opacity') !== undefined) ?
(+context.storage('background-opacity')) : 0.5;
function getSources() {
var ext = context.map().extent();
return layers.filter(function(layer) {
return !layer.data.extent ||
iD.geo.Extent(layer.data.extent).intersects(ext);
});
}
function background(selection) {
function setOpacity(d) {
@@ -34,9 +25,7 @@ iD.ui.Background = function(context) {
function selectLayer() {
function active(d) {
var overlay = context.map().layers[2].source();
return d.data.name === context.background().source().data.name ||
(overlay.data && overlay.data.name === d.data.name);
return context.background().showsLayer(d);
}
content.selectAll('label.layer')
@@ -55,43 +44,28 @@ iD.ui.Background = function(context) {
}
d = configured;
}
context.background().source(d);
if (d.data.name === 'Custom (customized)') {
context.history()
.imagery_used('Custom (' + d.data.template + ')');
} else {
context.history()
.imagery_used(d.data.sourcetag || d.data.name);
}
context.redraw();
context.background().baseLayerSource(d);
selectLayer();
}
function clickSetOverlay(d) {
d3.event.preventDefault();
var overlay = context.map().layers[2];
if (overlay.source() === d) {
overlay.source(d3.functor(''));
} else {
overlay.source(d);
}
context.redraw();
context.background().toggleOverlayLayer(d);
selectLayer();
}
function clickGpx() {
context.map().layers[1]
.enable(!context.map().layers[1].enable());
context.redraw();
context.background().toggleGpxLayer();
update();
}
function drawList(layerList, type, change, filter) {
var sources = context.background()
.sources(context.map().extent())
.filter(filter);
var layerLinks = layerList.selectAll('label.layer')
.data(getSources().filter(filter), function(d) {
return d.data.name;
});
.data(sources, function(d) { return d.data.name; });
var layerInner = layerLinks.enter()
.append('label')
@@ -130,12 +104,11 @@ iD.ui.Background = function(context) {
return d.data.overlay;
});
var gpxLayer = context.map().layers[1],
hasGpx = !_.isEmpty(gpxLayer.geojson()),
showsGpx = hasGpx && gpxLayer.enable();
var hasGpx = context.background().hasGpxLayer(),
showsGpx = context.background().showsGpxLayer();
gpxLayerItem
.classed('active', hasGpx && gpxLayer.enable())
.classed('active', showsGpx)
.selectAll('input')
.property('disabled', !hasGpx)
.property('checked', showsGpx);
@@ -157,10 +130,10 @@ iD.ui.Background = function(context) {
});
function nudge() {
context.background().nudge(d[1], context.map().zoom());
var offset = context.background().offset();
var offset = context.background()
.nudge(d[1], context.map().zoom())
.offset();
resetButton.classed('disabled', offset[0] === 0 && offset[1] === 0);
context.redraw();
}
}
@@ -274,13 +247,7 @@ iD.ui.Background = function(context) {
.on('click', function() {
d3.event.preventDefault();
d3.event.stopPropagation();
if (context.map().layers[1].geojson().type) {
context.map()
.extent(d3.geo.bounds(context
.map()
.layers[1]
.geojson()));
}
context.background().zoomToGpxLayer();
})
.append('span')
.attr('class', 'icon geocode' );
@@ -317,7 +284,6 @@ iD.ui.Background = function(context) {
.on('click', function () {
context.background().offset([0, 0]);
resetButton.classed('disabled', true);
context.redraw();
});
resetButton.append('div')

View File

@@ -9,7 +9,7 @@ iD.ui.intro = function(context) {
// Save current map state
var history = context.history().toJSON(),
hash = window.location.hash,
background = context.background().source(),
background = context.background().baseLayerSource(),
opacity = d3.select('.background-layer').style('opacity'),
loadedTiles = context.connection().loadedTiles(),
baseEntities = context.history().graph().base().entities;
@@ -18,10 +18,7 @@ iD.ui.intro = function(context) {
context.connection().toggle(false).flush();
context.history().save().reset();
context.history().merge(iD.Graph().load(JSON.parse(iD.introGraph)).entities);
context.background().source(_.find(context.backgroundSources(), function(d) {
return d.data.sourcetag === "Bing";
}));
context.background().bing();
// Block saving
var savebutton = d3.select('#bar button.save'),
@@ -59,7 +56,7 @@ iD.ui.intro = function(context) {
d3.select('.background-layer').style('opacity', opacity);
context.connection().toggle(true).flush().loadedTiles(loadedTiles);
context.history().reset().merge(baseEntities);
context.background().source(background);
context.background().baseLayerSource(background);
if (history) context.history().fromJSON(history);
window.location.replace(hash);
window.onbeforeunload = beforeunload;

View File

@@ -48,7 +48,8 @@
<script src='../js/id/renderer/background.js'></script>
<script src='../js/id/renderer/background_source.js'></script>
<script src='../js/id/renderer/map.js'></script>
<script src='../js/id/renderer/localgpx.js'></script>
<script src='../js/id/renderer/gpx_layer.js'></script>
<script src='../js/id/renderer/tile_layer.js'></script>
<script src="../js/id/svg.js"></script>
<script src="../js/id/svg/areas.js"></script>
@@ -230,7 +231,7 @@
<script src="spec/core/difference.js"></script>
<script src="spec/core/tree.js"></script>
<script src="spec/renderer/background.js"></script>
<script src="spec/renderer/tile_layer.js"></script>
<script src="spec/renderer/background_source.js"></script>
<script src="spec/renderer/map.js"></script>

View File

@@ -61,7 +61,7 @@
<script src="spec/core/difference.js"></script>
<script src="spec/core/tree.js"></script>
<script src="spec/renderer/background.js"></script>
<script src="spec/renderer/tile_layer.js"></script>
<script src="spec/renderer/background_source.js"></script>
<script src="spec/renderer/map.js"></script>

View File

@@ -1,9 +1,9 @@
describe('iD.Background', function() {
describe('iD.TileLayer', function() {
var c, d;
beforeEach(function() {
d = d3.select(document.createElement('div'));
c = iD.Background().projection(d3.geo.mercator());
c = iD.TileLayer().projection(d3.geo.mercator());
d.call(c);
});
@@ -11,7 +11,7 @@ describe('iD.Background', function() {
d.remove();
});
describe('iD.Background', function() {
describe('iD.TileLayer', function() {
it('is instantiated', function() {
expect(c).to.be.ok;
});