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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. var L = require('leaflet')
  2. require('./layout.css')
  3. require('./range.css')
  4. var mapWasDragEnabled
  5. var mapWasTapEnabled
  6. // Leaflet v0.7 backwards compatibility
  7. function on (el, types, fn, context) {
  8. types.split(' ').forEach(function (type) {
  9. L.DomEvent.on(el, type, fn, context)
  10. })
  11. }
  12. // Leaflet v0.7 backwards compatibility
  13. function off (el, types, fn, context) {
  14. types.split(' ').forEach(function (type) {
  15. L.DomEvent.off(el, type, fn, context)
  16. })
  17. }
  18. function getRangeEvent (rangeInput) {
  19. return 'oninput' in rangeInput ? 'input' : 'change'
  20. }
  21. function cancelMapDrag () {
  22. mapWasDragEnabled = this._map.dragging.enabled()
  23. mapWasTapEnabled = this._map.tap && this._map.tap.enabled()
  24. this._map.dragging.disable()
  25. this._map.tap && this._map.tap.disable()
  26. }
  27. function uncancelMapDrag (e) {
  28. this._refocusOnMap(e)
  29. if (mapWasDragEnabled) {
  30. this._map.dragging.enable()
  31. }
  32. if (mapWasTapEnabled) {
  33. this._map.tap.enable()
  34. }
  35. }
  36. // convert arg to an array - returns empty array if arg is undefined
  37. function asArray (arg) {
  38. return (arg === 'undefined') ? [] : Array.isArray(arg) ? arg : [arg]
  39. }
  40. function noop () {
  41. return
  42. }
  43. L.Control.SideBySide = L.Control.extend({
  44. options: {
  45. thumbSize: 42,
  46. padding: 0
  47. },
  48. initialize: function (leftLayers, rightLayers, options) {
  49. this.setLeftLayers(leftLayers)
  50. this.setRightLayers(rightLayers)
  51. L.setOptions(this, options)
  52. },
  53. getPosition: function () {
  54. var rangeValue = this._range.value
  55. var offset = (0.5 - rangeValue) * (2 * this.options.padding + this.options.thumbSize)
  56. return this._map.getSize().x * rangeValue + offset
  57. },
  58. setPosition: noop,
  59. includes: L.Mixin.Events,
  60. addTo: function (map) {
  61. this.remove()
  62. this._map = map
  63. var container = this._container = L.DomUtil.create('div', 'leaflet-sbs', map._controlContainer)
  64. this._divider = L.DomUtil.create('div', 'leaflet-sbs-divider', container)
  65. var range = this._range = L.DomUtil.create('input', 'leaflet-sbs-range', container)
  66. range.type = 'range'
  67. range.min = 0
  68. range.max = 1
  69. range.step = 'any'
  70. range.value = 0.5
  71. range.style.paddingLeft = range.style.paddingRight = this.options.padding + 'px'
  72. this._addEvents()
  73. this._updateLayers()
  74. return this
  75. },
  76. remove: function () {
  77. if (!this._map) {
  78. return this
  79. }
  80. if (this._leftLayer) {
  81. this._leftLayer.getContainer().style.clip = ""
  82. }
  83. if (this._rightLayer) {
  84. this._rightLayer.getContainer().style.clip = ""
  85. }
  86. this._removeEvents()
  87. L.DomUtil.remove(this._container)
  88. this._map = null
  89. return this
  90. },
  91. setLeftLayers: function (leftLayers) {
  92. this._leftLayers = asArray(leftLayers)
  93. this._updateLayers()
  94. return this
  95. },
  96. setRightLayers: function (rightLayers) {
  97. this._rightLayers = asArray(rightLayers)
  98. this._updateLayers()
  99. return this
  100. },
  101. _updateClip: function () {
  102. var map = this._map
  103. var nw = map.containerPointToLayerPoint([0, 0])
  104. var se = map.containerPointToLayerPoint(map.getSize())
  105. var clipX = nw.x + this.getPosition()
  106. var dividerX = this.getPosition()
  107. this._divider.style.left = dividerX + 'px'
  108. this.fire('dividermove', {x: dividerX})
  109. var clipLeft = 'rect(' + [nw.y, clipX, se.y, nw.x].join('px,') + 'px)'
  110. var clipRight = 'rect(' + [nw.y, se.x, se.y, clipX].join('px,') + 'px)'
  111. if (this._leftLayer) {
  112. this._leftLayer.getContainer().style.clip = clipLeft
  113. }
  114. if (this._rightLayer) {
  115. this._rightLayer.getContainer().style.clip = clipRight
  116. }
  117. },
  118. _updateLayers: function () {
  119. if (!this._map) {
  120. return this
  121. }
  122. var prevLeft = this._leftLayer
  123. var prevRight = this._rightLayer
  124. this._leftLayer = this._rightLayer = null
  125. this._leftLayers.forEach(function (layer) {
  126. if (this._map.hasLayer(layer)) {
  127. this._leftLayer = layer
  128. }
  129. }, this)
  130. this._rightLayers.forEach(function (layer) {
  131. if (this._map.hasLayer(layer)) {
  132. this._rightLayer = layer
  133. }
  134. }, this)
  135. if (prevLeft !== this._leftLayer) {
  136. prevLeft && this.fire('leftlayerremove', {layer: prevLeft})
  137. this._leftLayer && this.fire('leftlayeradd', {layer: this._leftLayer})
  138. }
  139. if (prevRight !== this._rightLayer) {
  140. prevRight && this.fire('rightlayerremove', {layer: prevRight})
  141. this._rightLayer && this.fire('rightlayeradd', {layer: this._rightLayer})
  142. }
  143. this._updateClip()
  144. },
  145. _addEvents: function () {
  146. var range = this._range
  147. var map = this._map
  148. if (!map || !range) return
  149. map.on('move', this._updateClip, this)
  150. map.on('layeradd layerremove', this._updateLayers, this)
  151. on(range, getRangeEvent(range), this._updateClip, this)
  152. on(range, L.Browser.touch ? 'touchstart' : 'mousedown', cancelMapDrag, this)
  153. on(range, L.Browser.touch ? 'touchend' : 'mouseup', uncancelMapDrag, this)
  154. },
  155. _removeEvents: function () {
  156. var range = this._range
  157. var map = this._map
  158. if (range) {
  159. off(range, getRangeEvent(range), this._updateClip, this)
  160. off(range, L.Browser.touch ? 'touchstart' : 'mousedown', cancelMapDrag, this)
  161. off(range, L.Browser.touch ? 'touchend' : 'mouseup', uncancelMapDrag, this)
  162. }
  163. if (map) {
  164. map.off('layeradd layerremove', this._updateLayers, this)
  165. map.off('move', this._updateClip, this)
  166. }
  167. }
  168. })
  169. L.control.sideBySide = function (leftLayers, rightLayers, options) {
  170. return new L.Control.SideBySide(leftLayers, rightLayers, options)
  171. }
  172. module.exports = L.Control.SideBySide