foliage 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +9 -0
  4. data/app/assets/images/.keep +0 -0
  5. data/app/assets/images/map/marker/icon-2x.png +0 -0
  6. data/app/assets/images/map/marker/icon.png +0 -0
  7. data/app/assets/images/map/marker/icon.svg +67 -0
  8. data/app/assets/images/map/marker/shadow.png +0 -0
  9. data/app/assets/javascripts/core_ext.js.coffee +61 -0
  10. data/app/assets/javascripts/foliage.js.coffee +23 -0
  11. data/app/assets/javascripts/foliage/band.js.coffee +99 -0
  12. data/app/assets/javascripts/foliage/bubbles.js.coffee +77 -0
  13. data/app/assets/javascripts/foliage/categories.js.coffee +70 -0
  14. data/app/assets/javascripts/foliage/choropleth.js.coffee +51 -0
  15. data/app/assets/javascripts/foliage/color.js.coffee +39 -0
  16. data/app/assets/javascripts/foliage/gradient.js.coffee +72 -0
  17. data/app/assets/javascripts/foliage/heatmap.js.coffee +49 -0
  18. data/app/assets/javascripts/foliage/leaf.js.coffee +422 -0
  19. data/app/assets/javascripts/foliage/path.js.coffee +76 -0
  20. data/app/assets/javascripts/foliage/paths.js.coffee +131 -0
  21. data/app/assets/javascripts/foliage/point_group.js.coffee +83 -0
  22. data/app/assets/javascripts/foliage/points.js.coffee +79 -0
  23. data/app/assets/javascripts/foliage/simple.js.coffee +35 -0
  24. data/app/assets/javascripts/leaflet/geographic_util.js.coffee +23 -0
  25. data/app/assets/javascripts/leaflet/ghost_label.js.coffee +100 -0
  26. data/app/assets/javascripts/leaflet/ghost_label_cluster.js.coffee +192 -0
  27. data/app/assets/javascripts/leaflet/layers_scheduler.js.coffee +57 -0
  28. data/app/assets/javascripts/leaflet/reactive_measure.js.coffee +414 -0
  29. data/app/assets/stylesheets/all.scss +16 -0
  30. data/app/assets/stylesheets/application.css +15 -0
  31. data/app/assets/stylesheets/compass/reset.scss +3 -0
  32. data/app/assets/stylesheets/compass/reset/utilities.scss +142 -0
  33. data/app/assets/stylesheets/leaflet.scss +1093 -0
  34. data/app/assets/stylesheets/leaflet/label.scss +40 -0
  35. data/app/assets/stylesheets/leaflet/tooltip.scss +42 -0
  36. data/app/assets/stylesheets/mixins.scss +131 -0
  37. data/app/assets/stylesheets/reset.scss +89 -0
  38. data/app/assets/stylesheets/variables.scss +47 -0
  39. data/app/helpers/foliage_helper.rb +23 -0
  40. data/lib/foliage.rb +9 -0
  41. data/lib/foliage/leaf.rb +235 -0
  42. data/lib/foliage/rails.rb +2 -0
  43. data/lib/foliage/rails/engine.rb +7 -0
  44. data/lib/foliage/rails/integration.rb +8 -0
  45. data/lib/foliage/version.rb +3 -0
  46. data/vendor/assets/javascripts/.keep +0 -0
  47. data/vendor/assets/javascripts/autosize.js +211 -0
  48. data/vendor/assets/javascripts/geographiclib.js +3074 -0
  49. data/vendor/assets/javascripts/leaflet.js.erb +9175 -0
  50. data/vendor/assets/javascripts/leaflet/draw.js +3573 -0
  51. data/vendor/assets/javascripts/leaflet/easy-button.js +366 -0
  52. data/vendor/assets/javascripts/leaflet/fullscreen.js +162 -0
  53. data/vendor/assets/javascripts/leaflet/heatmap.js +142 -0
  54. data/vendor/assets/javascripts/leaflet/label.js +545 -0
  55. data/vendor/assets/javascripts/leaflet/measure.js +6966 -0
  56. data/vendor/assets/javascripts/leaflet/modal.js +364 -0
  57. data/vendor/assets/javascripts/leaflet/providers.js +479 -0
  58. data/vendor/assets/javascripts/rbush.js +621 -0
  59. data/vendor/assets/stylesheets/.keep +0 -0
  60. data/vendor/assets/stylesheets/bootstrap/mixins.scss +55 -0
  61. data/vendor/assets/stylesheets/bootstrap/variables.scss +10 -0
  62. data/vendor/assets/stylesheets/leaflet.scss +479 -0
  63. data/vendor/assets/stylesheets/leaflet/draw.scss +282 -0
  64. data/vendor/assets/stylesheets/leaflet/easy-button.scss +56 -0
  65. data/vendor/assets/stylesheets/leaflet/fullscreen.scss +2 -0
  66. data/vendor/assets/stylesheets/leaflet/measure.scss +168 -0
  67. data/vendor/assets/stylesheets/leaflet/modal.scss +85 -0
  68. metadata +171 -0
@@ -0,0 +1,76 @@
1
+ # Foliage.Paths class
2
+ # displays crumbs by intervention as a path
3
+ #
4
+ # @data is an array of hashes containing info to display
5
+ # @layer is the layer name
6
+ #
7
+ # ==== examples
8
+ #
9
+ # @data is an array of hashes built according to the following model:
10
+ # * minimal example of a hash representing a crumb:
11
+ # item {
12
+ # name: <intervention name>, # may be the date, the doer's name,
13
+ # # whatever you want as long as all the crumbs
14
+ # # for a given intervention have the same one.
15
+ # # This is what is called in the
16
+ # # FoliageHelper to build the legend if
17
+ # # you wrote something like:
18
+ # # = foliage do |leaf|
19
+ # # - leaf.serie :crumbs, my_array_of_crumbs_hashes
20
+ # # - leaf.paths :name, :crumbs
21
+ # # :name being the @layer parameter the constructor requires.
22
+ # nature: crumb.nature, # proper to the crumb. May be one of the natures
23
+ # # enumerated in Crumb model.
24
+ # # this option is used to display particular points
25
+ # # bigger and to change the path opacity for parts
26
+ # # that correspond to actual works (points between a
27
+ # # hard_start) and a hard_stop crumb
28
+ # shape: crumb.geolocation, # proper to the crumb. contains the actual crumb
29
+ # # location as a Charta::Geometry object.
30
+ # # This is what is used to draw the crumb on the map
31
+ # }
32
+ class Foliage.Path
33
+
34
+ constructor: (@layer, @data, @options = {}) ->
35
+ if this.valid()
36
+ @options.color ?= Foliage.colors[0]
37
+ @options.fillColor ?= @options.color
38
+ console.log "Paths computed", @options
39
+ else
40
+ console.warn "Invalid paths"
41
+
42
+ # Build layer as wanted
43
+ buildLayerGroup: (widget, globalStyle = {}) ->
44
+ group = []
45
+ for crumb in @data
46
+ crumbLayer = new L.circleMarker(new L.geoJson(crumb.shape).getBounds().getCenter(), $.extend(true, {}, globalStyle, @options, {className: "crumb crumb-#{crumb.name}"}))
47
+ widget._bindPopup(crumbLayer, crumb)
48
+ group.push(crumbLayer)
49
+ previous_crumb = @data[@data.indexOf(crumb) - 1]
50
+ if previous_crumb
51
+ points = []
52
+ points.push(new L.geoJson(previous_crumb.shape).getBounds().getCenter())
53
+ points.push(new L.geoJson(crumb.shape).getBounds().getCenter())
54
+ crumbLayer = new L.polyline(points, $.extend(true, {}, globalStyle, @options))
55
+ group.push(crumbLayer)
56
+ return group
57
+
58
+ # Build HTML legend for given paths computed layer
59
+ buildLegend: () ->
60
+ html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
61
+ html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
62
+ html += "<span class='leaflet-categories-items'>"
63
+ html += "<span class='leaflet-categories-item'>"
64
+ html += "<i class='leaflet-categories-sample' style='background-color: #{@options.color};'></i>"
65
+ html += " #{@layer.label}"
66
+ html += "</span>"
67
+ html += "</span>"
68
+ html += "</div>"
69
+ html += "</div>"
70
+ return html
71
+
72
+ # Check if paths are valid
73
+ valid: () ->
74
+ true
75
+
76
+ Foliage.registerLayerType "path", Foliage.Path
@@ -0,0 +1,131 @@
1
+ # Foliage.Paths class
2
+ # displays crumbs by intervention as a path
3
+ #
4
+ # @data is an array of hashes containing info to display
5
+ # @layer is the layer name
6
+ #
7
+ # ==== examples
8
+ #
9
+ # @data is an array of hashes built according to the following model:
10
+ # * minimal example of a hash representing a crumb:
11
+ # item {
12
+ # name: <intervention name>, # may be the date, the doer's name,
13
+ # # whatever you want as long as all the crumbs
14
+ # # for a given intervention have the same one.
15
+ # # This is what is called in the
16
+ # # FoliageHelper to build the legend if
17
+ # # you wrote something like:
18
+ # # = foliage do |leaf|
19
+ # # - leaf.serie :crumbs, my_array_of_crumbs_hashes
20
+ # # - leaf.paths :name, :crumbs
21
+ # # :name being the @layer parameter the constructor requires.
22
+ # nature: crumb.nature, # proper to the crumb. May be one of the natures
23
+ # # enumerated in Crumb model.
24
+ # # this option is used to display particular points
25
+ # # bigger and to change the path opacity for parts
26
+ # # that correspond to actual works (points between a
27
+ # # hard_start) and a hard_stop crumb
28
+ # shape: crumb.geolocation, # proper to the crumb. contains the actual crumb
29
+ # # location as a Charta::Geometry object.
30
+ # # This is what is used to draw the crumb on the map
31
+ # }
32
+ class Foliage.Paths
33
+
34
+ constructor: (@layer, @data, options = {}) ->
35
+ @items = []
36
+ property = @layer.reference
37
+ for crumb in @data
38
+ unless this.itemFor(crumb[property])
39
+ @items.push
40
+ name: crumb[property]
41
+
42
+ if this.valid()
43
+ @items = @items.sort (a, b) ->
44
+ a.name > b.name
45
+ @colors = options.colors ? []
46
+ if @items.length > @colors.length
47
+ for x in [@colors.length..@items.length]
48
+ @colors.push(Foliage.colors[x] ? "#000000")
49
+ for item, index in @items
50
+ item.fillColor = @colors[index]
51
+
52
+ console.log "Paths computed"
53
+ else
54
+ console.warn "Invalid paths"
55
+
56
+ # Build layer as wanted
57
+ buildLayerGroup: (widget, globalStyle = {}) ->
58
+ group = []
59
+ # defining styles
60
+ strokeWidth = 4
61
+ crumbStyle =
62
+ radius: strokeWidth
63
+ stroke: true
64
+ weight: strokeWidth/2
65
+ color: "#000000"
66
+ fillColor: "#FFFFFF"
67
+ opacity: 1
68
+ lineStyle =
69
+ weight: strokeWidth
70
+ stroke: true
71
+ color: this.itemFor(@data[0][@layer.reference]).fillColor
72
+ fillColor: "rgba(0,0,0,0)"
73
+ opacity: 1
74
+
75
+ # drawing line
76
+ points = []
77
+ current_name = @data[0].name
78
+ current_color = this.itemFor(@data[0][@layer.reference]).fillColor
79
+ for crumb in @data
80
+ if crumb.name != current_name
81
+ lineStyle.color = current_color
82
+ lineLayer = new L.polyline(points, $.extend(true, {}, globalStyle, lineStyle))
83
+ group.push(lineLayer)
84
+ points = []
85
+ current_name = crumb.name
86
+ current_color = this.itemFor(crumb[@layer.reference]).fillColor
87
+ points.push(new L.geoJson(crumb.shape).getBounds().getCenter())
88
+ if points.length > 0
89
+ lineStyle.color = current_color
90
+ lineLayer = new L.polyline(points, $.extend(true, {}, globalStyle, lineStyle))
91
+ group.push(lineLayer)
92
+ # drawing circles
93
+ for crumb in @data
94
+ crumbStyle.color= this.itemFor(crumb[@layer.reference]).fillColor
95
+ if crumb.nature == 'hard_start'
96
+ crumbStyle.fillColor = "#000000"
97
+ if crumb.nature == 'hard_stop'
98
+ crumbStyle.fillColor = "#FFFFFF"
99
+ crumbLayer = new L.circleMarker(new L.geoJson(crumb.shape).getBounds().getCenter(), $.extend(true, {}, globalStyle, crumbStyle))
100
+ widget._bindPopup(crumbLayer, crumb)
101
+ group.push(crumbLayer)
102
+ group
103
+
104
+ # Build HTML legend for given paths computed layer
105
+ buildLegend: () ->
106
+ html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
107
+ html += "<h3>#{@layer.label}</h3>"
108
+ html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
109
+ html += "<span class='leaflet-categories-items'>"
110
+ for name, item of @items
111
+ html += "<span class='leaflet-categories-item'>"
112
+ html += "<i class='leaflet-categories-sample' style='background-color: #{item.fillColor};'></i>"
113
+ html += " #{item.name}"
114
+ html += "</span>"
115
+ html += "</span>"
116
+ html += "</div>"
117
+ html += "</div>"
118
+ return html
119
+
120
+ # Returns the item matching the given name
121
+ itemFor: (name) ->
122
+ back = null
123
+ @items.forEach (item, index, array) ->
124
+ back = item if item.name == name
125
+ return back
126
+
127
+ # Check if paths are valid
128
+ valid: () ->
129
+ @items.length > 0
130
+
131
+ Foliage.registerLayerType "paths", Foliage.Paths
@@ -0,0 +1,83 @@
1
+ class Foliage.PointGroup
2
+
3
+ constructor: (@layer, @data, @options = {}) ->
4
+ @items = []
5
+ console.log "Layer: ", @layer
6
+ for zone in @data
7
+ lnglat = zone.shape.coordinates
8
+ @items.push
9
+ name: zone.name
10
+ point: [lnglat[1], lnglat[0]]
11
+ radius: zone.radius ? @options.radius
12
+ group: zone.group
13
+ fillColor: zone.shapeColor
14
+ popup: zone.popup
15
+ sensorId: zone.sensorId
16
+ if this.valid()
17
+ @items = @items.sort (a, b) ->
18
+ a.name > b.name
19
+ @groups = {}
20
+ for {group, name, fillColor} in @items
21
+ @groups[group] or= fillColor
22
+ console.log "Point group computed"
23
+ else
24
+ console.warn "Invalid categories"
25
+
26
+ # Build layer as wanted
27
+ buildLayerGroup: (widget, globalStyle = {}) ->
28
+ group = []
29
+ # Shadow
30
+ if @options.stroke
31
+ for zone in @items
32
+ zoneStyle =
33
+ fillColor: zone.color ? @options.color
34
+ radius: (zone.radius ? @options.radius) + @options.weight
35
+ stroke: false
36
+ fillOpacity: 0.8
37
+ console.log zone.point
38
+ shadow = new L.circleMarker(zone.point, zoneStyle)
39
+ shadow.markerSensorId = zone.sensorId
40
+ group.push shadow
41
+ # Core
42
+ for zone in @items
43
+ console.log zone
44
+ zoneStyle =
45
+ fillColor: zone.fillColor ? @options.fillColor
46
+ radius: zone.radius ? @options.radius
47
+ stroke: false
48
+ fillOpacity: 1
49
+ console.log zoneStyle
50
+ zoneLayer = new L.circleMarker(zone.point, zoneStyle)
51
+ zoneLayer.sensorId = zone.sensorId
52
+ widget._bindPopup(zoneLayer, zone)
53
+ group.push(zoneLayer)
54
+ group
55
+
56
+ # Build HTML legend for given points computed layer
57
+ buildLegend: () ->
58
+ html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
59
+ html += "<h3>#{@layer.label}</h3>"
60
+ html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
61
+ html += "<span class='leaflet-categories-items'>"
62
+ for group in Object.keys(@groups)
63
+ html += "<span class='leaflet-categories-item'>"
64
+ html += "<i class='leaflet-categories-sample' style='background-color: #{@groups[group]};'></i>"
65
+ html += " <span class='leaflet-categories-item_label'>#{group}</span>"
66
+ html += "</span>"
67
+ html += "</span>"
68
+ html += "</div>"
69
+ html += "</div>"
70
+ return html
71
+
72
+ # Returns the item matching the given name
73
+ itemFor: (name) ->
74
+ back = null
75
+ @items.forEach (item, index, array) ->
76
+ back = item if item.name == name
77
+ return back
78
+
79
+ # Check if categories are valid
80
+ valid: () ->
81
+ @items.length > 0
82
+
83
+ Foliage.registerLayerType "point_group", Foliage.PointGroup
@@ -0,0 +1,79 @@
1
+ class Foliage.Points
2
+
3
+ constructor: (@layer, @data, @options = {}) ->
4
+ @items = []
5
+ console.log "Layer: ", @layer
6
+ for zone in @data
7
+ lnglat = zone.shape.coordinates
8
+ @items.push
9
+ name: zone.name
10
+ point: [lnglat[1], lnglat[0]]
11
+ radius: zone.radius ? @options.radius
12
+ if this.valid()
13
+ @items = @items.sort (a, b) ->
14
+ a.name > b.name
15
+ @colors = @options.colors ? []
16
+ if @items.length > @colors.length
17
+ for x in [@colors.length..@items.length]
18
+ @colors.push(Foliage.colors[x] ? "#000000")
19
+ for item, index in @items
20
+ item.fillColor = @colors[index]
21
+ console.log "Points computed"
22
+ else
23
+ console.warn "Invalid categories"
24
+
25
+ # Build layer as wanted
26
+ buildLayerGroup: (widget, globalStyle = {}) ->
27
+ group = []
28
+ # Shadow
29
+ if @options.stroke
30
+ for zone in @items
31
+ zoneStyle =
32
+ fillColor: zone.color ? @options.color
33
+ radius: (zone.radius ? @options.radius) + @options.weight
34
+ stroke: false
35
+ fillOpacity: 0.8
36
+ console.log zone.point
37
+ group.push new L.circleMarker(zone.point, zoneStyle)
38
+ # Core
39
+ for zone in @items
40
+ console.log zone
41
+ zoneStyle =
42
+ fillColor: zone.fillColor ? @options.fillColor
43
+ radius: zone.radius ? @options.radius
44
+ stroke: false
45
+ fillOpacity: 1
46
+ console.log zoneStyle
47
+ zoneLayer = new L.circleMarker(zone.point, zoneStyle)
48
+ widget._bindPopup(zoneLayer, zone)
49
+ group.push(zoneLayer)
50
+ group
51
+
52
+ # Build HTML legend for given points computed layer
53
+ buildLegend: () ->
54
+ html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
55
+ html += "<h3>#{@layer.label}</h3>"
56
+ html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
57
+ html += "<span class='leaflet-categories-items'>"
58
+ for name, item of @items
59
+ html += "<span class='leaflet-categories-item'>"
60
+ html += "<i class='leaflet-categories-sample' style='background-color: #{item.fillColor};'></i>"
61
+ html += " #{item.name}"
62
+ html += "</span>"
63
+ html += "</span>"
64
+ html += "</div>"
65
+ html += "</div>"
66
+ return html
67
+
68
+ # Returns the item matching the given name
69
+ itemFor: (name) ->
70
+ back = null
71
+ @items.forEach (item, index, array) ->
72
+ back = item if item.name == name
73
+ return back
74
+
75
+ # Check if categories are valid
76
+ valid: () ->
77
+ @items.length > 0
78
+
79
+ Foliage.registerLayerType "points", Foliage.Points
@@ -0,0 +1,35 @@
1
+ class Foliage.Simple
2
+
3
+ constructor: (@layer, @data, @options = {}) ->
4
+
5
+ # Build layer as wanted
6
+ buildLayerGroup: (widget, globalStyle = {}) ->
7
+ group = []
8
+ for zone in @data
9
+ zoneLayer = new L.GeoJSON(zone.shape, globalStyle)
10
+ label = new L.GhostLabel(className: 'leaflet-ghost-label', toBack: false).setContent(zone.name).toCentroidOfBounds(zoneLayer.getLayers()[0].getLatLngs())
11
+ widget.ghostLabelCluster.bind label, zoneLayer.getLayers()[0]
12
+ widget._bindPopup(zoneLayer, zone)
13
+ group.push(zoneLayer)
14
+ group
15
+
16
+ # Build HTML legend for given categories computed layer
17
+ buildLegend: () ->
18
+ html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
19
+ # html += "<h3>#{@layer.label}</h3>"
20
+ html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
21
+ html += "<span class='leaflet-categories-items'>"
22
+ html += "<span class='leaflet-categories-item'>"
23
+ html += "<i class='leaflet-categories-sample' style='background-color: #{@layer.fillColor || @options.parent.options.layerDefaults[@layer.type].fillColor };'></i>"
24
+ html += " <span class='leaflet-categories-item_label'>#{@layer.label}</span>"
25
+ html += "</span>"
26
+ html += "</span>"
27
+ html += "</div>"
28
+ html += "</div>"
29
+ return html
30
+
31
+ # Check if categories are valid
32
+ valid: () ->
33
+ true
34
+
35
+ Foliage.registerLayerType "simple", Foliage.Simple
@@ -0,0 +1,23 @@
1
+ L.GeographicUtil = L.extend L.GeographicUtil || {},
2
+ geod: GeographicLib.Geodesic.WGS84
3
+
4
+ # Use Karney distance formula
5
+ # ([lat, lng], [lat, lng]) -> Number (in meters)
6
+ distance: (a, b) ->
7
+ r = @geod.Inverse(a[0], a[1], b[0], b[1])
8
+ r.s12.toFixed(3)
9
+
10
+ Polygon: (points) -> # (Array of [lat,lng] pair)
11
+ @geod = GeographicLib.Geodesic.WGS84
12
+ @poly = @geod.Polygon(false)
13
+ for point in points
14
+ @poly.AddPoint point[0], point[1]
15
+
16
+ @poly = @poly.Compute(false, true)
17
+ return
18
+
19
+ L.GeographicUtil.Polygon.prototype =
20
+ perimeter: ->
21
+ @poly.perimeter
22
+ area: ->
23
+ Math.abs @poly.area
@@ -0,0 +1,100 @@
1
+ ###
2
+ # Extend L.Label to provide a label on centroid, calculated from a L.Latlng[]
3
+ # options:
4
+ # toBack {boolean} if true, label is set to objectsPane, allowing to be covered by higher level pane
5
+ # opacity: {string} ([0..1] | 'inherit') inherit allows to use opacity in your class. Default: 'inherit'
6
+ ###
7
+ L.GhostLabel = L.Label.extend
8
+ __initialize: L.Label::initialize
9
+ _onAdd: L.Label.prototype.onAdd
10
+ __updateContent: L.Label.prototype._updateContent
11
+ __setOpacity: L.Label::setOpacity
12
+
13
+ initialize: (options, source) ->
14
+ options.opacity ||= 'inherit'
15
+
16
+ @__initialize.apply @, arguments
17
+
18
+ ###
19
+ # Set the latLng[] to calculate the centroid
20
+ ###
21
+ toCentroidOfBounds: (latLngs) ->
22
+ # To center of bounds if centroid can't be calculated during onAdd
23
+ @_latlng = L.latLngBounds(latLngs).getCenter()
24
+ @_latLngs = latLngs
25
+ return this
26
+
27
+ onAdd: (map) ->
28
+ # Don't hide labels on click
29
+ @options.noHide = true
30
+
31
+ if @options.toBack
32
+ @options.pane = 'objectsPane'
33
+
34
+ @_onAdd.apply this, arguments
35
+
36
+ map.on 'zoomend', @_onZoomEnd, @
37
+
38
+ if @options.toBack
39
+ # ZIndex 3 is default index of objectsPane
40
+ @updateZIndex '3'
41
+
42
+ @_updatePosition()
43
+ return
44
+
45
+ setOpacity: (opacity) ->
46
+ unless opacity is 'inherit'
47
+ @__setOpacity.call @, opacity
48
+
49
+ getLatLng: ->
50
+ @_latlng
51
+
52
+ _onZoomEnd: (e) ->
53
+ @getCenter(e.target)
54
+
55
+ getCenter: (map)->
56
+ if @_latLngs
57
+ poly = L.polygon(@_latLngs)
58
+ poly._map = @_map || map
59
+ @_latlng = poly.__getCenter()
60
+
61
+ @_latlng
62
+
63
+
64
+ ###
65
+ # Override to set position on pos, considering label center
66
+ ###
67
+ _setPosition: (pos) ->
68
+ map = @_map
69
+ container = @_container
70
+ labelWidth = @_labelWidth
71
+ labelHeight = @_labelHeight || 0
72
+
73
+ pos = pos.add(L.point(-labelWidth/2, -labelHeight/2))
74
+ L.DomUtil.setPosition container, pos
75
+ return
76
+
77
+ ###
78
+ # Override to set position on pos, considering label center
79
+ ###
80
+ _updateContent: ->
81
+ @__updateContent.call this
82
+ @_labelHeight = @_container.offsetHeight if @_container
83
+
84
+
85
+ L.extendedMethods =
86
+ # Allow to be updated
87
+ bindGhostLabel: (object, options) ->
88
+
89
+ if !@label
90
+ @label = object
91
+
92
+ if !@_showLabelAdded
93
+ @on 'remove', @_hideLabel, @
94
+
95
+ @_showLabelAdded = true
96
+ return
97
+
98
+ L.Polygon.include L.extendedMethods
99
+ L.FeatureGroup.include L.extendedMethods
100
+