diff --git a/src/main/webapp/scripts/dialogs/clustering-dialog.js b/src/main/webapp/scripts/dialogs/clustering-dialog.js
index 216a71d99..1e47efdad 100644
--- a/src/main/webapp/scripts/dialogs/clustering-dialog.js
+++ b/src/main/webapp/scripts/dialogs/clustering-dialog.js
@@ -462,6 +462,10 @@ ClusteringDialog.Facet = function(dialog, title, property, elmt, clusters) {
if (this._binCount > 100) {
this._step *= 2;
this._binCount = Math.round((1 + this._binCount) / 2);
+ } else if (this._binCount < 3) {
+ this._step /= 2;
+ this._binCount *= 2;
+ this._max = (Math.ceil(this._max / this._step) * this._step);
}
this._baseBins = this._computeDistribution(clusters);
@@ -478,12 +482,17 @@ ClusteringDialog.Facet = function(dialog, title, property, elmt, clusters) {
this._elmts = DOM.bind(html);
- this._histogram = new HistogramWidget(this._elmts.histogramContainer, { binColors: [ "#aaaaff", "#000088" ] });
+ this._histogram = new HistogramWidget(this._elmts.histogramContainer, { binColors: [ "#ccccff", "#6666ff" ] });
this._elmts.slider.slider({
min: this._min,
max: this._max,
values: [ this._from, this._to ],
+ slide: function(evt, ui) {
+ self._from = ui.values[0];
+ self._to = ui.values[1];
+ self._setRangeIndicators();
+ },
stop: function(evt, ui) {
self._from = ui.values[0];
self._to = ui.values[1];
@@ -525,11 +534,14 @@ ClusteringDialog.Facet.prototype.update = function(clusters) {
this._min,
this._max,
this._step,
- [ this._baseBins, bins ]
+ [ this._baseBins, bins ],
+ this._from,
+ this._to
);
};
ClusteringDialog.Facet.prototype._setRangeIndicators = function() {
+ this._histogram.highlight(this._from, this._to);
this._elmts.selectionContainer.text(this._from + " to " + this._to);
};
diff --git a/src/main/webapp/scripts/facets/range-facet.js b/src/main/webapp/scripts/facets/range-facet.js
index 7b337f2b4..ed92790e2 100644
--- a/src/main/webapp/scripts/facets/range-facet.js
+++ b/src/main/webapp/scripts/facets/range-facet.js
@@ -144,7 +144,7 @@ RangeFacet.prototype._initializeUI = function() {
this._statusDiv = $('
').addClass("facet-range-status").appendTo(bodyDiv);
this._otherChoicesDiv = $('
').addClass("facet-range-other-choices").appendTo(bodyDiv);
- this._histogram = new HistogramWidget(this._histogramDiv, { binColors: [ "#aaaaff", "#000088" ] });
+ this._histogram = new HistogramWidget(this._histogramDiv, { binColors: [ "#ccccff", "#6666ff" ] });
var onSlide = function(event, ui) {
switch (self._config.mode) {
@@ -264,6 +264,7 @@ RangeFacet.prototype._setRangeIndicators = function() {
}
this._statusDiv.text(text);
+ this._histogram.highlight(this._from, this._to);
};
RangeFacet.prototype.updateState = function(data) {
@@ -333,7 +334,9 @@ RangeFacet.prototype.render = function() {
this._config.min,
this._config.max,
this._config.step,
- [ this._baseBins, this._bins ]
+ [ this._baseBins, this._bins ],
+ this._from,
+ this._to
);
this._setRangeIndicators();
diff --git a/src/main/webapp/scripts/util/histogram-widget.js b/src/main/webapp/scripts/util/histogram-widget.js
index 906ab1c3e..e9b54571e 100644
--- a/src/main/webapp/scripts/util/histogram-widget.js
+++ b/src/main/webapp/scripts/util/histogram-widget.js
@@ -14,7 +14,7 @@ HistogramWidget.prototype.highlight = function(from, to) {
this._update();
};
-HistogramWidget.prototype.update = function(min, max, step, binMatrix) {
+HistogramWidget.prototype.update = function(min, max, step, binMatrix, from, to) {
if (typeof min == "undefined" || typeof binMatrix == "undefined" || binMatrix.length === 0 || binMatrix[0].length === 0) {
this._range = null;
this._binMatrix = null;
@@ -33,6 +33,10 @@ HistogramWidget.prototype.update = function(min, max, step, binMatrix) {
}
}
+ if (typeof from != "undefined" && typeof to != "undefined") {
+ this._highlight = { from: from, to: to };
+ }
+
this._update();
}
};
@@ -40,8 +44,8 @@ HistogramWidget.prototype.update = function(min, max, step, binMatrix) {
HistogramWidget.prototype._update = function() {
if (this._binMatrix != null) {
if (this._highlight != null) {
- this._highlight.from = Math.max(this._highlight.from, min);
- this._highlight.to = Math.min(this._highlight.to, max);
+ this._highlight.from = Math.max(this._highlight.from, this._range.min);
+ this._highlight.to = Math.min(this._highlight.to, this._range.max);
}
this._elmt.show();
@@ -73,12 +77,16 @@ HistogramWidget.prototype._render = function() {
var canvas = this._elmts.canvas[0];
var ctx = canvas.getContext('2d');
- ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.fillStyle = "white";
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(0, canvas.height);
ctx.scale(1, -1);
+ var stepPixels = canvas.width / this._binMatrix[0].length;
+ var stepScale = stepPixels / this._range.step;
+
/*
* Draw axis
*/
@@ -93,7 +101,6 @@ HistogramWidget.prototype._render = function() {
/*
* Draw bins
*/
- var stepPixels = canvas.width / this._binMatrix[0].length;
var makeColor = function(i) {
var n = Math.floor(15 * (self._binMatrix.length - i) / self._binMatrix.length);
var h = n.toString(16);
@@ -104,11 +111,14 @@ HistogramWidget.prototype._render = function() {
ctx.lineWidth = 0;
ctx.fillStyle = color;
for (var c = 0; c < row.length; c++) {
- var value = row[c];
- if (value > 0) {
+ var x = self._range.min + c * self._range.step;
+ var y = row[c];
+ if (y > 0) {
var left = c * stepPixels;
- var height = Math.ceil(value * canvas.height / self._peak);
- ctx.fillRect(left, 0, Math.ceil(stepPixels), height);
+ var width = Math.ceil(stepPixels);
+ var height = Math.ceil(y * canvas.height / self._peak);
+
+ ctx.fillRect(left, 0, width, height);
}
}
ctx.restore();
@@ -121,6 +131,30 @@ HistogramWidget.prototype._render = function() {
makeColor(r)
);
}
-
+
+ /*
+ * Draw highlight
+ */
+ if (this._highlight != null) {
+ ctx.fillStyle = "rgba(192,192,192, 0.5)";
+ ctx.globalCompositeOperation = "source-over";
+ if (this._highlight.from > this._range.min) {
+ ctx.fillRect(
+ 0,
+ 0,
+ (this._highlight.from - this._range.min) * stepScale,
+ canvas.height
+ );
+ }
+ if (this._highlight.to < this._range.max) {
+ ctx.fillRect(
+ (this._highlight.to - this._range.min) * stepScale,
+ 0,
+ canvas.width - (this._highlight.to - this._range.min) * stepScale,
+ canvas.height
+ );
+ }
+ }
+
ctx.restore();
};
diff --git a/src/main/webapp/scripts/views/data-table-column-header-ui.js b/src/main/webapp/scripts/views/data-table-column-header-ui.js
index 313f33c9e..0636e0433 100644
--- a/src/main/webapp/scripts/views/data-table-column-header-ui.js
+++ b/src/main/webapp/scripts/views/data-table-column-header-ui.js
@@ -119,6 +119,20 @@ DataTableColumnHeaderUI.prototype._createMenuForColumnHeader = function(elmt) {
{
label: "Common Numeric Facets",
submenu: [
+ {
+ label: "Numeric Log Facet",
+ click: function() {
+ ui.browsingEngine.addFacet(
+ "range",
+ {
+ "name" : self._column.name + ": value.log()",
+ "columnName" : self._column.name,
+ "expression" : "value.log()",
+ "mode" : "range"
+ }
+ );
+ }
+ },
{
label: "Text Length Facet",
click: function() {
diff --git a/src/main/webapp/styles/common.css b/src/main/webapp/styles/common.css
index 6a39f0c2d..68c1c121e 100644
--- a/src/main/webapp/styles/common.css
+++ b/src/main/webapp/styles/common.css
@@ -135,11 +135,13 @@ img {
.ui-widget-content a.ui-state-default.ui-slider-handle {
background: url(../images/slider-left-bracket.png) no-repeat bottom left;
border: none;
+ margin-left: -12px;
top: -10px;
}
.ui-widget-content a.ui-state-default.ui-slider-handle:last-child {
background: url(../images/slider-right-bracket.png) no-repeat bottom right;
border: none;
+ margin-left: -3px;
top: -10px;
}
.ui-slider .ui-slider-handle {
diff --git a/src/main/webapp/styles/dialogs/clustering-dialog.css b/src/main/webapp/styles/dialogs/clustering-dialog.css
index d02d6a349..a9230efd6 100644
--- a/src/main/webapp/styles/dialogs/clustering-dialog.css
+++ b/src/main/webapp/styles/dialogs/clustering-dialog.css
@@ -64,11 +64,11 @@ table.clustering-dialog-entry-table a:hover {
font-weight: bold;
}
.clustering-dialog-facet-histogram {
- margin: 10px 8px 5px 8px;
- height: 52px;
+ margin: 10px;
+ overflow: hidden;
}
.clustering-dialog-facet-slider {
- margin: 5px;
+ margin: 5px 10px;
}
.clustering-dialog-facet-selection {
text-align: center;
diff --git a/src/main/webapp/styles/project/browsing.css b/src/main/webapp/styles/project/browsing.css
index 69b7efca3..6aef30821 100644
--- a/src/main/webapp/styles/project/browsing.css
+++ b/src/main/webapp/styles/project/browsing.css
@@ -125,11 +125,17 @@ img.facet-choice-link {
color: #f88;
}
.facet-range-histogram {
- margin: 10px 4px;
+ margin: 10px 0px;
overflow: hidden;
}
-.facet-range-slider {
+.facet-range-slider.ui-corner-all {
+ border-bottom-left-radius: 0px 0px;
+ border-bottom-right-radius: 0px 0px;
+ border-top-left-radius: 0px 0px;
+ border-top-right-radius: 0px 0px;
}
+
+
.facet-range-status {
margin: 10px 0;
text-align: center;