Merge pull request #1327 from ostephens/invert-filter
Invert text search facet/text filter
This commit is contained in:
commit
78b7f01be5
@ -60,6 +60,7 @@ public class TextSearchFacet implements Facet {
|
||||
protected String _query;
|
||||
protected String _mode;
|
||||
protected boolean _caseSensitive;
|
||||
protected boolean _invert;
|
||||
|
||||
/*
|
||||
* Derived configuration
|
||||
@ -80,6 +81,7 @@ public class TextSearchFacet implements Facet {
|
||||
writer.key("query"); writer.value(_query);
|
||||
writer.key("mode"); writer.value(_mode);
|
||||
writer.key("caseSensitive"); writer.value(_caseSensitive);
|
||||
writer.key("invert"); writer.value(_invert);
|
||||
writer.endObject();
|
||||
}
|
||||
|
||||
@ -110,6 +112,7 @@ public class TextSearchFacet implements Facet {
|
||||
_query = _query.toLowerCase();
|
||||
}
|
||||
}
|
||||
_invert = o.has("invert") && o.getBoolean("invert");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -123,14 +126,14 @@ public class TextSearchFacet implements Facet {
|
||||
Evaluable eval = new VariableExpr("value");
|
||||
|
||||
if ("regex".equals(_mode)) {
|
||||
return new ExpressionStringComparisonRowFilter(eval, _columnName, _cellIndex) {
|
||||
return new ExpressionStringComparisonRowFilter(eval, _invert, _columnName, _cellIndex) {
|
||||
@Override
|
||||
protected boolean checkValue(String s) {
|
||||
return _pattern.matcher(s).find();
|
||||
};
|
||||
};
|
||||
} else {
|
||||
return new ExpressionStringComparisonRowFilter(eval, _columnName, _cellIndex) {
|
||||
return new ExpressionStringComparisonRowFilter(eval, _invert, _columnName, _cellIndex) {
|
||||
@Override
|
||||
protected boolean checkValue(String s) {
|
||||
return (_caseSensitive ? s : s.toLowerCase()).contains(_query);
|
||||
|
@ -52,11 +52,13 @@ import com.google.refine.model.Row;
|
||||
*/
|
||||
abstract public class ExpressionStringComparisonRowFilter implements RowFilter {
|
||||
final protected Evaluable _evaluable;
|
||||
final protected Boolean _invert;
|
||||
final protected String _columnName;
|
||||
final protected int _cellIndex;
|
||||
|
||||
public ExpressionStringComparisonRowFilter(Evaluable evaluable, String columnName, int cellIndex) {
|
||||
public ExpressionStringComparisonRowFilter(Evaluable evaluable, Boolean invert, String columnName, int cellIndex) {
|
||||
_evaluable = evaluable;
|
||||
_invert = invert;
|
||||
_columnName = columnName;
|
||||
_cellIndex = cellIndex;
|
||||
}
|
||||
@ -67,23 +69,23 @@ abstract public class ExpressionStringComparisonRowFilter implements RowFilter {
|
||||
|
||||
Properties bindings = ExpressionUtils.createBindings(project);
|
||||
ExpressionUtils.bind(bindings, row, rowIndex, _columnName, cell);
|
||||
|
||||
Boolean invert = _invert;
|
||||
Object value = _evaluable.evaluate(bindings);
|
||||
if (value != null) {
|
||||
if (value.getClass().isArray()) {
|
||||
Object[] a = (Object[]) value;
|
||||
for (Object v : a) {
|
||||
if (checkValue(v instanceof String ? ((String) v) : v.toString())) {
|
||||
return true;
|
||||
return !invert;
|
||||
}
|
||||
}
|
||||
} else if (value instanceof Collection<?>) {
|
||||
for (Object v : ExpressionUtils.toObjectCollection(value)) {
|
||||
if (checkValue(v.toString())) {
|
||||
return true;
|
||||
return !invert;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return invert;
|
||||
} else if (value instanceof JSONArray) {
|
||||
JSONArray a = (JSONArray) value;
|
||||
int l = a.length();
|
||||
@ -91,20 +93,20 @@ abstract public class ExpressionStringComparisonRowFilter implements RowFilter {
|
||||
for (int i = 0; i < l; i++) {
|
||||
try {
|
||||
if (checkValue(a.get(i).toString())) {
|
||||
return true;
|
||||
return !invert;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return invert;
|
||||
} else {
|
||||
if (checkValue(value instanceof String ? ((String) value) : value.toString())) {
|
||||
return true;
|
||||
return !invert;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return invert;
|
||||
}
|
||||
|
||||
abstract protected boolean checkValue(String s);
|
||||
|
@ -0,0 +1,265 @@
|
||||
/*
|
||||
|
||||
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:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
package com.google.refine.tests.model;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.refine.ProjectManager;
|
||||
import com.google.refine.ProjectMetadata;
|
||||
import com.google.refine.RefineServlet;
|
||||
import com.google.refine.importers.SeparatorBasedImporter;
|
||||
import com.google.refine.importing.ImportingJob;
|
||||
import com.google.refine.importing.ImportingManager;
|
||||
import com.google.refine.io.FileProjectManager;
|
||||
import com.google.refine.model.ModelException;
|
||||
import com.google.refine.model.Project;
|
||||
import com.google.refine.browsing.RowFilter;
|
||||
import com.google.refine.browsing.facets.TextSearchFacet;
|
||||
import com.google.refine.tests.RefineServletStub;
|
||||
import com.google.refine.tests.RefineTest;
|
||||
import com.google.refine.tests.util.TestUtils;
|
||||
|
||||
|
||||
public class TextSearchFacetTests extends RefineTest {
|
||||
// dependencies
|
||||
private RefineServlet servlet;
|
||||
private Project project;
|
||||
private ProjectMetadata pm;
|
||||
private JSONObject options;
|
||||
private ImportingJob job;
|
||||
private SeparatorBasedImporter importer;
|
||||
private TextSearchFacet textfilter;
|
||||
private JSONObject textsearchfacet;
|
||||
private RowFilter rowfilter;
|
||||
|
||||
@Override
|
||||
@BeforeTest
|
||||
public void init() {
|
||||
logger = LoggerFactory.getLogger(this.getClass());
|
||||
}
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() throws JSONException, IOException, ModelException {
|
||||
servlet = new RefineServletStub();
|
||||
File dir = TestUtils.createTempDirectory("openrefine-test-workspace-dir");
|
||||
FileProjectManager.initialize(dir);
|
||||
project = new Project();
|
||||
pm = new ProjectMetadata();
|
||||
pm.setName("TextSearchFacet test");
|
||||
ProjectManager.singleton.registerProject(project, pm);
|
||||
options = mock(JSONObject.class);
|
||||
|
||||
ImportingManager.initialize(servlet);
|
||||
job = ImportingManager.createJob();
|
||||
importer = new SeparatorBasedImporter();
|
||||
|
||||
String csv = "Value\n"
|
||||
+ "a\n"
|
||||
+ "b\n"
|
||||
+ "ab\n"
|
||||
+ "Abc\n";
|
||||
prepareOptions(",", 10, 0, 0, 1, false, false);
|
||||
List<Exception> exceptions = new ArrayList<Exception>();
|
||||
importer.parseOneFile(project, pm, job, "filesource", new StringReader(csv), -1, options, exceptions);
|
||||
project.update();
|
||||
ProjectManager.singleton.registerProject(project, pm);
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
public void tearDown() {
|
||||
ImportingManager.disposeJob(job.id);
|
||||
ProjectManager.singleton.deleteProject(project.id);
|
||||
job = null;
|
||||
project = null;
|
||||
pm = null;
|
||||
options = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to demonstrate the intended behaviour of the function
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testTextFilter() throws Exception {
|
||||
//Apply text filter "a"
|
||||
|
||||
//Column: "Value"
|
||||
//Filter Query: "a"
|
||||
//Mode: "text"
|
||||
//Case sensitive: False
|
||||
//Invert: False
|
||||
String filter = "{\"type\":\"text\","
|
||||
+ "\"name\":\"Value\","
|
||||
+ "\"columnName\":\"Value\","
|
||||
+ "\"mode\":\"text\","
|
||||
+ "\"caseSensitive\":false,"
|
||||
+ "\"invert\":false,"
|
||||
+ "\"query\":\"a\"}";
|
||||
|
||||
//Add the facet to the project and create a row filter
|
||||
textfilter = new TextSearchFacet();
|
||||
textsearchfacet = new JSONObject(filter);
|
||||
textfilter.initializeFromJSON(project,textsearchfacet);
|
||||
rowfilter = textfilter.getRowFilter(project);
|
||||
|
||||
//Check each row in the project against the filter
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),true);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),false);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),true);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvertedTextFilter() throws Exception {
|
||||
//Apply inverted text filter "a"
|
||||
|
||||
//Column: "Value"
|
||||
//Filter Query: "a"
|
||||
//Mode: "text"
|
||||
//Case sensitive: False
|
||||
//Invert: True
|
||||
String filter = "{\"type\":\"text\","
|
||||
+ "\"name\":\"Value\","
|
||||
+ "\"columnName\":\"Value\","
|
||||
+ "\"mode\":\"text\","
|
||||
+ "\"caseSensitive\":false,"
|
||||
+ "\"invert\":true,"
|
||||
+ "\"query\":\"a\"}";
|
||||
|
||||
//Add the facet to the project and create a row filter
|
||||
textfilter = new TextSearchFacet();
|
||||
textsearchfacet = new JSONObject(filter);
|
||||
textfilter.initializeFromJSON(project,textsearchfacet);
|
||||
rowfilter = textfilter.getRowFilter(project);
|
||||
|
||||
//Check each row in the project against the filter
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),true);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),false);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegExFilter() throws Exception {
|
||||
//Apply regular expression filter "[bc]"
|
||||
|
||||
//Column: "Value"
|
||||
//Filter Query: "[bc]"
|
||||
//Mode: "regex"
|
||||
//Case sensitive: False
|
||||
//Invert: False
|
||||
String filter = "{\"type\":\"text\","
|
||||
+ "\"name\":\"Value\","
|
||||
+ "\"columnName\":\"Value\","
|
||||
+ "\"mode\":\"regex\","
|
||||
+ "\"caseSensitive\":false,"
|
||||
+ "\"invert\":false,"
|
||||
+ "\"query\":\"[bc]\"}";
|
||||
|
||||
//Add the facet to the project and create a row filter
|
||||
textfilter = new TextSearchFacet();
|
||||
textsearchfacet = new JSONObject(filter);
|
||||
textfilter.initializeFromJSON(project,textsearchfacet);
|
||||
rowfilter = textfilter.getRowFilter(project);
|
||||
|
||||
//Check each row in the project against the filter
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),true);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),true);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaseSensitiveFilter() throws Exception {
|
||||
//Apply case-sensitive filter "A"
|
||||
|
||||
//Column: "Value"
|
||||
//Filter Query: "A"
|
||||
//Mode: "text"
|
||||
//Case sensitive: True
|
||||
//Invert: False
|
||||
String filter = "{\"type\":\"text\","
|
||||
+ "\"name\":\"Value\","
|
||||
+ "\"columnName\":\"Value\","
|
||||
+ "\"mode\":\"text\","
|
||||
+ "\"caseSensitive\":true,"
|
||||
+ "\"invert\":false,"
|
||||
+ "\"query\":\"A\"}";
|
||||
|
||||
//Add the facet to the project and create a row filter
|
||||
textfilter = new TextSearchFacet();
|
||||
textsearchfacet = new JSONObject(filter);
|
||||
textfilter.initializeFromJSON(project,textsearchfacet);
|
||||
rowfilter = textfilter.getRowFilter(project);
|
||||
|
||||
//Check each row in the project against the filter
|
||||
//Expect to retrieve one row containing "Abc"
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 0, project.rows.get(0)),false);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 1, project.rows.get(1)),false);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 2, project.rows.get(2)),false);
|
||||
Assert.assertEquals(rowfilter.filterRow(project, 3, project.rows.get(3)),true);
|
||||
}
|
||||
|
||||
private void prepareOptions(
|
||||
String sep, int limit, int skip, int ignoreLines,
|
||||
int headerLines, boolean guessValueType, boolean ignoreQuotes) {
|
||||
|
||||
whenGetStringOption("separator", options, sep);
|
||||
whenGetIntegerOption("limit", options, limit);
|
||||
whenGetIntegerOption("skipDataLines", options, skip);
|
||||
whenGetIntegerOption("ignoreLines", options, ignoreLines);
|
||||
whenGetIntegerOption("headerLines", options, headerLines);
|
||||
whenGetBooleanOption("guessCellValueTypes", options, guessValueType);
|
||||
whenGetBooleanOption("processQuotes", options, !ignoreQuotes);
|
||||
whenGetBooleanOption("storeBlankCellsAsNulls", options, true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ ListFacet.prototype.updateState = function(data) {
|
||||
};
|
||||
|
||||
ListFacet.prototype._reSortChoices = function() {
|
||||
this._data.choices.sort(this._options.sort == "name" ?
|
||||
this._data.choices.sort(this._options.sort === "name" ?
|
||||
function(a, b) {
|
||||
return a.v.l.toLowerCase().localeCompare(b.v.l.toLowerCase());
|
||||
} :
|
||||
@ -146,7 +146,7 @@ ListFacet.prototype._initializeUI = function() {
|
||||
var facet_id = this._div.attr("id");
|
||||
|
||||
this._div.empty().show().html(
|
||||
'<div class="facet-title">' +
|
||||
'<div class="facet-title" bind="facetTitle">' +
|
||||
'<div class="grid-layout layout-tightest layout-full"><table><tr>' +
|
||||
'<td width="1%"><a href="javascript:{}" title="'+$.i18n._('core-facets')["remove-facet"]+'" class="facet-title-remove" bind="removeButton"> </a></td>' +
|
||||
'<td>' +
|
||||
@ -259,9 +259,11 @@ ListFacet.prototype._update = function(resetScroll) {
|
||||
|
||||
var invert = this._config.invert;
|
||||
if (invert) {
|
||||
this._elmts.facetTitle.addClass("facet-title-inverted");
|
||||
this._elmts.bodyInnerDiv.addClass("facet-mode-inverted");
|
||||
this._elmts.invertButton.addClass("facet-mode-inverted");
|
||||
} else {
|
||||
this._elmts.facetTitle.removeClass("facet-title-inverted");
|
||||
this._elmts.bodyInnerDiv.removeClass("facet-mode-inverted");
|
||||
this._elmts.invertButton.removeClass("facet-mode-inverted");
|
||||
}
|
||||
@ -277,7 +279,7 @@ ListFacet.prototype._update = function(resetScroll) {
|
||||
//this._elmts.statusDiv.hide();
|
||||
this._elmts.controlsDiv.hide();
|
||||
|
||||
if (this._data.error == "Too many choices") {
|
||||
if (this._data.error === "Too many choices") {
|
||||
this._elmts.bodyInnerDiv.empty();
|
||||
|
||||
var messageDiv = $('<div>')
|
||||
@ -345,7 +347,7 @@ ListFacet.prototype._update = function(resetScroll) {
|
||||
this._elmts.invertButton.hide();
|
||||
}
|
||||
|
||||
if (this._options.sort == "name") {
|
||||
if (this._options.sort === "name") {
|
||||
this._elmts.sortByNameLink.removeClass("action").addClass("selected");
|
||||
this._elmts.sortByCountLink.removeClass("selected").addClass("action");
|
||||
} else {
|
||||
@ -359,7 +361,7 @@ ListFacet.prototype._update = function(resetScroll) {
|
||||
return temp.text(s).html();
|
||||
};
|
||||
|
||||
var renderEdit = this._config.expression == "value";
|
||||
var renderEdit = this._config.expression === "value";
|
||||
var renderChoice = function(index, choice, customLabel) {
|
||||
var label = customLabel || choice.v.l;
|
||||
var count = choice.c;
|
||||
@ -400,9 +402,9 @@ ListFacet.prototype._update = function(resetScroll) {
|
||||
|
||||
var getChoice = function(elmt) {
|
||||
var index = parseInt(elmt.attr("choiceIndex"),10);
|
||||
if (index == -1) {
|
||||
if (index === -1) {
|
||||
return self._blankChoice;
|
||||
} else if (index == -2) {
|
||||
} else if (index === -2) {
|
||||
return self._errorChoice;
|
||||
} else {
|
||||
return choices[index];
|
||||
@ -448,7 +450,7 @@ ListFacet.prototype._update = function(resetScroll) {
|
||||
bodyInnerDiv.on('mouseenter mouseleave', '.facet-choice', function(e) {
|
||||
e.preventDefault();
|
||||
var visibility = 'visible';
|
||||
if (e.type == 'mouseleave') {
|
||||
if (e.type === 'mouseleave') {
|
||||
visibility = 'hidden';
|
||||
}
|
||||
$(this).find('.facet-choice-edit').css("visibility", visibility);
|
||||
@ -577,7 +579,7 @@ ListFacet.prototype._editChoice = function(choice, choiceDiv) {
|
||||
var gotSelection = false;
|
||||
for (var i = 0; i < self._selection.length; i++) {
|
||||
var choice = self._selection[i];
|
||||
if (choice.v.v == originalContent) {
|
||||
if (choice.v.v === originalContent) {
|
||||
if (gotSelection) {
|
||||
continue;
|
||||
}
|
||||
@ -597,9 +599,9 @@ ListFacet.prototype._editChoice = function(choice, choiceDiv) {
|
||||
.text(originalContent)
|
||||
.keydown(function(evt) {
|
||||
if (!evt.shiftKey) {
|
||||
if (evt.keyCode == 13) {
|
||||
if (evt.keyCode === 13) {
|
||||
commit();
|
||||
} else if (evt.keyCode == 27) {
|
||||
} else if (evt.keyCode === 27) {
|
||||
MenuSystem.dismissAll();
|
||||
}
|
||||
}
|
||||
@ -697,7 +699,7 @@ ListFacet.prototype._editExpression = function() {
|
||||
|
||||
self._elmts.expressionDiv.text(self._config.expression);
|
||||
self._elmts.changeButton.attr("title", $.i18n._('core-facets')["current-exp"]+": " + self._config.expression);
|
||||
if (self._config.expression == "value" || self._config.expression == "grel:value") {
|
||||
if (self._config.expression === "value" || self._config.expression === "grel:value") {
|
||||
self._elmts.clusterLink.show();
|
||||
} else {
|
||||
self._elmts.clusterLink.hide();
|
||||
@ -726,9 +728,9 @@ ListFacet.prototype._setChoiceCountLimit = function(choiceCount) {
|
||||
value : n
|
||||
},
|
||||
function(o) {
|
||||
if (o.code == "ok") {
|
||||
if (o.code === "ok") {
|
||||
ui.browsingEngine.update();
|
||||
} else if (o.code == "error") {
|
||||
} else if (o.code === "error") {
|
||||
alert(o.message);
|
||||
}
|
||||
},
|
||||
|
@ -34,12 +34,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
function TextSearchFacet(div, config, options) {
|
||||
this._div = div;
|
||||
this._config = config;
|
||||
if (!("invert" in this._config)) {
|
||||
this._config.invert = false;
|
||||
}
|
||||
|
||||
this._options = options;
|
||||
|
||||
this._query = config.query || null;
|
||||
this._timerID = null;
|
||||
|
||||
this._initializeUI();
|
||||
this._update();
|
||||
}
|
||||
|
||||
TextSearchFacet.reconstruct = function(div, uiState) {
|
||||
@ -70,6 +75,7 @@ TextSearchFacet.prototype.getJSON = function() {
|
||||
columnName: this._config.columnName,
|
||||
mode: this._config.mode,
|
||||
caseSensitive: this._config.caseSensitive,
|
||||
invert: this._config.invert,
|
||||
query: this._query
|
||||
};
|
||||
return o;
|
||||
@ -82,11 +88,13 @@ TextSearchFacet.prototype.hasSelection = function() {
|
||||
TextSearchFacet.prototype._initializeUI = function() {
|
||||
var self = this;
|
||||
this._div.empty().show().html(
|
||||
'<div class="facet-title">' +
|
||||
'<div class="facet-title" bind="facetTitle">' +
|
||||
'<div class="grid-layout layout-tightest layout-full"><table><tr>' +
|
||||
'<td width="1%"><a href="javascript:{}" title="'+$.i18n._('core-facets')["remove-facet"]+'" class="facet-title-remove" bind="removeButton"> </a></td>' +
|
||||
'<td>' +
|
||||
'<span>' + this._config.name + '</span>' +
|
||||
'<a href="javascript:{}" class="facet-choice-link" bind="resetButton">'+$.i18n._('core-facets')["reset"]+'</a>' +
|
||||
'<a href="javascript:{}" class="facet-choice-link" bind="invertButton">'+$.i18n._('core-facets')["invert"]+'</a>' +
|
||||
'<span bind="titleSpan"></span>' +
|
||||
'</td>' +
|
||||
'</tr></table></div>' +
|
||||
'</div>' +
|
||||
@ -99,24 +107,27 @@ TextSearchFacet.prototype._initializeUI = function() {
|
||||
'</table></div></div>'
|
||||
);
|
||||
|
||||
var elmts = DOM.bind(this._div);
|
||||
this._elmts = DOM.bind(this._div);
|
||||
|
||||
this._elmts.titleSpan.text(this._config.name);
|
||||
if (this._config.caseSensitive) {
|
||||
elmts.caseSensitiveCheckbox.attr("checked", "true");
|
||||
this._elmts.caseSensitiveCheckbox.attr("checked", "true");
|
||||
}
|
||||
if (this._config.mode == "regex") {
|
||||
elmts.regexCheckbox.attr("checked", "true");
|
||||
if (this._config.mode === "regex") {
|
||||
this._elmts.regexCheckbox.attr("checked", "true");
|
||||
}
|
||||
|
||||
elmts.removeButton.click(function() { self._remove(); });
|
||||
this._elmts.removeButton.click(function() { self._remove(); });
|
||||
this._elmts.resetButton.click(function() { self._reset(); });
|
||||
this._elmts.invertButton.click(function() { self._invert(); });
|
||||
|
||||
elmts.caseSensitiveCheckbox.bind("change", function() {
|
||||
this._elmts.caseSensitiveCheckbox.bind("change", function() {
|
||||
self._config.caseSensitive = this.checked;
|
||||
if (self._query !== null && self._query.length > 0) {
|
||||
self._scheduleUpdate();
|
||||
}
|
||||
});
|
||||
elmts.regexCheckbox.bind("change", function() {
|
||||
this._elmts.regexCheckbox.bind("change", function() {
|
||||
self._config.mode = this.checked ? "regex" : "text";
|
||||
if (self._query !== null && self._query.length > 0) {
|
||||
self._scheduleUpdate();
|
||||
@ -124,10 +135,10 @@ TextSearchFacet.prototype._initializeUI = function() {
|
||||
});
|
||||
|
||||
if (this._query) {
|
||||
elmts.input[0].value = this._query;
|
||||
this._elmts.input[0].value = this._query;
|
||||
}
|
||||
|
||||
elmts.input.bind("keyup change input",function(evt) {
|
||||
this._elmts.input.bind("keyup change input",function(evt) {
|
||||
// Ignore non-character keyup changes
|
||||
if(evt.type === "keyup" && (this.value === self._query || this.value === '' && !self._query)) {
|
||||
return;
|
||||
@ -139,6 +150,7 @@ TextSearchFacet.prototype._initializeUI = function() {
|
||||
};
|
||||
|
||||
TextSearchFacet.prototype.updateState = function(data) {
|
||||
this._update();
|
||||
};
|
||||
|
||||
TextSearchFacet.prototype.render = function() {
|
||||
@ -147,6 +159,19 @@ TextSearchFacet.prototype.render = function() {
|
||||
|
||||
TextSearchFacet.prototype._reset = function() {
|
||||
this._query = null;
|
||||
this._config.mode = "text";
|
||||
this._config.caseSensitive = false;
|
||||
this._elmts.input.val([]);
|
||||
this._elmts.caseSensitiveCheckbox.prop("checked", false);
|
||||
this._elmts.regexCheckbox.prop("checked", false);
|
||||
this._config.invert = false;
|
||||
|
||||
this._updateRest();
|
||||
};
|
||||
|
||||
TextSearchFacet.prototype._invert = function() {
|
||||
this._config.invert = !this._config.invert;
|
||||
|
||||
this._updateRest();
|
||||
};
|
||||
|
||||
@ -158,6 +183,17 @@ TextSearchFacet.prototype._remove = function() {
|
||||
this._options = null;
|
||||
};
|
||||
|
||||
TextSearchFacet.prototype._update = function () {
|
||||
var invert = this._config.invert;
|
||||
if (invert) {
|
||||
this._elmts.facetTitle.addClass("facet-title-inverted");
|
||||
this._elmts.invertButton.addClass("facet-mode-inverted");
|
||||
} else {
|
||||
this._elmts.facetTitle.removeClass("facet-title-inverted");
|
||||
this._elmts.invertButton.removeClass("facet-mode-inverted");
|
||||
}
|
||||
};
|
||||
|
||||
TextSearchFacet.prototype._scheduleUpdate = function() {
|
||||
if (!this._timerID) {
|
||||
var self = this;
|
||||
|
@ -57,6 +57,11 @@ li.facet-container {
|
||||
|
||||
}
|
||||
|
||||
.facet-title-inverted {
|
||||
background: #ffa500;
|
||||
border-bottom: 1px solid #ffc04d;
|
||||
}
|
||||
|
||||
a.facet-title-remove {
|
||||
display: block;
|
||||
width: 12px;
|
||||
|
Loading…
Reference in New Issue
Block a user