You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
3.5 KiB

  1. /* globals setPath, history */
  2. var queryString = require('query-string')
  3. function get () {
  4. var state = {}
  5. // repo
  6. if (global.mainRepo !== '') {
  7. state.repo = global.mainRepo
  8. }
  9. // path
  10. if (currentPath) {
  11. state.path = currentPath
  12. }
  13. // location
  14. if (typeof map.getZoom() !== 'undefined') {
  15. var center = map.getCenter().wrap()
  16. var zoom = map.getZoom()
  17. state.lat = center.lat
  18. state.lon = center.lng
  19. state.zoom = zoom
  20. }
  21. // other modules
  22. call_hooks('state-get', state)
  23. // done
  24. return state
  25. }
  26. function apply (state) {
  27. // path
  28. setPath(state.path, state)
  29. // location
  30. if (state.lat && state.lon && state.zoom) {
  31. if (typeof map.getZoom() === 'undefined') {
  32. map.setView({ lat: state.lat, lng: state.lon }, state.zoom)
  33. } else {
  34. map.flyTo({ lat: state.lat, lng: state.lon }, state.zoom)
  35. }
  36. }
  37. // other modules
  38. call_hooks('state-apply', state)
  39. }
  40. function stringify (state) {
  41. var link = ''
  42. if (!state) {
  43. state = get()
  44. }
  45. var tmpState = JSON.parse(JSON.stringify(state))
  46. // path
  47. if (state.path) {
  48. link += state.path
  49. delete tmpState.path
  50. }
  51. // location
  52. var locPrecision = 5
  53. if (state.zoom) {
  54. locPrecision =
  55. state.zoom > 16 ? 5
  56. : state.zoom > 8 ? 4
  57. : state.zoom > 4 ? 3
  58. : state.zoom > 2 ? 2
  59. : state.zoom > 1 ? 1
  60. : 0
  61. }
  62. if (state.zoom && state.lat && state.lon) {
  63. link += (link === '' ? '' : '&') + 'map=' +
  64. parseFloat(state.zoom).toFixed(0) + '/' +
  65. state.lat.toFixed(locPrecision) + '/' +
  66. state.lon.toFixed(locPrecision)
  67. delete tmpState.zoom
  68. delete tmpState.lat
  69. delete tmpState.lon
  70. }
  71. var newHash = queryString.stringify(tmpState)
  72. // Characters we dont's want escaped
  73. newHash = newHash.replace(/%2F/g, '/')
  74. newHash = newHash.replace(/%2C/g, ',')
  75. if (newHash !== '') {
  76. link += (link === '' ? '' : '&') + newHash
  77. }
  78. return link
  79. }
  80. function parse (link) {
  81. var firstEquals = link.search('=')
  82. var firstAmp = link.search('&')
  83. var urlNonPathPart = ''
  84. var newState = {}
  85. var newPath = ''
  86. if (link === '') {
  87. // nothing
  88. } else if (firstEquals === -1) {
  89. if (firstAmp === -1) {
  90. newPath = link
  91. } else {
  92. newPath = link.substr(0, firstAmp)
  93. }
  94. } else {
  95. if (firstAmp === -1) {
  96. urlNonPathPart = link
  97. } else if (firstAmp < firstEquals) {
  98. newPath = link.substr(0, firstAmp)
  99. urlNonPathPart = link.substr(firstAmp + 1)
  100. } else {
  101. urlNonPathPart = link
  102. }
  103. }
  104. newState = queryString.parse(urlNonPathPart)
  105. if (newPath !== '') {
  106. newState.path = newPath
  107. }
  108. if ('map' in newState) {
  109. var parts = newState.map.split('/')
  110. newState.zoom = parts[0]
  111. newState.lat = parts[1]
  112. newState.lon = parts[2]
  113. delete newState.map
  114. }
  115. return newState
  116. }
  117. function update (state, push) {
  118. if (!state) {
  119. state = get()
  120. }
  121. var newHash = '#' + stringify(state)
  122. call_hooks('state-update', state, newHash)
  123. if (push) {
  124. history.pushState(null, null, newHash)
  125. call_hooks('statePush', state, newHash)
  126. } else if (location.hash !== newHash && (location.hash !== '' || newHash !== '#')) {
  127. history.replaceState(null, null, newHash)
  128. call_hooks('stateReplace', state, newHash)
  129. }
  130. }
  131. module.exports = {
  132. get: get, // get the current app state
  133. apply: apply, // apply a state to the current app
  134. stringify: stringify, // create a link from a state (or the current state)
  135. parse: parse, // parse a state from a link
  136. update: update // update url (either replace or push)
  137. }