Switched to a canvas-based implementation of histograms.
git-svn-id: http://google-refine.googlecode.com/svn/trunk@319 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
parent
b9b4bb0ab4
commit
91241539cf
@ -1 +1 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Gridworks</title>
<link type="text/css" rel="stylesheet" href="externals/suggest/css/suggest-1.0.3.min.css" />
<link type="text/css" rel="stylesheet" href="externals/jquery-ui/css/ui-lightness/jquery-ui-1.7.2.custom.css" />
<link rel="stylesheet" href="/styles/common.css" />
<link rel="stylesheet" href="/styles/util/menu.css" />
<link rel="stylesheet" href="/styles/util/dialog.css" />
<link rel="stylesheet" href="/styles/util/custom-suggest.css" />
<link rel="stylesheet" href="/styles/project.css" />
<link rel="stylesheet" href="/styles/project/history.css" />
<link rel="stylesheet" href="/styles/project/browsing.css" />
<link rel="stylesheet" href="/styles/project/process.css" />
<link rel="stylesheet" href="/styles/project/menu-bar.css" />
<link rel="stylesheet" href="/styles/views/data-table-view.css" />
<link rel="stylesheet" href="/styles/dialogs/expression-preview-dialog.css" />
<link rel="stylesheet" href="/styles/dialogs/recon-dialog.css" />
<link rel="stylesheet" href="/styles/dialogs/clustering-dialog.css" />
<link rel="stylesheet" href="/styles/dialogs/extend-data-preview-dialog.css" />
<link rel="stylesheet" href="/styles/protograph/schema-alignment-dialog.css" />
<script type="text/javascript" src="externals/jquery-1.4.1.min.js"></script>
<script type="text/javascript" src="externals/suggest/suggest-1.0.3.min.js"></script>
<script type="text/javascript" src="externals/jquery-ui/jquery-ui-1.7.2.custom.min.js"></script>
<script type="text/javascript" src="externals/date.js"></script>
<script type="text/javascript" src="scripts/util/misc.js"></script>
<script type="text/javascript" src="scripts/util/url.js"></script>
<script type="text/javascript" src="scripts/util/string.js"></script>
<script type="text/javascript" src="scripts/util/ajax.js"></script>
<script type="text/javascript" src="scripts/util/menu.js"></script>
<script type="text/javascript" src="scripts/util/dialog.js"></script>
<script type="text/javascript" src="scripts/util/dom.js"></script>
<script type="text/javascript" src="scripts/util/custom-suggest.js"></script>
<script type="text/javascript" src="scripts/project.js"></script>
<script type="text/javascript" src="scripts/project/history-widget.js"></script>
<script type="text/javascript" src="scripts/project/process-widget.js"></script>
<script type="text/javascript" src="scripts/project/menu-bar.js"></script>
<script type="text/javascript" src="scripts/project/browsing-engine.js"></script>
<script type="text/javascript" src="scripts/project/scripting.js"></script>
<script type="text/javascript" src="scripts/facets/list-facet.js"></script>
<script type="text/javascript" src="scripts/facets/range-facet.js"></script>
<script type="text/javascript" src="scripts/facets/text-search-facet.js"></script>
<script type="text/javascript" src="scripts/views/data-table-view.js"></script>
<script type="text/javascript" src="scripts/views/data-table-cell-ui.js"></script>
<script type="text/javascript" src="scripts/views/data-table-column-header-ui.js"></script>
<script type="text/javascript" src="scripts/dialogs/recon-dialog.js"></script>
<script type="text/javascript" src="scripts/dialogs/expression-preview-dialog.js"></script>
<script type="text/javascript" src="scripts/dialogs/clustering-dialog.js"></script>
<script type="text/javascript" src="scripts/dialogs/extend-data-preview-dialog.js"></script>
<script type="text/javascript" src="scripts/protograph/schema-alignment.js"></script>
<script type="text/javascript" src="scripts/protograph/schema-alignment-ui-node.js"></script>
<script type="text/javascript" src="scripts/protograph/schema-alignment-ui-link.js"></script>
</head>
<body>
<div id="header">
<a id="logo" href="http://www.freebase.com/" title="Freebase"><img alt="Freebase" src="images/freebase-headerlogo.png" /></a>
<div id="path"><a class="app-path-section" href="./index.html">Gridworks</a> » </div>
</div>
<div id="body">
<div id="loading-message"><img src="images/large-spinner.gif" /> starting up ...</div>
</div>
<div id="footer">
<a href="about.html">About Freebase Gridworks</a>
•
© 2010 <a href="http://www.metaweb.com/">Metaweb Technologies, Inc.</a>
</div>
</body>
</html>
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Gridworks</title>
<link type="text/css" rel="stylesheet" href="externals/suggest/css/suggest-1.0.3.min.css" />
<link type="text/css" rel="stylesheet" href="externals/jquery-ui/css/ui-lightness/jquery-ui-1.7.2.custom.css" />
<link rel="stylesheet" href="/styles/common.css" />
<link rel="stylesheet" href="/styles/util/menu.css" />
<link rel="stylesheet" href="/styles/util/dialog.css" />
<link rel="stylesheet" href="/styles/util/custom-suggest.css" />
<link rel="stylesheet" href="/styles/util/histogram-widget.css" />
<link rel="stylesheet" href="/styles/project.css" />
<link rel="stylesheet" href="/styles/project/history.css" />
<link rel="stylesheet" href="/styles/project/browsing.css" />
<link rel="stylesheet" href="/styles/project/process.css" />
<link rel="stylesheet" href="/styles/project/menu-bar.css" />
<link rel="stylesheet" href="/styles/views/data-table-view.css" />
<link rel="stylesheet" href="/styles/dialogs/expression-preview-dialog.css" />
<link rel="stylesheet" href="/styles/dialogs/recon-dialog.css" />
<link rel="stylesheet" href="/styles/dialogs/clustering-dialog.css" />
<link rel="stylesheet" href="/styles/dialogs/extend-data-preview-dialog.css" />
<link rel="stylesheet" href="/styles/protograph/schema-alignment-dialog.css" />
<script type="text/javascript" src="externals/jquery-1.4.1.min.js"></script>
<script type="text/javascript" src="externals/suggest/suggest-1.0.3.min.js"></script>
<script type="text/javascript" src="externals/jquery-ui/jquery-ui-1.7.2.custom.min.js"></script>
<script type="text/javascript" src="externals/date.js"></script>
<script type="text/javascript" src="scripts/util/misc.js"></script>
<script type="text/javascript" src="scripts/util/url.js"></script>
<script type="text/javascript" src="scripts/util/string.js"></script>
<script type="text/javascript" src="scripts/util/ajax.js"></script>
<script type="text/javascript" src="scripts/util/menu.js"></script>
<script type="text/javascript" src="scripts/util/dialog.js"></script>
<script type="text/javascript" src="scripts/util/dom.js"></script>
<script type="text/javascript" src="scripts/util/custom-suggest.js"></script>
<script type="text/javascript" src="scripts/util/histogram-widget.js"></script>
<script type="text/javascript" src="scripts/project.js"></script>
<script type="text/javascript" src="scripts/project/history-widget.js"></script>
<script type="text/javascript" src="scripts/project/process-widget.js"></script>
<script type="text/javascript" src="scripts/project/menu-bar.js"></script>
<script type="text/javascript" src="scripts/project/browsing-engine.js"></script>
<script type="text/javascript" src="scripts/project/scripting.js"></script>
<script type="text/javascript" src="scripts/facets/list-facet.js"></script>
<script type="text/javascript" src="scripts/facets/range-facet.js"></script>
<script type="text/javascript" src="scripts/facets/text-search-facet.js"></script>
<script type="text/javascript" src="scripts/views/data-table-view.js"></script>
<script type="text/javascript" src="scripts/views/data-table-cell-ui.js"></script>
<script type="text/javascript" src="scripts/views/data-table-column-header-ui.js"></script>
<script type="text/javascript" src="scripts/dialogs/recon-dialog.js"></script>
<script type="text/javascript" src="scripts/dialogs/expression-preview-dialog.js"></script>
<script type="text/javascript" src="scripts/dialogs/clustering-dialog.js"></script>
<script type="text/javascript" src="scripts/dialogs/extend-data-preview-dialog.js"></script>
<script type="text/javascript" src="scripts/protograph/schema-alignment.js"></script>
<script type="text/javascript" src="scripts/protograph/schema-alignment-ui-node.js"></script>
<script type="text/javascript" src="scripts/protograph/schema-alignment-ui-link.js"></script>
</head>
<body>
<div id="header">
<a id="logo" href="http://www.freebase.com/" title="Freebase"><img alt="Freebase" src="images/freebase-headerlogo.png" /></a>
<div id="path"><a class="app-path-section" href="./index.html">Gridworks</a> » </div>
</div>
<div id="body">
<div id="loading-message"><img src="images/large-spinner.gif" /> starting up ...</div>
</div>
<div id="footer">
<a href="about.html">About Freebase Gridworks</a>
•
© 2010 <a href="http://www.metaweb.com/">Metaweb Technologies, Inc.</a>
</div>
</body>
</html>
|
@ -477,6 +477,9 @@ ClusteringDialog.Facet = function(dialog, title, property, elmt, clusters) {
|
|||||||
).appendTo(elmt);
|
).appendTo(elmt);
|
||||||
|
|
||||||
this._elmts = DOM.bind(html);
|
this._elmts = DOM.bind(html);
|
||||||
|
|
||||||
|
this._histogram = new HistogramWidget(this._elmts.histogramContainer, { binColors: [ "#aaaaff", "#000088" ] });
|
||||||
|
|
||||||
this._elmts.slider.slider({
|
this._elmts.slider.slider({
|
||||||
min: this._min,
|
min: this._min,
|
||||||
max: this._max,
|
max: this._max,
|
||||||
@ -518,29 +521,12 @@ ClusteringDialog.Facet.prototype.update = function(clusters) {
|
|||||||
|
|
||||||
var bins = this._computeDistribution(clusters);
|
var bins = this._computeDistribution(clusters);
|
||||||
|
|
||||||
var max = 0;
|
this._histogram.update(
|
||||||
for (var i = 0; i < this._baseBins.length; i++) {
|
this._min,
|
||||||
max = Math.max(max, this._baseBins[i]);
|
this._max,
|
||||||
}
|
this._step,
|
||||||
|
[ this._baseBins, bins ]
|
||||||
var values = [];
|
);
|
||||||
var diffs = [];
|
|
||||||
for (var i = 0; i < this._baseBins.length; i++) {
|
|
||||||
var v = Math.ceil(100 * 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._elmts.histogramContainer.empty();
|
|
||||||
$('<img />').attr("src",
|
|
||||||
"http://chart.apis.google.com/chart?" + [
|
|
||||||
"chs=" + this._elmts.histogramContainer[0].offsetWidth + "x50",
|
|
||||||
"cht=bvs&chbh=r,0&chco=000088,aaaaff",
|
|
||||||
"chd=t:" + values.join(",") + "|" + diffs.join(",")
|
|
||||||
].join("&")
|
|
||||||
).appendTo(this._elmts.histogramContainer);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ClusteringDialog.Facet.prototype._setRangeIndicators = function() {
|
ClusteringDialog.Facet.prototype._setRangeIndicators = function() {
|
||||||
|
@ -144,6 +144,8 @@ RangeFacet.prototype._initializeUI = function() {
|
|||||||
this._statusDiv = $('<div>').addClass("facet-range-status").appendTo(bodyDiv);
|
this._statusDiv = $('<div>').addClass("facet-range-status").appendTo(bodyDiv);
|
||||||
this._otherChoicesDiv = $('<div>').addClass("facet-range-other-choices").appendTo(bodyDiv);
|
this._otherChoicesDiv = $('<div>').addClass("facet-range-other-choices").appendTo(bodyDiv);
|
||||||
|
|
||||||
|
this._histogram = new HistogramWidget(this._histogramDiv, { binColors: [ "#aaaaff", "#000088" ] });
|
||||||
|
|
||||||
var onSlide = function(event, ui) {
|
var onSlide = function(event, ui) {
|
||||||
switch (self._config.mode) {
|
switch (self._config.mode) {
|
||||||
case "min":
|
case "min":
|
||||||
@ -327,35 +329,12 @@ RangeFacet.prototype.render = function() {
|
|||||||
this._sliderDiv.slider("option", "max", this._config.max);
|
this._sliderDiv.slider("option", "max", this._config.max);
|
||||||
this._sliderDiv.slider("option", "step", this._config.step);
|
this._sliderDiv.slider("option", "step", this._config.step);
|
||||||
|
|
||||||
var max = 0;
|
this._histogram.update(
|
||||||
for (var i = 0; i < this._baseBins.length; i++) {
|
this._config.min,
|
||||||
max = Math.max(max, this._baseBins[i]);
|
this._config.max,
|
||||||
}
|
this._config.step,
|
||||||
|
[ this._baseBins, this._bins ]
|
||||||
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();
|
|
||||||
$('<img />').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._setRangeIndicators();
|
this._setRangeIndicators();
|
||||||
this._renderOtherChoices();
|
this._renderOtherChoices();
|
||||||
|
126
src/main/webapp/scripts/util/histogram-widget.js
Normal file
126
src/main/webapp/scripts/util/histogram-widget.js
Normal file
@ -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(
|
||||||
|
'<canvas bind="canvas"></canvas>'
|
||||||
|
);
|
||||||
|
|
||||||
|
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();
|
||||||
|
};
|
@ -128,11 +128,6 @@ img.facet-choice-link {
|
|||||||
margin: 10px 4px;
|
margin: 10px 4px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.facet-range-histogram img {
|
|
||||||
height: 50px;
|
|
||||||
position: relative;
|
|
||||||
left: -2px;
|
|
||||||
}
|
|
||||||
.facet-range-slider {
|
.facet-range-slider {
|
||||||
}
|
}
|
||||||
.facet-range-status {
|
.facet-range-status {
|
||||||
|
9
src/main/webapp/styles/util/histogram-widget.css
Normal file
9
src/main/webapp/styles/util/histogram-widget.css
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.histogram-widget {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.histogram-widget canvas {
|
||||||
|
width: 100%;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user