Have utilStringQs advance past any leading '?' or '#' characters

This lets us remove a bunch of substring(1) and +1 from the code.
This commit is contained in:
Bryan Housel
2020-02-20 17:09:54 -05:00
parent 1f4fe57d8b
commit dc7fba4bf8
10 changed files with 61 additions and 38 deletions

View File

@@ -39,7 +39,7 @@ export function behaviorHash(context) {
var center = map.center(); var center = map.center();
var zoom = map.zoom(); var zoom = map.zoom();
var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)); var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
var q = utilObjectOmit(utilStringQs(window.location.hash.substring(1)), var q = utilObjectOmit(utilStringQs(window.location.hash),
['comment', 'source', 'hashtags', 'walkthrough'] ['comment', 'source', 'hashtags', 'walkthrough']
); );
var newParams = {}; var newParams = {};
@@ -91,7 +91,7 @@ export function behaviorHash(context) {
.on('hashchange.hash', hashchange); .on('hashchange.hash', hashchange);
if (window.location.hash) { if (window.location.hash) {
var q = utilStringQs(window.location.hash.substring(1)); var q = utilStringQs(window.location.hash);
if (q.id) { if (q.id) {
context.zoomToEntity(q.id.split(',')[0], !q.map); context.zoomToEntity(q.id.split(',')[0], !q.map);

View File

@@ -203,7 +203,7 @@ export function rendererBackground(context) {
const EPSILON = 0.01; const EPSILON = 0.01;
const x = +meters[0].toFixed(2); const x = +meters[0].toFixed(2);
const y = +meters[1].toFixed(2); const y = +meters[1].toFixed(2);
let q = utilStringQs(window.location.hash.substring(1)); let hash = utilStringQs(window.location.hash);
let id = currSource.id; let id = currSource.id;
if (id === 'custom') { if (id === 'custom') {
@@ -211,25 +211,25 @@ export function rendererBackground(context) {
} }
if (id) { if (id) {
q.background = id; hash.background = id;
} else { } else {
delete q.background; delete hash.background;
} }
if (o) { if (o) {
q.overlays = o; hash.overlays = o;
} else { } else {
delete q.overlays; delete hash.overlays;
} }
if (Math.abs(x) > EPSILON || Math.abs(y) > EPSILON) { if (Math.abs(x) > EPSILON || Math.abs(y) > EPSILON) {
q.offset = `${x},${y}`; hash.offset = `${x},${y}`;
} else { } else {
delete q.offset; delete hash.offset;
} }
if (!window.mocha) { if (!window.mocha) {
window.location.replace('#' + utilQsString(q, true)); window.location.replace('#' + utilQsString(hash, true));
} }
let imageryUsed = []; let imageryUsed = [];
@@ -444,9 +444,9 @@ export function rendererBackground(context) {
return geoExtent([params[2], params[1]]); // lon,lat return geoExtent([params[2], params[1]]); // lon,lat
} }
const q = utilStringQs(window.location.hash.substring(1)); const hash = utilStringQs(window.location.hash);
const requested = q.background || q.layer; const requested = hash.background || hash.layer;
let extent = parseMapParams(q.map); let extent = parseMapParams(hash.map);
ensureImageryIndex() ensureImageryIndex()
.then(imageryIndex => { .then(imageryIndex => {
@@ -479,7 +479,7 @@ export function rendererBackground(context) {
background.toggleOverlayLayer(locator); background.toggleOverlayLayer(locator);
} }
const overlays = (q.overlays || '').split(','); const overlays = (hash.overlays || '').split(',');
overlays.forEach(overlay => { overlays.forEach(overlay => {
overlay = background.findSource(overlay); overlay = background.findSource(overlay);
if (overlay) { if (overlay) {
@@ -487,15 +487,15 @@ export function rendererBackground(context) {
} }
}); });
if (q.gpx) { // todo: move elsewhere - this doesn't belong in background if (hash.gpx) { // todo: move elsewhere - this doesn't belong in background
const gpx = context.layers().layer('data'); const gpx = context.layers().layer('data');
if (gpx) { if (gpx) {
gpx.url(q.gpx, '.gpx'); gpx.url(hash.gpx, '.gpx');
} }
} }
if (q.offset) { if (hash.offset) {
const offset = q.offset const offset = hash.offset
.replace(/;/g, ',') .replace(/;/g, ',')
.split(',') .split(',')
.map(n => !isNaN(n) && n); .map(n => !isNaN(n) && n);

View File

@@ -64,14 +64,14 @@ export function rendererFeatures(context) {
function update() { function update() {
if (!window.mocha) { if (!window.mocha) {
var q = utilStringQs(window.location.hash.substring(1)); var hash = utilStringQs(window.location.hash);
var disabled = features.disabled(); var disabled = features.disabled();
if (disabled.length) { if (disabled.length) {
q.disable_features = disabled.join(','); hash.disable_features = disabled.join(',');
} else { } else {
delete q.disable_features; delete hash.disable_features;
} }
window.location.replace('#' + utilQsString(q, true)); window.location.replace('#' + utilQsString(hash, true));
context.storage('disabled-features', disabled.join(',')); context.storage('disabled-features', disabled.join(','));
} }
_hidden = features.hidden(); _hidden = features.hidden();
@@ -579,9 +579,9 @@ export function rendererFeatures(context) {
storageDisabled.forEach(features.disable); storageDisabled.forEach(features.disable);
} }
var q = utilStringQs(window.location.hash.substring(1)); var hash = utilStringQs(window.location.hash);
if (q.disable_features) { if (hash.disable_features) {
var hashDisabled = q.disable_features.replace(/;/g, ',').split(','); var hashDisabled = hash.disable_features.replace(/;/g, ',').split(',');
hashDisabled.forEach(features.disable); hashDisabled.forEach(features.disable);
} }
}; };

View File

@@ -15,18 +15,18 @@ export function rendererPhotos(context) {
function updateStorage() { function updateStorage() {
if (window.mocha) return; if (window.mocha) return;
var q = utilStringQs(window.location.hash.substring(1)); var hash = utilStringQs(window.location.hash);
var enabled = context.layers().all().filter(function(d) { var enabled = context.layers().all().filter(function(d) {
return _layerIDs.indexOf(d.id) !== -1 && d.layer && d.layer.supported() && d.layer.enabled(); return _layerIDs.indexOf(d.id) !== -1 && d.layer && d.layer.supported() && d.layer.enabled();
}).map(function(d) { }).map(function(d) {
return d.id; return d.id;
}); });
if (enabled.length) { if (enabled.length) {
q.photo_overlay = enabled.join(','); hash.photo_overlay = enabled.join(',');
} else { } else {
delete q.photo_overlay; delete hash.photo_overlay;
} }
window.location.replace('#' + utilQsString(q, true)); window.location.replace('#' + utilQsString(hash, true));
} }
photos.overlayLayerIDs = function() { photos.overlayLayerIDs = function() {
@@ -73,9 +73,9 @@ export function rendererPhotos(context) {
}; };
photos.init = function() { photos.init = function() {
var q = utilStringQs(window.location.hash.substring(1)); var hash = utilStringQs(window.location.hash);
if (q.photo_overlay) { if (hash.photo_overlay) {
var hashOverlayIDs = q.photo_overlay.replace(/;/g, ',').split(','); var hashOverlayIDs = hash.photo_overlay.replace(/;/g, ',').split(',');
hashOverlayIDs.forEach(function(id) { hashOverlayIDs.forEach(function(id) {
var layer = context.layers().layer(id); var layer = context.layers().layer(id);
if (layer) layer.enabled(true); if (layer) layer.enabled(true);

View File

@@ -318,6 +318,10 @@ export function utilCombinedTags(entityIDs, graph) {
export function utilStringQs(str) { export function utilStringQs(str) {
var i = 0; // advance past any leading '?' or '#' characters
while (i < str.length && (str[i] === '?' || str[i] === '#')) i++;
str = str.slice(i);
return str.split('&').reduce(function(obj, pair){ return str.split('&').reduce(function(obj, pair){
var parts = pair.split('='); var parts = pair.split('=');
if (parts.length === 2) { if (parts.length === 2) {

View File

@@ -21,7 +21,7 @@ describe('iD.serviceNominatim', function() {
}); });
function query(url) { function query(url) {
return iD.utilStringQs(url.substring(url.indexOf('?') + 1)); return iD.utilStringQs(url.substring(url.indexOf('?')));
} }

View File

@@ -21,7 +21,7 @@ describe('iD.serviceOsmWikibase', function () {
function query(url) { function query(url) {
return iD.utilStringQs(url.substring(url.indexOf('?') + 1)); return iD.utilStringQs(url.substring(url.indexOf('?')));
} }
function adjust(params, data) { function adjust(params, data) {

View File

@@ -31,7 +31,7 @@ describe('iD.serviceTaginfo', function() {
}); });
function query(url) { function query(url) {
return iD.utilStringQs(url.substring(url.indexOf('?') + 1)); return iD.utilStringQs(url.substring(url.indexOf('?')));
} }

View File

@@ -7,6 +7,8 @@ for (var k in iD.services) { delete iD.services[k]; }
// Run without data for speed (tests which need data can set it up themselves) // Run without data for speed (tests which need data can set it up themselves)
// Initializing `coreContext` will try loading the English locale strings:
iD.data.locale_en = { en: {} };
// Initializing `coreContext` initializes `_background`, which tries loading: // Initializing `coreContext` initializes `_background`, which tries loading:
iD.data.imagery = []; iD.data.imagery = [];
// Initializing `coreContext` initializes `_presets`, which tries loading: // Initializing `coreContext` initializes `_presets`, which tries loading:

View File

@@ -79,9 +79,26 @@ describe('iD.util', function() {
}); });
it('utilStringQs', function() { it('utilStringQs', function() {
expect(iD.utilStringQs('foo=bar')).to.eql({foo: 'bar'}); it('splits a parameter string into k=v pairs', function() {
expect(iD.utilStringQs('foo=bar&one=2')).to.eql({foo: 'bar', one: '2' }); expect(iD.utilStringQs('foo=bar')).to.eql({foo: 'bar'});
expect(iD.utilStringQs('')).to.eql({}); expect(iD.utilStringQs('foo=bar&one=2')).to.eql({foo: 'bar', one: '2' });
expect(iD.utilStringQs('')).to.eql({});
});
it('trims leading # if present', function() {
expect(iD.utilStringQs('#foo=bar')).to.eql({foo: 'bar'});
expect(iD.utilStringQs('#foo=bar&one=2')).to.eql({foo: 'bar', one: '2' });
expect(iD.utilStringQs('#')).to.eql({});
});
it('trims leading ? if present', function() {
expect(iD.utilStringQs('?foo=bar')).to.eql({foo: 'bar'});
expect(iD.utilStringQs('?foo=bar&one=2')).to.eql({foo: 'bar', one: '2' });
expect(iD.utilStringQs('?')).to.eql({});
});
it('trims leading #? if present', function() {
expect(iD.utilStringQs('#?foo=bar')).to.eql({foo: 'bar'});
expect(iD.utilStringQs('#?foo=bar&one=2')).to.eql({foo: 'bar', one: '2' });
expect(iD.utilStringQs('#?')).to.eql({});
});
}); });
it('utilQsString', function() { it('utilQsString', function() {