Search Templates (kmig 123)
authorBill Erickson <berickxx@gmail.com>
Wed, 29 Oct 2014 21:05:52 +0000 (17:05 -0400)
committerBill Erickson <berickxx@gmail.com>
Thu, 21 Mar 2019 19:46:23 +0000 (15:46 -0400)
    Cross-port: 5f1f13e

KCLS/openils/var/templates_kcls/conify/global/config/search_templates.tt2 [new file with mode: 0644]
KCLS/openils/var/templates_kcls/opac/parts/advanced/search.tt2
KCLS/openils/var/templates_kcls/opac/parts/config.tt2
KCLS/openils/var/templates_kcls/opac/parts/misc_util.tt2
Open-ILS/web/js/ui/kcls/conify/global/config/search_templates.js [new file with mode: 0644]
Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/xul/staff_client/chrome/content/OpenILS/data.js
Open-ILS/xul/staff_client/chrome/content/main/menu.js
Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties

diff --git a/KCLS/openils/var/templates_kcls/conify/global/config/search_templates.tt2 b/KCLS/openils/var/templates_kcls/conify/global/config/search_templates.tt2
new file mode 100644 (file)
index 0000000..a04847c
--- /dev/null
@@ -0,0 +1,286 @@
+[% WRAPPER base.tt2 %]
+[% INCLUDE 'opac/parts/js.tt2' %]
+[%
+    PROCESS "opac/parts/config.tt2";
+%]
+<script type="text/javascript" src="/xul/server/OpenILS/global_util.js"></script>
+<script type="text/javascript" src="/xul/server/main/constants.js"></script>
+<script type="text/javascript" src="/xul/server/main/JSAN.js"></script>
+<script type="text/javascript" src="/xul/server/util/file.js"></script>
+<script type="text/javascript" src="/xul/server/util/error.js"></script>
+<script type="text/javascript" src="/js/ui/kcls/conify/global/config/search_templates.js"></script>
+
+<style>
+    #adv_global_tbody input, #adv_global_tbody a {display:none;}
+    .ccvmSelect {width:200px;}
+    #currentSettings {float:right;  width:300px; height:200px;}
+    #options {float:left;}
+    #searchFilters td {padding:.5em;}
+    #currentSettings td {padding:.3em;}
+    #adv_global_tbody select {max-width:115px;}
+    #ssContainer {width:1200px;}
+</style>
+<div id="ssContainer">
+    <h1>[% l('Search Settings') %]</h1>
+    <br/>
+
+    <div id="currentSettings">
+        <h2>[% l('Current Template') %]</h2>
+        <select id="templateListSel" onChange="selectSearchTemplateOrClear(this.value), textIn.value = this.value" style="min-width:150px;">
+            <option value="">--Default--</option>
+        </select>
+        <br/>
+        <br/>
+        <br/>
+        <br/>
+
+        <strong>[% l('Template Name') %]</strong>
+        <br/>
+        <table>
+            <tr>
+                <td>
+                    <input type="text" id="nameInput" name="nameInput"/>
+                </td>
+                <td>
+                    <button id="save" onclick="create_template(textIn.value)">Save Template To Disk</button>
+                </td>
+            </tr>
+            <tr>
+                <td>
+                    <button id="delete" onclick="removeTemplate(templateList,template)">[% l('Delete Template') %]</button>
+                </td>
+            </tr>
+        </table>
+    </div>
+    <div id="options">
+        <table width='100%' id='adv_global_input_table'>
+
+            <tbody id='adv_global_tbody' >
+               [% INCLUDE "opac/parts/advanced/global_row.tt2" %]
+
+            </tbody>
+        </table>
+
+        <br/>
+
+        <table id="searchFilters">
+[%
+    in_row = 0;
+    FOR adv_chunk IN search.adv_config;
+        NEXT IF adv_chunk.adv_hide;
+        IF in_row == 0;
+            in_row = 1; %]
+            <tr>
+[%
+        END; %]
+        [% IF adv_chunk.adv_attr.size || adv_chunk.adv_filter.size; %]
+                <td>
+                    <strong>[% adv_chunk.adv_label %]</strong>
+                    <br />
+                    <select name="type" multiple="multiple" size="7" class="ccvmSelect">
+                    </select>
+                </td>
+        [% END; %]
+      [%  IF adv_chunk.adv_break;
+            in_row = 0; %]
+            </tr>
+        [% END; %]
+ [%   END; %]
+            <tr>
+                <td>
+                    <strong>[% l('Search Library') %]</strong>
+                    <br />
+                    <select id="orgSel" name="orgSel"></select>
+                </td>
+                <td>
+                    <strong>[% l('Publication Date') %]</strong>
+                    <br/>
+                    <select id="pubdateSel" name="pubdateSel">
+                        <option value="is">[% l('Is') %]</option>
+                        <option value="before">[% l('Before') %]</option>
+                        <option value="after">[% l('After') %]</option>
+                        <option value="between">[% l('Between') %]</option>
+                    </select>
+                </td>
+            </tr>
+
+            <tr>
+                <td>
+                    <strong>[% l('Search Results') %]</strong>
+                    <br/>
+                    <select id="sortBySel" name="sortBySel">
+                        <option value="">[% l('Sort by Relevance') %]</option>
+                        <optgroup label="[% l('Sort by Title') %]">
+                            <option value="titlesort">[% l('Title: A to Z') %]</option>
+                            <option value="titlesort.descending">[% l('Title: Z to A') %]</option>
+                        </optgroup>
+                        <optgroup label="[% l('Sort by Author') %]">
+                            <option value="authorsort">[% l('Author: A to Z') %]</option>
+                            <option value="authorsort.descending">[% l('Author: Z to A') %]</option>
+                        </optgroup>
+                        <optgroup label="[% l('Sort by Publication Date') %]">
+                            <option value="pubdate.descending">[% l('Date: Newest to Oldest') %]</option>
+                            <option value="pubdate">[% l('Date: Oldest to Newest') %]</option>
+                        </optgroup>
+                    </select>
+                </td>
+                <td>
+                    <strong>[% l('Result View') %]</strong>
+                    <br/>
+                    <select id="resultViewSel">
+                        <option value="0">[% l('Simple View') %]</option>
+                        <option value="1">[% l('Detail View') %]</option>
+                    </select>
+                </td>
+                <td>
+                    <input type="checkbox" name="modifier" id="modifier" value="available" />
+                    <span>[% l('Limit to Available') %]</span>
+                </td>
+            </tr>
+            <tr>
+                <td>
+                <button id="clear" onclick="clearOptions()">[% l('Clear Options') %]</button>
+                </td>
+            </tr>
+        </table>
+
+    </div>
+
+</div>
+
+<!-- /////////////////  -- JAVASCRIPT -- /////////////////////// -->
+
+<script type="text/javascript">
+    dojo.require('openils.PermaCrud');
+    var pcrud;
+    pcrud = new openils.PermaCrud();
+    //HTML element handles
+    var templateSel = document.getElementById("templateListSel");
+    var pubdateSel = document.getElementById("pubdateSel");
+    var orgSel = document.getElementById("orgSel");
+    var sortBySel = document.getElementById("sortBySel");
+    var resultViewSel = document.getElementById("resultViewSel");
+    var modCheck = document.getElementById("modifier");
+    var textIn = document.getElementById("nameInput");
+    var ccvmTable = document.getElementById("searchFilters");
+    var searchFilters = ccvmTable.getElementsByTagName("select");
+
+
+    var ccvmList = pcrud.retrieveAll("ccvm", {"order_by" : {"ccvm" : 'value'}});
+    var searchfilterList = pcrud.retrieveAll("asfg",{ "flesh":2, "flesh_fields":{"asfg":["entries"],"asfge":["query"]},"order_by" : {"asfg" : 'code'}});
+    var ccvmLength = ccvmList.length;
+    var filterList = new Array();
+    var foundValue = 0;
+    var n = 0; //tracks filterList
+    var s = 0; // tracks adv_config
+    [%  FOR adv_chunk IN search.adv_config;
+        NEXT IF adv_chunk.adv_hide;
+        IF adv_chunk.adv_special; %]
+        s++;
+        [% NEXT; END; %]
+        foundValue = 0;
+        filterList[n] = {};
+        filterList[n].label = "[% adv_chunk.adv_label %]";
+        filterList[n].last_in_row = "[% adv_chunk.adv_break %]";
+        filterList[n].codeList = [];
+        filterList[n].groupList = [];
+        [% IF adv_chunk.adv_attr.defined; %]
+            [% FOR attr IN adv_chunk.adv_attr; %]
+            if(!foundValue)
+            {
+                filterList[n].ctype = "[% attr %]";
+                for ( i= 0; i < ccvmLength; i++)
+                {
+                    if (ccvmList[i].ctype() == "[% attr %]")
+                    {
+                        filterList[n].codeList.push(ccvmList[i]);
+                    }
+                }
+                if (filterList[n].codeList.length )
+                {
+                    foundValue = 1;
+                }
+            }
+            searchFilters[s].setAttribute("id", "[% attr %]" + "_selector");
+            filterList[n].id = "[% attr %]" + "_selector";
+           [% END;
+        ELSIF adv_chunk.adv_filter.defined; %]
+            [% FOR filter IN adv_chunk.adv_filter; %]
+            if(!foundValue)
+            {
+                filterList[n].ctype = "[% filter %]";
+                for ( i= 0; i < searchfilterList.length; i++)
+                {
+                    if (searchfilterList[i].code() == "[% filter %]")
+                    {
+                         var len = searchfilterList[i].entries().length;
+                        for (var k = 0; k < len; k++)
+                        {
+                           filterList[n].groupList.push(searchfilterList[i].entries()[k]);
+                        }
+                    }
+                }
+                if (filterList[n].groupList.length )
+                {
+                    foundValue = 1;
+                }
+            }
+            searchFilters[s].setAttribute("id", "[% filter %]" + "_selector");
+            filterList[n].id = "[% filter %]" + "_selector";
+            [% END; %]
+        [% END; %]
+        n++;
+
+[% END; %]
+
+    //Add option tags to searchFilters
+    for (var f = 0; f < searchFilters.length; f++)
+    {
+        if (searchFilters[f].multiple)
+        {
+            if (filterList[f] && filterList[f].id)
+            {
+                if (filterList[f].codeList.length)
+                {
+                    if (filterList[f].codeList.length)
+                    for(var i=0; i<filterList[f].codeList.length; i++)
+                    {
+                        searchFilters[f].options[i]= new Option(filterList[f].codeList[i].value(), filterList[f].codeList[i].code());
+                    }
+                }
+                else if (filterList[f].groupList.length)
+                {
+                    if (filterList[f].groupList.length)
+                    for(var i=0; i<filterList[f].groupList.length; i++)
+                    {
+                        searchFilters[f].options[i]= new Option(filterList[f].groupList[i].query().label(), filterList[f].groupList[i].id());
+                    }
+                }
+            }
+        }
+    }
+
+    //create org unit dropdown
+    var orgList;
+    orgList = pcrud.retrieveAll("aou",{"order_by" : [{'class' : "aou", 'field' : 'ou_type'}, {'class' : "aou", 'field' : "name" }]});
+    for(var i=0; i< orgList.length; i++){
+        document.getElementById("orgSel").options[i]= new Option(orgList[i].name(), orgList[i].id());
+    }
+
+    //get g.data cache
+    getSearchStash();
+    populateTemplateOptions(templateList);
+
+    if (template)
+    {
+        selectOptionValue(templateSel, template.name);
+        textIn.value = template.name;
+        if(template.name != "Default")
+        {
+            populateSearchOptions(template);
+        }
+    }
+
+</script>
+
+[% END %]
index 13155df..17ae818 100644 (file)
-<form id="adv_search_form" action="[% ctx.opac_root %]/results" method="GET">
-<table id='adv_global_search' class='data_grid data_grid_center' width='100%'>
-    <tr style='border-bottom: none;'>
-        <!-- Contains the user-addable(?) rows to define search class, containment and text -->
-        <td valign='top' class='opac-auto-012'>
-            <table width='100%' id='adv_global_input_table'>
-                <thead>
-                    <tr>
-                        <td>
-                            <div style="width:100%;" class="header_middle">
-                                [% l("Search Input") %]
-                            </div>
-                        </td>
-                    </tr>
-                </thead>
-                <tbody id='adv_global_tbody'>
-                    [% INCLUDE "opac/parts/advanced/global_row.tt2" %]
-                    <!-- add a new row -->
-                    <tr id='adv_global_addrow'>
-                        <td align='left' style="padding-top:7px;">
-                            <a href="javascript:;" id="myopac_new_global_row" onclick='addSearchRow();'>[% l('Add Search Row') %]</a>
-                        </td>
-                    </tr>
-                </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr>
-        <td align='top'>
-          <div style="width:100%;" class="header_middle">[% l('Search Filters') %]</div>
-          <table cellpadding='10' cellspacing='0' border='0'><tr>
-            <td valign='top'>
-                <strong>[% l("Item Type") %]</strong><br />
-                [%  INCLUDE "opac/parts/coded_value_selector.tt2"
-                        attr=["mattype", "item_type"] multiple="multiple" size="4"
-                        id="adv_global_item_type_basic" %]
+[% 
+    PROCESS "opac/parts/misc_util.tt2";
+    PROCESS get_library;
+%]
+<form id="adv_search_form" action="[% ctx.opac_root %]/results" method="get">
+    <table id='adv_global_search' class='data_grid data_grid_center' width='100%'>
+        <tr style='border-bottom: none;'>
+            <!-- Contains the user-addable(?) rows to define search class, containment and text -->
+            <td valign='top' class='opac-auto-012'>
+                <table width='100%' id='adv_global_input_table'>
+                    <thead>
+                        <tr>
+                            <td>
+                                <div style="width:100%;" class="header_middle">
+                                    [% l("Search Input") %]
+                                </div>
+                            </td>
+                        </tr>
+                    </thead>
+                    <tbody id='adv_global_tbody'>
+                        [% INCLUDE "opac/parts/advanced/global_row.tt2" %]
+                        <!-- add a new row -->
+                        <tr id='adv_global_addrow'>
+                            <td align='left' style="padding-top:7px;">
+                                <a href="javascript:;" id="myopac_new_global_row" onclick='addSearchRow();'>[% l('Add Search Row') %]</a>
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
             </td>
-            <td valign='top'>
-                <strong>[% l("Language") %]</strong><br />
-                [%  INCLUDE "opac/parts/coded_value_selector.tt2"
-                        attr="item_lang" multiple="multiple" size="4" 
-                                               id="adv_global_language_basic" %]
-            </td>
-            <td valign='top'>
-                <strong>[% l("Audience") %]</strong><br />
-                    [% INCLUDE "opac/parts/coded_value_selector.tt2"
-                        attr=["audience_group", "audience"] id="adv_global_audience_basic" 
-                        multiple="multiple" size="4" %]
-                </select>
-                    <!--<a id='adv_global_audience_link_adv' class='classic_link adv_adv_link'
-                        href='javascript:void(0);' onclick='
-                        hideMe($("adv_global_audience_basic"));
-                        unHideMe($("adv_global_audience"));
-                        hideMe(this);
-                        unHideMe($("adv_global_audience_link_basic"));
-                        '>[% l("Advanced") %]</a>
-                    <a id='adv_global_audience_link_basic' class='hide_me classic_link adv_adv_link'
-                        href='javascript:void(0);' onclick='
-                        unHideMe($("adv_global_audience_basic"));
-                        hideMe($("adv_global_audience"));
-                        unHideMe($("adv_global_audience_link_adv"));
-                        hideMe(this);'>[% l("Basic") %]</a>-->
-            </td>
-            <td valign='top'>
-            <strong>[% l("Sort Results") %]</strong>
-              <table class='opac-auto-017'>
+        </tr>
+        <tr>
+            <td align='top'>
+              <div style="width:100%;" class="header_middle">[% l('Search Filters') %]</div>
+              <table cellpadding='10' cellspacing='0' border='0' id='filterTable'>
+    [%
+        in_row = 0;
+        FOR adv_chunk IN search.adv_config;
+            NEXT IF adv_chunk.adv_hide;
+            IF in_row == 0;
+                in_row = 1; %]
                 <tr>
-                    <td align='center' width='100%'>
-                        [% INCLUDE "opac/parts/filtersort.tt2"
-                            value=CGI.param('sort') %]
-                    </td>
+    [%
+            END; %]
+                <td valign='top'>
+                    <strong>[% adv_chunk.adv_label %]</strong><br />
+    [%
+            IF adv_chunk.adv_special;
+                SWITCH adv_chunk.adv_special;
+                    CASE "lib_selector";
+                        PROCESS "opac/parts/org_selector.tt2";
+                            INCLUDE build_org_selector show_loc_groups=1 id='org_selector'; %]
+                                <div style="position:relative;top:7px;">
+                                    <input type='checkbox' name="modifier"
+                                        value="available"[% CGI.param('modifier').grep('available').size ? ' checked="checked"' : '' %]
+                                        id='opac.result.limit2avail' />
+                                    <label style="position:relative;top:-2px;"
+                                        for='opac.result.limit2avail'>
+                                        [% l("Limit to Available") %]</label>
+                                </div>
+    [%
+                    CASE "pub_year"; %]
+                                <select id='adv_global_pub_date_type' name='pubdate' onchange='
+                                    if(this.selectedIndex == 3)
+                                        unHideMe($("adv_global_pub_date_2_span"));
+                                    else
+                                        hideMe($("adv_global_pub_date_2_span"));'>
+                                        [%  FOR opt IN [
+                                                {"code" => "is", "label" => l("Is")},
+                                                {"code" => "before", "label" => l("Before")},
+                                                {"code" => "after", "label" => l("After")},
+                                                {"code" => "between", "label" => l("Between")} ] %]
+                                            <option value="[% opt.code %]"[% CGI.param('pubdate') == opt.code ? ' selected="selected"' : '' %]>[% opt.label | html %]</option>
+                                        [%  END %]
+                                </select>    
+                                <div style='margin-top:5px;'>
+                                    <input name='date1' id='adv_global_pub_date_1_input' type='text' size='4' maxlength='4' value="[% CGI.param('date1') | html %]" />
+                                    <span id='adv_global_pub_date_2_span' class='[% CGI.param("pubdate") == "between" ? "" : "hide_me" %]'>
+                                       [% l("and") %] <input name='date2' id='adv_global_pub_date_2_input' type='text' size='4' maxlength='4' value="[% CGI.param('date2') | html %]" />
+                                    </span>
+                                </div>
+    [%
+                    CASE "sort_selector";
+                        INCLUDE "opac/parts/filtersort.tt2"
+                            value=CGI.param('sort') class='results_header_sel' id='opac.result.sort';
+                END;
+            ELSIF adv_chunk.adv_attr;
+                INCLUDE "opac/parts/coded_value_selector.tt2"
+                    attr=adv_chunk.adv_attr multiple="multiple" size="4";
+            ELSIF adv_chunk.adv_filter;
+                INCLUDE "opac/parts/filter_group_selector.tt2"
+                    filter_group=adv_chunk.adv_filter multiple="multiple" size="4";
+            END; %]
+                </td>
+    [%
+            IF adv_chunk.adv_break;
+                in_row = 0; %]
                 </tr>
-              </table>
-               [% IF ctx.is_staff %]
-                       <td valign='top' style="padding-left:100px;">
-                               <strong>Search Templates</strong>
-                               <br/>
-                               <select id="templateList" onChange="selectSearchTemplateOrClearAll(this.value);">
-                               </select>
-                       </td>
-               [% END %]
+    [%
+            END;
+        END; %]
+                </table>
             </td>
-          </tr></table>
-        </td>
-    </tr>
-    <tr>
-        <td colspan="2">
-            <table cellpadding='10' cellspacing='0' border='0'>
-                <tbody>
-                    <tr>
-                        <td valign='top'>
-                            <strong>[% l("Search Library") %]</strong><br />
-                            [% PROCESS "opac/parts/org_selector.tt2";
-                                PROCESS build_org_selector name='loc' value=loc id='org_selector'%]
-                            <div style="position:relative;top:7px;">
-                                <input type='checkbox' name="modifier"
-                                value="available"[% CGI.param('modifier').grep('available').size ? ' checked="checked"' : '' %]
-                                    id='opac.result.limit2avail' />
-                                <label style="position:relative;top:-2px;"
-                                    for='opac.result.limit2avail'>
-                                    [% l("Limit to Available") %]</label>
-                            </div>
-                        </td>
-                        <td valign='top'>
-                            <strong>[% l("Publication Year") %]</strong><br />
-                            <select id='adv_global_pub_date_type' name='pubdate' onchange='
-                                if(this.selectedIndex == 3)
-                                    unHideMe($("adv_global_pub_date_2_span"));
-                                else
-                                    hideMe($("adv_global_pub_date_2_span"));'>
-                                    [%  FOR opt IN [
-                                            {"code" => "is", "label" => l("Is")},
-                                            {"code" => "before", "label" => l("Before")},
-                                            {"code" => "after", "label" => l("After")},
-                                            {"code" => "between", "label" => l("Between")}
-                                        ];
-                                            |l(opt.code, opt.label) %]
-                                        <option value="[_1]"[% CGI.param('pubdate') == opt.code ? ' selected="selected"' : '' %]>[_2]</option>
-                                    [%  END; END %]
-                            </select>    
-                            <div style='margin-top:5px;'>
-                                <input id='adv_global_pub_date_1' name='date1' type='text' size='4' maxlength='4' value="[% CGI.param('date1') | html %]" />
-                                <span id='adv_global_pub_date_2_span' class='[% CGI.param("pubdate") == "between" ? "" : "hide_me" %]'>
-                                   [% l("and") %] <input name='date2' id='adv_global_pub_date_2' type='text' size='4' maxlength='4' value="[% CGI.param('date2') | html %]" />
-                                </span>
-                            </div>
-                        </td>
-                       <td valign="top" class="hide_me">
-                       <strong>Result Detail</strong><br/>
-                          <select id="resultViewSel" name="detail_record_view" >
-                               <option value="0" selected="selected">Simple View</option>
-                               <option value="1">Detail View</option>
-                          </select>
-                       </td>
-                    </tr>
-                    <!-- copy location selector -->
-                    <tr id='adv_copy_location_filter_row' class='hide_me'>
-                        <td align='right'>[% l("Shelving Location") %]</td>
-                        <td align='left' id='adv_copy_location_filter_td'>
-                            <select size='3' id='adv_copy_location_filter_select' multiple='multiple'>
-                            </select>
-                        </td>
-                    </tr>
-                </tbody>
-            </table>
-        </td>
-    </tr>
-    <tr class='border_4_2'>
-        <td align="left" colspan='2'>
-            <input type="image" src="[% ctx.media_prefix %]/images/search_btn.gif"
-            alt="[% l('Search') %]" class='pointer' />
-
-            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-
-            <a href='[% mkurl('', {}, 1) %]' onclick='clearAll(); return false;'>[% l('Clear Form') %]</a>
-        </td>
-    </tr>
-</table>
-
-<input type="hidden" name="_adv" value="1" />
-</form>
-<div id='adv_quick_search_sidebar' class='sidebar_chunk hide_me'> 
-    <div id='adv_quick_search'>
-        <div class='adv_quick_search color_4'><b>[% l("Quick Search") %]</b></div>
-        <div style='margin-top: 8px;'>
-            <table><tbody><tr>
-                <td>
-                    <select id='adv_quick_type'>
-                        <option value='isbn'>[% l("ISBN") %]</option>
-                        <option value='issn'>[% l("ISSN") %]</option>
-                        <option value='cn'>[% l("Call Number") %]</option>
-                        <option value='lccn'>[% l("LCCN") %]</option>
-                        <option value='tcn'>[% l("TCN") %]</option>
-                        <option value='barcode'>[% l("Item Barcode") %]</option>
+            [% IF ctx.is_staff && search.allow_templates == 'true' %]
+                <td valign='top' style="padding-left:50px;">
+                    <div style="width:100%;" class="header_middle">[% l('Search Templates') %]</div>
+                    <br/>
+                    <strong>[% l('Select Template') %]</strong>
+                    <br/>
+                    <select id="templateList" onChange="selectSearchTemplateOrClearAll(this.value);">
                     </select>
-                </td><td>
-                    <input type='text' id='adv_quick_text' size='16' />
                 </td>
-            </tr></tbody></table>
-        </div>
-
-        <div style='margin-top: 8px;' class='adv_quick_search_submit'>
-            <!-- XXX TODO make a real form, and make a real submitter (quick
-            submit, FKA advGenericSearch() -->
-            <img src="[% ctx.media_prefix %]/images/search_btn.gif"
-                alt="[% l('Search') %]" id="adv_quick_submit" class='pointer' />
-        </div>
-    </div>
-</div>
-
-<div id='adv_marc_search_sidebar' class='sidebar_chunk hide_me'
-    style='width:400px; margin-top: 20px;'> 
-    <div class='adv_quick_search color_4'><b>[% l("MARC Expert Search") %]</b></div>
-    <table style='margin: 3px; width: 100%;' id='adv_sdbar_table'
-        class='border_4_3'>
-        <tbody>
-            <tr>
-                <td align="right">[% l("Tag:") %]</td>
-                <td align="left"><input name='advanced.marc.tag' maxlength='3' size='3' /></td>
-                <td align="right">[% l("Subfield:") %]</td>
-                <td align="left"><input name='advanced.marc.subfield' maxlength='1' size='1' /></td>
-            </tr>
-            <tr>
-                <td align="right">[% l("Value:") %]</td>
-                <td colspan='3' align="left"><input name='advanced.marc.value' size='18' /></td>
-            </tr>
-            <tr name='crow' class='hide_me'>
-                <td colspan='4' align='center'>
-                    <a href='javascript:void(0);' class='classic_link'>[% l("close") %]</a>
+                    <td valign="top" class="hide_me">
+                   <select id="resultViewSel" name="detail_record_view" >
+                    <option value="0" selected="selected">Simple View</option>
+                    <option value="1">Detail View</option>
+                   </select>
                 </td>
-            </tr>
-        </tbody>
-    </table>
-    <div id='adv_marc_submit' class='adv_quick_search_submit'>
-        <a style='margin-right: 4px; position:relative;top:-10px;'
-            class='classic_link' href='javascript:advAddMARC();'>[% l("Add Row") %]</a>
-        <!-- XXX TODO make a real form, and make a real submitter (FKA
-        advMARCRun()) -->
-        <img alt="Search" src="[% ctx.media_prefix %]/images/search_btn.gif" class='pointer' />
-    </div>
-</div>
-
-[% IF ctx.is_staff %]
-       <script type="text/javascript" src="/js/ui/default/conify/global/config/search_settings.js"></script>
-       <script type="text/javascript">
-       
-       var selects = document.getElementsByTagName("select");
-
-       var langSel = document.getElementById("adv_global_language_basic"); 
-       var audnSel = document.getElementById("adv_global_audience_basic");  
-       var typeSel = document.getElementById("adv_global_item_type_basic");  
-       var pubdateSel = document.getElementById("adv_global_pub_date_type"); 
-       var orgSel = document.getElementById("org_selector"); 
-       var sortBySel = document.getElementById("opac.result.sort"); 
-       var resultViewSel = document.getElementById("resultViewSel");
-       var modCheck = document.getElementById("opac.result.limit2avail");
-       var templateSel = document.getElementById("templateList"); 
-               
+            [% END %]
+        </tr>
 
-               getSearchStash();
-
-               populateTemplateOptions(templateList);
-               if (template)
-               {
-                       selectOptionValue(templateSel, template.name);
-                       populateSearchOptions(template);
-               }
-       </script>
-[% END %]
+        <tr class='border_4_2'>
+            <td align="left" colspan='2'>
+                <input type="hidden" name="_adv" value="1" />
+                    <span>
+                        <input type="image" src="[% ctx.media_prefix %]/images/search_btn.gif"
+                            alt="[% l('Search') %]" class='pointer' />
+                            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+                        <img id='search-submit-spinner' src='/opac/images/progressbar_green.gif' style='height:16px;width:16px;' class='hidden' alt=''/>
+                    </span>
 
+                    [% IF ctx.is_staff && search.allow_templates == 'true' %]
+                    <a onclick="clearAll()"
+                    [% ELSE %]
+                    <a href="[% mkurl(ctx.opac_root _ '/advanced', {$loc_name => loc_value}, 1) %]"
+                    [% END %]
+                        class="pointer opac-button">[% l('Clear Form') %]</a>
+                  </td>
+              </tr>
+    </table>
+</form>
 
+[% IF ctx.is_staff && search.allow_templates == 'true' %]
+<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/opac/staff.js"></script>
+<script type="text/javascript" src="/xul/server/OpenILS/global_util.js"></script>
+<script type="text/javascript" src="/js/ui/default/opac/simple.js"></script>
+<script type="text/javascript" src="/xul/server/main/constants.js"></script>
+<script type="text/javascript" src="/xul/server/main/JSAN.js"></script>
+<script type="text/javascript" src="/js/ui/kcls/conify/global/config/search_templates.js"></script>
+<script type="text/javascript">
+    var pubdateSel = $("adv_global_pub_date_type");
+    var orgSel = document.getElementById("org_selector");
+    var sortBySel = document.getElementById("opac.result.sort");
+    var resultViewSel = document.getElementById("resultViewSel");
+    var modCheck = document.getElementById("opac.result.limit2avail");
+    var templateSel = document.getElementById("templateList");
+    var filterTable = document.getElementById("filterTable");
+    var searchFilters = filterTable.getElementsByTagName("select");
+    getSearchStash();
+    
+    populateTemplateOptions(templateList);
+    if (template)
+    {
+        selectOptionValue(templateSel, template.name);
+        populateSearchOptions(template);
+    }
+</script>
+[% END %]
\ No newline at end of file
index 696a99d..caff294 100644 (file)
@@ -6,6 +6,15 @@
 ##############################################################################
 
 ##############################################################################
+# Holds blocking
+##############################################################################
+# Prevent the "Place hold" link from being displayed if a copy is available.
+# This is not perfect, given the umpteen different types of holds that are
+# possible, but addresses the major use case for libraries that don't want
+# to fetch copies from the shelves.
+ctx.holds_block.enabled = 'false';
+
+##############################################################################
 # RefWorks configuration
 ##############################################################################
 # RefWorks is a Web-based citation manager
@@ -47,6 +56,22 @@ google_analytics.code = 'UA-9999999-99';
 reset_password = 'true';
 
 ##############################################################################
+# Hide various options from user preferences that you might not want to expose
+# if you rely on centralized authentication via open-ils.auth_proxy, like LDAP
+#
+# Username changes can be disabled by the opac.lock_usernames OU setting.
+##############################################################################
+disable_password_change = 'false';
+disable_email_change = 'false';
+
+##############################################################################
+# Some libraries do not do notifications by phone; if not true, then this
+# hides the user preference for phone notifications as well as the phone
+# notification portion of the hold dialogue
+##############################################################################
+allow_phone_notifications = 'true';
+
+##############################################################################
 # Misc. UI Settings
 ##############################################################################
 
@@ -56,16 +81,90 @@ reset_password = 'true';
 # Options are "small", "medium", and "large"
 record.summary.jacket_size = 'medium';
 
+
 ##############################################################################
 # Define the order in which facets are displayed.  Only facets listed here 
 # will be displayed.  To show all facets sorted by name, comment out this 
 # setting.  
 # facet.display = [] # show no facets
 facet.display = [
-    {facet_class => 'subject',    facet_order => ['complete']}
-    {facet_class => 'series',     facet_order => ['seriestitle']},
-    {facet_class => 'identifier', facet_order => ['mattype']},
+    {facet_class => 'author',  facet_order => ['personal', 'corporate']},
+    {facet_class => 'subject', facet_order => ['topic']},
+    {facet_class => 'series',  facet_order => ['seriestitle']},
+    {facet_class => 'subject', facet_order => ['name', 'geographic']}
 ];
+facet.default_display_count = 5;
+
+##################
+## KCLS settings from 2.2 
+#facet.display = [
+#    {facet_class => 'subject',    facet_order => ['complete']}
+#    {facet_class => 'series',     facet_order => ['seriestitle']},
+#    {facet_class => 'identifier', facet_order => ['mattype']},
+#];
+##################
+
+##############################################################################
+# Define the advanced search limiters and labels.
+# adv_label is the (translated) label for the limiter
+# adv_attr is an array of possible limiters, the first one that has any
+#   values will be used
+# adv_filter is the same as adv_attr, but for search filter groups
+# adv_break will end the current row. If specified with a label/attr it
+#   will do so *after* that limiter.
+# adv_special will drop in a special entry:
+#   lib_selector will put the search library box (with limit to available)
+#   pub_year will put the publication year box
+#   sort_selector will put the sort results selector
+
+search.adv_config = [
+    {adv_label => l("Item Type"), adv_attr => ["mattype", "item_type"]},
+#   {adv_label => l("Item Form"), adv_attr => "item_form"},
+    {adv_label => l("Language"),  adv_attr => "item_lang"},
+    {adv_label => l("Audience"),  adv_attr => ["audience_group", "audience"]},
+    {adv_label => l("Sort Results"), adv_special => "sort_selector", adv_break => 1},
+#   {adv_label => l("Video Format"), adv_attr => "vr_format"},
+#   {adv_label => l("Bib Level"), adv_attr => "bib_level"},
+#   {adv_label => l("Literary Form"), adv_attr => "lit_form", adv_break => 1},
+    {adv_label => l("Search Library"), adv_special => "lib_selector"},
+    {adv_label => l("Publication Year"), adv_special => "pub_year"},
+];
+
+##############################################################################
+# For each search box the default "query type" value can be specified here
+# This is the actual backend value, not the label
+# Also note that including more than the row count entries won't add rows
+# The first entry should be used as a default for "basic" search as well
+
+search.default_qtypes = ['keyword','title','author'];
+
+##############################################################################
+# Basic Search Box definition
+# This allows selection of what, exactly, basic search uses for a selection
+# box. Previously it was hardcoded to use an attr box of mattype or item_type.
+#
+# type can be "attr" or "filter"
+# group is the attr or filter entries you want to check for
+# none_label is the label for the default nothing selected entry.
+
+search.basic_config = {
+    type => 'attr',
+    group => ['mattype','item_type'],
+    none_label => l("All Formats"),
+};
+
+##############################################################################
+# Show Google Book Previews
+# Set to 1 or 'true' to enable
+ctx.google_books_preview = 0;
+
+##############################################################################
+# This will allow the display and use of a Search Template dropdown that
+# staff may use to select often used searches. Upon selection of a Template, the
+# Advanced Search page's Global Rows and Search Filters will populate according
+# to the Template. Templates are configurable at
+# Admin->WorkStation Administraion->Search Templates
 
+search.allow_templates = 'true';
 
 %]
index 49a1714..a1dbb94 100644 (file)
@@ -1,9 +1,96 @@
 [% 
+    # Support multiscript records via alternate graphic 880 fields
+    # get_graphic_880s(target_field='100')
+    # See "Model A" in http://www.loc.gov/marc/bibliographic/ecbdmulti.html
+    # and $6 description in http://www.loc.gov/marc/bibliographic/ecbdcntf.html
+    MACRO get_graphic_880s BLOCK;
+        FOR node IN xml.findnodes('//*[@tag="' _ target_field _ '"]');
+            raw_vals = [];
+            core_val = '';
+            FOR subnode IN node.findnodes('./*[not(contains("w 0 4 5 6 8 9", @code))]');
+                raw_vals.push(subnode.textContent());
+            END;
+            core_val = raw_vals.join(" ");
+            raw_vals = [];
+
+            linked_fields = [];
+            FOR sub IN node.findnodes('./*[@code="6"]');
+                linked_fields.push(sub.textContent);
+            END;
+            graphics = [];
+            get_linked_880s;
+            graphic_880s.push({
+                primary => {"occur" => occurrence, "value" => core_val},
+                graphic => graphics
+            });
+        END;
+    END;
+
+    MACRO get_linked_880s BLOCK;
+        FOR link_field IN linked_fields;
+            target = target_field _ link_field.substr(3);
+            # Get the linked 880 value
+            raw_val = '';
+            dir = '';
+            occurrence = '';
+            script = '';
+            FOR node IN xml.findnodes('//*[@tag="880"]');
+                # Operate only on the target linked fields
+                FOR linknode IN node.findnodes('./*[@code="6"]');
+                    lf = linknode.textContent();
+                    IF lf.substr(0, target.length) == target;
+                        occurrence = lf.substr(4, 2);
+                        rawscript = lf.substr(7, 2);
+                        SWITCH rawscript;
+                        CASE '(3';
+                            script = 'Arabic';
+                        CASE '(B';
+                            script = 'Latin';
+                        CASE '$1';
+                            script = 'CJK';
+                        CASE '(N';
+                            script = 'Cyrillic';
+                        CASE '(S';
+                            script = 'Greek';
+                        CASE '(2';
+                            script = 'Hebrew';
+                        END;
+
+                        rawdir = lf.substr(9, 1);
+                        SWITCH rawdir;
+                        CASE 'r';
+                            dir = 'rtl';
+                        END;
+
+                        raw_vals = [];
+                        FOR subnode IN node.findnodes('./*[not(contains("w 0 5 6 8 9", @code))]');
+                            raw_vals.push(subnode.textContent());
+                        END;
+                        raw_val = raw_vals.join(" ");
+                    END;
+                END;
+            END;
+            graphics.push({
+                occur => occurrence,
+                value => raw_val,
+                script => script,
+                dir => dir
+            });
+        END;
+    END;
+
     # Extract MARC fields from XML
     #   get_marc_attrs( { marc_xml => doc } )
     BLOCK get_marc_attrs;
         xml = args.marc_xml;
-               
+
+        # Map item types to schema.org types; impedance mismatch :(
+        args.schema.itemtype = {};
+        schema_typemap = {};
+        schema_typemap.a = 'http://schema.org/Book';
+        schema_typemap.e = 'http://schema.org/Map';
+        schema_typemap.j = 'http://schema.org/MusicAlbum';
+
         args.isbns = [];
         FOR isbn IN xml.findnodes('//*[@tag="020"]/*[@code="a"]');
             args.isbns.push(isbn.textContent);
             args.upcs.push(upc.textContent);
         END;
         args.upc = args.upcs.0; # use first UPC as the default
-        args.issn = xml.findnodes('//*[@tag="022"]/*[@code="a"]').textContent;
-        
-               titresults = xml.findnodes('//*[@tag="245"]/*[@code="a" or @code="b" or @code="n" or @code="p"]');
+
+        args.issns = [];
+        FOR sub IN xml.findnodes('//*[@tag="022"]/*[@code="a"]');
+            args.issns.push(sub.textContent);
+        END;
+        args.issn = (args.issns.size) ? args.issn.0 : '';
+
+        graphic_880s = [];
+        get_graphic_880s(target_field='100');
+        get_graphic_880s(target_field='110');
+        get_graphic_880s(target_field='111');
+        args.graphic_authors = graphic_880s;
+        args.authors = [];
+        FOR author IN args.graphic_authors;
+            args.authors.push(author.primary.value);
+        END;
+        args.author = (args.authors.size) ? args.authors.0 : '';
+
+        # Include subfields 'abnp' to generate a more comprehensive title display in search results
+        titresults = xml.findnodes('//*[@tag="245"]/*[@code="a" or @code="b" or @code="n" or @code="p"]');
         titresults_content = [];
-            FOR sub IN titresults; 
-                               titresults_content.push(sub.textContent); 
-                       END;
-        attrs.title = titresults_content.join(" ");    
-               attrs.title = attrs.title | replace('[:;/,]$', '');
-               
-               args.title_extended = '';
-        FOR node IN xml.findnodes('//*[@tag="245"]/*'); 
-            args.title_extended = args.title_extended _ ' ' _ node.textContent;
-        END;
-               
-        args.author = xml.findnodes('//*[@tag="100"]/*[@code="a"]').textContent || xml.findnodes('//*[@tag="110"]/*[@code="a"]').textContent || '';
-               
-               args.publishers = xml.findnodes('//*[@tag="260"]/*[@code="b"]') 
-                                               || xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="b"]') 
-                                               || '';
-               args.publishers_content = [];
-               FOR sub IN args.publishers;
-                       args.publishers_content.push(sub.textContent);
-        END;
-               args.publisher = (args.publishers_content.size) ? args.publishers_content.0 : '';
-
-               args.pubdates = xml.findnodes('//*[@tag="260"]/*[@code="c"]');
-               args.pubdates_content = [];
-               IF args.pubdates;
-                       FOR sub IN args.pubdates;
-                               args.pubdates_content.push(sub.textContent);
-                       END;
-               ELSE;
-                       args.pubdates = xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="c"]');
-                       args.pubdates_content = [];
-                       FOR sub IN args.pubdates;
-                               args.pubdates_content.push(sub.textContent);
-                       END;
-                       IF args.pubdates;
-                               args.copyright = xml.findnodes('//*[@tag="264" and @ind2="4"]/*[@code="c"]').textContent || '';
-                       END;
-               END;
-               args.pubdate = (args.pubdates_content.size) ? args.pubdates_content.0 : '';
-               
-        args.edition = xml.findnodes('//*[@tag="250"]/*[@code="a"]').textContent ||
-            xml.findnodes('//*[@tag="534"]/*[@code="b"]').textContent ||
-            xml.findnodes('//*[@tag="775"]/*[@code="b"]').textContent;
-        phys = xml.findnodes(
+            FOR sub IN titresults; titresults_content.push(sub.textContent); END;
+        args.title = titresults_content.join(" ");
+        # Avoid ugly trailing syntax on brief titles
+        args.title = args.title | replace('[:;/]$', '');
+
+        graphic_880s = [];
+        get_graphic_880s(target_field='245');
+        args.graphic_titles = graphic_880s;
+        args.titles = [];
+        FOR title IN args.graphic_titles;
+            args.titles.push(title.primary.value);
+        END;
+        args.title_extended = (args.titles.size) ? args.titles.0 : '';
+
+        args.pubplaces = [];
+        pubplace_hunt = xml.findnodes('//*[@tag="260"]/*[@code="a"]') ||
+            xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="a"]');
+        FOR sub IN pubplace_hunt;
+            args.pubplaces.push(sub.textContent);
+        END;
+        args.pubplace = (args.pubplaces.size) ? args.pubplaces.0 : '';
+
+        args.publishers = [];
+        publishers_hunt = xml.findnodes('//*[@tag="260"]/*[@code="b"]') ||
+            xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="b"]');
+        FOR sub IN publishers_hunt;
+            args.publishers.push(sub.textContent);
+        END;
+        args.publisher = (args.publishers.size) ? args.publishers.0 : '';
+
+        args.pubdates = [];
+        pubdates_hunt = xml.findnodes('//*[@tag="260"]/*[@code="c"]') || 
+            xml.findnodes('//*[@tag="264" and @ind2="1"]/*[@code="c"]');
+        FOR sub IN pubdates_hunt;
+            args.pubdates.push(sub.textContent);
+        END;
+        args.pubdate = (args.pubdates.size) ? args.pubdates.0 : '';
+
+        # Full publisher info
+        args.pubinfo = "$args.pubplace $args.publisher $args.pubdate";
+
+        graphic_880s = [];
+        get_graphic_880s(target_field='260');
+        args.graphic_pubinfos = graphic_880s;
+        args.pubinfos = [];
+        FOR pubinfo IN args.graphic_pubinfos;
+            args.pubinfos.push(pubinfo.primary.value);
+        END;
+        args.pubinfo = (args.pubinfos.size) ? args.pubinfos.0 : '';
+
+        args.summaries = [];
+        FOR sub IN xml.findnodes('//*[@tag="520"]/*[@code="a"]');
+            args.summaries.push(sub.textContent);
+        END;
+        args.summary = (args.summaries.size) ? args.summaries.0 : '';
+
+        # 250 gets pride of place for edition statement, and is the
+        # only logical choice for 880 graphic fields
+        graphic_880s = [];
+        get_graphic_880s(target_field='250');
+        args.graphic_editions = graphic_880s;
+        args.editions = [];
+        FOR edition IN args.graphic_editions;
+            args.editions.push(edition.primary.value);
+        END;
+
+        ed_hunt = xml.findnodes('//*[@tag="250"]/*[@code="a"]') ||
+            xml.findnodes('//*[@tag="534"]/*[@code="b"]') ||
+            xml.findnodes('//*[@tag="775"]/*[@code="b"]');
+        FOR sub IN ed_hunt;
+            args.editions.push(sub.textContent);
+        END;
+        args.edition = (args.editions.size) ? args.editions.0 : '';
+
+        phys_content = [];
+        FOR sub IN xml.findnodes(
             '//*[@tag="300"]/*[@code="a" or @code="b" or @code="c" or @code="e"]'
         );
-        phys_content = [];
-        FOR p IN phys; phys_content.push(p.textContent); END;
-        args.phys_desc = phys_content.join("");
-
-        args.contents = xml.findnodes('//*[@tag="505"]').textContent;
-
-        # capture all of the 520a's
-        args.summary = [];
-        FOR s IN xml.findnodes('//*[@tag="520"]/*[@code="a"]');
-            args.summary.push(s.textContent); 
-        END;
-               
-               # Marc CN
-               marcresults = xml.findnodes('//*[@tag="092"]/*[@code="a"]') || xml.findnodes('//*[@tag="099"]/*[@code="a"]');
-               marcresults_content = [];
-            FOR sub IN marcresults; 
-                               marcresults_content.push(sub.textContent); 
-                       END;
-               IF marcresults_content.size;
-                       attrs.marc_cn = marcresults_content.join(" ");
-               ELSE;
-                       attrs.marc_cn = "N/A";
-               END;
-               
+            phys_content.push(sub.textContent);
+        END;
+        args.phys_desc = phys_content.join(" ");
+
+        graphic_880s = [];
+        get_graphic_880s(target_field='505');
+        args.graphic_contents = graphic_880s;
+        FOR content IN args.graphic_contents;
+            args.contents.push(content.primary.value);
+        END;
+        args.content = (args.contents.size) ? args.contents.0 : '';
+
+        # Maintain contents_list in case any custom use was made of it
+        args.contents_list = [];
+        FOR sub IN xml.findnodes('//*[@tag="505"]');
+            args.contents_list.push(sub.textContent);
+        END;
+
+        # MARC Callnumber
+        args.marc_cns = [];
+        FOR sub IN xml.findnodes('//*[@tag="092" or @tag="099"]/*');
+            args.marc_cns.push(sub.textContent);
+        END;
+        args.marc_cn = (args.marc_cns.size ) ? args.marc_cns.0 : '';
+            
+
         # clean up the ISBN
         args.isbn_clean = args.isbns.0.replace('\ .*', '');
 
         # Extract the 856 URLs that are not otherwise represented by asset.uri's
         args.online_res = [];
-        FOR node IN xml.findnodes('//*[@tag="856"]');
+        FOR node IN xml.findnodes('//*[@tag="856" and @ind1="4" and (@ind2="0" or @ind2="1")]');
             IF node.findnodes('./*[@code="9" or @code="w" or @code="n"]'); NEXT; END; # asset.uri's
-            label = node.findnodes('./*[@code="z"]'); # XXX KCLS => y -> z
-            #notes = node.findnodes('./*[@code="z" or @code="3"]'); # XXX KCLS
+            label = node.findnodes('./*[@code="y"]');
+            notes = node.findnodes('./*[@code="z" or @code="3"]');
             FOR href IN node.findnodes('./*[@code="u"]');
                 NEXT UNLESS href;
                 # it's possible for multiple $u's to exist within 1 856 tag.
                 args.online_res.push({
                     href => href.textContent, 
                     link => (loop.first AND label) ? label.textContent : href.textContent,
-                    #note => (loop.first) ? notes.textContent : '' # XXX KCLS
-                    note => ''
+                    note => (loop.first) ? notes.textContent : ''
                 });
             END;
         END;
-
         args.holdings = [];
-        FOR holding IN xml.findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]');
-            args.holdings.push(
-                holding.getAttribute('label')
+        args.uris = [];
+        args.issns = [];
+        args.resolver_isbns = [];
+        args.resolver_issns = [];
+
+        # we use $9 of ISBN and ISSN as a flag for e-version
+        FOR resolver_isbn IN xml.findnodes('//*[@tag="020"]/*[@code="9"]');
+            IF resolver_isbn.textContent == "SFX" || resolver_isbn.textContent == "CUFTS";
+                my_parent = resolver_isbn.parentNode();
+                FOR resolver_isbn_val IN my_parent.findnodes('./*[@code="a"]');
+                    args.resolver_isbns.push(
+                        resolver_isbn_val.textContent.replace('-', '').replace('\ .*', '')
+                    );
+                END;
+            END;
+        END;
+
+        FOR resolver_issn IN xml.findnodes('//*[@tag="022"]/*[@code="9"]');
+            IF resolver_issn.textContent == "SFX" || resolver_issn.textContent == "CUFTS";
+                my_parent = resolver_issn.parentNode();
+                FOR resolver_issn_val IN my_parent.findnodes('./*[@code="a"]');
+                    args.resolver_issns.push(
+                        resolver_issn_val.textContent.replace('[^\d\-X]', '')
+                    );
+                END;
+            END;
+        END;
+
+        # now snag all issns 
+        FOR rawissn IN xml.findnodes('//*[@tag="022"]/*[@code="a"]');
+            args.issns.push(
+                rawissn.textContent.replace('[^\d\-X]', '')
             );
         END;
 
+        ou_hiding_disabled = ctx.org_hiding_disabled();
+
+        FOR volume IN xml.findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]');
+
+            # Check volume visibility - could push this into XPath
+            vol.label = volume.getAttribute('label');
+
+            # Prepend prefix, if any
+            prefix = volume.findnodes('./*[local-name()="call_number_prefix"][@ident!="-1"]');
+            IF prefix.getAttribute('label') != '';
+                vol.label = prefix.getAttribute('label') _ " " _ vol.label;
+            END;
+
+            # Append prefix, if any
+            suffix = volume.findnodes('./*[local-name()="call_number_suffix"][@ident!="-1"]');
+            IF suffix.getAttribute('label') != '';
+                vol.label = vol.label _ " " _ suffix.getAttribute('label');
+            END;
+
+            vol.id = volume.getAttribute('id');
+            NEXT IF volume.getAttribute('opac_visible') == 'false';
+            NEXT IF volume.getAttribute('deleted') == 'true';
+
+            IF vol.label == '##URI##';
+                FOR uri IN volume.findnodes('./*[local-name()="uris"]/*[local-name()="uri"]');
+                    res = {};
+                    res.href = uri.getAttribute('href');
+                    res.link = uri.getAttribute('label');
+                    res.note = uri.getAttribute('use_restriction');
+                    args.uris.push(res);
+                END;
+                NEXT;
+            ELSE;
+                copies = volume.findnodes('./*[local-name()="copies"]/*[local-name()="copy"]');
+                FOR copy IN copies;
+                    parts = copy.findnodes('./*[local-name()="monograph_parts"]/*[local-name()="monograph_part"]');
+                    FOREACH part IN parts;
+                        part_label = part.getAttribute('label');
+                        LAST IF part_label != '';
+                    END;
+                    # Check copy visibility
+                    cp.deleted = copy.getAttribute('deleted');    
+                    cp.visible = copy.getAttribute('opac_visible');
+                    NEXT IF (cp.deleted == 'true' OR cp.visible == 'false');
+
+                    # Iterate through all of the children to determine visibility
+                    FOR node IN cp.childNodes;
+                        NEXT IF cp.visible == 'false';
+                        vis = node.getAttribute('opac_visible');
+                        del = node.getAttribute('deleted');
+                        IF vis == 'false' or del == 'true';
+                            cp.visible = 'false';
+                        END;
+                    END;
+
+                    NEXT IF cp.visible == 'false';
+                    
+                    loc = copy.findnodes('./*[local-name()="location"]');
+                    NEXT IF loc.getAttribute('opac_visible') == 'false';
+
+                    circlib = copy.findnodes('./*[local-name()="circlib"]');
+                    NEXT IF circlib.getAttribute('opac_visible') == 'false';
+
+                    status = copy.findnodes('./*[local-name()="status"]');
+                    NEXT IF status.getAttribute('opac_visible') == 'false';
+
+                    UNLESS ou_hiding_disabled;
+                        # extract the circ_lib id from the circ_lib node
+                        circ_lib = copy.findnodes('./*[local-name()="circ_lib"]');
+                        circ_lib_id = circ_lib.getAttribute('id').replace('.*/', '');
+                        NEXT UNLESS ctx.org_within_hiding_scope(circ_lib_id);
+                    END;
+
+                    holding = {
+                        label => vol.label,
+                        part_label => part_label,
+                        location => loc.textContent,
+                        library => circlib.textContent,
+                        status => status.textContent,
+                        barcode => copy.getAttribute('barcode'),
+                        owner => volume.getAttribute('lib')
+                    };
+                    args.holdings.push(holding);
+                    part_label = '';
+                END;
+            END;
+        END;
+
         # Extract the copy count summary
         count_type = (ctx.is_staff) ? 'staff' : 'public';
+
+        # Consortial copy count summary first
         xpath = '//*[local-name()="counts"]/*[local-name()="count"][@type="' _ count_type _ '"]';
+        args.copy_counts = {};
         FOR node IN xml.findnodes(xpath);
-            args.copy_counts = {};
-            FOR attr IN ['count', 'available', 'unshadow', 'transcendant']; 
-                args.copy_counts.$attr = node.getAttribute(attr);
+            FOR attr IN ['count', 'available', 'unshadow', 'transcendant', 'org_unit']; 
+                depth = node.getAttribute('depth');
+                count_org_unit = node.getAttribute('org_unit');
+                args.copy_counts.$depth.$attr = node.getAttribute(attr);
+                args.org_copy_counts.$count_org_unit.$attr = node.getAttribute(attr);
+            END;
+        END;
+
+        # Get preferred library copy count
+        args.plib_copy_counts = {};
+        count_type = 'pref_lib';
+        xpath = '//*[local-name()="counts"]/*[local-name()="count"][@type="' _ count_type _ '"]';
+        FOR node IN xml.findnodes(xpath);
+            FOR attr IN ['count', 'available', 'unshadow', 'transcendant', 'org_unit']; 
+                depth = node.getAttribute('depth');
+                args.plib_copy_counts.$depth.$attr = node.getAttribute(attr);
             END;
         END;
 
             node = xml.findnodes(
                 '//*[local-name()="attributes"]/*[local-name()="field"][@name="' _ icon_style _ '"]');
             IF node AND node.textContent;
+                type = node.textContent;
                 args.format_label = node.getAttribute('coded-value')
-                args.format_icon = ctx.media_prefix _ '/images/format_icons/' _ icon_style _ '/' _ node.textContent _ '.png';
+                args.schema.itemtype = schema_typemap.$type;
+                args.format_icon = ctx.media_prefix _ '/images/format_icons/' _ icon_style _ '/' _ type _ '.png';
                 LAST;
             END;
         END;
+
     END;
-%]
 
+    # Get the library or location group
+    # get_library()
+    # magically upgrades any use of 'loc' to 'locg', 
+    # which is a superset of 'loc'.
+    BLOCK get_library;
+        loc_name = 'locg';
+        loc_value = CGI.param(loc_name) || CGI.param('loc') || ctx.search_ou;
+    END;
+
+%]
diff --git a/Open-ILS/web/js/ui/kcls/conify/global/config/search_templates.js b/Open-ILS/web/js/ui/kcls/conify/global/config/search_templates.js
new file mode 100644 (file)
index 0000000..c6f6ca9
--- /dev/null
@@ -0,0 +1,427 @@
+
+
+    var g = {};
+    var templateList;
+    var template;
+    var DEFAULT = "--Default--";
+    var myPackageDir = 'open_ils_staff_client';
+
+function getSearchStash() {
+    try
+    {
+        if (typeof JSAN == 'undefined')
+        {
+            throw( document.getElementById("commonStrings").getString('common.jsan.missing') );
+        }
+        JSAN.errorLevel = "die"; // none, warn, or die
+        JSAN.addRepository('/xul/server/');
+        JSAN.use('util.error');
+        g.error = new util.error();
+        g.error.sdump('D_TRACE','getSearchStash() from search_settings.tt2 or search.tt2');
+
+        JSAN.use('OpenILS.data');
+        g.data = new OpenILS.data();
+        g.data.stash_retrieve();
+
+        //populate templateList, or not.
+        if (g.data.search_templates)
+        {
+            templateList = g.data.search_templates;
+
+            //check for current template
+            if (g.data.current_search_template)
+            {
+                template = g.data.current_search_template;
+            }
+        }
+        else
+        {
+            templateList = new Array();
+        }
+    } catch(E) {
+        try { g.error.standard_unexpected_error_alert('search_settings.tt2',E); } catch(F) { alert(E); }
+        return 0;
+    }
+}
+
+//Creates, or edits, a search template based off the currently selected values
+function create_template(tName) {
+    var template;
+    if (!tName || tName == DEFAULT)
+    {
+        alert("That is not a valid name.");
+        return;
+    }
+    template = getTemplateByName(tName, templateList);
+
+    if (template == null)
+    {
+        var isNew = 1;
+        template = new Object();
+        populateTemplate(template);
+        this.template = template;
+        templateList.push(template);
+        templateList.sort(compareTemplateNames)
+    }
+    else
+    {
+        if (confirm("Do you want to overwrite " + template.name + " template?"))
+        {
+            populateTemplate(template);
+            this.template = template;
+        }
+        else
+        { return;}
+    }
+    saveCurrentTemplate( template );
+    saveTemplateList(templateList);
+
+    //Add to templateSel and select if new template
+    if(isNew)
+    {
+        populateTemplateOptions(templateList);
+        selectOptionValue(templateSel, template.name);
+    }
+}
+
+//Returns the selected values of of a given element
+function getSelectedValues(elmnt)   {
+elmntVals = [];
+    var x = 0;
+    for (x=0;x<elmnt.length;x++)
+    {
+        if (elmnt[x].selected)
+        {
+            elmntVals.push(elmnt[x].value);
+        }
+    }
+return elmntVals;
+}
+
+//Select options in element whose values are equal to the values submitted
+function selectOptionValues(elmnt, values){
+    elmnt.selectedIndex = -1;
+    for(var i=0; i < elmnt.options.length; i++)
+    {
+        for (v in values)
+        {
+            if(elmnt.options[i].value == values[v])
+            {
+            elmnt.options[i].selected = true;
+            break;
+            }
+        }
+    }
+}
+
+//Saves templateList to File in JSON format.
+function saveTemplateListToFile( templateList ) {
+    try {
+        JSAN.use('util.file');
+        var file = new util.file('search_templates');
+        file.write_content( 'truncate', String( JSON.stringify(templateList) ) );
+        file.close();
+        alert("Template List has been updated.");
+        } catch(E) {
+            try { g.error.standard_unexpected_error_alert('saving in search_settings.tt2',E); } catch(F) { alert(E); }
+        }
+}
+
+//Saves current template name to file
+function saveCurrentTemplateToFile( template ) {
+    try {
+        JSAN.use('util.file');
+        var file = new util.file('yesterdays_search_template');
+        file.write_content( 'truncate', String( JSON.stringify(template) ) );
+        file.close();
+    } catch(E) {
+        try { g.error.standard_unexpected_error_alert('saving in search_settings.tt2',E); } catch(F) { alert(E); }
+    }
+}
+
+//Populates template dropdown from given template list
+function populateTemplateOptions(templateList)  {
+    templateSel.options.length = 0;
+    templateSel.options[0]= new Option(DEFAULT, "");
+    var len = templateList.length;
+
+    for(var i=1; i<=len; i++)
+    {
+        templateSel.options[i]= new Option(templateList[i-1].name, templateList[i-1].name);
+        if (template && template.name == templateList[i-1].name)
+        {
+            templateSel.options[i].selected= true;
+        }
+    }
+
+}
+//returns template with a given name from templatelist
+function getTemplateByName(templateName, templateList)  {
+    var len = templateList.length;
+
+    for(var i=0; i<len; i++)
+    {
+        if (templateList[i].name == templateName)
+        {
+            return templateList[i];
+        }
+    }
+    return null;
+}
+
+//returns template's index value in templateList with a given name from templatelist
+function getTemplateIndex(templateName, templateList)   {
+    var len = templateList.length;
+
+    for(var i=0; i<len; i++)
+    {
+        if (templateList[i].name == templateName)
+        {
+            return i;
+        }
+    }
+    return null;
+}
+
+//Saves selected values to a search template
+function populateTemplate(template) {
+    template.name = document.getElementById("nameInput").value;
+    template.gRows = getGlobalRowValues();
+    template.advFilters = getFilterValues();
+    template.pubdate = pubdateSel.value;
+    template.org = orgSel.value;
+    template.sort = sortBySel.value;
+    template.view = resultViewSel.value;
+    template.modifier = document.getElementById("modifier").checked;
+}
+
+//returns array containing the selected values of the global rows
+function getGlobalRowValues(){
+    var tBody = document.getElementById("adv_global_tbody");
+    var rows = tBody.getElementsByTagName("tr");
+    var gRows = [];
+    for (var i=0; i<rows.length; i++)
+    {
+        gRows[i] = {};
+        var gSels = rows[i].getElementsByTagName("select");
+        for (var s = 0; s<gSels.length; s++)
+        {
+            gRows[i][gSels[s].name] = gSels[s].value;
+        }
+    }
+    return gRows;
+}
+
+//returns array containing the selected values of the search filters
+function getFilterValues()   {
+    var filters = [];
+    for (var s = 0; s < searchFilters.length; s++)
+    {
+        filters[s] = getSelectedValues(searchFilters[s]);
+    }
+    return filters;
+}
+
+//Select the apropriate search options given a search template
+function populateSearchOptions(template) {
+    setFilterValues(template);
+    selectOptionValue(pubdateSel, template.pubdate);
+    if (template.pubdate == "between")
+        { unHideMe(document.getElementById("adv_global_pub_date_2_span")); }
+    else
+        { hideMe(document.getElementById("adv_global_pub_date_2_span")); }
+
+    selectOptionValue(orgSel, template.org);
+    selectOptionValue(sortBySel, template.sort);
+
+    selectOptionValue(resultViewSel, template.view);
+    modCheck.checked = template.modifier;
+    setGlobalRowValues(template);
+}
+//clears all selects and inputs, except the templateList select
+function clearOptions() {
+    resultViewSel.selectedIndex = 0;
+    modCheck.checked = false;
+    clearGlobalRowValues();
+    clearSearchFilters();
+    hideMe(document.getElementById("adv_global_pub_date_2_span"));
+}
+//removes any selections in the searchFilter table
+function clearSearchFilters() {
+    for (var s = 0; s < searchFilters.length; s++)
+    {
+        if (searchFilters[s].multiple)
+        { searchFilters[s].selectedIndex = -1; }
+        else
+        { searchFilters[s].selectedIndex = 0; }
+    }
+}
+
+//Given a template name, saves template as the current search template if name found in TemplateList
+//Populates options, or not, accordingly
+function selectSearchTemplateOrClear(tName) {
+    template = getTemplateByName(tName, templateList);
+    saveCurrentTemplate( template )
+
+    if (template)
+    {
+        populateSearchOptions(template);
+    } else {
+        clearOptions();
+    }
+}
+//Given a template name, saves template as the current search template if name found in TemplateList
+//Populates options, or not, accordingly. Then clears search text fields
+function selectSearchTemplateOrClearAll(tName)  {
+    selectSearchTemplateOrClear(tName);
+    clearGlobalRowInputs();
+    clearPubDateInputs();
+}
+
+ //Unselects all search options, clears text inputs
+function clearAll()     {
+    clearOptions();
+    clearGlobalRowInputs();
+    clearPubDateInputs();
+}
+
+//Make selections in the "global_row.tt2" according to the given search template
+function setGlobalRowValues(template){
+    var tBody = document.getElementById("adv_global_tbody");
+    var rows = tBody.getElementsByTagName("tr");
+    var gRows = [];
+    for (var i=0; i<rows.length; i++)
+    {
+        var gRowSels = rows[i].getElementsByTagName("select");
+        gRow = template.gRows[i];
+        var qtypeSel;
+        var containsSel;
+        for (var s = 0; s<gRowSels.length; s++)
+        {
+            selectOptionValue(gRowSels[s], gRow[gRowSels[s].name]);
+        }
+    }
+}
+//Sets the values of the adv_attr and adv_filter filters from a template
+function setFilterValues(template) {
+    var t = 0;
+    for (var s = 0; s < searchFilters.length; s++)
+    {
+        //determining adv_attr or adv_filter by checking if select is multiple, there may be a better way...
+        if(searchFilters[s].multiple)
+        {
+            selectOptionValues(searchFilters[s], template.advFilters[t]);
+            t++;
+        }
+    }
+}
+//select the first option in each Select in the "global_row.tt2)
+function clearGlobalRowValues() {
+    var tBody = document.getElementById("adv_global_tbody");
+    var rows = tBody.getElementsByTagName("tr");
+    for (var i=0; i<rows.length; i++)
+    {
+        var gRowSels = rows[i].getElementsByTagName("select");
+        for (var s = 0; s<gRowSels.length; s++)
+        {
+            gRowSels[s].selectedIndex = 0;
+        }
+    }
+}
+
+//Select a single value in an element
+function selectOptionValue(elmnt, value) {
+    for(var i=0; i < elmnt.options.length; i++)
+    {
+        if(elmnt.options[i].value == value)
+        {
+            elmnt.options[i].selected = true;
+            break;
+        }
+    }
+}
+//sort comparator for template names
+function compareTemplateNames(templateA,templateB) {
+    if (templateA.name < templateB.name)
+        { return -1; }
+    if (templateA.name > templateB.name)
+        { return 1; }
+    else
+        { return 0; }
+}
+
+//removes a template from the templateList object
+function deleteTemplatefromTemplateList(tName, templateList) {
+    var index = getTemplateIndex(tName, templateList);
+    templateList.splice(index,1);
+    saveTemplateList(templateList);
+    return templateList;
+}
+
+//Removes template from templateList and saved file if it exists and user wants it deleted
+function removeTemplate(templateList, currentTemplate)  {
+    var tempTemplate = getTemplateByName(textIn.value, templateList);
+    if (tempTemplate)
+    {
+        if(confirm("Are you sure you want to delete Template '" + tempTemplate.name + "'?"))
+        {
+            deleteTemplatefromTemplateList(tempTemplate.name, templateList);
+            populateTemplateOptions(templateList);
+
+            //deleted template is the current template in use
+            if (currentTemplate.name == tempTemplate.name)
+            {
+                saveCurrentTemplate(null);
+                clearOptions();
+                templateSel.selectedIndex = 0;
+            }
+            else
+            {
+                selectOptionValue(templateSel, currentTemplate.name);
+            }
+            textIn.value = "";
+        }
+        else {
+            return;
+        }
+    }
+    else {
+        alert("Template '" + textIn.value + "' does not exist.");
+    }
+}
+//caches templateList and saves to file for posterity
+function saveTemplateList(templateList) {
+    g.data.search_templates = templateList;
+    g.data.stash('search_templates');
+    saveTemplateListToFile(templateList);
+}
+
+//caches template currently in use and saves it to file
+function saveCurrentTemplate(template)  {
+    g.data.current_search_template = template;
+    g.data.stash('current_search_template');
+    saveCurrentTemplateToFile(template)
+}
+
+//clears all global row input fields
+function clearGlobalRowInputs() {
+    var tBody = document.getElementById("adv_global_tbody");
+    if(tBody)
+    {
+        var rows = tBody.getElementsByTagName("tr");
+        if(rows.length > 0)
+        for (var i=0; i<rows.length; i++)
+        {
+            var inputs = rows[i].getElementsByTagName("input");
+            if (inputs.length > 0) {
+                inputs[0].value = '';
+            }
+        }
+    }
+}
+//clears input fields associated with the pubdate
+function clearPubDateInputs()
+    {
+        document.getElementById("adv_global_pub_date_1_input").value = '';
+        document.getElementById("adv_global_pub_date_2_input").value = '';
+    }
index 306f941..78c8b78 100644 (file)
 <!ENTITY staff.server.admin.index.library_configuration "Library Configuration">
 <!ENTITY staff.server.admin.index.maintenance_reports "Maintenance Reports">
 <!ENTITY staff.server.admin.index.fonts_and_sounds "Global Font and Sound Settings">
+<!ENTITY staff.server.admin.index.search_templates "Search Templates">
 <!ENTITY staff.server.admin.index.printer "Printer Settings Editor">
 <!ENTITY staff.server.admin.index.do_not_auto_attempt_print_setting.label "'Do Not Attempt Auto-Print' Setting">
 <!ENTITY staff.server.admin.index.do_not_auto_attempt_print_setting.accesskey "">
index 0295318..e235de1 100644 (file)
@@ -515,8 +515,38 @@ OpenILS.data.prototype = {
         }
         file.close();
 
-        obj.print_list_defaults();
-        obj.data_progress('Default print templates set. ');
+        JSAN.use('util.file'); var file = new util.file('yesterdays_search_template');
+        if (file._file.exists()) {
+            try {
+                var x = file.get_content();
+                if (x && x != "null") {
+                    obj.current_search_template = JSON.parse(x);
+                    obj.stash('current_search_template');
+                    obj.data_progress('Saved current search template retrieved from file. ');
+                }
+            } catch(E) {
+                alert(E);
+            }
+        }
+        file.close();
+
+        JSAN.use('util.file'); var file = new util.file('search_templates');
+        if (file._file.exists()) {
+            try {
+                var x = file.get_content();
+                if (x) {
+                    obj.search_templates = JSON.parse(x);
+                    obj.stash('search_templates');
+                    obj.data_progress('Saved search templates retrieved from file. ');
+                }
+            } catch(E) {
+                alert(E);
+            }
+        }
+        file.close();
+
+
+        obj.print_list_defaults(); obj.data_progress('Default print templates set. ');
         obj.load_saved_print_templates();
         obj.fetch_print_strategy();
         JSAN.use('util.print'); (new util.print()).GetPrintSettings();
index 54248c8..0f983da 100644 (file)
@@ -774,6 +774,12 @@ main.menu.prototype = {
                 ['oncommand'],
                 function(event) { open_admin_page('font_settings.xul', 'menu.cmd_local_admin_fonts_and_sounds.tab', false, event); }
             ],
+            'cmd_local_admin_search_templates' : [
+                ['oncommand'],
+                function(event) {
+                    open_eg_web_page('conify/global/config/search_templates', 'menu.cmd_local_admin_search_templates.tab', event);
+                }
+            ],
             'cmd_local_admin_printer' : [
                 ['oncommand'],
                 function(event) { open_admin_page('printer_settings.xul', 'menu.cmd_local_admin_printer.tab', false, event); }
index 9fe3ded..2e4d8d5 100644 (file)
 
     <!-- local admin menu commands -->
     <command id="cmd_local_admin_fonts_and_sounds" />
+    <command id="cmd_local_admin_search_templates" />
     <command id="cmd_local_admin_printer" />
     <command id="cmd_local_admin_do_not_auto_attempt_print_setting" />
     <command id="cmd_local_admin_closed_dates"
                 <menuitem label="&staff.server.admin.index.printer;" command="cmd_local_admin_printer"/>
                 <menuitem label="&staff.main.menu.admin.template_edit.label;" accesskey="&staff.main.menu.admin.template_edit.accesskey;" command="cmd_print_list_template_edit"/>
                 <menuitem label="&staff.server.admin.index.fonts_and_sounds;" command="cmd_local_admin_fonts_and_sounds"/>
+                <menuitem label="&staff.server.admin.index.search_templates;" command="cmd_local_admin_search_templates"/>
                 <menuitem label="&staff.main.menu.admin.client.search_prefs.label;" command="cmd_search_prefs"/>
                 <menuitem label="&staff.main.menu.admin.client.server_addon_ws_configure.label;" command="cmd_server_addon_ws_configure"/>
                 <menuitem type="checkbox" label="&staff.main.menu.admin.client.copy_editor.copy_location.label;" command="cmd_copy_editor_copy_location_first_toggle"/>
index b16e2a1..d75651e 100644 (file)
@@ -229,6 +229,7 @@ list.dump_extended_format.record_separator==-=-=
 list.line_number=#
 menu.cmd_survey_wizard.inadequate_perm=You are lacking the CREATE_SURVEY permission and/or working locations.
 menu.cmd_local_admin_fonts_and_sounds.tab=Global Font and Sound Settings
+menu.cmd_local_admin_search_templates.tab=Search Templates
 menu.cmd_local_admin_printer.tab=Printer Settings Editor
 menu.cmd_local_admin_do_not_auto_attempt_print_setting.tab='Do Not Attempt Auto-Print' Setting
 menu.cmd_local_admin_closed_dates.tab=Closed Dates Editor