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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ddfe5960094bf8bbd1f7250eea1b7470eb04dfe3
4
+ data.tar.gz: 233456b00d6ea184176015a33e739039a5358a68
5
+ SHA512:
6
+ metadata.gz: 29489a93eb3b3fba23d0769c825579911dbefe1317d3061a856ad484636179cf42a96789579e26c5eee90b5db280bec21734a330b118a45b097b823ac15daa0b
7
+ data.tar.gz: 221131a3db6c00fdd8d2331d50574f5aa5ce60746f037bf165e13c92074a832e65e0b1f0764ac2bec74049d374e47f95a7621ce4cf0188283913334b48a5d34e
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014-2016 Ekylibre, Jérémie Bonal
2
+
3
+ The MIT LICENSE
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # Foliage
2
+
3
+ Extracted from [Ekylibre's repo](http://github.com/ekylibre/ekylibre) as part of the [Osmosis](http://github.com/Aquaj/osmosis) fork, this gem provides convenient helpers, javascript and styles to quickly and easily display maps.
4
+
5
+ Based on [Leaflet.js](http://leafletjs.com).
6
+
7
+ ## Dependencies
8
+
9
+ `// TODO`
File without changes
@@ -0,0 +1,67 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+
4
+ <svg
5
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
6
+ xmlns:cc="http://creativecommons.org/ns#"
7
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8
+ xmlns:svg="http://www.w3.org/2000/svg"
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12
+ id="svg2"
13
+ version="1.1"
14
+ inkscape:version="0.91 r13725"
15
+ width="25"
16
+ height="41"
17
+ viewBox="0 0 25 41"
18
+ sodipodi:docname="icon.svg">
19
+ <metadata
20
+ id="metadata8">
21
+ <rdf:RDF>
22
+ <cc:Work
23
+ rdf:about="">
24
+ <dc:format>image/svg+xml</dc:format>
25
+ <dc:type
26
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
27
+ <dc:title></dc:title>
28
+ </cc:Work>
29
+ </rdf:RDF>
30
+ </metadata>
31
+ <defs
32
+ id="defs6" />
33
+ <sodipodi:namedview
34
+ pagecolor="#ffffff"
35
+ bordercolor="#666666"
36
+ borderopacity="1"
37
+ objecttolerance="10"
38
+ gridtolerance="10"
39
+ guidetolerance="10"
40
+ inkscape:pageopacity="0"
41
+ inkscape:pageshadow="2"
42
+ inkscape:window-width="1920"
43
+ inkscape:window-height="1057"
44
+ id="namedview4"
45
+ showgrid="false"
46
+ borderlayer="true"
47
+ inkscape:showpageshadow="false"
48
+ inkscape:zoom="5.7560976"
49
+ inkscape:cx="-82.783211"
50
+ inkscape:cy="-19.01566"
51
+ inkscape:window-x="0"
52
+ inkscape:window-y="0"
53
+ inkscape:window-maximized="1"
54
+ inkscape:current-layer="svg2" />
55
+ <path
56
+ style="fill:#187fce;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.75420874"
57
+ d="M 12.5,1 C 6.8467643,0.94037552 0.90011975,5.0932125 1,13 1.101235,21.014031 10.609264,28.121771 12.5,40 14.347762,28.312508 23.976551,21.962273 24,13 24.02093,5.0006739 18.153235,1.0596245 12.5,1 Z m 0.181641,7.3398438 c 2.494371,-3.473e-4 4.516847,2.0212542 4.517578,4.5156252 3.47e-4,2.495133 -2.022445,4.517925 -4.517578,4.517578 C 10.18727,17.372316 8.1656683,15.34984 8.1660156,12.855469 8.1667464,10.361861 10.188033,8.3405745 12.681641,8.3398438 Z"
58
+ id="path4138"
59
+ inkscape:connector-curvature="0"
60
+ sodipodi:nodetypes="sscssccccc" />
61
+ <path
62
+ style="fill:#1886d8;fill-opacity:0.85858583;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.53535354"
63
+ d="M 12.509053,0.90052064 C 6.855818,0.84089624 0.90917349,4.9937331 1.0090537,12.900521 c 0.101235,8.014031 9.6092633,15.121771 11.4999993,27 1.847762,-11.687492 11.476551,-18.037727 11.5,-27 0.02093,-7.9993265 -5.846765,-11.94037586 -11.5,-12.00000036 z m 0.181641,7.33984376 c 2.494371,-3.473e-4 4.516847,2.0212546 4.517578,4.5156256 3.47e-4,2.495133 -2.022445,4.517925 -4.517578,4.517578 C 10.196323,17.272837 8.174722,15.250361 8.1750693,12.75599 8.1758001,10.262382 10.197086,8.2410951 12.690694,8.2403644 Z"
64
+ id="path4138-3"
65
+ inkscape:connector-curvature="0"
66
+ sodipodi:nodetypes="sscssccccc" />
67
+ </svg>
@@ -0,0 +1,61 @@
1
+ # Core extension for vizualisation
2
+ #
3
+ String.prototype.camelize = () ->
4
+ array = jQuery.map this.split("_"), (word)->
5
+ word.charAt(0).toUpperCase() + word.slice(1)
6
+ return array.join()
7
+
8
+ String.prototype.repeat = (count) ->
9
+ return new Array(count + 1).join(this)
10
+
11
+ Math.magnitude = (number, step = 1) ->
12
+ value = Math.abs(number)
13
+ power = 0
14
+ if value > 1
15
+ while Math.pow(10, power + step) < value
16
+ power += step
17
+ else
18
+ while Math.pow(10, power - step) > value
19
+ power -= step
20
+ mag = Math.pow(10, power)
21
+ result =
22
+ power: power
23
+ magnitude: mag
24
+ base: number / mag
25
+
26
+ Math.round2 = (number, round = 1) ->
27
+ return round * Math.round(number / round)
28
+
29
+ Math.humanize = (value, power = 0) ->
30
+ return Math.round(value)
31
+ # return Math.round(value / Math.pow(10, power)) + "e#{power}"
32
+ size = Math.round(power / 3)
33
+ return Math.round(value / Math.pow(10, 3 * size)) + "pnµm KMGTPE"[size + 4]
34
+
35
+ Math.ceil2 = (number, round = 1) ->
36
+ return round * Math.ceil(number / round)
37
+
38
+ Math.floor2 = (number, round = 1) ->
39
+ return round * Math.floor(number / round)
40
+
41
+ # Returns logarithm value in given base (10 by default)
42
+ Math.logg = (value, base = 10) ->
43
+ return Math.log(value) / Math.log(base)
44
+
45
+ # Compute number of decimal
46
+ # Negative value is return if trailing zero are found.
47
+ # Ex: 200 => -2
48
+ # 0.12500 => 3
49
+ # 0.125 => 3
50
+ # 125 => 0
51
+ Math.decimalCount = (value) ->
52
+ return 0 if value == 0
53
+ count = 0
54
+ integersCount = Math.ceil(Math.logg(Math.floor(value)))
55
+ value /= Math.pow(10, integersCount)
56
+ while (value != Math.floor(value))
57
+ count += 1
58
+ value *= 10
59
+ break if count > 100
60
+ return count - integersCount
61
+
@@ -0,0 +1,23 @@
1
+ # Add sprockets directives below:
2
+
3
+ #= require jquery
4
+ #= require jquery-ui
5
+ #= require jquery_ujs
6
+ #= require turbolinks
7
+ #= require_self
8
+ #= require geographiclib
9
+ #= require leaflet.js.erb
10
+ #= require leaflet/draw
11
+ #= require leaflet/fullscreen
12
+ #= require leaflet/providers
13
+ #= require leaflet/heatmap
14
+ #= require leaflet/measure
15
+ #= require leaflet/easy-button
16
+ #= require leaflet/modal
17
+ #= require leaflet/label
18
+ #= require rbush
19
+ #= require autosize
20
+ #= require_tree ./leaflet
21
+ #= require foliage/leaf
22
+
23
+ this.Foliage = {};
@@ -0,0 +1,99 @@
1
+ class Foliage.Band
2
+
3
+ constructor: (@layer, @data, options = {}) ->
4
+ @items = []
5
+ property = @layer.reference
6
+ console.log "Property: ", property
7
+ previous = null
8
+ minValue = null
9
+ maxValue = null
10
+ for zone in @data
11
+ minValue ?= zone[property]
12
+ maxValue ?= zone[property]
13
+ minValue = zone[property] if minValue > zone[property]
14
+ maxValue = zone[property] if maxValue < zone[property]
15
+ if previous
16
+ @items.push
17
+ polygon: this.computeTrapez({x: previous.shape.coordinates[1], y: previous.shape.coordinates[0], w: previous.width}, {x: zone.shape.coordinates[1], y: zone.shape.coordinates[0], w: zone.width})
18
+ value: zone[property]
19
+ style:
20
+ stroke: false
21
+ fillOpacity: 1
22
+ previous = zone
23
+ if this.valid()
24
+ start = new Foliage.Color(options.startColor)
25
+ stop = new Foliage.Color(options.stopColor)
26
+ console.log(maxValue, minValue)
27
+ for item in @items
28
+ level = (item.value - minValue) / (maxValue - minValue)
29
+ item.style.fillColor = Foliage.Color.toString
30
+ red: start.red + (Math.round(stop.red - start.red) * level)
31
+ green: start.green + (Math.round(stop.green - start.green) * level)
32
+ blue: start.blue + (Math.round(stop.blue - start.blue) * level)
33
+ console.log "Bands computed"
34
+ else
35
+ console.warn "Invalid bands"
36
+
37
+ # Build layer as wanted
38
+ buildLayerGroup: (widget, globalStyle = {}) ->
39
+ group = []
40
+ for item in @items
41
+ edge = new L.polygon(item.polygon, item.style)
42
+ group.push(edge)
43
+ group
44
+
45
+ # Build HTML legend for given bands computed layer
46
+ buildLegend: () ->
47
+ html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
48
+ html += "<h3>#{@layer.label}</h3>"
49
+ # html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
50
+ # html += "<span class='leaflet-categories-items'>"
51
+ # html += "<span class='leaflet-categories-item'>"
52
+ # html += "<i class='leaflet-categories-sample' style='background-color: #{@items[0].fillColor};'></i>"
53
+ # html += " #{@layer.label}"
54
+ # html += "</span>"
55
+ # html += "</span>"
56
+ # html += "</div>"
57
+ html += "</div>"
58
+ return html
59
+
60
+ # Returns the item matching the given name
61
+ itemFor: (name) ->
62
+ back = null
63
+ @items.forEach (item, index, array) ->
64
+ back = item if item.name == name
65
+ return back
66
+
67
+ # Check if bands are valid
68
+ valid: () ->
69
+ @items.length > 0
70
+
71
+ # http://stackoverflow.com/questions/7854043/drawing-rectangle-between-two-points-with-arbitrary-width
72
+ computeTrapez: (a, b) ->
73
+ # Calculate a vector between start and end points
74
+ v =
75
+ x: b.x - a.x
76
+ y: b.y - a.y
77
+
78
+ # Then calculate a perpendicular to it (just swap X and Y coordinates)
79
+ p =
80
+ x: v.y # Use separate variable otherwise you overwrite X coordinate here
81
+ y: -v.x # Flip the sign of either the X or Y (edit by adam.wulf)
82
+
83
+ # Normalize that perpendicular
84
+ l = Math.sqrt(p.x * p.x + p.y * p.y); # That's length of perpendicular
85
+ n =
86
+ x: p.x / l
87
+ y: p.y / l # Now N is normalized perpendicular
88
+
89
+ # Calculate 4 points that form a rectangle by adding normalized perpendicular and multiplying it by half of the desired width
90
+ ar = (a.w / 2) * 9 / 1000000
91
+ br = (b.w / 2) * 9 / 1000000
92
+ r1 = new L.LatLng(a.x + n.x * ar, a.y + n.y * ar)
93
+ r2 = new L.LatLng(a.x - n.x * ar, a.y - n.y * ar)
94
+ r3 = new L.LatLng(b.x + n.x * br, b.y + n.y * br)
95
+ r4 = new L.LatLng(b.x - n.x * br, b.y - n.y * br)
96
+ return [r1, r2, r4, r3]
97
+
98
+
99
+ Foliage.registerLayerType "band", Foliage.Band
@@ -0,0 +1,77 @@
1
+ # Add sprockets directives below:
2
+ #= require foliage/gradient
3
+ #
4
+
5
+ class Foliage.Bubbles extends Foliage.Gradient
6
+
7
+ constructor: (@layer, @data, options = {}) ->
8
+ options.levelNumber ?= 5
9
+
10
+ super @data, @layer.reference, options
11
+
12
+ if this.valid()
13
+
14
+ # Compute radius
15
+ options.startRadius ?= 4
16
+ options.stopRadius ?= 24
17
+ start = options.startRadius
18
+ stop = options.stopRadius
19
+ for grade in @grades
20
+ level = grade.index / (@levelNumber - 1.0)
21
+ grade.radius = start + Math.round((stop - start) * level)
22
+ grade.fillColor = options.fillColor
23
+ grade.color = options.color
24
+ grade.weight = options.weight
25
+ grade.stroke = options.stroke
26
+ console.log "Radiuses computed"
27
+ else
28
+ console.warn "Invalid bubbles"
29
+
30
+ # Build layer as wanted
31
+ buildLayerGroup: (widget, globalStyle = {}) ->
32
+ group = []
33
+ # Shadow
34
+ for zone in @data
35
+ grade = this.gradeFor(zone[@layer.reference])
36
+ if grade.stroke
37
+ zoneStyle =
38
+ fillColor: grade.color
39
+ radius: grade.radius + grade.weight
40
+ stroke: false
41
+ fillOpacity: 0.8
42
+ group.push new L.CircleMarker(this._centroid(zone.shape), zoneStyle)
43
+ # Core
44
+ for zone in @data
45
+ grade = this.gradeFor(zone[@layer.reference])
46
+ zoneStyle =
47
+ fillColor: grade.fillColor
48
+ radius: grade.radius
49
+ stroke: false
50
+ fillOpacity: 1
51
+ zoneLayer = new L.CircleMarker(this._centroid(zone.shape), zoneStyle)
52
+ widget._bindPopup(zoneLayer, zone)
53
+ group.push(zoneLayer)
54
+ group
55
+
56
+ # Build HTML legend for given bubbles 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-bubbles-scale'>"
61
+ html += "<span class='min-value'>#{@grades[0].minLabel}</span>"
62
+ html += "<span class='leaflet-bubbles-grades'>"
63
+ for grade in @grades
64
+ html += "<i class='leaflet-bubbles-grade' style='width: #{2 * grade.radius}px; height: #{2 * grade.radius}px; background-color: #{grade.fillColor}; border-width: #{grade.weight}px; border-color: #{grade.color}' title='#{grade.minLabel} ~ #{grade.maxLabel}'></i>"
65
+ html += "</span>"
66
+ html += "<span class='max-value'>#{@grades[@levelNumber - 1].maxLabel}</span>"
67
+ html += "</div>"
68
+ html += "</div>"
69
+ return html
70
+
71
+ # Compute a centroid based on bounds
72
+ # The point can be out of the surface...
73
+ _centroid: (shape) ->
74
+ geojson = new L.GeoJSON(shape)
75
+ return geojson.getBounds().getCenter()
76
+
77
+ Foliage.registerLayerType "bubbles", Foliage.Bubbles
@@ -0,0 +1,70 @@
1
+ class Foliage.Categories
2
+
3
+ constructor: (@layer, @data, options = {}) ->
4
+ @items = []
5
+ property = @layer.reference
6
+ for zone in @data
7
+ unless this.itemFor(zone[property])
8
+ @items.push
9
+ name: zone[property],
10
+ color: zone['shapeColor']
11
+
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(options.parent.options.colors[x] ? "#000000")
19
+ for item, index in @items
20
+ if item.color?
21
+ item.fillColor = item.color
22
+ else
23
+ item.fillColor = @colors[index]
24
+
25
+ console.log "Categories computed"
26
+ else
27
+ console.warn "Invalid categories"
28
+
29
+ # Build layer as wanted
30
+ buildLayerGroup: (widget, globalStyle = {}) ->
31
+ group = []
32
+ for zone in @data
33
+ zoneStyle =
34
+ fillColor: this.itemFor(zone[@layer.reference]).fillColor
35
+ zoneLayer = new L.GeoJSON(zone.shape, $.extend(true, {}, globalStyle, zoneStyle))
36
+ widget._bindPopup(zoneLayer, zone)
37
+ unless @layer.withoutGhostLabel
38
+ label = new L.GhostLabel(className: 'leaflet-ghost-label', toBack: false).setContent(zone.name).toCentroidOfBounds(zoneLayer.getLayers()[0].getLatLngs())
39
+ widget.ghostLabelCluster.bind label, zoneLayer.getLayers()[0]
40
+ group.push(zoneLayer)
41
+ group
42
+
43
+ # Build HTML legend for given categories computed layer
44
+ buildLegend: () ->
45
+ html = "<div class='leaflet-legend-item' id='legend-#{@layer.name}'>"
46
+ html += "<h3>#{@layer.label}</h3>"
47
+ html += "<div class='leaflet-legend-body leaflet-categories-scale'>"
48
+ html += "<span class='leaflet-categories-items'>"
49
+ for name, item of @items
50
+ html += "<span class='leaflet-categories-item'>"
51
+ html += "<i class='leaflet-categories-sample' style='background-color: #{item.fillColor};'></i>"
52
+ html += " <span class='leaflet-categories-item_label'>#{item.name}</span>"
53
+ html += "</span>"
54
+ html += "</span>"
55
+ html += "</div>"
56
+ html += "</div>"
57
+ return html
58
+
59
+ # Returns the item matching the given name
60
+ itemFor: (name) ->
61
+ back = null
62
+ @items.forEach (item, index, array) ->
63
+ back = item if item.name == name
64
+ return back
65
+
66
+ # Check if categories are valid
67
+ valid: () ->
68
+ @items.length > 0
69
+
70
+ Foliage.registerLayerType "categories", Foliage.Categories