* Clustering dialog choices limit & performance improvements - fixes #695 Fixes #695 - Caps the total number of choices displayed at 10,000 and warns when over the limit. Users can use facets to tune which clusters are displayed. - Doubles the performance of the Javascript processing - Only displays count of rows for a choice if it's > 1 to DOM elements - Adds internationalization for row count For 41K clusters containing 118K choices, processing dropped from 3m20s to 1m20s, but with the 10K choice cap total time is ~10sec. * Restore even/odd row class * Updates from review feedback
This commit is contained in:
parent
5985f95ce1
commit
0ebd89c952
@ -177,7 +177,9 @@
|
|||||||
"core-dialogs/choice-avg-length": "Average Length of Choices",
|
"core-dialogs/choice-avg-length": "Average Length of Choices",
|
||||||
"core-dialogs/choice-var-length": "Length Variance of Choices",
|
"core-dialogs/choice-var-length": "Length Variance of Choices",
|
||||||
"core-dialogs/clusters-found": "<b>$1</b> {{plural:$1|cluster|clusters}} found",
|
"core-dialogs/clusters-found": "<b>$1</b> {{plural:$1|cluster|clusters}} found",
|
||||||
"core-dialogs/clusters-filtered": "<b>$1</b> {{plural:$1|cluster|clusters}} filtered from <b>$2</b> total",
|
"core-dialogs/clusters-filtered": "<b>$1</b> {{plural:$1|cluster|clusters}} included from <b>$2</b> total",
|
||||||
|
"core-dialogs/cluster-row-limit-exceeded": "Exceeded limit of $1 total choices",
|
||||||
|
"core-dialogs/cluster-rows": "($1 rows)",
|
||||||
"core-dialogs/cluster-descr": "This feature helps you find groups of different cell values that might be alternative representations of the same thing. For example, the two strings \"New York\" and \"new york\" are very likely to refer to the same concept and just have capitalization differences, and \"Gödel\" and \"Godel\" probably refer to the same person.",
|
"core-dialogs/cluster-descr": "This feature helps you find groups of different cell values that might be alternative representations of the same thing. For example, the two strings \"New York\" and \"new york\" are very likely to refer to the same concept and just have capitalization differences, and \"Gödel\" and \"Godel\" probably refer to the same person.",
|
||||||
"core-dialogs/find-more": "Find out more…",
|
"core-dialogs/find-more": "Find out more…",
|
||||||
"core-dialogs/method": "Method ",
|
"core-dialogs/method": "Method ",
|
||||||
|
@ -165,6 +165,9 @@ ClusteringDialog.prototype._renderTable = function(clusters) {
|
|||||||
var container = this._elmts.tableContainer;
|
var container = this._elmts.tableContainer;
|
||||||
|
|
||||||
if (clusters.length > 0) {
|
if (clusters.length > 0) {
|
||||||
|
// TODO: This will never get rendered because we're blocking rendering
|
||||||
|
container.empty().html('<div>Processing clusters...</div>');
|
||||||
|
|
||||||
var table = $('<table></table>').addClass("clustering-dialog-entry-table")[0];
|
var table = $('<table></table>').addClass("clustering-dialog-entry-table")[0];
|
||||||
|
|
||||||
var trHead = table.insertRow(table.rows.length);
|
var trHead = table.insertRow(table.rows.length);
|
||||||
@ -175,13 +178,24 @@ ClusteringDialog.prototype._renderTable = function(clusters) {
|
|||||||
$(trHead.insertCell(3)).text($.i18n('core-dialogs/merge'));
|
$(trHead.insertCell(3)).text($.i18n('core-dialogs/merge'));
|
||||||
$(trHead.insertCell(4)).text($.i18n('core-dialogs/new-cell-val'));
|
$(trHead.insertCell(4)).text($.i18n('core-dialogs/new-cell-val'));
|
||||||
|
|
||||||
var renderCluster = function(cluster) {
|
var entryTemplate = document.createElement('a');
|
||||||
var tr = table.insertRow(table.rows.length);
|
entryTemplate.href = "javascript:{}";
|
||||||
tr.className = table.rows.length % 2 === 0 ? "odd" : "even";
|
entryTemplate.title = $.i18n('core-dialogs/use-this-val');
|
||||||
|
|
||||||
$(tr.insertCell(0)).text(cluster.choices.length);
|
var browseLinkTemplate = $('<a target="_new" title="'+$.i18n('core-dialogs/browse-only-these')+'">'+$.i18n('core-dialogs/browse-this-cluster')+'</a>')
|
||||||
|
.addClass("clustering-dialog-browse-focus")
|
||||||
|
.css("visibility","hidden")
|
||||||
|
|
||||||
$(tr.insertCell(1)).text(cluster.rowCount);
|
|
||||||
|
var renderCluster = function(cluster, index) {
|
||||||
|
var tr = table.insertRow();
|
||||||
|
tr.className = index % 2 === 0 ? "odd" : "even"; // TODO: Unused?
|
||||||
|
|
||||||
|
var cell = tr.insertCell()
|
||||||
|
cell.textContent = cluster.choices.length.toString();
|
||||||
|
|
||||||
|
cell = tr.insertCell();
|
||||||
|
cell.textContent = cluster.rowCount.toString();
|
||||||
|
|
||||||
var facet = {
|
var facet = {
|
||||||
"c": {
|
"c": {
|
||||||
@ -197,9 +211,8 @@ ClusteringDialog.prototype._renderTable = function(clusters) {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
var ul = $('<ul></ul>');
|
var ul = document.createElement('ul');
|
||||||
var choices = cluster.choices;
|
var choices = cluster.choices;
|
||||||
var rowCount = 0;
|
|
||||||
var onClick = function() {
|
var onClick = function() {
|
||||||
var parent = $(this).closest("tr");
|
var parent = $(this).closest("tr");
|
||||||
var value = $(this).text();
|
var value = $(this).text();
|
||||||
@ -212,17 +225,21 @@ ClusteringDialog.prototype._renderTable = function(clusters) {
|
|||||||
};
|
};
|
||||||
for (var c = 0; c < choices.length; c++) {
|
for (var c = 0; c < choices.length; c++) {
|
||||||
var choice = choices[c];
|
var choice = choices[c];
|
||||||
var li = $('<li></li>');
|
var li = document.createElement('li');
|
||||||
$('<a href="javascript:{}" title='+$.i18n('core-dialogs/use-this-val')+'></a>').text(choice.v).click(onClick).appendTo(li);
|
var entry = entryTemplate.cloneNode();
|
||||||
$('<span></span>').text("(" + choice.c + " rows)").addClass("clustering-dialog-entry-count").appendTo(li);
|
entry.textContent = choice.v.toString();
|
||||||
rowCount += choice.c;
|
entry.addEventListener('click', onClick);
|
||||||
|
li.append(entry);
|
||||||
|
if (choice.c > 1) {
|
||||||
|
$('<span></span>').text($.i18n("core-dialogs/cluster-rows", choice.c)).addClass("clustering-dialog-entry-count").appendTo(li);
|
||||||
|
}
|
||||||
facet.s[c] = {
|
facet.s[c] = {
|
||||||
"v": {
|
"v": {
|
||||||
"v":choice.v,
|
"v":choice.v,
|
||||||
"l":choice.v
|
"l":choice.v
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
li.appendTo(ul);
|
ul.append(li);
|
||||||
}
|
}
|
||||||
|
|
||||||
var params = [
|
var params = [
|
||||||
@ -233,12 +250,11 @@ ClusteringDialog.prototype._renderTable = function(clusters) {
|
|||||||
];
|
];
|
||||||
var url = "project?" + params.join("&");
|
var url = "project?" + params.join("&");
|
||||||
|
|
||||||
var div = $('<div></div>').addClass("clustering-dialog-value-focus");
|
var div = document.createElement('div');
|
||||||
|
div.class = "clustering-dialog-value-focus";
|
||||||
|
|
||||||
var browseLink = $('<a target="_new" title="'+$.i18n('core-dialogs/browse-only-these')+'">'+$.i18n('core-dialogs/browse-this-cluster')+'</a>')
|
var browseLink = $(browseLinkTemplate).clone()
|
||||||
.addClass("clustering-dialog-browse-focus")
|
|
||||||
.attr("href",url)
|
.attr("href",url)
|
||||||
.css("visibility","hidden")
|
|
||||||
.appendTo(div);
|
.appendTo(div);
|
||||||
|
|
||||||
$(tr.insertCell(2))
|
$(tr.insertCell(2))
|
||||||
@ -256,23 +272,29 @@ ClusteringDialog.prototype._renderTable = function(clusters) {
|
|||||||
editCheck.attr("checked", "true");
|
editCheck.attr("checked", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
var input = $('<input type="text" size="25" />')
|
$('<input type="text" size="25" />')
|
||||||
.attr("value", cluster.value)
|
.attr("value", cluster.value)
|
||||||
.bind("keyup change input",function() {
|
.bind("keyup change input",function() {
|
||||||
cluster.value = this.value;
|
cluster.value = this.value;
|
||||||
}).appendTo(tr.insertCell(4));
|
}).appendTo(tr.insertCell(4));
|
||||||
|
|
||||||
|
return choices.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (var i = 0; i < clusters.length; i++) {
|
// TODO: Make this a preference "ui.clustering.choices.limit"
|
||||||
renderCluster(clusters[i]);
|
var maxRenderRows = 5000;
|
||||||
|
var totalRows = 0;
|
||||||
|
for (var clusterIndex = 0; clusterIndex < clusters.length && totalRows < maxRenderRows; clusterIndex++) {
|
||||||
|
totalRows += renderCluster(clusters[clusterIndex], clusterIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
container.empty().append(table);
|
container.empty().append(table);
|
||||||
|
|
||||||
this._elmts.resultSummary.html(
|
this._elmts.resultSummary.html(
|
||||||
(clusters.length === this._clusters.length) ?
|
((totalRows >= maxRenderRows) ? $.i18n('core-dialogs/cluster-row-limit-exceeded', maxRenderRows) + '<br/> ' : '') +
|
||||||
|
((clusterIndex === this._clusters.length) ?
|
||||||
$.i18n('core-dialogs/clusters-found', this._clusters.length) :
|
$.i18n('core-dialogs/clusters-found', this._clusters.length) :
|
||||||
$.i18n('core-dialogs/clusters-filtered', clusters.length, this._clusters.length)
|
$.i18n('core-dialogs/clusters-filtered', clusterIndex, this._clusters.length))
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user