diff --git a/index.html b/index.html index 3c2924650..122569faa 100644 --- a/index.html +++ b/index.html @@ -43,6 +43,7 @@ + diff --git a/js/id/id.js b/js/id/id.js index 42e75e994..3248740cf 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -134,33 +134,8 @@ window.iD = function(container) { return d[0] + ' icon'; }); - var gc = this.append('div').attr('class', 'geocode-control map-control'); - gc.append('button') - .attr('class','narrow') - .html("") - .on('click', function() { - d3.select(this).classed('active', gcForm.classed('hide')); - gcForm.classed('hide', !gcForm.classed('hide')); - - if (!gcForm.classed('hide')) d3.select('.map-overlay input').node().focus(); - else map.surface.node().focus(); - }); - var gcForm = gc.append('form'); - gcForm.attr('class','content map-overlay hide') - .append('input') - .attr({ - type: 'text', - placeholder: 'find a place' - }) - .on('keydown', function () { - if (d3.event.keyCode !== 13) return; - d3.event.preventDefault(); - d3.json('http://api.tiles.mapbox.com/v3/mapbox/geocode/' + - encodeURIComponent(this.value) + '.json', function(err, resp) { - gc.select('button').on('click').apply(gc.select('button').node()); - map.center([resp.results[0][0].lon, resp.results[0][0].lat]); - }); - }); + var gc = this.append('div').attr('class', 'geocode-control map-control') + .call(iD.geocoder().map(map)); this.append('div').attr('class', 'map-control layerswitcher-control') .call(iD.layerswitcher(map)); diff --git a/js/id/ui/geocoder.js b/js/id/ui/geocoder.js new file mode 100644 index 000000000..e93eaa9dc --- /dev/null +++ b/js/id/ui/geocoder.js @@ -0,0 +1,57 @@ +iD.geocoder = function() { + + var map; + + function geocoder(selection) { + function keydown() { + if (d3.event.keyCode !== 13) return; + d3.event.preventDefault(); + d3.json('http://api.tiles.mapbox.com/v3/mapbox/geocode/' + + encodeURIComponent(this.value) + '.json', function(err, resp) { + hide(); + map.center([resp.results[0][0].lon, resp.results[0][0].lat]); + }); + } + + function clickoutside(selection) { + selection + .on('click.geocoder-inside', function() { + return d3.event.stopPropagation(); + }); + d3.select('body').on('click.geocoder-outside', hide); + } + + function show() { setVisible(true); } + function hide() { setVisible(false); } + function toggle() { setVisible(gcForm.classed('hide')); } + + function setVisible(show) { + button.classed('active', show); + gcForm.classed('hide', !show); + if (show) d3.select('.map-overlay input').node().focus(); + else map.surface.node().focus(); + } + + var button = selection.append('button') + .attr('class','narrow') + .html('') + .on('click', toggle); + + var gcForm = selection.append('form'); + + gcForm.attr('class','content map-overlay hide') + .append('input') + .attr({ type: 'text', placeholder: 'find a place' }) + .on('keydown', keydown); + + selection.call(clickoutside); + } + + geocoder.map = function(_) { + if (!arguments.length) return map; + map = _; + return geocoder; + }; + + return geocoder; +}; diff --git a/js/id/ui/layerswitcher.js b/js/id/ui/layerswitcher.js index 5f40b3fff..18f802e1f 100644 --- a/js/id/ui/layerswitcher.js +++ b/js/id/ui/layerswitcher.js @@ -20,37 +20,29 @@ iD.layerswitcher = function(map) { var content = selection .append('div').attr('class', 'content map-overlay hide'); - var toggle = selection + var button = selection .append('button') .attr('class', 'narrow') .html("") - .on('click.toggle', function() { - d3.select(this) - .classed('active', function() { - return content.classed('hide'); - }); - content.classed('hide', function() { - if (content.classed('hide')) clickoutside(selection); - else { - d3.select('body').on('click.outside', null); - selection.on('click.inside', null); - } - return !content.classed('hide'); - }); - }); + .on('click.layerswitcher-toggle', toggle); - function clickoutside(selection) { - selection - .on('click.inside', function() { - return d3.event.stopPropagation(); - }); - d3.select('body') - .on('click.outside', function() { - toggle.on('click.toggle').apply(toggle.node(), d3.event); - }); + function show() { setVisible(true); } + function hide() { setVisible(false); } + function toggle() { setVisible(content.classed('hide')); } + + function setVisible(show) { + button.classed('active', show); + content.classed('hide', !show); } - opa = content + function clickoutside(selection) { + selection.on('click.layerswitcher-inside', function() { + return d3.event.stopPropagation(); + }); + d3.select('body').on('click.layerswitcher-outside', hide); + } + + var opa = content .append('div') .attr('class', 'opacity-options-wrapper fillL2') .html("Layers") @@ -116,6 +108,8 @@ iD.layerswitcher = function(map) { .insert('span') .attr('class','icon toggle'); + + selection.call(clickoutside); selectLayer(map.background.source()); } diff --git a/test/index.html b/test/index.html index 85d99fc74..7e5abcda2 100644 --- a/test/index.html +++ b/test/index.html @@ -42,6 +42,7 @@ + @@ -107,6 +108,7 @@ + diff --git a/test/spec/ui/geocoder.js b/test/spec/ui/geocoder.js new file mode 100644 index 000000000..7a2ad5f89 --- /dev/null +++ b/test/spec/ui/geocoder.js @@ -0,0 +1,6 @@ +describe("Geocoder", function () { + it('can be instantiated', function () { + var geocoder = iD.geocoder(); + expect(geocoder).to.be.ok; + }); +});