diff --git a/main/webapp/modules/core/MOD-INF/controller.js b/main/webapp/modules/core/MOD-INF/controller.js index 99cdff49e..7067f4c0a 100644 --- a/main/webapp/modules/core/MOD-INF/controller.js +++ b/main/webapp/modules/core/MOD-INF/controller.js @@ -466,6 +466,7 @@ function init() { "scripts/project/exporters.js", "scripts/project/scripting.js", + "scripts/facets/facet.js", "scripts/facets/list-facet.js", "scripts/facets/range-facet.js", "scripts/facets/timerange-facet.js", diff --git a/main/webapp/modules/core/langs/translation-en.json b/main/webapp/modules/core/langs/translation-en.json index 05ea3a4bc..e56d40845 100644 --- a/main/webapp/modules/core/langs/translation-en.json +++ b/main/webapp/modules/core/langs/translation-en.json @@ -333,6 +333,7 @@ "core-facets/big-dot": "Big Dot Size", "core-facets/export-plot": "export plot", "core-facets/numeric": "Numeric", + "core-facets/value-range": "$1 — $2", "core-project/open": "Open", "core-project/permalink": "Permalink", "core-project/export": "Export", diff --git a/main/webapp/modules/core/scripts/facets/facet.js b/main/webapp/modules/core/scripts/facets/facet.js new file mode 100644 index 000000000..b225e0482 --- /dev/null +++ b/main/webapp/modules/core/scripts/facets/facet.js @@ -0,0 +1,67 @@ +/* + +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. + + */ + +class Facet { + constructor(div, config, options) { + this._div = div; + this._config = config; + this._options = options || {}; + this._minimizeState = false; + }; + + _minimize() { + if(!this._minimizeState) { + this._div.addClass("facet-state-minimize"); + } else { + this._div.removeClass("facet-state-minimize"); + } + + this._minimizeState = !this._minimizeState; + }; + + _remove() { + ui.browsingEngine.removeFacet(this); + + this._div = null; + this._config = null; + + this._selection = null; + this._blankChoice = null; + this._errorChoice = null; + this._data = null; + this._options = null; + }; + + dispose() { + }; +}; diff --git a/main/webapp/modules/core/scripts/facets/list-facet.js b/main/webapp/modules/core/scripts/facets/list-facet.js index febaf7930..64def353b 100644 --- a/main/webapp/modules/core/scripts/facets/list-facet.js +++ b/main/webapp/modules/core/scripts/facets/list-facet.js @@ -31,731 +31,706 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -function ListFacet(div, config, options, selection) { - this._div = div; - this._config = config; - if (!("invert" in this._config)) { +class ListFacet extends Facet { + constructor(div, config, options, selection) { + super(div, config, options); + + if (!("sort" in this._options)) { + this._options.sort = "name"; + } + + this._selection = selection || []; + + if (!("invert" in this._config)) { + this._config.invert = false; + } + + this._blankChoice = (config.selectBlank) ? { s : true, c : 0 } : null; + this._errorChoice = (config.selectError) ? { s : true, c : 0 } : null; + + this._data = null; + + this._initializeUI(); + this._update(); + }; + + reset() { + this._selection = []; + this._blankChoice = null; + this._errorChoice = null; + }; + + getUIState() { + var json = { + c: this.getJSON(), + o: this._options + }; + + json.s = json.c.selection; + delete json.c.selection; + + return json; + }; + + getJSON() { + var o = { + type: "list", + name: this._config.name, + columnName: this._config.columnName, + expression: this._config.expression, + omitBlank: "omitBlank" in this._config ? this._config.omitBlank : false, + omitError: "omitError" in this._config ? this._config.omitError : false, + selection: [], + selectBlank: this._blankChoice !== null && this._blankChoice.s, + selectError: this._errorChoice !== null && this._errorChoice.s, + invert: this._config.invert + }; + for (var i = 0; i < this._selection.length; i++) { + var choice = { + v: cloneDeep(this._selection[i].v) + }; + o.selection.push(choice); + } + return o; + }; + + hasSelection() { + return this._selection.length > 0 || + (this._blankChoice !== null && this._blankChoice.s) || + (this._errorChoice !== null && this._errorChoice.s); + }; + + updateState(data) { + this._data = data; + + if ("choices" in data) { + var selection = []; + var choices = data.choices; + for (var i = 0; i < choices.length; i++) { + var choice = choices[i]; + if (choice.s) { + selection.push(choice); + } + } + this._selection = selection; + this._reSortChoices(); + + this._blankChoice = data.blankChoice || null; + this._errorChoice = data.errorChoice || null; + } + + this._update(); + }; + + _reSortChoices() { + this._data.choices.sort(this._options.sort === "name" ? + function(a, b) { + return a.v.l.toLowerCase().localeCompare(b.v.l.toLowerCase()); + } : + function(a, b) { + var c = b.c - a.c; + return c !== 0 ? c : a.v.l.localeCompare(b.v.l); + } + ); + }; + + _initializeUI() { + var self = this; + + var facet_id = this._div.attr("id"); + + this._div.empty().show().html( + '
' + + '
' + + '' + + '' + + '' + + '
' + + ' ' + + '' + + ' ' + + '' + + ''+$.i18n('core-facets/reset')+'' + + ''+$.i18n('core-facets/invert')+'' + + ''+$.i18n('core-facets/change')+'' + + '' + + '
' + + '
' + + '
' + + '' + + '
' + + '
' + + '
' + ); + this._elmts = DOM.bind(this._div); + + this._elmts.titleSpan.text(this._config.name); + this._elmts.changeButton.attr("title",$.i18n('core-facets/current-exp')+": " + this._config.expression).click(function() { + self._elmts.expressionDiv.slideToggle(100, function() { + if (self._elmts.expressionDiv.css("display") != "none") { + self._editExpression(); + } + }); + }); + + this._elmts.expressionDiv.text(this._config.expression).hide().click(function() { self._editExpression(); }); + this._elmts.removeButton.click(function() { self._remove(); }); + this._elmts.minimizeButton.click(function() { self._minimize(); }); + this._elmts.resetButton.click(function() { self._reset(); }); + this._elmts.invertButton.click(function() { self._invert(); }); + + this._elmts.choiceCountContainer.click(function() { self._copyChoices(); }); + this._elmts.sortByCountLink.click(function() { + if (self._options.sort != "count") { + self._options.sort = "count"; + self._reSortChoices(); + self._update(true); + } + }); + this._elmts.sortByNameLink.click(function() { + if (self._options.sort != "name") { + self._options.sort = "name"; + self._reSortChoices(); + self._update(true); + } + }); + + this._elmts.clusterLink.click(function() { self._doEdit(); }); + if (this._config.expression != "value" && this._config.expression != "grel:value") { + this._elmts.clusterLink.hide(); + } + + if (!("scroll" in this._options) || this._options.scroll) { + this._elmts.bodyDiv.addClass("facet-body-scrollable"); + this._elmts.bodyDiv.resizable({ + minHeight: 30, + handles: 's', + stop: function(event, ui) { + event.target.style.width = "auto"; // don't force the width + } + }); + } + }; + + _copyChoices() { + var self = this; + var frame = DialogSystem.createDialog(); + frame.width("600px"); + + var header = $('
').addClass("dialog-header").text($.i18n('core-facets/facet-choices')).appendTo(frame); + var body = $('
').addClass("dialog-body").appendTo(frame); + var footer = $('
').addClass("dialog-footer").appendTo(frame); + + body.html('