/* globals setPath, history */ var queryString = require('query-string') function get () { var state = {} // repo if (global.mainRepo !== '') { state.repo = global.mainRepo } // path if (currentPath) { state.path = currentPath } // location if (typeof map.getZoom() !== 'undefined') { var center = map.getCenter().wrap() var zoom = map.getZoom() state.lat = center.lat state.lon = center.lng state.zoom = zoom } // other modules call_hooks('state-get', state) // done return state } function apply (state) { // path setPath(state.path, state) // location if (state.lat && state.lon && state.zoom) { if (typeof map.getZoom() === 'undefined') { map.setView({ lat: state.lat, lng: state.lon }, state.zoom) } else { map.flyTo({ lat: state.lat, lng: state.lon }, state.zoom) } } // other modules call_hooks('state-apply', state) } function stringify (state) { var link = '' if (!state) { state = get() } var tmpState = JSON.parse(JSON.stringify(state)) // path if (state.path) { link += state.path delete tmpState.path } // location var locPrecision = 5 if (state.zoom) { locPrecision = state.zoom > 16 ? 5 : state.zoom > 8 ? 4 : state.zoom > 4 ? 3 : state.zoom > 2 ? 2 : state.zoom > 1 ? 1 : 0 } if (state.zoom && state.lat && state.lon) { link += (link === '' ? '' : '&') + 'map=' + parseFloat(state.zoom).toFixed(0) + '/' + state.lat.toFixed(locPrecision) + '/' + state.lon.toFixed(locPrecision) delete tmpState.zoom delete tmpState.lat delete tmpState.lon } var newHash = queryString.stringify(tmpState) // Characters we dont's want escaped newHash = newHash.replace(/%2F/g, '/') newHash = newHash.replace(/%2C/g, ',') if (newHash !== '') { link += (link === '' ? '' : '&') + newHash } return link } function parse (link) { var firstEquals = link.search('=') var firstAmp = link.search('&') var urlNonPathPart = '' var newState = {} var newPath = '' if (link === '') { // nothing } else if (firstEquals === -1) { if (firstAmp === -1) { newPath = link } else { newPath = link.substr(0, firstAmp) } } else { if (firstAmp === -1) { urlNonPathPart = link } else if (firstAmp < firstEquals) { newPath = link.substr(0, firstAmp) urlNonPathPart = link.substr(firstAmp + 1) } else { urlNonPathPart = link } } newState = queryString.parse(urlNonPathPart) if (newPath !== '') { newState.path = newPath } if ('map' in newState) { var parts = newState.map.split('/') newState.zoom = parts[0] newState.lat = parts[1] newState.lon = parts[2] delete newState.map } return newState } function update (state, push) { if (!state) { state = get() } var newHash = '#' + stringify(state) call_hooks('state-update', state, newHash) if (push) { history.pushState(null, null, newHash) call_hooks('statePush', state, newHash) } else if (location.hash !== newHash && (location.hash !== '' || newHash !== '#')) { history.replaceState(null, null, newHash) call_hooks('stateReplace', state, newHash) } } module.exports = { get: get, // get the current app state apply: apply, // apply a state to the current app stringify: stringify, // create a link from a state (or the current state) parse: parse, // parse a state from a link update: update // update url (either replace or push) }