').addClass("facet-range-status").appendTo(bodyDiv);
this._otherChoicesDiv = $('
').addClass("facet-range-other-choices").appendTo(bodyDiv);
+ this._histogram = new HistogramWidget(this._histogramDiv, { binColors: [ "#aaaaff", "#000088" ] });
+
var onSlide = function(event, ui) {
switch (self._config.mode) {
case "min":
@@ -327,35 +329,12 @@ RangeFacet.prototype.render = function() {
this._sliderDiv.slider("option", "max", this._config.max);
this._sliderDiv.slider("option", "step", this._config.step);
- var max = 0;
- for (var i = 0; i < this._baseBins.length; i++) {
- max = Math.max(max, this._baseBins[i]);
- }
-
- if (max == 0) {
- this._histogramDiv.hide();
- } else {
- var values = [];
- var diffs = [];
-
- for (var i = 0; i < this._baseBins.length; i++) {
- var v = Math.ceil(100 * this._bins[i] / max);
- var diff = Math.ceil(100 * this._baseBins[i] / max) - v;
-
- values.push(v == 0 ? 0 : Math.max(2, v)); // use min 2 to make sure something shows up
- diffs.push(diff == 0 ? 0 : Math.max(2, diff));
- }
-
- this._histogramDiv.empty().show();
- $('
![]()
').attr("src",
- "http://chart.apis.google.com/chart?" + [
- "chs=" + this._histogramDiv[0].offsetWidth + "x50",
- //"cht=ls&chm=o,ff6600,0,-1,3&chls=0", // use for line plot
- "cht=bvs&chbh=r,0&chco=000088,aaaaff", // use for histogram
- "chd=t:" + values.join(",") + "|" + diffs.join(",")
- ].join("&")
- ).appendTo(this._histogramDiv);
- }
+ this._histogram.update(
+ this._config.min,
+ this._config.max,
+ this._config.step,
+ [ this._baseBins, this._bins ]
+ );
this._setRangeIndicators();
this._renderOtherChoices();
diff --git a/src/main/webapp/scripts/util/histogram-widget.js b/src/main/webapp/scripts/util/histogram-widget.js
new file mode 100644
index 000000000..906ab1c3e
--- /dev/null
+++ b/src/main/webapp/scripts/util/histogram-widget.js
@@ -0,0 +1,126 @@
+function HistogramWidget(elmt, options) {
+ this._elmt = elmt;
+ this._options = options;
+
+ this._range = null;
+ this._binMatrix = null;
+ this._highlight = null;
+
+ this._initializeUI();
+}
+
+HistogramWidget.prototype.highlight = function(from, to) {
+ this._highlight = { from: from, to: to };
+ this._update();
+};
+
+HistogramWidget.prototype.update = function(min, max, step, binMatrix) {
+ if (typeof min == "undefined" || typeof binMatrix == "undefined" || binMatrix.length === 0 || binMatrix[0].length === 0) {
+ this._range = null;
+ this._binMatrix = null;
+ this._highlight = null;
+
+ this._elmt.hide();
+ } else {
+ this._range = { min: min, max: max, step: step };
+ this._binMatrix = binMatrix;
+
+ this._peak = 0;
+ for (var r = 0; r < binMatrix.length; r++) {
+ var row = binMatrix[r];
+ for (var c = 0; c < row.length; c++) {
+ this._peak = Math.max(this._peak, row[c]);
+ }
+ }
+
+ this._update();
+ }
+};
+
+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._elmt.show();
+ this._resize();
+ this._render();
+ }
+};
+
+HistogramWidget.prototype._initializeUI = function() {
+ this._elmt
+ .empty()
+ .hide()
+ .addClass("histogram-widget")
+ .html(
+ '
'
+ );
+
+ this._elmts = DOM.bind(this._elmt);
+};
+
+HistogramWidget.prototype._resize = function() {
+ this._elmts.canvas.attr("height", "height" in this._options ? this._options.height : 50);
+ this._elmts.canvas.attr("width", this._elmts.canvas.width());
+};
+
+HistogramWidget.prototype._render = function() {
+ var self = this;
+ var options = this._options;
+
+ var canvas = this._elmts.canvas[0];
+ var ctx = canvas.getContext('2d');
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ ctx.save();
+ ctx.translate(0, canvas.height);
+ ctx.scale(1, -1);
+
+ /*
+ * Draw axis
+ */
+ ctx.save();
+ ctx.strokeStyle = "emptyBinColor" in options ? options.emptyBinColor : "#faa";
+ ctx.lineWidth = 1;
+ ctx.moveTo(0, 0);
+ ctx.lineTo(canvas.width, 0);
+ ctx.stroke();
+ ctx.restore();
+
+ /*
+ * 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);
+ return "#" + h + h + h;
+ };
+ var renderRow = function(row, color) {
+ ctx.save();
+ ctx.lineWidth = 0;
+ ctx.fillStyle = color;
+ for (var c = 0; c < row.length; c++) {
+ var value = row[c];
+ if (value > 0) {
+ var left = c * stepPixels;
+ var height = Math.ceil(value * canvas.height / self._peak);
+ ctx.fillRect(left, 0, Math.ceil(stepPixels), height);
+ }
+ }
+ ctx.restore();
+ };
+ for (var r = 0; r < this._binMatrix.length; r++) {
+ renderRow(
+ this._binMatrix[r],
+ "binColors" in options && r < options.binColors.length ?
+ options.binColors[r] :
+ makeColor(r)
+ );
+ }
+
+ ctx.restore();
+};
diff --git a/src/main/webapp/styles/project/browsing.css b/src/main/webapp/styles/project/browsing.css
index 5ed1fdc24..69b7efca3 100644
--- a/src/main/webapp/styles/project/browsing.css
+++ b/src/main/webapp/styles/project/browsing.css
@@ -128,11 +128,6 @@ img.facet-choice-link {
margin: 10px 4px;
overflow: hidden;
}
-.facet-range-histogram img {
- height: 50px;
- position: relative;
- left: -2px;
-}
.facet-range-slider {
}
.facet-range-status {
diff --git a/src/main/webapp/styles/util/histogram-widget.css b/src/main/webapp/styles/util/histogram-widget.css
new file mode 100644
index 000000000..f225171e7
--- /dev/null
+++ b/src/main/webapp/styles/util/histogram-widget.css
@@ -0,0 +1,9 @@
+.histogram-widget {
+ margin: 0;
+ padding: 0;
+ position: relative;
+}
+
+.histogram-widget canvas {
+ width: 100%;
+}