diff --git a/umap/static/umap/base.css b/umap/static/umap/base.css index b5f1ce9a..12cd7d39 100644 --- a/umap/static/umap/base.css +++ b/umap/static/umap/base.css @@ -354,7 +354,8 @@ input.switch:checked ~ label:after { .button-bar.half { grid-template-columns: 1fr 1fr; } -.umap-multiplechoice.by3 { +.umap-multiplechoice.by3, +.umap-multiplechoice.by5 { grid-template-columns: 1fr 1fr 1fr; } .umap-multiplechoice.by4 { diff --git a/umap/static/umap/js/umap.layer.js b/umap/static/umap/js/umap.layer.js index ff806eba..5d7f619f 100644 --- a/umap/static/umap/js/umap.layer.js +++ b/umap/static/umap/js/umap.layer.js @@ -122,6 +122,7 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({ equidistant: L._('Equidistant'), jenks: L._('Jenks-Fisher'), quantiles: L._('Quantiles'), + manual: L._('Manual'), }, initialize: function (datalayer) { @@ -159,20 +160,26 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({ return } let mode = this.datalayer.options.choropleth.mode, - steps = +this.datalayer.options.choropleth.steps || 5, - breaks - if (mode === 'equidistant') { - breaks = ss.equalIntervalBreaks(values, steps) + classes = +this.datalayer.options.choropleth.classes || 5, + breaks = [] + if (mode === 'manual') { + const manualBreaks = this.datalayer.options.choropleth.breaks + if (manualBreaks) { + breaks = manualBreaks.split(",").map(b => +b).filter(b => !isNaN(b)) + } + } else if (mode === 'equidistant') { + breaks = ss.equalIntervalBreaks(values, classes) } else if (mode === 'jenks') { - breaks = ss.jenks(values, steps) + breaks = ss.jenks(values, classes) } else if (mode === 'quantiles') { - const quantiles = [...Array(steps)].map((e, i) => i/steps).concat(1) + const quantiles = [...Array(classes)].map((e, i) => i/classes).concat(1) breaks = ss.quantile(values, quantiles) } else { - breaks = ss.ckmeans(values, steps).map((cluster) => cluster[0]) + breaks = ss.ckmeans(values, classes).map((cluster) => cluster[0]) breaks.push(ss.max(values)) // Needed for computing the legend } this.options.breaks = breaks + this.datalayer.options.choropleth.breaks = this.options.breaks.map(b => +b.toFixed(2)).join(',') const fillColor = this.datalayer.getOption('fillColor') || this.defaults.fillColor let colorScheme = this.datalayer.options.choropleth.brewer if (!colorbrewer[colorScheme]) colorScheme = 'Blues' @@ -207,6 +214,17 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({ L.FeatureGroup.prototype.onAdd.call(this, map) }, + postUpdate: function (e) { + if (e.helper.field === 'options.choropleth.breaks') { + this.datalayer.options.choropleth.mode = 'manual' + e.helper.builder.helpers["options.choropleth.mode"].fetch() + } + this.computeBreaks() + if (e.helper.field !== 'options.choropleth.breaks') { + e.helper.builder.helpers["options.choropleth.breaks"].fetch() + } + }, + getEditableOptions: function () { const brewerSchemes = Object.keys(colorbrewer) .filter((k) => k !== 'schemeGroups') @@ -218,8 +236,7 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({ { handler: 'Select', selectOptions: this.datalayer._propertiesIndex, - placeholder: L._('Choropleth property value'), - helpText: L._('Choropleth property value'), + label: L._('Choropleth property value'), }, ], [ @@ -231,14 +248,22 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({ }, ], [ - 'options.choropleth.steps', + 'options.choropleth.classes', { handler: 'Range', min: 3, max: 9, step: 1, - placeholder: L._('Choropleth steps'), - helpText: L._('Choropleth steps (default 5)'), + label: L._('Choropleth classes'), + helpText: L._('Number of desired classes (default 5)'), + }, + ], + [ + 'options.choropleth.breaks', + { + handler: 'BlurInput', + label: L._('Choropleth breakpoints'), + helpText: L._('Comma separated list of numbers, including min and max values.'), }, ], [ @@ -1060,9 +1085,9 @@ L.U.DataLayer = L.Evented.extend({ 'options.fillOpacity', ] - const redrawCallback = function (field) { + const redrawCallback = function (e) { this.hide() - this.layer.postUpdate(field) + this.layer.postUpdate(e) this.show() } diff --git a/umap/static/umap/test/Choropleth.js b/umap/static/umap/test/Choropleth.js index faf2daac..f87e7cce 100644 --- a/umap/static/umap/test/Choropleth.js +++ b/umap/static/umap/test/Choropleth.js @@ -233,7 +233,7 @@ describe('L.U.Choropleth', function () { }) it('choropleth should allow to change steps', function () { this.datalayer.options.choropleth.brewer = 'Blues' - this.datalayer.options.choropleth.steps = 6 + this.datalayer.options.choropleth.classes = 6 this.datalayer.resetLayer(true) assert.equal(poly1._path.attributes.fill.value, '#eff3ff') assert.equal(poly4._path.attributes.fill.value, '#c6dbef')