This patch replaces the result page sidebar new-search trees
authormiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 29 Jul 2010 21:08:36 +0000 (21:08 +0000)
committermiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 29 Jul 2010 21:08:36 +0000 (21:08 +0000)
(implemented before "faceting" became a thing, and designed for
new-search, not drill-down) with and implementation of what has become
the generally accepted "way to do faceting".  This is implemented as a
Dojo Dijit, and the markup and code footprints within the OPAC proper
are small, just  a couple <div>s and a little bit of glue code to help
the facet rendering engine find the data it needs.  The set and order
of facet classes to display in a given facet bar (title, author,
subject, etc) is configurable in the markup, as are the number of
values displayed for each facet when collapsed (before the [More...]
button is pushed).

Also included is a Searcher Dijit which implements an embeddable
advanced search interface.  This is mainly useful for constructing
boolean-chained searches (we support AND and OR now, though they're
spelled && and || in the query string), and has the beginnings of
support for filters and modifiers.

git-svn-id: svn://svn.open-ils.org/ILS/trunk@17057 dcc99617-32d9-48b4-a31d-7c20da2025e4

20 files changed:
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/metabib.pm
Open-ILS/src/perlmods/OpenILS/Application/SuperCat.pm
Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm
Open-ILS/web/js/dojo/fieldmapper/Fieldmapper.js
Open-ILS/web/js/dojo/openils/widget/FacetSidebar.js [new file with mode: 0644]
Open-ILS/web/js/dojo/openils/widget/Searcher.js [new file with mode: 0644]
Open-ILS/web/js/dojo/openils/widget/nls/Searcher.js [new file with mode: 0644]
Open-ILS/web/opac/common/js/config.js
Open-ILS/web/opac/common/js/opac_utils.js
Open-ILS/web/opac/locale/en-US/opac.dtd
Open-ILS/web/opac/skin/default/js/rdetail.js
Open-ILS/web/opac/skin/default/js/result_common.js
Open-ILS/web/opac/skin/default/js/search_bar.js
Open-ILS/web/opac/skin/default/js/sidebar.js
Open-ILS/web/opac/skin/default/xml/common/js_common.xml
Open-ILS/web/opac/skin/default/xml/common/searchbar.xml
Open-ILS/web/opac/skin/default/xml/common/sidebar.xml
Open-ILS/web/opac/skin/default/xml/rdetail/rdetail_summary.xml
Open-ILS/web/opac/theme/default/css/colors.css

index 6b64b3f..bb4fd58 100644 (file)
@@ -1510,7 +1510,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
         </permacrud>
        </class>
 
-       <class id="cmsa" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::metabib_search_alias" oils_persist:tablename="config.metabib_search_alias" reporter:label="Metabib Search Alias">
+       <class id="cmsa" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::metabib_search_alias" oils_persist:tablename="config.metabib_search_alias" reporter:label="Metabib Search Alias" oils_persist:field_safe="true">
                <fields oils_persist:primary="alias">
                        <field reporter:label="Alias (RegExp)" name="alias" reporter:datatype="text"/>
                        <field reporter:label="Class" name="field_class" reporter:datatype="link"/>
@@ -1530,7 +1530,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
         </permacrud>
        </class>
 
-       <class id="cmc" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::metabib_class" oils_persist:tablename="config.metabib_class" reporter:label="Metabib Class">
+       <class id="cmc" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::metabib_class" oils_persist:tablename="config.metabib_class" reporter:label="Metabib Class" oils_persist:field_safe="true">
                <fields oils_persist:primary="name">
                        <field reporter:label="Name" name="name" reporter:datatype="text"/>
                        <field reporter:label="Label" name="label" reporter:datatype="text"/>
@@ -1549,7 +1549,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
         </permacrud>
        </class>
 
-       <class id="cmf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::metabib_field" oils_persist:tablename="config.metabib_field" reporter:label="Metabib Field">
+       <class id="cmf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::metabib_field" oils_persist:tablename="config.metabib_field" reporter:label="Metabib Field" oils_persist:field_safe="true">
                <fields oils_persist:primary="id" oils_persist:sequence="config.metabib_field_id_seq">
                        <field reporter:label="Class" name="field_class" reporter:datatype="link"/>
                        <field reporter:label="ID" name="id" reporter:datatype="id" />
index 22cf193..10f223e 100644 (file)
@@ -3092,6 +3092,8 @@ sub query_parser_fts_wrapper {
     my $query = $base_query;
     $log->debug("Full base query: $base_query", DEBUG);
 
+    $query = "$args{facets} $query" if  ($args{facets});
+
     if (!$locale_map{COMPLETE}) {
 
         my @locales = config::i18n_locale->search_where({ code => { '<>' => '' } });
index d80ddc4..d02a5cf 100644 (file)
@@ -1862,6 +1862,9 @@ Returns the XML representation of the requested bibliographic record's holdings
                                { name => 'orgUnit',
                                  desc => 'An OpenILS actor::org_unit short name that limits the scope of returned holdings',
                                  type => 'text' },
+                               { name => 'depth',
+                                 desc => 'An OpenILS actor::org_unit_type depththat limits the scope of returned holdings',
+                                 type => 'number' },
                                { name => 'hideCopies',
                                  desc => 'Flag that prevents the inclusion of copies in the returned holdings',
                                  type => 'boolean' },
index a9eaa90..a38bcf8 100644 (file)
@@ -367,7 +367,7 @@ sub unapi {
                if ($uri =~ m{^tag:[^:]+:([^\/]+)/([^\/[]+)(?:\[([0-9,]+)\])?(?:/(.+))?}o) {
                        $id = $2;
                        $paging = $3;
-                       $lib = uc($4);
+                       ($lib,$depth) = split('/', $4);
                        $type = 'record';
                        $type = 'metarecord' if ($1 =~ /^m/o);
                        $type = 'authority' if ($1 =~ /^authority/o);
index 54ff091..9471b81 100644 (file)
@@ -182,7 +182,7 @@ if(!dojo._hasResource["fieldmapper.Fieldmapper"]){
                        if (dojo.isObject(params)) {
                                args = params;
                        } else {
-                args.params = [].splice.call(arguments, 1, arguments.length - 1);
+                args.params = [].splice.call(arguments, 2, arguments.length - 2);
                        }
 
                }
diff --git a/Open-ILS/web/js/dojo/openils/widget/FacetSidebar.js b/Open-ILS/web/js/dojo/openils/widget/FacetSidebar.js
new file mode 100644 (file)
index 0000000..19d69f0
--- /dev/null
@@ -0,0 +1,223 @@
+/* ---------------------------------------------------------------------------
+ * Copyright (C) 2010  Equinox Software, Inc
+ * Mike Rylander <miker@esilibrary.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * ---------------------------------------------------------------------------
+ */
+
+if(!dojo._hasResource["openils.widget.FacetSidebar"]) {
+
+    dojo._hasResource["openils.widget.FacetSidebar"] = true;
+    dojo.provide("openils.widget.FacetSidebar");
+    dojo.require("openils.widget.Searcher");
+
+    dojo.declare(
+        'openils.widget.FacetSidebar',
+        [dijit._Widget, dijit._Templated],
+        {   
+
+            templateString : '<div dojoAttachPoint="myTop"><div dojoAttachPoint="containerNode"></div><div class="facetClassContainer" dojoAttachPoint="facetClasses"></div></div>',
+            widgetsInTemplate: false,
+
+            facetData : {},
+            facetCacheKey : '',
+            searchBox : '',
+            classOrder : null,
+            searchSubmit : '',
+            facetLimit : 10,
+
+            startup : function () {
+                this.populate();
+                this.inherited(arguments)
+            },
+
+            populate : function () {},
+
+            render : function () {
+                if (!this.facetCacheKey) return;
+
+                if (openils.widget.Searcher._cache.facetData) {
+                    this.facetData = openils.widget.Searcher._cache.facetData;
+                } else {
+                    var facetData = fieldmapper.standardRequest( [ 'open-ils.search', 'open-ils.search.facet_cache.retrieve'], this.facetCacheKey );
+                    if (!facetData) return;
+                    this.facetData = openils.widget.Searcher._cache.facetData = facetData;
+                }
+
+                var classes = openils.widget.Searcher._cache.arr.cmc;
+                if (this.classOrder && this.classOrder.length > 0) {
+                    classes = [];
+                    dojo.forEach(
+                        this.classOrder,
+                        function(x) { classes.push({name:x}); }
+                    );
+                }
+
+                var me = this;
+                dojo.forEach(
+                    classes,
+                    function (x) {
+                        var possible_facets = dojo.filter(
+                            openils.widget.Searcher._cache.arr.cmf,
+                            function (y) {
+                                if (y.field_class == x.name && facetData[y.id]) return 1;
+                                return 0;
+                            }
+                        );
+                        if (possible_facets.length > 0) me.addClass( x.name, possible_facets );
+                    }
+                );
+            },
+
+            addClass : function (thisclass, facets) {
+                return new openils.widget.FacetSidebar.facetClass(
+                    { facetLimit: this.facetLimit, searchBox : this.searchBox, searchSubmit : this.searchSubmit, facetClass : thisclass, facetData : this.facetData, facetList : facets }
+                ).placeAt(this.facetClasses, 'last');
+            }
+        }
+    );
+
+    dojo._hasResource["openils.widget.FacetSidebar.facetClass"] = true;
+    dojo.provide("openils.widget.FacetSidebar.facetClass");
+
+    dojo.declare(
+        'openils.widget.FacetSidebar.facetClass',
+        [dijit._Widget, dijit._Templated],
+        {   
+
+            templateString :
+'<div class="facetClassLabelContainer">' +
+'  <div class="facetClassLabel" dojoAttachPoint="facetClassLabel"></div>' +
+'  <div class="facetFieldContainer" dojoAttachPoint="facetFields"></div>' +
+'</div>',
+            widgetsInTemplate: false,
+
+            facetLimit : 10,
+            facetClass : '',
+            facetData : null,
+            facetList : null,
+            searchBox : '',
+            searchSubmit : '',
+
+            postCreate : function () {
+                if (!this.facetClass) return;
+                if (!this.facetData) return;
+
+                var myclass = this.facetClass;
+
+                var fclass = dojo.filter(openils.widget.Searcher._cache.arr.cmc, function (x) { if (x.name == myclass) return 1; return 0; })[0];
+                this.facetClassLabel.innerHTML = fclass.label;
+
+                var me = this;
+                dojo.forEach(
+                    this.facetList,
+                    function (f) { me.addFacets(f); }
+                );
+            },
+
+            addFacets : function (f) {
+                return new openils.widget.FacetSidebar.facetField(
+                    { facetLimit: this.facetLimit, searchBox : this.searchBox, searchSubmit : this.searchSubmit, facet : f, facetData : this.facetData[f.id] }
+                ).placeAt( this.facetFields, 'last' );
+            }
+        }
+    );
+
+    dojo._hasResource["openils.widget.FacetSidebar.facetField"] = true;
+    dojo.provide("openils.widget.FacetSidebar.facetField");
+
+    dojo.declare(
+        'openils.widget.FacetSidebar.facetField',
+        [dijit._Widget, dijit._Templated],
+        {   
+
+            templateString : 
+'<div class="facetField" dojoAttachPoint="myTop">' +
+'  <div class="extraFacetFieldsWrapper" dojoAttachPoint="toggleExtraFacetFieldsWrapper"><button class="toggleExtraFacetFieldsButton" dojoType="dijit.form.Button" dojoAttachPoint="toggleExtraFacetFields" dojoAttachEvent="onClick:toggleExtraFacets"></button></div>' +
+'  <div class="facetFieldLabel" dojoAttachPoint="facetLabel"></div>' +
+'  <div class="facetFields" dojoAttachPoint="facetFields"></div>' +
+'  <div class="facetFields hide_me" dojoAttachPoint="extraFacetFields"></div>' +
+'</div>',
+
+            widgetsInTemplate: true,
+            facet : null,
+            facetData : null,
+            facetLimit : 10,
+            searchBox : '',
+            searchSubmit : '',
+            extraHidden : true,
+
+            postCreate : function () {
+                this.nls = dojo.i18n.getLocalization("openils.widget", "Searcher");
+                var me = this;
+                var keylist = []; for (var i in this.facetData) { keylist.push(i); }
+
+                keylist = keylist.sort(function(a,b){
+                    if (me.facetData[a] < me.facetData[b]) return 1;
+                    if (me.facetData[a] > me.facetData[b]) return -1;
+                    if (a < b) return -1;
+                    if (a > b) return 1;
+                    return 0;
+                });
+
+                this.facetLabel.innerHTML = this.facet.label;
+                this.toggleExtraFacetFields.setLabel(this.nls.more);
+
+                var pos = 0;
+                dojo.forEach(
+                    keylist,
+                    function(value){
+
+                        var have_it = dojo.byId(me.searchBox).value.indexOf(me.facet.field_class + '|' + me.facet.name + '[' + value + ']') > -1;
+
+                        var container = dojo.create('div',{'class':'facetFieldLine'});
+                        dojo.create('span',{'class':'facetFieldLineCount', innerHTML: me.facetData[value]},container);
+
+                        if (have_it) {
+                            dojo.create('a',{href : '#', 'class':'facetFieldLineValue', onclick : function(){ me.undoSearch(value); return false;}, innerHTML: '<b>(' + value + ')</b>'},container);
+                        } else {
+                            dojo.create('a',{href : '#', 'class':'facetFieldLineValue', onclick : function(){ me.doSearch(value); return false;}, innerHTML: value},container);
+                        }
+
+                        if (pos >= me.facetLimit) dojo.place(container,me.extraFacetFields,'last');
+                        else dojo.place(container,me.facetFields,'last');
+
+                        pos++;
+                    }
+                );
+
+                if (pos < me.facetLimit + 1) dojo.query(this.toggleExtraFacetFieldsWrapper).toggleClass('hide_me');
+
+            },
+
+            toggleExtraFacets : function () {
+                dojo.query(this.extraFacetFields).toggleClass('hide_me');
+                this.extraHidden = !this.extraHidden;
+                this.extraHidden ? this.toggleExtraFacetFields.setLabel(this.nls.more) : this.toggleExtraFacetFields.setLabel(this.nls.less);
+            },
+
+            undoSearch : function (value) {
+                var sb = dojo.byId(this.searchBox);
+                sb.value = sb.value.replace(this.facet.field_class + '|' + this.facet.name + '[' + value + ']','');
+                dojo.byId(this.searchSubmit).click();
+            },
+
+            doSearch : function (value) {
+                dojo.byId(this.searchBox).value += ' ' + this.facet.field_class + '|' + this.facet.name + '[' + value + ']';
+                dojo.byId(this.searchSubmit).click();
+            }
+        }
+    );
+
+
+}
+
diff --git a/Open-ILS/web/js/dojo/openils/widget/Searcher.js b/Open-ILS/web/js/dojo/openils/widget/Searcher.js
new file mode 100644 (file)
index 0000000..d2fa58b
--- /dev/null
@@ -0,0 +1,543 @@
+/* ---------------------------------------------------------------------------
+ * Copyright (C) 2010  Equinox Software, Inc
+ * Mike Rylander <miker@esilibrary.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * ---------------------------------------------------------------------------
+ */
+
+if(!dojo._hasResource["openils.widget.Searcher"]) {
+
+    dojo._hasResource["openils.widget.Searcher"] = true;
+    dojo.provide("openils.widget.Searcher");
+
+    dojo.require("fieldmapper.AutoIDL");
+    dojo.require("openils.I18N");
+    dojo.require("fieldmapper.dojoData");
+    dojo.require("DojoSRF");
+    dojo.require("dojo.data.ItemFileReadStore");
+    dojo.require("dijit._Widget");
+    dojo.require("dijit._Templated");
+    dojo.require("dijit.form.Button");
+    dojo.require("dijit.form.TextBox");
+    dojo.require("dijit.form.FilteringSelect");
+    dojo.requireLocalization("openils.widget", "Searcher");
+
+    fieldmapper.IDL.load(['cmf','cmc','cmsa']);
+
+//------ searching wrapper, uses dijits below -----------------------------------------------
+
+    dojo.declare(
+        'openils.widget.Searcher',
+        [dijit._Widget, dijit._Templated],
+        {
+
+            templateString : 
+"<div dojoAttachPoint='searcherTopNode'>" +
+
+"  <div dojoAttachPoint='deck'>" +
+"    <div dojoAttachPoint='basicSearch'>" +
+"      <span dojoAttachPoint='containerNode' class='searcherSimpleSearchWrapper'></span>" +
+"    </div>" +
+
+"    <div dojoAttachPoint='advSearch' class='hide_me searcherAdvancedSearchWrapper'>" +
+"      <div dojoAttachPoint='searcherClassedSearchesContainer' class='searcherClassedSearchesContainer hide_me'>" +
+"        <div dojoAttachPoint='classedSearches' class='searcherClassedSearches'>" +
+"          <span dojoAttachPoint='searcherClassedSearchesLabel' class='searcherClassedSearchesLabel'></span>" +
+"        </div>" +
+"        <div class='searcherClassedSearchesAddContainer'>" +
+"          <button dojoType='dijit.form.Button' dojoAttachPoint='andClassedSearch' dojoAttachEvent='onClick:addClassAnd'></button>" +
+"          <button dojoType='dijit.form.Button' dojoAttachPoint='orClassedSearch' dojoAttachEvent='onClick:addClassOr'></button>" +
+"        </div>" +
+"      </div>" +
+
+"      <div dojoAttachPoint='searcherFacetedSearchesContainer' class='searcherFacetedSearchesContainer hide_me'>" +
+"        <div class='searcherFacetedSearches' dojoAttachPoint='facetedSearches'>" +
+"          <span dojoAttachPoint='searcherFacetedSearchesLabel' class='searcherFacetedSearchesLabel'></span>" +
+"        </div>" +
+"        <span>" +
+"          <button dojoType='dijit.form.Button' dojoAttachPoint='addFacetedSearch' dojoAttachEvent='onClick:addFacet'></button>" +
+"        </span>" +
+"      </div>" +
+
+"      <div dojoAttachPoint='searcherFilterModifierContainer' class='searcherFilterModifierContainer hide_me'>" +
+"        <table width='100%'><tbody><tr>" +
+"          <td dojoAttachPoint='searcherFilterContainer' class='searcherFilterContainer hide_me' valign='top' width='50%'>" +
+"            <div dojoAttachPoint='filters'>" +
+"              <span dojoAttachPoint='searcherFiltersLabel' class='searcherFiltersLabel'></span>" +
+"            </div>" +
+"            <button dojoType='dijit.form.Button' dojoAttachPoint='addFilterButton' dojoAttachEvent='onClick:addFilter'></button>" +
+"          </td>" +
+"          <td dojoAttachPoint='searcherModifierContainer' class='searcherModifierContainer hide_me' valign='top' width='50%'>" +
+"            <div dojoAttachPoint='modifiers'>" +
+"              <span dojoAttachPoint='searcherModifiersLabel' class='searcherModifiersLabel'></span>" +
+"            </div>" +
+"            <button dojoType='dijit.form.Button' dojoAttachPoint='addModifierButton' dojoAttachEvent='onClick:addModifier'></button>" +
+"          </td>" +
+"        </tr></tbody></table>" +
+"      </div>" +
+
+"      <div class='searcherGoContainer'>" +
+"        <span dojoType='dijit.form.Button' dojoAttachPoint='goButton' dojoAttachEvent='onClick:performSearch'></span>" +
+"      </div>" +
+"    </div>" +
+"  </div>" +
+
+"  <div class='searcherDeckSwapContainer'>" +
+"    <span dojoType='dijit.form.Button' dojoAttachPoint='advToggle' dojoAttachEvent='onClick:swapDeck'></span>" +
+"  </div>" +
+"</div>",
+            widgetsInTemplate: true,
+            advanced : false,
+            basicTextBox : '',
+            facetTextBox : '',
+            withClassedSearches : true,
+            withFacetedSearches : false,
+            withFiltersModifiers : false,
+            withFilters : false,
+            withModifiers : false,
+            basic_query : '',
+            facet_query : '',
+
+            compileFullSearch : function () {
+                if (!this.advanced) return dojo.byId( this.basicTextBox ).attr('value');
+
+                var query = '';
+
+                var first_cs = true;
+
+                // First, classed searches
+                dojo.query( '.classedSearch', this.classedSearches ).forEach(
+                    function (csearch) {
+                        csearch = dijit.byNode(csearch);
+                        var part = csearch.searchValue.attr('value');
+                        if (!part || part.match(/^\s+$/)) return;
+
+                        if (first_cs) first_cs = false;
+                        else query += csearch.anded ? '' : ' ||';
+
+                        query += ' ' + csearch.matchIndex.attr('value') + ':';
+                        if (csearch.matchType.attr('value') == 'exact') {
+                            query += '"';
+                        } else if (csearch.matchType.attr('value') == 'notcontains') {
+                            part = '-' + part.replace(/\s+/g, ' -');
+                        }
+
+                        query += part;
+
+                        if (csearch.matchType.attr('value') == 'exact') query += '"';
+                    }
+                );
+
+                var fquery = '';
+                // Now facets
+                dojo.query( '.facetedSearch', this.facetedSearches ).forEach(
+                    function (facet) {
+                        facet = dijit.byNode(facet);
+                        var part = facet.searchValue.attr('value');
+                        if (!part || part.match(/^\s+$/)) return;
+                        fquery += ' ' + facet.matchIndex.attr('value') + '[' + part + ']';
+                    }
+                );
+
+                // and filters...
+                dojo.query( '.filter', this.filters ).forEach(
+                    function (filt) {
+                        filt = dijit.byNode(filt);
+                        var part = filt.valueList.attr('value');
+                        if (!part || part.match(/^\s+$/) || filt.filterSelect.attr('value') == '-') return;
+                        query += ' ' + filt.filterSelect.attr('value') + '(' + part + ')';
+                    }
+                );
+
+                // finally, modifiers
+                dojo.query( '.modifier', this.modifiers ).forEach(
+                    function (modifier) {
+                        modifier = dijit.byNode(modifier);
+                        var part = modifier.modifierSelect.attr('value')
+                        if (!part || part == '-') return;
+                        query += ' #' + part;
+                    }
+                );
+
+
+                this.basic_query = query;
+                this.facet_query = fquery;
+
+                return query;
+            },
+
+            addFilter : function () {
+                return new openils.widget.Searcher.filter({}, dojo.create('div',null,this.filters));
+            },
+
+            addModifier : function () {
+                return new openils.widget.Searcher.modifier({}, dojo.create('div',null,this.modifiers));
+            },
+
+            addClassAnd : function () {
+                return new openils.widget.Searcher.classedSearch({}, dojo.create('div',null,this.classedSearches));
+            },
+
+            addClassOr  : function () {
+                return new openils.widget.Searcher.classedSearch({anded:false}, dojo.create('div',null,this.classedSearches));
+            },
+
+            addFacet : function () {
+                return new openils.widget.Searcher.facetedSearch({}, dojo.create('div',null,this.facetedSearches));
+            },
+
+            performSearch  : function () {},
+            populate  : function () {},
+
+            startup : function () {
+                if (this.advanced) {
+                    dojo.query(this.basicSearch).toggleClass('hide_me');
+                    dojo.query(this.advSearch).toggleClass('hide_me');
+                }
+
+                if (!this.facetTextBox) this.facetTextBox = this.basicTextBox;
+
+                if (this.withFiltersModifiers) {
+                    this.withFilters = true;
+                    this.withModifiers = true;
+                } else if (this.withFilters || this.withModifiers) {
+                    this.withFiltersModifiers = true;
+                }
+
+                if (this.withFiltersModifiers) dojo.query(this.searcherFilterModifierContainer).toggleClass('hide_me');
+                if (this.withFilters) dojo.query(this.searcherFilterContainer).toggleClass('hide_me');
+                if (this.withModifiers) dojo.query(this.searcherModifierContainer).toggleClass('hide_me');
+                if (this.withFacetedSearches) dojo.query(this.searcherFacetedSearchesContainer).toggleClass('hide_me');
+                if (this.withClassedSearches) dojo.query(this.searcherClassedSearchesContainer).toggleClass('hide_me');
+
+                this.populate();
+                this.inherited(arguments)
+            },
+    
+            swapDeck : function () {
+                if (this.advanced) this.advanced = false;
+                else this.advanced = true;
+
+                dojo.query(this.basicSearch).toggleClass('hide_me');
+                dojo.query(this.advSearch).toggleClass('hide_me');
+
+                if (this.advanced) this.advToggle.setLabel(this.nls.basic);
+                else this.advToggle.setLabel(this.nls.advanced);
+            },
+
+            postCreate : function () {
+                this.nls = dojo.i18n.getLocalization("openils.widget", "Searcher");
+
+                this.searcherClassedSearchesLabel.innerHTML = this.nls.classed_searches;
+                this.searcherFacetedSearchesLabel.innerHTML = this.nls.faceted_searches;
+                this.searcherFiltersLabel.innerHTML = this.nls.filters;
+                this.searcherModifiersLabel.innerHTML = this.nls.modifiers;
+                this.addFacetedSearch.setLabel(this.nls.new_facet);
+
+                this.andClassedSearch.setLabel(this.nls.and);
+                this.orClassedSearch.setLabel(this.nls.or);
+
+                this.addFilterButton.setLabel(this.nls.new_filter);
+                this.addModifierButton.setLabel(this.nls.new_modifier);
+
+                this.goButton.setLabel(this.nls.perform_search);
+
+                if (this.advanced) this.advToggle.setLabel(this.nls.basic);
+                else this.advToggle.setLabel(this.nls.advanced);
+                
+                new openils.widget.Searcher.classedSearch(
+                    { noRemove : true },
+                    dojo.create('div',null,this.classedSearches)
+                );
+            }
+
+        } 
+    );
+
+    openils.widget.Searcher._cache = {arr : {}, obj : {}, store : {}};
+
+    dojo.forEach(
+        [ {ident:'name',classname:'cmc',label:'label'}, {ident:'id',classname:'cmf',label:'label'}, {ident:'alias',classname:'cmsa',label:'alias'} ],
+        function (c) {
+
+            var q = {};
+            q[c.ident] = { '!=' :  null };
+
+            var fielder_result = fieldmapper.standardRequest(
+                [ 'open-ils.fielder', 'open-ils.fielder.'+c.classname+'.atomic'],
+                [ { query : q } ]
+            );
+
+            var sorted_fielder_result = fielder_result.sort( function(a,b) {
+                if(a[c.label] > b[c.label]) return 1;
+                if(a[c.label] < b[c.label]) return -1;
+                return 0;
+            });
+
+            openils.widget.Searcher._cache.arr[c.classname] = sorted_fielder_result;
+
+            var list = [];
+            openils.widget.Searcher._cache.obj[c.classname] = {};
+
+            dojo.forEach(
+                openils.widget.Searcher._cache.arr[c.classname],
+                function (x) {
+                    openils.widget.Searcher._cache.obj[c.classname][x[c.ident]] = x;
+                    list.push(x);
+                }
+            );
+
+            openils.widget.Searcher._cache.store[c.classname] = new dojo.data.ItemFileReadStore( { data : {identifier : c.ident, label : c.label, items : list } } );
+        }
+    );
+
+    var facet_list = [];
+    var search_list = [];
+
+    dojo.forEach(
+        openils.widget.Searcher._cache.arr.cmc,
+        function (cmc_obj) {
+            search_list.push({
+                name    : cmc_obj.name,
+                label   : cmc_obj.label
+            });
+            dojo.forEach(
+                dojo.filter(
+                    openils.widget.Searcher._cache.arr.cmf,
+                    function (x) {
+                        if (x.field_class == cmc_obj.name) return 1;
+                        return 0;
+                    }
+                ),
+                function (cmf_obj) {
+                    if (cmf_obj.search_field == 't') {
+                        search_list.push({
+                            name : cmc_obj.name + '|' + cmf_obj.name,
+                            label : ' -- ' + cmf_obj.label
+                        });
+                    }
+                    if (cmf_obj.facet_field == 't') {
+                        facet_list.push({
+                            name : cmc_obj.name + '|' + cmf_obj.name,
+                            label : cmc_obj.label + ' : '  + cmf_obj.label
+                        });
+                    }
+                }
+            )
+        }
+    );
+
+    openils.widget.Searcher.facetStore = new dojo.data.ItemFileReadStore( { data : {identifier : 'name', label : 'label', items : facet_list} } );
+    openils.widget.Searcher.searchStore = new dojo.data.ItemFileReadStore( { data : {identifier : 'name', label : 'label', items : search_list} } );
+
+//------ modifiers template -----------------------------------------------
+
+    dojo._hasResource["openils.widget.Searcher.modifier"] = true;
+    dojo.provide("openils.widget.Searcher.modifier");
+
+    dojo.declare(
+        'openils.widget.Searcher.modifier',
+        [dijit._Widget, dijit._Templated],
+        {
+
+            templateString :
+'<table dojoAttachPoint="myTop" class="modifier"><tbody><tr>' +
+'   <td>' +
+'     <select value="-" name="modifierSelect" dojoAttachPoint="modifierSelect" dojoType="dijit.form.FilteringSelect" >' +
+'       <option dojoAttachPoint="modifierDefault" value="-">-- Select a Modifier --</option>' +
+'       <option dojoAttachPoint="modifierAvailable" value="available"></option>' +
+'       <option dojoAttachPoint="modifierDescending" value="descending"></option>' +
+'       <option dojoAttachPoint="modifierAscending" value="ascending"></option>' +
+'       <option dojoAttachPoint="modifierMetabib" value="metabib"></option>' +
+'       <option dojoAttachPoint="modifierStaff" value="staff"></option>' +
+'     </select>' +
+'   </td> ' +
+'   <td dojoAttachPoint="removeWrapper"><span dojoType="dijit.form.Button" dojoAttachPoint="removeButton" dojoAttachEvent="onClick:killMe"></span></td> ' +
+'</tr></tbody></table>',
+            widgetsInTemplate: true,
+
+            postCreate : function () {
+                this.nls = dojo.i18n.getLocalization("openils.widget", "Searcher");
+
+                this.modifierDefault.innerHTML = this.nls.modifier_default;
+                this.modifierAvailable.innerHTML = this.nls.available;
+                this.modifierDescending.innerHTML = this.nls.descending;
+                this.modifierAscending.innerHTML = this.nls.ascending;
+                this.modifierMetabib.innerHTML = this.nls.metabib;
+                this.modifierStaff.innerHTML = this.nls.staff;
+
+                this.removeButton.setLabel(this.nls.remove);
+            },
+    
+            killMe : function () {
+                dijit.byNode(this.myTop).destroyRecursive();
+                this.destroy();
+            }
+        }
+    );
+
+//------ filters template -----------------------------------------------
+
+    dojo._hasResource["openils.widget.Searcher.filter"] = true;
+    dojo.provide("openils.widget.Searcher.filter");
+
+    dojo.declare(
+        'openils.widget.Searcher.filter',
+        [dijit._Widget, dijit._Templated],
+        {
+
+            templateString :
+'<table dojoAttachPoint="myTop" class="filter"><tbody><tr>' +
+'   <td>' +
+'     <select value="-" name="filterSelect" dojoAttachPoint="filterSelect" dojoType="dijit.form.FilteringSelect">' +
+'       <option dojoAttachPoint="filterDefault" value="-">-- Select a Filter --</option>' +
+'       <option dojoAttachPoint="filterSite" value="site">Site</option>' +
+'       <option dojoAttachPoint="filterDepth" value="depth">Search Depth</option>' +
+'       <option dojoAttachPoint="filterSort" value="sort">Sort Axis</option>' +
+'       <option dojoAttachPoint="filterStatuses" value="statuses">Statuses</option>' +
+'       <option dojoAttachPoint="filterAudience" value="audience">Audience</option>' +
+'       <option dojoAttachPoint="filterBefore" value="before">Published Before</option>' +
+'       <option dojoAttachPoint="filterAfter" value="after">Published After</option>' +
+'       <option dojoAttachPoint="filterBetween" value="between">Published Between</option>' +
+'       <option dojoAttachPoint="filterDuring" value="during">In Publication</option>' +
+'       <option dojoAttachPoint="filterForm" value="item_form">Form</option>' +
+'       <option dojoAttachPoint="filterType" value="item_type">Type</option>' +
+'       <option dojoAttachPoint="filterTypeForm" value="format">Type and Form</option>' +
+'       <option dojoAttachPoint="filterVRFormat" value="vr_format">Videorecording Format</option>' +
+'       <option dojoAttachPoint="filterLitForm" value="lit_form">Literary Form</option>' +
+'       <option dojoAttachPoint="filterBibLevel" value="bib_level">Bibliographic Level</option>' +
+'     </select>' +
+'   </td> ' +
+'   <td><div dojoAttachPoint="valueList" dojoType="dijit.form.TextBox"></div></td> ' +
+'   <td dojoAttachPoint="removeWrapper"><span dojoType="dijit.form.Button" dojoAttachPoint="removeButton" dojoAttachEvent="onClick:killMe"></span></td> ' +
+'</tr></tbody></table>',
+            widgetsInTemplate: true,
+
+            postCreate : function () {
+                this.nls = dojo.i18n.getLocalization("openils.widget", "Searcher");
+
+                this.filterDefault.innerHTML = this.nls.filter_default;
+                this.filterSite.innerHTML = this.nls.site;
+                this.filterDepth.innerHTML = this.nls.depth;
+                this.filterSort.innerHTML = this.nls.sort;
+                this.filterStatuses.innerHTML = this.nls.statuses;
+                this.filterAudience.innerHTML = this.nls.audience;
+                this.filterBefore.innerHTML = this.nls.before;
+                this.filterAfter.innerHTML = this.nls.after;
+                this.filterBetween.innerHTML = this.nls.between;
+                this.filterDuring.innerHTML = this.nls.during;
+                this.filterForm.innerHTML = this.nls.item_form;
+                this.filterType.innerHTML = this.nls.item_type;
+                this.filterTypeForm.innerHTML = this.nls.format;
+                this.filterVRFormat.innerHTML = this.nls.vr_format;
+                this.filterLitForm.innerHTML = this.nls.lit_form;
+                this.filterBibLevel.innerHTML = this.nls.bib_level;
+
+                this.removeButton.setLabel(this.nls.remove);
+            },
+    
+            killMe : function () {
+                dijit.byNode(this.myTop).destroyRecursive();
+                this.destroy();
+            }
+        }
+    );
+
+//------ facet search template -----------------------------------------------
+
+    dojo._hasResource["openils.widget.Searcher.facetedSearch"] = true;
+    dojo.provide("openils.widget.Searcher.facetedSearch");
+
+    dojo.declare(
+        'openils.widget.Searcher.facetedSearch',
+        [dijit._Widget, dijit._Templated],
+        {
+
+            templateString :
+'<table dojoAttachPoint="myTop" class="facetedSearch"><tbody><tr>' +
+'   <td><div dojoAttachPoint="matchIndex" searchAttr="label" dojoType="dijit.form.FilteringSelect" store="openils.widget.Searcher.facetStore"></div></td> ' +
+'   <td><span style="margin-left:10px; margin-right:10px;" dojoAttachPoint="exactOption"></span></td> ' +
+'   <td><div dojoAttachPoint="searchValue" dojoType="dijit.form.TextBox"></div></td> ' +
+'   <td dojoAttachPoint="removeWrapper"><span dojoType="dijit.form.Button" dojoAttachPoint="removeButton" dojoAttachEvent="onClick:killMe"></span></td> ' +
+'</tr></tbody></table>',
+            widgetsInTemplate: true,
+
+            noRemove : false,
+
+            postCreate : function () {
+                this.nls = dojo.i18n.getLocalization("openils.widget", "Searcher");
+
+                this.exactOption.innerHTML = this.nls.exact;
+                this.removeButton.setLabel(this.nls.remove);
+
+                if (this.noRemove) dojo.destroy(this.removeWrapper);
+            },
+    
+            killMe : function () {
+                dijit.byNode(this.myTop).destroyRecursive();
+                this.destroy();
+            }
+        }
+    );
+
+//------ classed search template -----------------------------------------------
+
+    dojo._hasResource["openils.widget.Searcher.classedSearch"] = true;
+    dojo.provide("openils.widget.Searcher.classedSearch");
+
+    dojo.declare(
+        'openils.widget.Searcher.classedSearch',
+        [dijit._Widget, dijit._Templated],
+        {
+
+            templateString :
+'<table dojoAttachPoint="myTop" class="classedSearch"><tbody><tr>' +
+'   <td colspan="4" align="center"><span dojoAttachPoint="joinerSpan"></span></td></tr><tr> ' +
+'   <td><div dojoAttachPoint="matchIndex" value="keyword" searchAttr="label" dojoType="dijit.form.FilteringSelect" store="openils.widget.Searcher.searchStore"></div></td> ' +
+'   <td>' +
+'     <select dojoAttachPoint="matchType" dojoType="dijit.form.FilteringSelect" name="matchType">' +
+'       <option dojoAttachPoint="containsOption" value="contains">Contains</option>' +
+'       <option dojoAttachPoint="notContainsOption" value="notcontains">Does Not Contain</option>' +
+'       <option dojoAttachPoint="exactOption" value="exact"> Matches Exactly</option>' +
+'     </select>' +
+'   </td> ' +
+'   <td><div dojoAttachPoint="searchValue" dojoType="dijit.form.TextBox"></div></td> ' +
+'   <td dojoAttachPoint="removeWrapper"><span dojoType="dijit.form.Button" dojoAttachPoint="removeButton" dojoAttachEvent="onClick:killMe"></span></td> ' +
+'</tr></tbody></table>',
+            widgetsInTemplate: true,
+
+            anded : true,
+            noRemove : false,
+
+            postCreate : function () {
+                this.nls = dojo.i18n.getLocalization("openils.widget", "Searcher");
+
+                this.containsOption.innerHTML = this.nls.contains;
+                this.notContainsOption.innerHTML = this.nls.notcontains;
+                this.exactOption.innerHTML = this.nls.exact;
+
+                this.removeButton.setLabel(this.nls.remove);
+
+                if (this.noRemove) dojo.destroy(this.removeWrapper);
+                if (!this.noRemove && this.anded) this.joinerSpan.innerHTML = this.nls.and;
+                if (!this.noRemove && !this.anded) this.joinerSpan.innerHTML = this.nls.or;
+            },
+    
+            killMe : function () {
+                dojo.destroy(this.myTop);
+                this.destroy();
+            }
+        }
+    );
+
+
+}
diff --git a/Open-ILS/web/js/dojo/openils/widget/nls/Searcher.js b/Open-ILS/web/js/dojo/openils/widget/nls/Searcher.js
new file mode 100644 (file)
index 0000000..9cd0c87
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    and : '&&',
+    or  : '||',
+    more  : 'More...',
+    less  : '...Less',
+    classed_searches  : 'Classed Searches',
+    faceted_searches  : 'Facets',
+    filters  : 'Filters',
+    modifiers  : 'Modifiers',
+    new_facet  : 'New Facet',
+    new_filter  : 'New Filter',
+    new_modifier  : 'New Modifier',
+    remove  : 'Remove',
+    advanced  : 'Advanced',
+    basic  : 'Basic',
+    perform_search  : 'Go!',
+    contains : 'Contains',
+    notcontains : 'Does Not Contain',
+    exact : 'Exactly Matches',
+    modifier_default : '-- Select a Modifier --',
+    available : 'Available',
+    descending : 'Sort Descending',
+    ascending : 'Sort Ascending',
+    metabib : 'Metarecord Search',
+    staff : 'Staff Search',
+    filter_default : '-- Select a Filter --',
+    site : 'Site',
+    depth : 'Search Depth',
+    sort : 'Sort Axis',
+    statuses : 'Statuses',
+    audience : 'Audience',
+    before : 'Published Before',
+    after : 'Published After',
+    between : 'Published Between',
+    during : 'In Publication',
+    item_form : 'Form',
+    item_type : 'Type',
+    format : 'Type and Form',
+    vr_format : 'Videorecording Format',
+    lit_form : 'Literary Form',
+    bib_level : 'Bibliographic Level'
+}
index 50aee75..45fe0c4 100644 (file)
@@ -9,6 +9,7 @@ var STAFF_WEB_BASE_PATH = '/eg'; // root of the web-based staff interfaces
 
 /* URL param names */
 var PARAM_TERM                 = "t";                  /* search term */
+var PARAM_FACET                        = "ft";                 /* facet term */
 var PARAM_STYPE                = "tp";                 /* search type */
 var PARAM_LOCATION     = "l";                  /* current location */
 var PARAM_LASSO        = "sg";                 /* current location */
@@ -49,6 +50,7 @@ var PARAM_NOPERSIST_SEARCH = 'nps';
 
 /* URL param values (see comments above) */
 var TERM;  
+var FACET;  
 var STYPE;  
 var LOCATION;  
 var LASSO;  
index 09163e6..b6d89ec 100644 (file)
@@ -140,6 +140,7 @@ function initParams() {
        if(isNaN(DEPTH)) DEPTH = null;
 
 
+       FACET           = cgi.param(PARAM_FACET);
        TERM            = cgi.param(PARAM_TERM);
        STYPE           = cgi.param(PARAM_STYPE);
        FORM            = cgi.param(PARAM_FORM);
@@ -232,6 +233,7 @@ function initCookies() {
 
 /* URL param accessors */
 function getTerm(){return TERM;}
+function getFacet(){return FACET;}
 function getStype(){return STYPE;}
 function getLocation(){return LOCATION;}
 function getLasso(){return LASSO;}
@@ -376,6 +378,8 @@ function  buildOPACLink(args, slim, ssl) {
                string += _appendParam(ORIGLOC, PARAM_ORIGLOC, args, getOrigLocation, string);
        if(getTerm()) 
                string += _appendParam(TERM,            PARAM_TERM, args, getTerm, string);
+       if(getFacet()) 
+               string += _appendParam(FACET,           PARAM_FACET, args, getFacet, string);
        if(getStype()) 
                string += _appendParam(STYPE,           PARAM_STYPE, args, getStype, string);
        if(getLocation() != 1) 
@@ -504,7 +508,7 @@ function buildTitleDetailLink(rec, link) {
 function buildSearchLink(type, string, linknode, trunc) {
        if(!trunc) trunc = 65;
        var args = {};
-       if( SHOW_MR_DEFAULT) {
+       if( SHOW_MR_DEFAULT || findCurrentPage() == MRESULT ) {
                args.page = MRESULT;
        } else {
                args.page = RRESULT;
index 9c74dd3..d1086ad 100644 (file)
@@ -373,6 +373,7 @@ Please see a librarian to renew your account.">
 <!ENTITY navigate.loggedinas.title "Logged in as...">
 <!ENTITY navigate.titleGroupResults "My Search Results">
 <!ENTITY navigate.titleResults "My Title Results">
+<!ENTITY navigate.facetRefine "Refine your search">
 <!ENTITY navigate.title.details "My Title Details">
 <!ENTITY navigate.record.details "Record Details">
 
index 2455b29..aa78f1c 100644 (file)
@@ -464,9 +464,9 @@ function _rdetailDraw(r) {
        breq.callback( rdetailCheckDeleted );
        breq.send();
 
-       resultBuildCaches( [ record ] );
-       resultDrawSubjects();
-       resultDrawSeries();
+       //resultBuildCaches( [ record ] );
+       //resultDrawSubjects();
+       //resultDrawSeries();
 
        // grab added content 
 
index 1ae9074..6510750 100644 (file)
@@ -13,9 +13,7 @@ if( findCurrentPage() == MRESULT || findCurrentPage() == RRESULT ) {
        G.evt.result.hitCountReceived.push(resultSetHitInfo);
        G.evt.result.recordReceived.push(resultDisplayRecord, resultAddCopyCounts);
        G.evt.result.copyCountsReceived.push(resultDisplayCopyCounts);
-       G.evt.result.allRecordsReceived.push(resultBuildCaches, resultDrawSubjects, 
-      resultDrawAuthors, resultDrawSeries, function(){unHideMe($('result_info_2'))},
-         fetchGoogleBooksLink,fetchChiliFreshReviews);
+       G.evt.result.allRecordsReceived.push( function(){unHideMe($('result_info_2'))}, fetchGoogleBooksLink, fetchChiliFreshReviews);
 
        attachEvt('result','lowHits',resultLowHits);
        attachEvt('result','zeroHits',resultZeroHits);
@@ -81,6 +79,8 @@ function resultCollectSearchIds( type, method, handler ) {
     if(getAvail()) args.available = 1;
 
 
+       if(getFacet()) args.facets  = getFacet();
+
        if(getAudience()) args.audience  = getAudience().split(/,/);
        if(getLitForm()) args.lit_form  = getLitForm().split(/,/);
        if(getLanguage()) args.language = getLanguage().split(/,/);
index 37dc49e..76d123d 100644 (file)
@@ -31,6 +31,7 @@ function searchBarInit() {
 
        /* set up the selector objects, etc */
        G.ui.searchbar.text.value = (getTerm() != null) ? getTerm() : "";
+       if (!isFrontPage) G.ui.searchbar.facets.value = (getFacet() != null) ? getFacet() : "";
        setSelector(_ts,        getStype());
        setSelector(_fs,        getForm());
 
@@ -51,6 +52,7 @@ function searchBarInit() {
 function searchBarSubmit(isFilterSort) {
 
        var text = G.ui.searchbar.text.value;
+       var facet_text = isFrontPage ? '' : G.ui.searchbar.facets.value;
 
        clearSearchParams();
 
@@ -61,7 +63,7 @@ function searchBarSubmit(isFilterSort) {
 
        var args = {};
 
-       if(SHOW_MR_DEFAULT || (isFilterSort && findCurrentPage() == MRESULT)) {
+       if(SHOW_MR_DEFAULT || findCurrentPage() == MRESULT) {
                args.page                               = MRESULT;
        } else {
                args.page                               = RRESULT;
@@ -70,6 +72,7 @@ function searchBarSubmit(isFilterSort) {
 
        args[PARAM_STYPE]               = _ts.options[_ts.selectedIndex].value;
        args[PARAM_TERM]                = text;
+       args[PARAM_FACET]               = facet_text;
        args[PARAM_LOCATION] = depthSelGetNewLoc();
        args[PARAM_DEPTH]               = d;
        args[PARAM_FORM]                = _fs.options[_fs.selectedIndex].value;
index 45296e4..30a2ffe 100644 (file)
@@ -183,12 +183,14 @@ function setSidebarLinks() {
 }
 
 function sidebarTreesFree() {
+/*
        removeChildren($(subjectSidebarTree.rootid));
        removeChildren($(authorSidebarTree.rootid));
        removeChildren($(seriesSidebarTree.rootid));
        subjectSidebarTree = null;
        authorSidebarTree = null;
        seriesSidebarTree = null;
+*/
 }
 
 
index af0b797..70a67b6 100644 (file)
@@ -71,5 +71,5 @@
                dojo.require("dojo.date.locale");
                dojo.require("dojo.date.stamp");
                dojo.require("dojo.parser");
-               dojo.require("openils.I18N");
+               dojo.require("openils.widget.FacetSidebar"); // pulls in Searcher and I18N
        </script>
index 505f6ab..1638370 100644 (file)
@@ -1,13 +1,44 @@
 
 <!-- Searchbar for doing metarecord searches -->
 
-<div id='searchbar'>
+<div id='searchbar' dojoType="openils.widget.Searcher" basicTextBox='search_box'>
+    <script type='dojo/method' event='performSearch'>
+        this.compileFullSearch();
+        dojo.byId(this.basicTextBox).value = this.basic_query;
+        dojo.byId(this.facetTextBox).value += this.facet_query;
+        dojo.byId('search_submit').click();
+    </script>
+    <script type='dojo/method' event='populate'><![CDATA[
+        var searcher = this;
+        attachEvt("result", "allRecordsReceived", function () {
+            if(!resultCompiledSearch) {
+                return;
+            }
+        
+            var all_search = dojo.query( '.classedSearch', searcher.classedSearches );
+            if (all_search.length > 1) {
+                for (var i = 1; i < all_search.length; i++) {
+                    dojo.destroy(all_search[i]);
+                }
+            }
+
+            var csearch = dijit.byNode(dojo.query( '.classedSearch', searcher.classedSearches )[0]);
+        
+            for (var type in resultCompiledSearch.searches) {
+                csearch.matchIndex.attr('value',type);
+                csearch.searchValue.attr('value',resultCompiledSearch.searches[type].term);
+                csearch = searcher.addClassAnd();
+            }
+        });
+    ]]></script>
+
 
        <!-- load my js -->
        <script language='javascript' type='text/javascript'>
                config.ids.searchbar = {};
                config.css.searchbar = {};
                config.ids.searchbar.text                               = 'search_box'; 
+               config.ids.searchbar.facets                             = 'facet_box';  
                config.ids.searchbar.submit                     = 'search_submit';      
                config.ids.searchbar.type_selector      = 'search_type_selector';
                config.ids.searchbar.depth_selector     = 'depth_selector';
@@ -28,7 +59,8 @@
 
                                <td nowrap='nowrap' align='center'  class='search_box_container color_2'>
 
-                                       <input id='search_box' type='text' />
+                                       <input id='search_box' type='text' onkeyup='dojo.byId("facet_box").value = "";'/>
+                                       <input id='facet_box' type='hidden' />
                                        <span style='padding-left: 6px;'>
                                                <input type='button' style='width: 40px;' id='search_submit' value='&button.go;' />
                                        </span>
index cbdc677..39c0a94 100644 (file)
                </div>
        </div>
 
-       <div id='subject_tree_sidebar' class='sidebar_chunk hide_me' style='margin-top: 12px;'> 
-               <div id='subject_sidebar_tree_div'> </div>
-               <script language='javascript' type='text/javascript'>
-                       removeChildren($('subject_sidebar_tree_div'));
-                       var subjectSidebarTree = new SlimTree(
-                               document.getElementById('subject_sidebar_tree_div'),
-                               'subjectSidebarTree', '../../../../images/slimtree/related.jpg');
-                       subjectSidebarTree.addNode( 'subjectSidebarTreeRoot', -1, 
-                               "&sidebar.relevantSubjects.headerLabel;", 
-                               'javascript:subjectSidebarTree.toggle(' +
-                                       '"subjectSidebarTreeRoot");');
-               </script>
-       </div>
+    <div id='facetSidebarContainer' class='hide_me'>
 
-       <div id='author_tree_sidebar' class='sidebar_chunk hide_me'> 
-               <hr/>
-               <div id='author_sidebar_tree_div'> </div>
-               <script language='javascript' type='text/javascript'>
-                       removeChildren($('author_sidebar_tree_div'));
-                       var authorSidebarTree = new SlimTree(
-                               document.getElementById('author_sidebar_tree_div'),
-                               'authorSidebarTree','../../../../images/slimtree/people.jpg');
-                       authorSidebarTree.addNode( 'authorSidebarTreeRoot', -1, 
-                               "&sidebar.relevantAuthors.headerLabel;", 
-                               'javascript:authorSidebarTree.toggle(' +
-                                       '"authorSidebarTreeRoot");');
-               </script>
+        <div class="side_bar_item" style="margin-top: 10px; font-weight: bold;">
+      <span>&navigate.facetRefine;</span>
        </div>
 
-       <div id='series_tree_sidebar' class='sidebar_chunk hide_me'> 
-               <hr/>
-               <div id='series_sidebar_tree_div'> </div>
-               <script language='javascript' type='text/javascript'>
-                       removeChildren($('series_sidebar_tree_div'));
-                       var seriesSidebarTree = new SlimTree(
-                               document.getElementById('series_sidebar_tree_div'),
-                               'seriesSidebarTree',
-                               '../../../../images/slimtree/houses.jpg');
-                       seriesSidebarTree.addNode( 'seriesSidebarTreeRoot', -1, 
-                               "&sidebar.relevantSeries.headerLabel;", 
-                               'javascript:seriesSidebarTree.toggle(' +
-                                       '"seriesSidebarTreeRoot");');
-               </script>
+     <div dojoType='openils.widget.FacetSidebar' searchBox='facet_box' searchSubmit='search_submit' facetLimit='5' classOrder='["author","subject","series","title","keyword"]'>
+            <script type='dojo/method' event='populate'><![CDATA[
+                var fblob = this;
+                attachEvt("result", "allRecordsReceived", function () {
+                    if(!resultFacetKey) return;
+                    if (fblob.facetCacheKey) return; // already rendered it
+
+                    dojo.removeClass('facetSidebarContainer','hide_me');
+
+                    fblob.facetCacheKey = resultFacetKey;
+                    fblob.render();
+                });
+            ]]></script>
+        </div>
        </div>
 
        <div id='adv_quick_search_sidebar' class='sidebar_chunk hide_me' 
                config.ids.sidebar.loginbox             = 'login_link_div';
                config.ids.sidebar.logged_in_as = 'logged_in_as_div';
                config.ids.sidebar.username_dest        = 'username_dest';
-               config.ids.sidebar.subject                      = 'subject_sidebar';
-               config.ids.sidebar.subject_item = 'subject_item';
-               config.ids.sidebar.author                       = 'author_sidebar';
-               config.ids.sidebar.author_item  = 'author_item';
-               config.ids.sidebar.series                       = 'series_sidebar';
-               config.ids.sidebar.series_item  = 'series_item';
                
                config.ids.sidebar.home_link            = 'home_link'
                config.ids.sidebar.advanced_link        = 'advanced_link'
                config.ids.sidebar.myopac_link  = 'myopac_link'
                
-               config.names.sidebar.subject_item       = 'subject_item';
-               config.names.sidebar.author_item                = 'author_item';
-               config.names.sidebar.series_item                = 'series_item';
-
                config.css.encircled                            = 'encircled';
        </script>
 
index 78314b1..11cb5f0 100644 (file)
@@ -28,7 +28,7 @@
                         var out = '';
                         var list = dojo.query( 'subfield', item );
                         for (var i = 0; i < list.length; i++) {
-                            out += dojox.data.dom.textContent(list[i]) + ' ';
+                            out += BT.textContent(list[i]) + ' ';
                         }
                         return out;
                     ]]></script>
                         var output = [];
                         var list = dojo.query( 'subfield', item );
                         for (var i =0; i < list.length; i++) {
-                            total += dojox.data.dom.textContent(list[i]) + ' ';
+                            total += BT.textContent(list[i]) + ' ';
                             var current = '<a href="rresult.xml?rt=subject&tp=subject&t=' + total;
                             for (var p in other_params) {
                                 if (cgi.param(other_params[p]))
                                     current += '&' + other_params[p] + '=' + cgi.param(other_params[p]);
                             }
-                            current += '">' + dojox.data.dom.textContent(list[i]) + '</a>'
+                            current += '">' + BT.textContent(list[i]) + '</a>'
                             output.push(current);
                         }
                         return '<span>' + output.join(' &#x2d;&#x2d; ') + '</span><br/>';
index 0412887..b38227a 100644 (file)
@@ -30,8 +30,42 @@ body a:hover { color: red; text-decoration: underline;}
 .border_3_3 { border: 3px solid #E0F6E0; }
 .border_4_3 { border: 3px solid #E0F0E0; }
 
-
-
+/* some facet styling */
+.facetClassContainer { margin: 2px; border: 1px solid #64EA4F; }
+.facetClassLabelContainer { background: #A7EA9D; border: 1px solid #A7EA9D; }
+.facetClassLabel { font-weight: bold; text-align: center; }
+.facetFieldContainer { background: #E0F6E0; }
+.facetFieldLabel { padding-left: 2px; margin-top: 5px; margin-bottom: 5px; font-weight: bold; text-align: left; }
+.extraFacetFieldsWrapper { }
+.toggleExtraFacetFieldsButton { float: right; margin: 0px; padding: 0px; }
+.facetFieldLineCount { display: inline-block; border-right: 1px solid #A7EA9D; color: gray; width: 3em; margin-right: 3px }
+.facetField { border-top: 1px solid #A7EA9D; }
+.facetFields { padding-left: 5px; }
+.facetFieldLineValue { overflow: hidden; text-overflow: ellipsis; }
+
+.searcherSimpleSearchWrapper {} 
+.searcherAdvancedSearchWrapper { margin: 2px; border: 1px solid #64EA4F; } 
+
+.searcherClassedSearchesContainer { margin: 5px; } 
+.searcherClassedSearches {} 
+.searcherClassedSearchesLabel { font-weight: bold; } 
+
+.searcherClassedSearchesAddContainer { width: 50%; text-align: center; }
+
+.searcherFacetedSearchesContainer { margin: 5px; border-top: 1px solid black; } 
+.searcherFacetedSearches {} 
+.searcherFacetedSearchesLabel { font-weight: bold; } 
+
+.searcherFilterModifierContainer { margin: 5px; border-top: 1px solid black; } 
+
+.searcherFiltersLabel { font-weight: bold; } 
+.searcherFilterContainer {} 
+
+.searcherModifiersLabel { font-weight: bold; } 
+.searcherModifierContainer {} 
+
+.searcherGoContainer { width: 50%; text-align: right; }
+.searcherDeckSwapContainer {}
 
 /* general purpose light borders */
 .border_5 { border: 1px solid #D0D0D0; }