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.
- checksums.yaml +7 -0
 - data/LICENSE.txt +22 -0
 - data/README.md +9 -0
 - data/app/assets/images/.keep +0 -0
 - data/app/assets/images/map/marker/icon-2x.png +0 -0
 - data/app/assets/images/map/marker/icon.png +0 -0
 - data/app/assets/images/map/marker/icon.svg +67 -0
 - data/app/assets/images/map/marker/shadow.png +0 -0
 - data/app/assets/javascripts/core_ext.js.coffee +61 -0
 - data/app/assets/javascripts/foliage.js.coffee +23 -0
 - data/app/assets/javascripts/foliage/band.js.coffee +99 -0
 - data/app/assets/javascripts/foliage/bubbles.js.coffee +77 -0
 - data/app/assets/javascripts/foliage/categories.js.coffee +70 -0
 - data/app/assets/javascripts/foliage/choropleth.js.coffee +51 -0
 - data/app/assets/javascripts/foliage/color.js.coffee +39 -0
 - data/app/assets/javascripts/foliage/gradient.js.coffee +72 -0
 - data/app/assets/javascripts/foliage/heatmap.js.coffee +49 -0
 - data/app/assets/javascripts/foliage/leaf.js.coffee +422 -0
 - data/app/assets/javascripts/foliage/path.js.coffee +76 -0
 - data/app/assets/javascripts/foliage/paths.js.coffee +131 -0
 - data/app/assets/javascripts/foliage/point_group.js.coffee +83 -0
 - data/app/assets/javascripts/foliage/points.js.coffee +79 -0
 - data/app/assets/javascripts/foliage/simple.js.coffee +35 -0
 - data/app/assets/javascripts/leaflet/geographic_util.js.coffee +23 -0
 - data/app/assets/javascripts/leaflet/ghost_label.js.coffee +100 -0
 - data/app/assets/javascripts/leaflet/ghost_label_cluster.js.coffee +192 -0
 - data/app/assets/javascripts/leaflet/layers_scheduler.js.coffee +57 -0
 - data/app/assets/javascripts/leaflet/reactive_measure.js.coffee +414 -0
 - data/app/assets/stylesheets/all.scss +16 -0
 - data/app/assets/stylesheets/application.css +15 -0
 - data/app/assets/stylesheets/compass/reset.scss +3 -0
 - data/app/assets/stylesheets/compass/reset/utilities.scss +142 -0
 - data/app/assets/stylesheets/leaflet.scss +1093 -0
 - data/app/assets/stylesheets/leaflet/label.scss +40 -0
 - data/app/assets/stylesheets/leaflet/tooltip.scss +42 -0
 - data/app/assets/stylesheets/mixins.scss +131 -0
 - data/app/assets/stylesheets/reset.scss +89 -0
 - data/app/assets/stylesheets/variables.scss +47 -0
 - data/app/helpers/foliage_helper.rb +23 -0
 - data/lib/foliage.rb +9 -0
 - data/lib/foliage/leaf.rb +235 -0
 - data/lib/foliage/rails.rb +2 -0
 - data/lib/foliage/rails/engine.rb +7 -0
 - data/lib/foliage/rails/integration.rb +8 -0
 - data/lib/foliage/version.rb +3 -0
 - data/vendor/assets/javascripts/.keep +0 -0
 - data/vendor/assets/javascripts/autosize.js +211 -0
 - data/vendor/assets/javascripts/geographiclib.js +3074 -0
 - data/vendor/assets/javascripts/leaflet.js.erb +9175 -0
 - data/vendor/assets/javascripts/leaflet/draw.js +3573 -0
 - data/vendor/assets/javascripts/leaflet/easy-button.js +366 -0
 - data/vendor/assets/javascripts/leaflet/fullscreen.js +162 -0
 - data/vendor/assets/javascripts/leaflet/heatmap.js +142 -0
 - data/vendor/assets/javascripts/leaflet/label.js +545 -0
 - data/vendor/assets/javascripts/leaflet/measure.js +6966 -0
 - data/vendor/assets/javascripts/leaflet/modal.js +364 -0
 - data/vendor/assets/javascripts/leaflet/providers.js +479 -0
 - data/vendor/assets/javascripts/rbush.js +621 -0
 - data/vendor/assets/stylesheets/.keep +0 -0
 - data/vendor/assets/stylesheets/bootstrap/mixins.scss +55 -0
 - data/vendor/assets/stylesheets/bootstrap/variables.scss +10 -0
 - data/vendor/assets/stylesheets/leaflet.scss +479 -0
 - data/vendor/assets/stylesheets/leaflet/draw.scss +282 -0
 - data/vendor/assets/stylesheets/leaflet/easy-button.scss +56 -0
 - data/vendor/assets/stylesheets/leaflet/fullscreen.scss +2 -0
 - data/vendor/assets/stylesheets/leaflet/measure.scss +168 -0
 - data/vendor/assets/stylesheets/leaflet/modal.scss +85 -0
 - metadata +171 -0
 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .leaflet-label {
         
     | 
| 
      
 2 
     | 
    
         
            +
              color: black;
         
     | 
| 
      
 3 
     | 
    
         
            +
              font-size: 14px;
         
     | 
| 
      
 4 
     | 
    
         
            +
              display: block;
         
     | 
| 
      
 5 
     | 
    
         
            +
              padding: 0.5*10px 10px;
         
     | 
| 
      
 6 
     | 
    
         
            +
              position: absolute;
         
     | 
| 
      
 7 
     | 
    
         
            +
              pointer-events: none;
         
     | 
| 
      
 8 
     | 
    
         
            +
              white-space: nowrap;
         
     | 
| 
      
 9 
     | 
    
         
            +
              z-index: 1;
         
     | 
| 
      
 10 
     | 
    
         
            +
              text-shadow: 0 0 2px white;
         
     | 
| 
      
 11 
     | 
    
         
            +
              text-shadow: 2px 0 0 #fff, -2px 0 0 #fff, 0 2px 0 #fff, 0 -2px 0 #fff, 1px 1px #fff, -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff;
         
     | 
| 
      
 12 
     | 
    
         
            +
              &.leaflet-clickable {
         
     | 
| 
      
 13 
     | 
    
         
            +
                cursor: pointer;
         
     | 
| 
      
 14 
     | 
    
         
            +
                pointer-events: auto;
         
     | 
| 
      
 15 
     | 
    
         
            +
              }
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              &:before, &:after {
         
     | 
| 
      
 18 
     | 
    
         
            +
                border-top: 6px solid transparent;
         
     | 
| 
      
 19 
     | 
    
         
            +
                border-bottom: 6px solid transparent;
         
     | 
| 
      
 20 
     | 
    
         
            +
                content: none;
         
     | 
| 
      
 21 
     | 
    
         
            +
                position: absolute;
         
     | 
| 
      
 22 
     | 
    
         
            +
                top: 5px;
         
     | 
| 
      
 23 
     | 
    
         
            +
              }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              &:before {
         
     | 
| 
      
 26 
     | 
    
         
            +
                border-right: 6px solid black;
         
     | 
| 
      
 27 
     | 
    
         
            +
                border-right-color: inherit;
         
     | 
| 
      
 28 
     | 
    
         
            +
                left: -10px;
         
     | 
| 
      
 29 
     | 
    
         
            +
              }
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              &:after {
         
     | 
| 
      
 32 
     | 
    
         
            +
                border-left: 6px solid black;
         
     | 
| 
      
 33 
     | 
    
         
            +
                border-left-color: inherit;
         
     | 
| 
      
 34 
     | 
    
         
            +
                right: -10px;
         
     | 
| 
      
 35 
     | 
    
         
            +
              }
         
     | 
| 
      
 36 
     | 
    
         
            +
            }
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            .leaflet-label-right:before, .leaflet-label-left:after {
         
     | 
| 
      
 39 
     | 
    
         
            +
              content: "";
         
     | 
| 
      
 40 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            .leaflet-draw-tooltip-left {
         
     | 
| 
      
 2 
     | 
    
         
            +
              background: rgb(54, 54, 54);
         
     | 
| 
      
 3 
     | 
    
         
            +
              background: rgba(0, 0, 0, 0.5);
         
     | 
| 
      
 4 
     | 
    
         
            +
              border: 1px solid transparent;
         
     | 
| 
      
 5 
     | 
    
         
            +
              position: absolute;
         
     | 
| 
      
 6 
     | 
    
         
            +
              visibility: hidden;
         
     | 
| 
      
 7 
     | 
    
         
            +
              white-space: nowrap;
         
     | 
| 
      
 8 
     | 
    
         
            +
              z-index: 6;
         
     | 
| 
      
 9 
     | 
    
         
            +
              &:before {
         
     | 
| 
      
 10 
     | 
    
         
            +
                border: none !important;
         
     | 
| 
      
 11 
     | 
    
         
            +
              }
         
     | 
| 
      
 12 
     | 
    
         
            +
              &:after {
         
     | 
| 
      
 13 
     | 
    
         
            +
                border-left: 6px solid black;
         
     | 
| 
      
 14 
     | 
    
         
            +
                border-left-color: rgba(0, 0, 0, 0.5);
         
     | 
| 
      
 15 
     | 
    
         
            +
                border-top: 6px solid transparent;
         
     | 
| 
      
 16 
     | 
    
         
            +
                border-bottom: 6px solid transparent;
         
     | 
| 
      
 17 
     | 
    
         
            +
                content: "";
         
     | 
| 
      
 18 
     | 
    
         
            +
                position: absolute;
         
     | 
| 
      
 19 
     | 
    
         
            +
                top: 7px;
         
     | 
| 
      
 20 
     | 
    
         
            +
                left: 100%;
         
     | 
| 
      
 21 
     | 
    
         
            +
              }
         
     | 
| 
      
 22 
     | 
    
         
            +
              span {
         
     | 
| 
      
 23 
     | 
    
         
            +
                color: inherit;
         
     | 
| 
      
 24 
     | 
    
         
            +
              }
         
     | 
| 
      
 25 
     | 
    
         
            +
            }
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            .leaflet-draw-tooltip-measure {
         
     | 
| 
      
 28 
     | 
    
         
            +
              &.perimeter {
         
     | 
| 
      
 29 
     | 
    
         
            +
              }
         
     | 
| 
      
 30 
     | 
    
         
            +
              &.area {
         
     | 
| 
      
 31 
     | 
    
         
            +
                padding-left: 10px
         
     | 
| 
      
 32 
     | 
    
         
            +
              }
         
     | 
| 
      
 33 
     | 
    
         
            +
            }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            .reactive-measure-control {
         
     | 
| 
      
 36 
     | 
    
         
            +
              background: rgba(255,255,255, 0.6);
         
     | 
| 
      
 37 
     | 
    
         
            +
              padding: 0 10px;
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              &.selection {
         
     | 
| 
      
 40 
     | 
    
         
            +
                background: rgba(mix(white, red), 0.5);
         
     | 
| 
      
 41 
     | 
    
         
            +
              }
         
     | 
| 
      
 42 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,131 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            @import "bootstrap/mixins";
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            @mixin calc($property, $expression) {
         
     | 
| 
      
 4 
     | 
    
         
            +
              #{$property}: -webkit-calc(#{$expression});
         
     | 
| 
      
 5 
     | 
    
         
            +
              #{$property}: -khtml-calc(#{$expression});
         
     | 
| 
      
 6 
     | 
    
         
            +
              #{$property}: -moz-calc(#{$expression});
         
     | 
| 
      
 7 
     | 
    
         
            +
              #{$property}: -ms-calc(#{$expression});
         
     | 
| 
      
 8 
     | 
    
         
            +
              #{$property}: -o-calc(#{$expression});
         
     | 
| 
      
 9 
     | 
    
         
            +
              #{$property}: calc(#{$expression});
         
     | 
| 
      
 10 
     | 
    
         
            +
            }
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            @mixin prefixed-property($property, $value) {
         
     | 
| 
      
 13 
     | 
    
         
            +
              -webkit-#{$property}: $value;
         
     | 
| 
      
 14 
     | 
    
         
            +
              -khtml-#{$property}: $value;
         
     | 
| 
      
 15 
     | 
    
         
            +
              -moz-#{$property}: $value;
         
     | 
| 
      
 16 
     | 
    
         
            +
              -ms-#{$property}: $value;
         
     | 
| 
      
 17 
     | 
    
         
            +
              -o-#{$property}: $value;
         
     | 
| 
      
 18 
     | 
    
         
            +
              #{$property}: $value;
         
     | 
| 
      
 19 
     | 
    
         
            +
            }
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            @mixin border-radius($radius) {
         
     | 
| 
      
 22 
     | 
    
         
            +
              @include prefixed-property(border-radius, $radius);
         
     | 
| 
      
 23 
     | 
    
         
            +
            }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            @mixin inline-block($alignment: middle) {
         
     | 
| 
      
 26 
     | 
    
         
            +
              display: -moz-inline-stack;
         
     | 
| 
      
 27 
     | 
    
         
            +
              display: inline-block;
         
     | 
| 
      
 28 
     | 
    
         
            +
              @if $alignment and $alignment != none {
         
     | 
| 
      
 29 
     | 
    
         
            +
                vertical-align: $alignment;
         
     | 
| 
      
 30 
     | 
    
         
            +
              }
         
     | 
| 
      
 31 
     | 
    
         
            +
            }
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            @mixin basic-icon($font-size: null) {
         
     | 
| 
      
 35 
     | 
    
         
            +
              font-family: Agric;
         
     | 
| 
      
 36 
     | 
    
         
            +
              font-weight: normal;
         
     | 
| 
      
 37 
     | 
    
         
            +
              font-style: normal;
         
     | 
| 
      
 38 
     | 
    
         
            +
              text-decoration: inherit;
         
     | 
| 
      
 39 
     | 
    
         
            +
              -webkit-font-smoothing: antialiased;
         
     | 
| 
      
 40 
     | 
    
         
            +
              width: auto;
         
     | 
| 
      
 41 
     | 
    
         
            +
              height: auto;
         
     | 
| 
      
 42 
     | 
    
         
            +
              background-image: none;
         
     | 
| 
      
 43 
     | 
    
         
            +
              background-position: 0% 0%;
         
     | 
| 
      
 44 
     | 
    
         
            +
              background-repeat: repeat;
         
     | 
| 
      
 45 
     | 
    
         
            +
              margin-top: 0;
         
     | 
| 
      
 46 
     | 
    
         
            +
              @if $font-size != null {
         
     | 
| 
      
 47 
     | 
    
         
            +
                font-size: $font-size;
         
     | 
| 
      
 48 
     | 
    
         
            +
              }
         
     | 
| 
      
 49 
     | 
    
         
            +
            }
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            @mixin is-icon($font-size: round(1.2 * $fs-normal)) {
         
     | 
| 
      
 52 
     | 
    
         
            +
              @include basic-icon($font-size);
         
     | 
| 
      
 53 
     | 
    
         
            +
              vertical-align: middle;
         
     | 
| 
      
 54 
     | 
    
         
            +
            }
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            @mixin use-icon($name) {
         
     | 
| 
      
 57 
     | 
    
         
            +
              &::before { content: icon-character($name); }
         
     | 
| 
      
 58 
     | 
    
         
            +
            }
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            @mixin define-right-property($base-name, $value) {
         
     | 
| 
      
 62 
     | 
    
         
            +
              html & { #{$base-name}-right: $value; }
         
     | 
| 
      
 63 
     | 
    
         
            +
              html[dir="ltr"] & { #{$base-name}-right: $value; }
         
     | 
| 
      
 64 
     | 
    
         
            +
              html[dir="rtl"] & { #{$base-name}-left: $value; }
         
     | 
| 
      
 65 
     | 
    
         
            +
            }
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            @mixin define-left-property($base-name, $value) {
         
     | 
| 
      
 68 
     | 
    
         
            +
              html & { #{$base-name}-left: $value; }
         
     | 
| 
      
 69 
     | 
    
         
            +
              html[dir="ltr"] & { #{$base-name}-left: $value; }
         
     | 
| 
      
 70 
     | 
    
         
            +
              html[dir="rtl"] & { #{$base-name}-right: $value; }
         
     | 
| 
      
 71 
     | 
    
         
            +
            }
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            @mixin margin-right($value) { @include define-right-property(margin, $value); }
         
     | 
| 
      
 74 
     | 
    
         
            +
            @mixin margin-left($value)  { @include define-left-property(margin, $value); }
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            @mixin text-align($dir) {
         
     | 
| 
      
 77 
     | 
    
         
            +
              @if $dir == right {
         
     | 
| 
      
 78 
     | 
    
         
            +
                html & { text-align: right; }
         
     | 
| 
      
 79 
     | 
    
         
            +
                html[dir="ltr"] & { text-align: right; }
         
     | 
| 
      
 80 
     | 
    
         
            +
                html[dir="rtl"] & { text-align: left; }
         
     | 
| 
      
 81 
     | 
    
         
            +
              } @else if $dir == left {
         
     | 
| 
      
 82 
     | 
    
         
            +
                html & { text-align: left; }
         
     | 
| 
      
 83 
     | 
    
         
            +
                html[dir="ltr"] & { text-align: left; }
         
     | 
| 
      
 84 
     | 
    
         
            +
                html[dir="rtl"] & { text-align: right; }
         
     | 
| 
      
 85 
     | 
    
         
            +
              } @else {
         
     | 
| 
      
 86 
     | 
    
         
            +
                html &, html[dir="ltr"] &, html[dir="rtl"] & { text-align: $dir; }
         
     | 
| 
      
 87 
     | 
    
         
            +
              }
         
     | 
| 
      
 88 
     | 
    
         
            +
            }
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            @mixin float($dir) {
         
     | 
| 
      
 91 
     | 
    
         
            +
              @if $dir == right {
         
     | 
| 
      
 92 
     | 
    
         
            +
                html & { float: right; }
         
     | 
| 
      
 93 
     | 
    
         
            +
                html[dir="ltr"] & { float: right; }
         
     | 
| 
      
 94 
     | 
    
         
            +
                html[dir="rtl"] & { float: left; }
         
     | 
| 
      
 95 
     | 
    
         
            +
              } @else if $dir == left {
         
     | 
| 
      
 96 
     | 
    
         
            +
                html & { float: left; }
         
     | 
| 
      
 97 
     | 
    
         
            +
                html[dir="ltr"] & { float: left; }
         
     | 
| 
      
 98 
     | 
    
         
            +
                html[dir="rtl"] & { float: right; }
         
     | 
| 
      
 99 
     | 
    
         
            +
              } @else {
         
     | 
| 
      
 100 
     | 
    
         
            +
                html & html[dir="ltr"] &, html[dir="rtl"] & { float: $dir; }
         
     | 
| 
      
 101 
     | 
    
         
            +
              }
         
     | 
| 
      
 102 
     | 
    
         
            +
            }
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
            @mixin menu-box {
         
     | 
| 
      
 105 
     | 
    
         
            +
              background: $menu-background;
         
     | 
| 
      
 106 
     | 
    
         
            +
              @include menu-shadow;
         
     | 
| 
      
 107 
     | 
    
         
            +
              border: $menu-border;
         
     | 
| 
      
 108 
     | 
    
         
            +
            }
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
            @mixin menu-shadow {
         
     | 
| 
      
 111 
     | 
    
         
            +
              @include box-shadow(0 0 ($fs-normal/4) rgba(0, 0, 0, 0.3));
         
     | 
| 
      
 112 
     | 
    
         
            +
            }
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            @mixin menu {
         
     | 
| 
      
 115 
     | 
    
         
            +
              @include menu-box;
         
     | 
| 
      
 116 
     | 
    
         
            +
              &, li a {
         
     | 
| 
      
 117 
     | 
    
         
            +
                font-weight: normal;
         
     | 
| 
      
 118 
     | 
    
         
            +
                color: $text-color;
         
     | 
| 
      
 119 
     | 
    
         
            +
              }
         
     | 
| 
      
 120 
     | 
    
         
            +
            }
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
            @mixin legend-label {
         
     | 
| 
      
 123 
     | 
    
         
            +
              &, * {
         
     | 
| 
      
 124 
     | 
    
         
            +
                color: $neutral-color;
         
     | 
| 
      
 125 
     | 
    
         
            +
                text-transform: uppercase;
         
     | 
| 
      
 126 
     | 
    
         
            +
                font-size: $fs-small;
         
     | 
| 
      
 127 
     | 
    
         
            +
                line-height: $lh-small;
         
     | 
| 
      
 128 
     | 
    
         
            +
                font-weight: bold;
         
     | 
| 
      
 129 
     | 
    
         
            +
              }
         
     | 
| 
      
 130 
     | 
    
         
            +
            }
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,89 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            @import "compass/reset";
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video, input, textarea, select, options, button {
         
     | 
| 
      
 4 
     | 
    
         
            +
              margin:  0;
         
     | 
| 
      
 5 
     | 
    
         
            +
              padding: 0;
         
     | 
| 
      
 6 
     | 
    
         
            +
              font-family: $base-font-family;
         
     | 
| 
      
 7 
     | 
    
         
            +
              vertical-align: middle;
         
     | 
| 
      
 8 
     | 
    
         
            +
              font-size: $fs-normal;
         
     | 
| 
      
 9 
     | 
    
         
            +
              line-height: $lh-normal;
         
     | 
| 
      
 10 
     | 
    
         
            +
              color: $text-color;
         
     | 
| 
      
 11 
     | 
    
         
            +
            }
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            html {
         
     | 
| 
      
 14 
     | 
    
         
            +
              &, * {
         
     | 
| 
      
 15 
     | 
    
         
            +
                @include text-align(left);
         
     | 
| 
      
 16 
     | 
    
         
            +
              }
         
     | 
| 
      
 17 
     | 
    
         
            +
            }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            mark {
         
     | 
| 
      
 20 
     | 
    
         
            +
              background-color: $highlight-color;
         
     | 
| 
      
 21 
     | 
    
         
            +
            }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            td, th, a, p, input, textarea, select, div {
         
     | 
| 
      
 24 
     | 
    
         
            +
              font-size: $fs-normal;
         
     | 
| 
      
 25 
     | 
    
         
            +
            }
         
     | 
| 
      
 26 
     | 
    
         
            +
            small, sup, sub {
         
     | 
| 
      
 27 
     | 
    
         
            +
              font-size: $fs-small;
         
     | 
| 
      
 28 
     | 
    
         
            +
            }
         
     | 
| 
      
 29 
     | 
    
         
            +
            a:link,
         
     | 
| 
      
 30 
     | 
    
         
            +
            a:visited,
         
     | 
| 
      
 31 
     | 
    
         
            +
            a:focus {
         
     | 
| 
      
 32 
     | 
    
         
            +
              &, * {
         
     | 
| 
      
 33 
     | 
    
         
            +
                color: $active-link-color;
         
     | 
| 
      
 34 
     | 
    
         
            +
                text-decoration: none;
         
     | 
| 
      
 35 
     | 
    
         
            +
              }
         
     | 
| 
      
 36 
     | 
    
         
            +
              .label {
         
     | 
| 
      
 37 
     | 
    
         
            +
                color: $base-font-reversed-color;
         
     | 
| 
      
 38 
     | 
    
         
            +
              }
         
     | 
| 
      
 39 
     | 
    
         
            +
            }
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            /*
         
     | 
| 
      
 42 
     | 
    
         
            +
              Other input types are: color, date, datetime, datetime-local, email, month,
         
     | 
| 
      
 43 
     | 
    
         
            +
              number, range, search, tel, time, url, week, button, checkbox, color, date,
         
     | 
| 
      
 44 
     | 
    
         
            +
              datetime, datetime-local, email, file, hidden, image, month, number, password,
         
     | 
| 
      
 45 
     | 
    
         
            +
              radio, range, reset, search, submit, tel, text, time, url, week and file
         
     | 
| 
      
 46 
     | 
    
         
            +
            */
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            input[type="color"], input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="email"], input[type="image"], input[type="month"], input[type="number"], input[type="password"], input[type="range"], input[type="tel"], input[type="text"], input[type="time"], input[type="url"], input[type="week"], input[type="search"], textarea, select {
         
     | 
| 
      
 49 
     | 
    
         
            +
              border: $menu-border;
         
     | 
| 
      
 50 
     | 
    
         
            +
              padding: round($fs-normal * 0.2);
         
     | 
| 
      
 51 
     | 
    
         
            +
              @include box-sizing(content-box);
         
     | 
| 
      
 52 
     | 
    
         
            +
              @include border-radius($default-border-radius);
         
     | 
| 
      
 53 
     | 
    
         
            +
              background: #FFF; //$desktop-background;
         
     | 
| 
      
 54 
     | 
    
         
            +
              font-size: $fs-normal;
         
     | 
| 
      
 55 
     | 
    
         
            +
              line-height: $lh-normal;
         
     | 
| 
      
 56 
     | 
    
         
            +
              height: $lh-normal;
         
     | 
| 
      
 57 
     | 
    
         
            +
              vertical-align: middle;
         
     | 
| 
      
 58 
     | 
    
         
            +
              // @include box-shadow(0 2px round($fs-normal/2) rgba(black, 0.1) inset, 0 0 round($fs-normal*0.6) rgba(white, 0.6));
         
     | 
| 
      
 59 
     | 
    
         
            +
              // @include box-shadow(0 2px round($fs-normal/2) rgba(black, 0.1) inset);
         
     | 
| 
      
 60 
     | 
    
         
            +
              @include box-shadow(0 0 0 rgba(black, 0.1));
         
     | 
| 
      
 61 
     | 
    
         
            +
              @include transition(box-shadow 0.2s, border-color 0.2s);
         
     | 
| 
      
 62 
     | 
    
         
            +
              &:focus {
         
     | 
| 
      
 63 
     | 
    
         
            +
                // background: #FFF;
         
     | 
| 
      
 64 
     | 
    
         
            +
                border-color: $base-color;
         
     | 
| 
      
 65 
     | 
    
         
            +
                @include box-shadow(0 0 round($fs-normal*0.6) rgba($base-color, 0.6));
         
     | 
| 
      
 66 
     | 
    
         
            +
              }
         
     | 
| 
      
 67 
     | 
    
         
            +
              &:disabled, &[disabled] {
         
     | 
| 
      
 68 
     | 
    
         
            +
                background: #EEE;
         
     | 
| 
      
 69 
     | 
    
         
            +
                color: #777;
         
     | 
| 
      
 70 
     | 
    
         
            +
                cursor: not-allowed;
         
     | 
| 
      
 71 
     | 
    
         
            +
              }
         
     | 
| 
      
 72 
     | 
    
         
            +
            }
         
     | 
| 
      
 73 
     | 
    
         
            +
            input[type="number"] {
         
     | 
| 
      
 74 
     | 
    
         
            +
              @include text-align(right);
         
     | 
| 
      
 75 
     | 
    
         
            +
            }
         
     | 
| 
      
 76 
     | 
    
         
            +
            input[type="date"], input[type="datetime"] {
         
     | 
| 
      
 77 
     | 
    
         
            +
              @include text-align(center);
         
     | 
| 
      
 78 
     | 
    
         
            +
            }
         
     | 
| 
      
 79 
     | 
    
         
            +
            input[type="date"] {
         
     | 
| 
      
 80 
     | 
    
         
            +
              width: 12ex;
         
     | 
| 
      
 81 
     | 
    
         
            +
            }
         
     | 
| 
      
 82 
     | 
    
         
            +
            input[type="datetime"] {
         
     | 
| 
      
 83 
     | 
    
         
            +
              width: 20ex;
         
     | 
| 
      
 84 
     | 
    
         
            +
            }
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            textarea {
         
     | 
| 
      
 88 
     | 
    
         
            +
              min-height: 3em;
         
     | 
| 
      
 89 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            // Basic colors
         
     | 
| 
      
 2 
     | 
    
         
            +
            $white: #FFFFFF !default;
         
     | 
| 
      
 3 
     | 
    
         
            +
            $black: #000000 !default;
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            // Font sizes
         
     | 
| 
      
 6 
     | 
    
         
            +
            $fs-ratio:   1.2 !default;
         
     | 
| 
      
 7 
     | 
    
         
            +
            $fs-small:     11px !default;
         
     | 
| 
      
 8 
     | 
    
         
            +
            $fs-normal:    13px !default;
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            // Line heights
         
     | 
| 
      
 11 
     | 
    
         
            +
            $lh-ratio: 1.61803398875 !default;
         
     | 
| 
      
 12 
     | 
    
         
            +
            $lh-small:     round($lh-ratio * $fs-small);
         
     | 
| 
      
 13 
     | 
    
         
            +
            $lh-normal:    round($lh-ratio * $fs-normal);
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            // Colors
         
     | 
| 
      
 16 
     | 
    
         
            +
            $base-color:         #688ED8 !default;
         
     | 
| 
      
 17 
     | 
    
         
            +
            $highlight-color:    #FFEE80 !default;
         
     | 
| 
      
 18 
     | 
    
         
            +
            $neutral-color:      mix($black, $white, 45%) !default;
         
     | 
| 
      
 19 
     | 
    
         
            +
            $active-color:       $base-color !default;
         
     | 
| 
      
 20 
     | 
    
         
            +
            $active-link-color:  darken($base-color, 10%) !default;
         
     | 
| 
      
 21 
     | 
    
         
            +
            $title-color:        darken($base-color, 40%) !default;
         
     | 
| 
      
 22 
     | 
    
         
            +
            $text-color:        darken($base-color, 40%) !default;
         
     | 
| 
      
 23 
     | 
    
         
            +
            $base-font-reversed-color: $white !default;
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            $hover-transparency: 0.92 !default;
         
     | 
| 
      
 26 
     | 
    
         
            +
            $hover-mask: transparentize($neutral-color, $hover-transparency);
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            $neutral-background: change-color($neutral-color, $lightness: 94%) !default;
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            // Menu colors
         
     | 
| 
      
 31 
     | 
    
         
            +
            $menu-background: mix($neutral-background, $white, 55%) !default;
         
     | 
| 
      
 32 
     | 
    
         
            +
            $menu-border-color: mix($menu-background, $black, 90%);
         
     | 
| 
      
 33 
     | 
    
         
            +
            $menu-border-width: floor($fs-normal / 10);
         
     | 
| 
      
 34 
     | 
    
         
            +
            $menu-border: $menu-border-width solid $menu-border-color;
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            $default-border-radius: round($fs-normal * 0.2);
         
     | 
| 
      
 38 
     | 
    
         
            +
            $default-gap: round($fs-normal * 0.55);
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            // Map
         
     | 
| 
      
 41 
     | 
    
         
            +
            $map-button-size: round(2 * $fs-normal);
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            // Font families
         
     | 
| 
      
 44 
     | 
    
         
            +
            $sans-font-family:   'Open Sans', 'Droid Sans', 'Liberation Sans', Helvetica, sans-serif !default;
         
     | 
| 
      
 45 
     | 
    
         
            +
            $base-font-family:   $sans-font-family !default;
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            @import "bootstrap/variables"
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'foliage'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module FoliageHelper
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Example of how to use in HAML view:
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              #   = foliage do |leaf|
         
     | 
| 
      
 7 
     | 
    
         
            +
              #     - leaf.serie :data, <data>
         
     | 
| 
      
 8 
     | 
    
         
            +
              #     - leaf.background "openstreetmap.hot"
         
     | 
| 
      
 9 
     | 
    
         
            +
              #     - leaf.background "openweather.precipitations"
         
     | 
| 
      
 10 
     | 
    
         
            +
              #     - leaf.background "openweather.heat"
         
     | 
| 
      
 11 
     | 
    
         
            +
              #     - leaf.choropleth :<property>, :data
         
     | 
| 
      
 12 
     | 
    
         
            +
              #     - leaf.control :fullscreen
         
     | 
| 
      
 13 
     | 
    
         
            +
              #     - leaf.control :layer_selector
         
     | 
| 
      
 14 
     | 
    
         
            +
              #     - leaf.control :background_selector
         
     | 
| 
      
 15 
     | 
    
         
            +
              #     - leaf.control :search
         
     | 
| 
      
 16 
     | 
    
         
            +
              #
         
     | 
| 
      
 17 
     | 
    
         
            +
              def foliage(options = {}, html_options = {})
         
     | 
| 
      
 18 
     | 
    
         
            +
                theme_colors = ['#2f7ed8', '#0d233a', '#8bbc21', '#910000', '#1aadce', '#492970', '#f28f43', '#77a1e5', '#c42525', '#a6c96a']
         
     | 
| 
      
 19 
     | 
    
         
            +
                leaf = Foliage::Leaf.new({ categories_colors: theme_colors }.merge(options))
         
     | 
| 
      
 20 
     | 
    
         
            +
                yield leaf
         
     | 
| 
      
 21 
     | 
    
         
            +
                content_tag(:div, nil, html_options.deep_merge(data: { leaf: leaf.to_json }))
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/foliage.rb
    ADDED
    
    
    
        data/lib/foliage/leaf.rb
    ADDED
    
    | 
         @@ -0,0 +1,235 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Foliage
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Leaf
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(config = {})
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @config = config
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @categories_colors = @config.delete(:categories_colors)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @config[:backgrounds] = map_backgrounds
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def map_backgrounds
         
     | 
| 
      
 10 
     | 
    
         
            +
                  [
         
     | 
| 
      
 11 
     | 
    
         
            +
                    {
         
     | 
| 
      
 12 
     | 
    
         
            +
                      name: 'OpenStreetMap Hot',
         
     | 
| 
      
 13 
     | 
    
         
            +
                      url: 'http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png',
         
     | 
| 
      
 14 
     | 
    
         
            +
                      referenceName: 'open_street_map.hot',
         
     | 
| 
      
 15 
     | 
    
         
            +
                      attribution: '© <a href=\'http://openstreetmap.org\'>OpenStreetMap</a> contributors, <a href=\'http://creativecommons.org/licenses/by-sa/2.0/\'>CC-BY-SA</a>, Tiles courtesy of <a href=\'http://hot.openstreetmap.org/\' target=\'_blank\'>Humanitarian OpenStreetMap Team</a>',
         
     | 
| 
      
 16 
     | 
    
         
            +
                      tms: false,
         
     | 
| 
      
 17 
     | 
    
         
            +
                      byDefault: false
         
     | 
| 
      
 18 
     | 
    
         
            +
                    },
         
     | 
| 
      
 19 
     | 
    
         
            +
                    {
         
     | 
| 
      
 20 
     | 
    
         
            +
                      name: 'Thunderforest Landscape',
         
     | 
| 
      
 21 
     | 
    
         
            +
                      url: 'https://{s}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png',
         
     | 
| 
      
 22 
     | 
    
         
            +
                      referenceName: 'thunderforest.landscape',
         
     | 
| 
      
 23 
     | 
    
         
            +
                      attribution:
         
     | 
| 
      
 24 
     | 
    
         
            +
                       'Maps © <a href=\'http://www.thunderforest.com\'>Thunderforest</a>, Data © <a href=\'http://www.openstreetmap.org/copyright\'>OpenStreetMap contributors</a>',
         
     | 
| 
      
 25 
     | 
    
         
            +
                      subdomains: 'abc',
         
     | 
| 
      
 26 
     | 
    
         
            +
                      tms: false,
         
     | 
| 
      
 27 
     | 
    
         
            +
                      byDefault: false
         
     | 
| 
      
 28 
     | 
    
         
            +
                    },
         
     | 
| 
      
 29 
     | 
    
         
            +
                    {
         
     | 
| 
      
 30 
     | 
    
         
            +
                      name: 'Stamen Watercolor',
         
     | 
| 
      
 31 
     | 
    
         
            +
                      url: 'http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg',
         
     | 
| 
      
 32 
     | 
    
         
            +
                      referenceName: 'stamen.watercolor',
         
     | 
| 
      
 33 
     | 
    
         
            +
                      attribution: 'Map tiles by <a href=\'http://stamen.com\'>Stamen Design</a>, <a href=\'http://creativecommons.org/licenses/by/3.0\'>CC BY 3.0</a> — Map data © <a href=\'http://openstreetmap.org\'>OpenStreetMap</a> contributors, <a href=\'http://creativecommons.org/licenses/by-sa/2.0/\'>CC-BY-SA</a>',
         
     | 
| 
      
 34 
     | 
    
         
            +
                      subdomains: 'abcd',
         
     | 
| 
      
 35 
     | 
    
         
            +
                      minZoom: 3,
         
     | 
| 
      
 36 
     | 
    
         
            +
                      maxZoom: 15,
         
     | 
| 
      
 37 
     | 
    
         
            +
                      tms: false,
         
     | 
| 
      
 38 
     | 
    
         
            +
                      byDefault: true
         
     | 
| 
      
 39 
     | 
    
         
            +
                    },
         
     | 
| 
      
 40 
     | 
    
         
            +
                    {
         
     | 
| 
      
 41 
     | 
    
         
            +
                      name: 'Esri World imagery',
         
     | 
| 
      
 42 
     | 
    
         
            +
                      url: 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
         
     | 
| 
      
 43 
     | 
    
         
            +
                      referenceName: 'esri.world_imagery',
         
     | 
| 
      
 44 
     | 
    
         
            +
                      attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community',
         
     | 
| 
      
 45 
     | 
    
         
            +
                      tms: false,
         
     | 
| 
      
 46 
     | 
    
         
            +
                      byDefault: false
         
     | 
| 
      
 47 
     | 
    
         
            +
                    }
         
     | 
| 
      
 48 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def background(layer, options = {})
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # allow to add custom background
         
     | 
| 
      
 53 
     | 
    
         
            +
                  options[:name] = layer.name if layer.name?
         
     | 
| 
      
 54 
     | 
    
         
            +
                  options[:url] = layer.url if layer.url?
         
     | 
| 
      
 55 
     | 
    
         
            +
                  options[:by_default] = layer.by_default if layer.by_default?
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @config[:backgrounds] ||= []
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @config[:backgrounds] << options
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def overlay(name, provider_name)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @config[:overlays] ||= []
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @config[:overlays] << { name: name, provider_name: provider_name }
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                # def layer(name, list = {})
         
     | 
| 
      
 66 
     | 
    
         
            +
                #   @config[:layers] ||= []
         
     | 
| 
      
 67 
     | 
    
         
            +
                #   @config[:layers] << {name: name, list: list}
         
     | 
| 
      
 68 
     | 
    
         
            +
                # end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def layer(name, serie, options = {})
         
     | 
| 
      
 71 
     | 
    
         
            +
                  options[:label] = name.to_s.humanize unless options[:label]
         
     | 
| 
      
 72 
     | 
    
         
            +
                  name = name.to_s.parameterize.tr('-', '_') unless name.is_a?(Symbol)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  @config[:layers] ||= []
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @config[:layers] << { reference: name.to_s.camelcase(:lower) }.merge(options.merge(name: name, serie: serie.to_s.camelcase(:lower)))
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def simple(name, serie, options = {})
         
     | 
| 
      
 78 
     | 
    
         
            +
                  layer(name, serie, options.merge(type: :simple))
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def choropleth(name, serie, options = {})
         
     | 
| 
      
 82 
     | 
    
         
            +
                  layer(name, serie, options.merge(type: :choropleth))
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                def bubbles(name, serie, options = {})
         
     | 
| 
      
 86 
     | 
    
         
            +
                  layer(name, serie, options.merge(type: :bubbles))
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                def heatmap(name, serie, options = {})
         
     | 
| 
      
 90 
     | 
    
         
            +
                  layer(name, serie, options.merge(type: :heatmap))
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                def band(name, serie, options = {})
         
     | 
| 
      
 94 
     | 
    
         
            +
                  layer(name, serie, options.merge(type: :band))
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                def categories(name, serie, options = {})
         
     | 
| 
      
 98 
     | 
    
         
            +
                  layer(name, serie, { colors: @categories_colors }.merge(options.merge(type: :categories)))
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                def paths(name, serie, options = {})
         
     | 
| 
      
 102 
     | 
    
         
            +
                  layer(name, serie, { colors: @categories_colors }.merge(options.merge(type: :paths)))
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                def path(name, serie, options = {})
         
     | 
| 
      
 106 
     | 
    
         
            +
                  layer(name, serie, { colors: @categories_colors }.merge(options.merge(type: :path)))
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                def points(name, serie, options = {})
         
     | 
| 
      
 110 
     | 
    
         
            +
                  layer(name, serie, { colors: @categories_colors }.merge(options.merge(type: :points)))
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                def point_group(name, serie, options = {})
         
     | 
| 
      
 114 
     | 
    
         
            +
                  layer(name, serie, options.merge(type: :point_group))
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                # def multi_points(name, serie, options = {})
         
     | 
| 
      
 118 
     | 
    
         
            +
                #   layer(name, serie, options.merge(type: :multi_points))
         
     | 
| 
      
 119 
     | 
    
         
            +
                # end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                # Add a serie of geo data
         
     | 
| 
      
 122 
     | 
    
         
            +
                def serie(name, data)
         
     | 
| 
      
 123 
     | 
    
         
            +
                  raise StandardError, 'data must be an array. Got: ' + data.class.name unless data.is_a? Array
         
     | 
| 
      
 124 
     | 
    
         
            +
                  @config[:series] ||= {}.with_indifferent_access
         
     | 
| 
      
 125 
     | 
    
         
            +
                  @config[:series][name] = data.compact.collect do |item|
         
     | 
| 
      
 126 
     | 
    
         
            +
                    next unless item[:shape]
         
     | 
| 
      
 127 
     | 
    
         
            +
                    item
         
     | 
| 
      
 128 
     | 
    
         
            +
                      .merge(shape: item[:shape])
         
     | 
| 
      
 129 
     | 
    
         
            +
                      .merge(item[:popup] ? { popup: compile_leaf_popup(item[:popup], item) } : {})
         
     | 
| 
      
 130 
     | 
    
         
            +
                  end.compact
         
     | 
| 
      
 131 
     | 
    
         
            +
                end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                # Add a control
         
     | 
| 
      
 134 
     | 
    
         
            +
                def control(name, options = true)
         
     | 
| 
      
 135 
     | 
    
         
            +
                  @config[:controls] ||= {}.with_indifferent_access
         
     | 
| 
      
 136 
     | 
    
         
            +
                  @config[:controls][name.to_s.camelize(:lower)] = options
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                def to_json
         
     | 
| 
      
 140 
     | 
    
         
            +
                  @config.deep_transform_keys do |key|
         
     | 
| 
      
 141 
     | 
    
         
            +
                    key.to_s.camelize(:lower)
         
     | 
| 
      
 142 
     | 
    
         
            +
                  end.to_json
         
     | 
| 
      
 143 
     | 
    
         
            +
                end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                protected
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                # Build a data structure for popup building
         
     | 
| 
      
 148 
     | 
    
         
            +
                def compile_leaf_popup(object, item)
         
     | 
| 
      
 149 
     | 
    
         
            +
                  if object.is_a?(TrueClass)
         
     | 
| 
      
 150 
     | 
    
         
            +
                    hash = { header: item[:name] }
         
     | 
| 
      
 151 
     | 
    
         
            +
                    for key, value in item
         
     | 
| 
      
 152 
     | 
    
         
            +
                      unless [:header, :footer, :name, :shape].include?(key)
         
     | 
| 
      
 153 
     | 
    
         
            +
                        hash[key] = value.to_s
         
     | 
| 
      
 154 
     | 
    
         
            +
                      end
         
     | 
| 
      
 155 
     | 
    
         
            +
                    end
         
     | 
| 
      
 156 
     | 
    
         
            +
                    compile_leaf_popup(hash, item)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  elsif object.is_a?(String)
         
     | 
| 
      
 158 
     | 
    
         
            +
                    return [{ type: :content, content: object }]
         
     | 
| 
      
 159 
     | 
    
         
            +
                  elsif object.is_a?(Hash)
         
     | 
| 
      
 160 
     | 
    
         
            +
                    blocks = []
         
     | 
| 
      
 161 
     | 
    
         
            +
                    if header = object[:header]
         
     | 
| 
      
 162 
     | 
    
         
            +
                      blocks << compile_block(header, :header, content: item[:name])
         
     | 
| 
      
 163 
     | 
    
         
            +
                    end
         
     | 
| 
      
 164 
     | 
    
         
            +
                    if content = object[:content]
         
     | 
| 
      
 165 
     | 
    
         
            +
                      if content.is_a? String
         
     | 
| 
      
 166 
     | 
    
         
            +
                        blocks << { type: :content, content: content }
         
     | 
| 
      
 167 
     | 
    
         
            +
                      elsif content.is_a? Array
         
     | 
| 
      
 168 
     | 
    
         
            +
                        for value in content
         
     | 
| 
      
 169 
     | 
    
         
            +
                          block = {}
         
     | 
| 
      
 170 
     | 
    
         
            +
                          if value.is_a? String
         
     | 
| 
      
 171 
     | 
    
         
            +
                            block[:content] = value
         
     | 
| 
      
 172 
     | 
    
         
            +
                          elsif value.is_a? Hash
         
     | 
| 
      
 173 
     | 
    
         
            +
                            block.update(value)
         
     | 
| 
      
 174 
     | 
    
         
            +
                          else
         
     | 
| 
      
 175 
     | 
    
         
            +
                            raise "Not implemented array block for #{object.class}"
         
     | 
| 
      
 176 
     | 
    
         
            +
                          end
         
     | 
| 
      
 177 
     | 
    
         
            +
                          if block[:label].is_a?(TrueClass)
         
     | 
| 
      
 178 
     | 
    
         
            +
                            block[:label] = "attributes.#{attribute}".t(default: ["labels.#{attribute}".to_sym, attribute.to_s.humanize])
         
     | 
| 
      
 179 
     | 
    
         
            +
                          elsif !block[:label]
         
     | 
| 
      
 180 
     | 
    
         
            +
                            block.delete(:label)
         
     | 
| 
      
 181 
     | 
    
         
            +
                          end
         
     | 
| 
      
 182 
     | 
    
         
            +
                          blocks << block.merge(type: :content)
         
     | 
| 
      
 183 
     | 
    
         
            +
                        end
         
     | 
| 
      
 184 
     | 
    
         
            +
                      elsif content.is_a? Hash
         
     | 
| 
      
 185 
     | 
    
         
            +
                        for attribute, value in content
         
     | 
| 
      
 186 
     | 
    
         
            +
                          block = {}
         
     | 
| 
      
 187 
     | 
    
         
            +
                          if value.is_a? String
         
     | 
| 
      
 188 
     | 
    
         
            +
                            block[:content] = value
         
     | 
| 
      
 189 
     | 
    
         
            +
                          elsif value.is_a? Hash
         
     | 
| 
      
 190 
     | 
    
         
            +
                            block.update(value)
         
     | 
| 
      
 191 
     | 
    
         
            +
                          elsif value.is_a? TrueClass
         
     | 
| 
      
 192 
     | 
    
         
            +
                            block[:value] = item[attribute].to_s
         
     | 
| 
      
 193 
     | 
    
         
            +
                            block[:label] = true
         
     | 
| 
      
 194 
     | 
    
         
            +
                          end
         
     | 
| 
      
 195 
     | 
    
         
            +
                          if block[:label].is_a?(TrueClass)
         
     | 
| 
      
 196 
     | 
    
         
            +
                            block[:label] = attribute.to_s.humanize
         
     | 
| 
      
 197 
     | 
    
         
            +
                          elsif !block[:label]
         
     | 
| 
      
 198 
     | 
    
         
            +
                            block.delete(:label)
         
     | 
| 
      
 199 
     | 
    
         
            +
                          end
         
     | 
| 
      
 200 
     | 
    
         
            +
                          blocks << block.merge(type: :content)
         
     | 
| 
      
 201 
     | 
    
         
            +
                        end
         
     | 
| 
      
 202 
     | 
    
         
            +
                      else
         
     | 
| 
      
 203 
     | 
    
         
            +
                        raise "Not implemented content for #{content.class}"
         
     | 
| 
      
 204 
     | 
    
         
            +
                      end
         
     | 
| 
      
 205 
     | 
    
         
            +
                    end
         
     | 
| 
      
 206 
     | 
    
         
            +
                    if footer = object[:footer]
         
     | 
| 
      
 207 
     | 
    
         
            +
                      blocks << compile_block(footer, :footer, content: item[:name])
         
     | 
| 
      
 208 
     | 
    
         
            +
                    end
         
     | 
| 
      
 209 
     | 
    
         
            +
                    return blocks
         
     | 
| 
      
 210 
     | 
    
         
            +
                  else
         
     | 
| 
      
 211 
     | 
    
         
            +
                    raise "Not implemented for #{object.class}"
         
     | 
| 
      
 212 
     | 
    
         
            +
                  end
         
     | 
| 
      
 213 
     | 
    
         
            +
                end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                def compile_block(*args)
         
     | 
| 
      
 216 
     | 
    
         
            +
                  options = args.extract_options!
         
     | 
| 
      
 217 
     | 
    
         
            +
                  info = args.shift
         
     | 
| 
      
 218 
     | 
    
         
            +
                  type = args.shift || options[:type]
         
     | 
| 
      
 219 
     | 
    
         
            +
                  if info.is_a? String
         
     | 
| 
      
 220 
     | 
    
         
            +
                    block = { type: type, content: info }
         
     | 
| 
      
 221 
     | 
    
         
            +
                  elsif info.is_a? TrueClass
         
     | 
| 
      
 222 
     | 
    
         
            +
                    if options[:content]
         
     | 
| 
      
 223 
     | 
    
         
            +
                      block = { type: type, content: options[:content] }
         
     | 
| 
      
 224 
     | 
    
         
            +
                    else
         
     | 
| 
      
 225 
     | 
    
         
            +
                      raise StandardError, 'Option :content must be given when info is a TrueClass'
         
     | 
| 
      
 226 
     | 
    
         
            +
                    end
         
     | 
| 
      
 227 
     | 
    
         
            +
                  elsif info.is_a? Hash
         
     | 
| 
      
 228 
     | 
    
         
            +
                    block = info.merge(type: type)
         
     | 
| 
      
 229 
     | 
    
         
            +
                  else
         
     | 
| 
      
 230 
     | 
    
         
            +
                    raise StandardError, "Not implemented #{type} for #{object.class}"
         
     | 
| 
      
 231 
     | 
    
         
            +
                  end
         
     | 
| 
      
 232 
     | 
    
         
            +
                  block
         
     | 
| 
      
 233 
     | 
    
         
            +
                end
         
     | 
| 
      
 234 
     | 
    
         
            +
              end
         
     | 
| 
      
 235 
     | 
    
         
            +
            end
         
     |