2010-10-20 20:11:15 +02:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright 2010, Google Inc.
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are
|
|
|
|
met:
|
|
|
|
|
2011-08-04 22:37:14 +02:00
|
|
|
* Redistributions of source code must retain the above copyright
|
2010-10-20 20:11:15 +02:00
|
|
|
notice, this list of conditions and the following disclaimer.
|
2011-08-04 22:37:14 +02:00
|
|
|
* Redistributions in binary form must reproduce the above
|
2010-10-20 20:11:15 +02:00
|
|
|
copyright notice, this list of conditions and the following disclaimer
|
|
|
|
in the documentation and/or other materials provided with the
|
|
|
|
distribution.
|
2011-08-04 22:37:14 +02:00
|
|
|
* Neither the name of Google Inc. nor the names of its
|
2010-10-20 20:11:15 +02:00
|
|
|
contributors may be used to endorse or promote products derived from
|
|
|
|
this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
2011-08-04 22:37:14 +02:00
|
|
|
*/
|
2010-10-20 20:11:15 +02:00
|
|
|
|
2010-02-27 01:16:44 +01:00
|
|
|
function BrowsingEngine(div, facetConfigs) {
|
2011-08-04 22:37:14 +02:00
|
|
|
this._div = div;
|
2017-10-27 13:22:01 +02:00
|
|
|
this._mode = theProject.recordModel.hasRecords ? "record-based" : "row-based";
|
2011-08-04 22:37:14 +02:00
|
|
|
|
|
|
|
this._facets = [];
|
|
|
|
this._initializeUI();
|
|
|
|
|
|
|
|
if (facetConfigs.length > 0) {
|
|
|
|
for (var i = 0; i < facetConfigs.length; i++) {
|
|
|
|
var facetConfig = facetConfigs[i];
|
|
|
|
var type = facetConfig.c.type;
|
|
|
|
|
|
|
|
var elmt = this._createFacetContainer();
|
|
|
|
var facet;
|
|
|
|
switch (type) {
|
|
|
|
case "range":
|
|
|
|
facet = RangeFacet.reconstruct(elmt, facetConfig);
|
|
|
|
break;
|
|
|
|
case "timerange":
|
|
|
|
facet = TimeRangeFacet.reconstruct(elmt, facetConfig);
|
|
|
|
break;
|
|
|
|
case "scatterplot":
|
|
|
|
facet = ScatterplotFacet.reconstruct(elmt, facetConfig);
|
|
|
|
break;
|
|
|
|
case "text":
|
|
|
|
facet = TextSearchFacet.reconstruct(elmt, facetConfig);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
facet = ListFacet.reconstruct(elmt, facetConfig);
|
|
|
|
}
|
|
|
|
|
|
|
|
this._facets.push({ elmt: elmt, facet: facet });
|
2010-02-27 01:16:44 +01:00
|
|
|
}
|
2011-08-04 22:37:14 +02:00
|
|
|
}
|
2010-02-27 01:16:44 +01:00
|
|
|
}
|
|
|
|
|
2010-03-22 22:48:36 +01:00
|
|
|
BrowsingEngine.prototype.resize = function() {
|
2011-08-04 22:37:14 +02:00
|
|
|
if (this._facets.length > 0) {
|
|
|
|
var body = this._div.find(".facets-container");
|
|
|
|
var bodyPaddings = body.outerHeight(true) - body.height();
|
|
|
|
var height =
|
|
|
|
this._div.height() -
|
|
|
|
this._div.find(".browsing-panel-header").outerHeight(true) -
|
|
|
|
bodyPaddings;
|
|
|
|
|
|
|
|
body.css("height", height + "px");
|
|
|
|
|
|
|
|
this._elmts.facets.sortable("refresh");
|
|
|
|
}
|
2010-03-22 22:48:36 +01:00
|
|
|
};
|
|
|
|
|
2010-02-27 01:16:44 +01:00
|
|
|
BrowsingEngine.prototype.getFacetUIStates = function() {
|
2011-08-04 22:37:14 +02:00
|
|
|
var f = [];
|
|
|
|
for (var i = 0; i < this._facets.length; i++) {
|
|
|
|
var facet = this._facets[i];
|
|
|
|
f.push(facet.facet.getUIState());
|
|
|
|
}
|
|
|
|
return f;
|
2010-04-08 21:52:23 +02:00
|
|
|
};
|
2010-01-29 01:46:15 +01:00
|
|
|
|
2010-01-30 02:05:30 +01:00
|
|
|
BrowsingEngine.prototype._initializeUI = function() {
|
2011-08-04 22:37:14 +02:00
|
|
|
var self = this;
|
|
|
|
|
|
|
|
this._div.html(
|
|
|
|
'<div class="browsing-panel-help" bind="help">' +
|
2018-11-21 18:30:00 +01:00
|
|
|
'<h1>'+$.i18n('core-project/use-facets')+'</h1>' +
|
|
|
|
'<p>'+$.i18n('core-project/use-to-select')+'</p>' +
|
|
|
|
'<p>'+$.i18n('core-project/not-sure')+'<br /><a href="https://github.com/OpenRefine/OpenRefine/wiki/Screencasts" target="_blank"><b>'+$.i18n('core-project/watch-cast')+'</b></a></p>' +
|
2011-08-04 22:37:14 +02:00
|
|
|
'</div>' +
|
|
|
|
'<div class="browsing-panel-header" bind="header">' +
|
2017-10-27 11:59:03 +02:00
|
|
|
'<div class="browsing-panel-errors" bind="errors"></div>' +
|
2011-08-04 22:37:14 +02:00
|
|
|
'<div class="browsing-panel-indicator" bind="indicator">' +
|
2018-11-21 18:30:00 +01:00
|
|
|
'<img src="images/small-spinner.gif" /> '+$.i18n('core-project/refreshing-facet')+'' +
|
2011-08-04 22:37:14 +02:00
|
|
|
'</div>' +
|
|
|
|
'<div class="browsing-panel-controls" bind="controls">' +
|
|
|
|
'<div class="browsing-panel-controls-refresh">' +
|
2018-11-21 18:30:00 +01:00
|
|
|
'<a href="javascript:{}" bind="refreshLink" class="button" title="'+$.i18n('core-project/update-facets')+'">'+$.i18n('core-buttons/refresh')+'</a>' +
|
2011-08-04 22:37:14 +02:00
|
|
|
'</div>' +
|
2018-11-21 18:30:00 +01:00
|
|
|
'<a href="javascript:{}" bind="resetLink" class="button button-pill-left" title="'+$.i18n('core-project/clear-selection')+'">'+$.i18n('core-buttons/reset-all')+'</a>' +
|
|
|
|
'<a href="javascript:{}" bind="removeLink" class="button button-pill-right" title="'+$.i18n('core-project/remove-all')+'">'+$.i18n('core-buttons/remove-all')+'</a>' +
|
2011-08-04 22:37:14 +02:00
|
|
|
'</div>' +
|
|
|
|
'</div>' +
|
|
|
|
'<ul bind="facets" class="facets-container"></ul>'
|
|
|
|
);
|
|
|
|
this._elmts = DOM.bind(this._div);
|
|
|
|
this._elmts.facets.sortable({
|
|
|
|
handle: '.facet-title',
|
|
|
|
update: function(event, ui) {
|
|
|
|
self._updateFacetOrder();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this._elmts.refreshLink.click(function() { self.update(); });
|
|
|
|
this._elmts.resetLink.click(function() { self.reset(); });
|
|
|
|
this._elmts.removeLink.click(function() { self.remove(); });
|
2010-03-02 23:32:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
BrowsingEngine.prototype._updateFacetOrder = function() {
|
2011-08-04 22:37:14 +02:00
|
|
|
var elmts = this._elmts.facets.children();
|
|
|
|
var newFacets = [];
|
|
|
|
for (var e = 0; e < elmts.length; e++) {
|
|
|
|
var elmt = elmts[e];
|
|
|
|
for (var f = 0; f < this._facets.length; f++) {
|
|
|
|
if (elmt === this._facets[f].elmt[0]) {
|
|
|
|
newFacets.push(this._facets[f]);
|
|
|
|
break;
|
|
|
|
}
|
2010-03-02 23:32:52 +01:00
|
|
|
}
|
2011-08-04 22:37:14 +02:00
|
|
|
}
|
|
|
|
this._facets = newFacets;
|
2010-01-29 01:46:15 +01:00
|
|
|
};
|
|
|
|
|
2010-07-30 04:25:58 +02:00
|
|
|
BrowsingEngine.prototype.getMode = function() {
|
2011-08-04 22:37:14 +02:00
|
|
|
return this._mode;
|
2010-10-06 21:15:29 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
BrowsingEngine.prototype.setMode = function(mode) {
|
2011-08-04 22:37:14 +02:00
|
|
|
if (this._mode != mode) {
|
|
|
|
this._mode = mode;
|
|
|
|
Refine.update({ engineChanged: true });
|
|
|
|
}
|
2010-07-30 04:25:58 +02:00
|
|
|
};
|
|
|
|
|
2010-04-17 07:59:25 +02:00
|
|
|
BrowsingEngine.prototype.getJSON = function(keepUnrestrictedFacets, except) {
|
2011-08-04 22:37:14 +02:00
|
|
|
var a = {
|
|
|
|
facets: [],
|
|
|
|
mode: this._mode
|
|
|
|
};
|
|
|
|
for (var i = 0; i < this._facets.length; i++) {
|
|
|
|
var facet = this._facets[i];
|
|
|
|
if ((keepUnrestrictedFacets || facet.facet.hasSelection()) && (facet.facet !== except)) {
|
|
|
|
a.facets.push(facet.facet.getJSON());
|
2010-01-29 01:46:15 +01:00
|
|
|
}
|
2011-08-04 22:37:14 +02:00
|
|
|
}
|
|
|
|
return a;
|
2010-01-29 01:46:15 +01:00
|
|
|
};
|
2010-01-30 02:05:30 +01:00
|
|
|
|
2010-02-02 02:36:02 +01:00
|
|
|
BrowsingEngine.prototype.addFacet = function(type, config, options) {
|
2011-08-04 22:37:14 +02:00
|
|
|
var elmt = this._createFacetContainer();
|
|
|
|
var facet;
|
|
|
|
switch (type) {
|
|
|
|
case "range":
|
|
|
|
facet = new RangeFacet(elmt, config, options);
|
|
|
|
break;
|
|
|
|
case "timerange":
|
|
|
|
facet = new TimeRangeFacet(elmt, config, options);
|
|
|
|
break;
|
|
|
|
case "scatterplot":
|
|
|
|
facet = new ScatterplotFacet(elmt, config, options);
|
|
|
|
break;
|
|
|
|
case "text":
|
|
|
|
facet = new TextSearchFacet(elmt, config, options);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
facet = new ListFacet(elmt, config, options);
|
|
|
|
}
|
|
|
|
|
|
|
|
this._facets.push({ elmt: elmt, facet: facet });
|
|
|
|
|
2020-08-17 14:49:56 +02:00
|
|
|
ui.leftPanelTabs.tabs();
|
2011-08-04 22:37:14 +02:00
|
|
|
|
|
|
|
Refine.update({ engineChanged: true });
|
2010-01-30 02:05:30 +01:00
|
|
|
};
|
|
|
|
|
2010-03-02 23:32:52 +01:00
|
|
|
BrowsingEngine.prototype._createFacetContainer = function() {
|
2011-08-04 22:37:14 +02:00
|
|
|
return $('<li></li>').addClass("facet-container").attr("id","facet-" + this._facets.length).hide().appendTo(this._elmts.facets);
|
2010-03-02 23:32:52 +01:00
|
|
|
};
|
|
|
|
|
2010-02-01 01:19:41 +01:00
|
|
|
BrowsingEngine.prototype.removeFacet = function(facet) {
|
2011-08-04 22:37:14 +02:00
|
|
|
var update = facet.hasSelection();
|
|
|
|
for (var i = this._facets.length - 1;i >= 0; i--) {
|
|
|
|
var facetRecord = this._facets[i];
|
|
|
|
if (facetRecord.facet === facet) {
|
|
|
|
this._facets.splice(i, 1);
|
2010-04-24 08:29:30 +02:00
|
|
|
|
2011-08-04 22:37:14 +02:00
|
|
|
facetRecord.facet.dispose();
|
|
|
|
|
|
|
|
// This makes really big facet disappear right away. If you just call remove()
|
|
|
|
// then it takes a while for all the event handlers to get unwired, and the UI
|
|
|
|
// appear frozen.
|
|
|
|
facetRecord.elmt.hide();
|
|
|
|
window.setTimeout(function() {
|
|
|
|
facetRecord.elmt.remove();
|
|
|
|
}, 300);
|
|
|
|
|
|
|
|
break;
|
2010-02-01 01:19:41 +01:00
|
|
|
}
|
2011-08-04 22:37:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (var i = 0; i < this._facets.length; i++) {
|
|
|
|
if (typeof this._facets[i].facet.update == "function") {
|
|
|
|
this._facets[i].facet.update();
|
2010-02-01 01:19:41 +01:00
|
|
|
}
|
2011-08-04 22:37:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (update) {
|
|
|
|
Refine.update({ engineChanged: true });
|
2011-10-08 01:44:11 +02:00
|
|
|
} else if (this._facets.length === 0) {
|
2011-08-04 22:37:14 +02:00
|
|
|
this._elmts.help.show();
|
|
|
|
this._elmts.header.hide();
|
|
|
|
}
|
2010-02-01 01:19:41 +01:00
|
|
|
};
|
|
|
|
|
2010-02-26 22:56:41 +01:00
|
|
|
BrowsingEngine.prototype.update = function(onDone) {
|
2011-08-04 22:37:14 +02:00
|
|
|
var self = this;
|
|
|
|
|
|
|
|
this._elmts.help.hide();
|
|
|
|
|
|
|
|
this._elmts.header.show();
|
|
|
|
this._elmts.controls.css("visibility", "hidden");
|
2017-10-27 11:59:03 +02:00
|
|
|
this._elmts.indicator.css("display", "block");
|
2011-08-04 22:37:14 +02:00
|
|
|
|
|
|
|
$.post(
|
2012-10-13 19:47:08 +02:00
|
|
|
"command/core/compute-facets?" + $.param({ project: theProject.id }),
|
2011-08-04 22:37:14 +02:00
|
|
|
{ engine: JSON.stringify(this.getJSON(true)) },
|
|
|
|
function(data) {
|
2017-10-27 12:47:59 +02:00
|
|
|
if(data.code === "error") {
|
2017-10-27 11:59:03 +02:00
|
|
|
var clearErr = $('#err-text').remove();
|
|
|
|
var err = $('<div id="err-text">')
|
|
|
|
.text(data.message)
|
|
|
|
.appendTo(self._elmts.errors);
|
|
|
|
self._elmts.errors.css("display", "block");
|
|
|
|
if (onDone) {
|
|
|
|
onDone();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2011-08-04 22:37:14 +02:00
|
|
|
var facetData = data.facets;
|
|
|
|
|
|
|
|
for (var i = 0; i < facetData.length; i++) {
|
|
|
|
self._facets[i].facet.updateState(facetData[i]);
|
|
|
|
}
|
|
|
|
|
2017-10-27 11:59:03 +02:00
|
|
|
self._elmts.indicator.css("display", "none");
|
|
|
|
self._elmts.errors.css("display", "none");
|
2011-08-04 22:37:14 +02:00
|
|
|
if (self._facets.length > 0) {
|
|
|
|
self._elmts.header.show();
|
|
|
|
self._elmts.controls.css("visibility", "visible");
|
|
|
|
|
|
|
|
self.resize();
|
|
|
|
} else {
|
|
|
|
self._elmts.help.show();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (onDone) {
|
|
|
|
onDone();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"json"
|
|
|
|
);
|
2010-01-30 02:05:30 +01:00
|
|
|
};
|
2010-03-23 19:53:29 +01:00
|
|
|
|
|
|
|
BrowsingEngine.prototype.reset = function() {
|
2011-08-04 22:37:14 +02:00
|
|
|
for (var i = 0; i < this._facets.length; i++) {
|
|
|
|
this._facets[i].facet.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
Refine.update({ engineChanged: true });
|
2010-03-23 19:53:29 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
BrowsingEngine.prototype.remove = function() {
|
2011-08-04 22:37:14 +02:00
|
|
|
var oldFacets = this._facets;
|
|
|
|
|
|
|
|
this._facets = [];
|
|
|
|
|
|
|
|
for (var i = 0; i < oldFacets.length; i++) {
|
|
|
|
var facet = oldFacets[i];
|
|
|
|
facet.facet.dispose();
|
|
|
|
facet.elmt.hide();
|
|
|
|
}
|
|
|
|
window.setTimeout(function() {
|
2010-03-23 19:53:29 +01:00
|
|
|
for (var i = 0; i < oldFacets.length; i++) {
|
2011-08-04 22:37:14 +02:00
|
|
|
oldFacets[i].elmt.remove();
|
2010-03-23 19:53:29 +01:00
|
|
|
}
|
2011-08-04 22:37:14 +02:00
|
|
|
}, 300);
|
|
|
|
|
|
|
|
Refine.update({ engineChanged: true });
|
2010-03-23 19:53:29 +01:00
|
|
|
};
|