').addClass('tilemap-legend');
70 |
71 | self.$sliderScope = $rootScope.$new();
72 | self.$sliderScope.slider = {
73 | min: self.threshold.min,
74 | max: self.threshold.max,
75 | options: {
76 | floor: _.get(self.geoJson, 'properties.allmin', 0),
77 | ceil: _.get(self.geoJson, 'properties.allmax', 1),
78 | onEnd: function(sliderId, modelValue, highValue, pointerType) {
79 | self.threshold.min = modelValue;
80 | self.threshold.max = highValue;
81 | self.destroy();
82 | self._createMarkerGroup(self.markerOptions);
83 | }
84 | }
85 | };
86 | const linkFn = $compile(require('./legendSlider.html'));
87 | const $sliderEl = linkFn(self.$sliderScope);
88 | $div.append($sliderEl);
89 |
90 | _.each(self._legendColors, function (color, i) {
91 | let labelText = self._legendQuantizer
92 | .invertExtent(color)
93 | .map(self._valueFormatter)
94 | .join(' – ');
95 |
96 | let label = $('
').text(labelText);
97 |
98 | let icon = $('').css({
99 | background: color,
100 | 'border-color': self.darkerColor(color)
101 | });
102 |
103 | label.append(icon);
104 | $div.append(label);
105 | });
106 |
107 | return $div.get(0);
108 | };
109 |
110 | if (self.isVisible) self._legend.addTo(self.map);
111 | };
112 |
113 | BaseMarker.prototype.removeLegend = function () {
114 | if (this.$sliderScope) {
115 | this.$sliderScope.$destroy();
116 | }
117 |
118 | if (this._legend) {
119 | if (this._legend._map) {
120 | this.map.removeControl(this._legend);
121 | }
122 | this._legend = undefined;
123 | }
124 | }
125 |
126 | /**
127 | * Apply style with shading to feature
128 | *
129 | * @method applyShadingStyle
130 | * @param value {Object}
131 | * @return {Object}
132 | */
133 | BaseMarker.prototype.applyShadingStyle = function (value) {
134 | let color = this._legendQuantizer(value);
135 | if(color == undefined && 'Dynamic - Uneven' === this._attr.scaleType) {
136 | // Because this scale is threshold based and we added just as many ranges
137 | // as we did for the domain the max value is counted as being outside the
138 | // range so we get undefined. We want to count this as part of the last domain.
139 | color = this._legendColors[this._legendColors.length - 1];
140 | }
141 |
142 | return {
143 | fillColor: color,
144 | color: this.darkerColor(color),
145 | weight: 1.5,
146 | opacity: 1,
147 | fillOpacity: 0.75
148 | };
149 | };
150 |
151 | /**
152 | * Binds popup and events to each feature on map
153 | *
154 | * @method bindPopup
155 | * @param feature {Object}
156 | * @param layer {Object}
157 | * return {undefined}
158 | */
159 | BaseMarker.prototype.bindPopup = function (feature, layer) {
160 | let self = this;
161 |
162 | let popup = layer.on({
163 | mouseover: function (e) {
164 | let layer = e.target;
165 | // bring layer to front if not older browser
166 | if (!L.Browser.ie && !L.Browser.opera) {
167 | layer.bringToFront();
168 | }
169 | self._showTooltip(feature);
170 | },
171 | mouseout: function (e) {
172 | if (_.get(self._attr, 'tooltip.closeOnMouseout', true)) {
173 | self._hidePopup();
174 | }
175 | }
176 | });
177 |
178 | self.popups.push(popup);
179 | };
180 |
181 | /**
182 | * d3 method returns a darker hex color,
183 | * used for marker stroke color
184 | *
185 | * @method darkerColor
186 | * @param color {String} hex color
187 | * @param amount? {Number} amount to darken by
188 | * @return {String} hex color
189 | */
190 | BaseMarker.prototype.darkerColor = function (color, amount) {
191 | amount = amount || 1.3;
192 | return d3.hcl(color).darker(amount).toString();
193 | };
194 |
195 | /**
196 | * Remove marker layer, popup, and legend from map
197 | * @return {Object} marker layer display state
198 | */
199 | BaseMarker.prototype.destroy = function () {
200 | const state = {
201 | isVisible: this._markerGroup && this.map.hasLayer(this._markerGroup),
202 | threshold: {
203 | floor: _.get(this.geoJson, 'properties.allmin', 0),
204 | ceil: _.get(this.geoJson, 'properties.allmax', 1),
205 | min: this.threshold.min,
206 | max: this.threshold.max
207 | }
208 | };
209 |
210 | this._stopLoadingGeohash();
211 |
212 | // remove popups
213 | this.popups = this.popups.filter(function (popup) {
214 | popup.off('mouseover').off('mouseout');
215 | });
216 | this._hidePopup();
217 |
218 | this.removeLegend();
219 |
220 | // remove marker layer from map
221 | if (this._markerGroup) {
222 | this.layerControl.removeLayer(this._markerGroup);
223 | if (this.map.hasLayer(this._markerGroup)) {
224 | this.map.removeLayer(this._markerGroup);
225 | }
226 | this._markerGroup = undefined;
227 | }
228 |
229 | return state;
230 | };
231 |
232 | BaseMarker.prototype.hide = function () {
233 | this._stopLoadingGeohash();
234 | if (this._legend) {
235 | this.map.removeControl(this._legend);
236 | }
237 | }
238 |
239 | BaseMarker.prototype.show = function () {
240 | if (this._legend) {
241 | this._legend.addTo(this.map);
242 | }
243 | }
244 |
245 | BaseMarker.prototype._addToMap = function () {
246 | this.layerControl.addOverlay(this._markerGroup, "Aggregation");
247 | if (this.isVisible) this.map.addLayer(this._markerGroup);
248 |
249 | if (this.geoJson.features.length > 1) {
250 | this.addLegend();
251 | }
252 | };
253 |
254 | /**
255 | * Creates leaflet marker group, passing options to L.geoJson
256 | *
257 | * @method _createMarkerGroup
258 | * @param options {Object} Options to pass to L.geoJson
259 | */
260 | BaseMarker.prototype._createMarkerGroup = function (options) {
261 | let self = this;
262 | self.markerOptions = options;
263 | let defaultOptions = {
264 | filter: function(feature) {
265 | const value = _.get(feature, 'properties.value', 0);
266 | return value >= self.threshold.min && value <= self.threshold.max;
267 | },
268 | onEachFeature: function (feature, layer) {
269 | self.bindPopup(feature, layer);
270 | },
271 | style: function (feature) {
272 | let value = _.get(feature, 'properties.value');
273 | return self.applyShadingStyle(value);
274 | }
275 | };
276 |
277 | if(self.geoJson.features.length <= 250) {
278 | this._markerGroup = L.geoJson(self.geoJson, _.defaults(defaultOptions, options));
279 | } else {
280 | //don't block UI when processing lots of features
281 | this._markerGroup = L.geoJson(self.geoJson.features.slice(0,100), _.defaults(defaultOptions, options));
282 | this._stopLoadingGeohash();
283 |
284 | this._createSpinControl();
285 | var place = 100;
286 | this._intervalId = setInterval(
287 | function() {
288 | var stopIndex = place + 100;
289 | var halt = false;
290 | if(stopIndex > self.geoJson.features.length) {
291 | stopIndex = self.geoJson.features.length;
292 | halt = true;
293 | }
294 | for(var i=place; i