Bug 7400: Add auto-completion on auth_finder
authorMatthias Meusburger <matthias.meusburger@biblibre.com>
Wed, 4 Jan 2012 14:11:03 +0000 (15:11 +0100)
committerPaul Poulain <paul.poulain@biblibre.com>
Mon, 19 Mar 2012 17:20:30 +0000 (18:20 +0100)
While typing an authority, will automatically propose authorities (similar to
autocompletion for patron search if activated)

Signed-off-by: Jared Camins-Esakov <jcamins@cpbibliography.com>
Tested searching for authorities with and without autocomplete. Note that
this is most useful when used in the "Main entry" box instead of the
"Main entry ($a only)" box.
Signed-off-by: Jared Camins-Esakov <jcamins@cpbibliography.com>
Corrected tabs to spaces in auth-finder-search.inc while resolving merge
conflict.

Signed-off-by: Paul Poulain <paul.poulain@biblibre.com>

C4/Charset.pm
authorities/auth_finder.pl
authorities/ysearch.pl [new file with mode: 0755]
cataloguing/ysearch.pl
koha-tmpl/intranet-tmpl/prog/en/includes/auth-finder-search.inc
koha-tmpl/intranet-tmpl/prog/en/modules/authorities/auth_finder.tt

index a4e6b71..8b69848 100644 (file)
@@ -39,6 +39,7 @@ BEGIN {
         SetUTF8Flag
         SetMarcUnicodeFlag
         StripNonXmlChars
+        nsb_clean
     );
 }
 
@@ -382,6 +383,40 @@ sub StripNonXmlChars {
     return $str;
 }
 
+
+
+=head2 nsb_clean
+
+=over 4
+
+nsb_clean($string);
+
+=back
+
+Removes Non Sorting Block characters
+
+=cut
+sub nsb_clean {
+    my $NSB  = '\x88' ;        # NSB : begin Non Sorting Block
+    my $NSE  = '\x89' ;        # NSE : Non Sorting Block end
+    my $NSB2 = '\x98' ;        # NSB : begin Non Sorting Block
+    my $NSE2 = '\x9C' ;        # NSE : Non Sorting Block end
+    my $C2   = '\xC2' ;        # What is this char ? It is sometimes left by the regexp after removing NSB / NSE
+
+    # handles non sorting blocks
+    my ($string) = @_ ;
+    $_ = $string ;
+    s/$NSB//g ;
+    s/$NSE//g ;
+    s/$NSB2//g ;
+    s/$NSE2//g ;
+    s/$C2//g ;
+    $string = $_ ;
+
+    return($string) ;
+}
+
+
 =head1 INTERNAL FUNCTIONS
 
 =head2 _default_marc21_charconv_to_utf8
index 932886b..a3821ee 100755 (executable)
@@ -137,7 +137,7 @@ if ( $op eq "do_search" ) {
     }
     ( $template, $loggedinuser, $cookie ) = get_template_and_user(
         {
-            template_name   => "authorities/searchresultlist-auth.tmpl",
+            template_name   => "authorities/searchresultlist-auth.tt",
             query           => $query,
             type            => 'intranet',
             authnotrequired => 0,
@@ -168,7 +168,7 @@ if ( $op eq "do_search" ) {
 } else {
     ( $template, $loggedinuser, $cookie ) = get_template_and_user(
         {
-            template_name   => "authorities/auth_finder.tmpl",
+            template_name   => "authorities/auth_finder.tt",
             query           => $query,
             type            => 'intranet',
             authnotrequired => 0,
diff --git a/authorities/ysearch.pl b/authorities/ysearch.pl
new file mode 100755 (executable)
index 0000000..ff6adbb
--- /dev/null
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+# This software is placed under the gnu General Public License, v2 (http://www.gnu.org/licenses/gpl.html)
+
+# Copyright 2011 BibLibre
+#
+# This file is part of Koha.
+#
+# Koha 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.
+#
+# Koha 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.
+#
+# You should have received a copy of the GNU General Public License along
+# with Koha; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+=head1 ysearch.pl
+
+This script allows ajax call for dynamic authorities search
+(used in auth_finder.pl)
+
+=cut
+
+use CGI;
+use Modern::Perl;
+use C4::Context;
+use C4::Charset;
+use C4::AuthoritiesMarc;
+use C4::Auth qw/check_cookie_auth/;
+
+my $query = new CGI;
+
+binmode STDOUT, ":utf8";
+print $query->header( -type => 'text/plain', -charset => 'UTF-8' );
+
+my ( $auth_status, $sessionID ) = check_cookie_auth( $query->cookie('CGISESSID'), { } );
+if ( $auth_status ne "ok" ) {
+    exit 0;
+}
+
+    my $searchstr = $query->param('query');
+    my $searchtype = $query->param('querytype');
+    my @value;
+    given ($searchtype) {
+        when (/^marclist$/)      { @value = (undef, undef, $searchstr); }
+        when (/^mainentry$/)     { @value = (undef, $searchstr, undef); }
+        when (/^mainmainentry$/) { @value = ($searchstr, undef, undef); }
+    }
+    my @marclist  = ($searchtype);
+    my $authtypecode = $query->param('authtypecode');
+    my @and_or    = $query->param('and_or');
+    my @excluding = $query->param('excluding');
+    my @operator  = $query->param('operator');
+    my $orderby   = $query->param('orderby');
+
+    my $resultsperpage = 50;
+    my $startfrom = 0;
+
+    my ( $results, $total ) = SearchAuthorities( \@marclist, \@and_or, \@excluding, \@operator, \@value, $startfrom * $resultsperpage, $resultsperpage, $authtypecode, $orderby );
+    foreach (@$results) {
+       my ($value) = $_->{'summary'};
+        # Removes new lines
+        $value =~ s/<br \/>/ /g;
+        $value =~ s/\n//g;
+       print nsb_clean($value) . "\n";
+    }
index a697ddb..77144e1 100755 (executable)
 
 =cut
 
-use strict;
-
-#use warnings; FIXME - Bug 2505
+use Modern::Perl;
 use CGI;
 use C4::Context;
+use C4::Charset;
 use C4::Auth qw/check_cookie_auth/;
 
 my $input = new CGI;
@@ -59,20 +58,4 @@ while ( my $rec = $sth->fetchrow_hashref ) {
     print nsb_clean($rec->{$field}) . "\n";
 }
 
-sub nsb_clean {
-    my $NSB = '\x88' ;        # NSB : begin Non Sorting Block
-    my $NSE = '\x89' ;        # NSE : Non Sorting Block end
-    my $NSB2 = '\x98' ;        # NSB : begin Non Sorting Block
-    my $NSE2 = '\x9C' ;        # NSE : Non Sorting Block end
-    # handles non sorting blocks
-    my ($string) = @_ ;
-    $_ = $string ;
-    s/$NSB//g ;
-    s/$NSE//g ;
-    s/$NSB2//g ;
-    s/$NSE2//g ;
-    $string = $_ ;
-
-    return($string) ;
-}
 
index 3c7fd41..f412de3 100644 (file)
@@ -1,3 +1,69 @@
+<script type="text/javascript">
+//<![CDATA[
+YAHOO.util.Event.onContentReady("header_search", function() {
+    new function() {
+        // Define a custom formatter function
+        this.fnCustomFormatter = function(oResultItem, sQuery) {
+            var name        = oResultItem[0];
+            var aMarkup = [
+                "<div class=\"sample-result\">",
+                name,
+                "<\/div>"];
+            return (aMarkup.join(""));
+        };
+
+    // marclist
+        this.marclistDS = new YAHOO.widget.DS_XHR("/cgi-bin/koha/authorities/ysearch.pl", ["\n", "\t"]);
+        this.marclistDS.scriptQueryAppend = "op=do_search&type=intranet&and_or=and&operator=contains&orderby=HeadingAsc&querytype=marclist";
+        this.marclistDS.responseType = YAHOO.widget.DS_XHR.TYPE_FLAT;
+        this.marclistDS.maxCacheEntries = 60;
+        this.marclistDS.queryMatchSubset = false;
+
+        var myInput = document.getElementById('value_any');
+        var myContainer = document.getElementById('yvaluecontainermarclist');
+        this.oAutoComp = new YAHOO.widget.AutoComplete(myInput,myContainer,this.marclistDS);
+        this.oAutoComp.queryDelay = 1;
+        this.oAutoComp.formatResult = this.fnCustomFormatter;
+        this.oAutoComp.maxResultsDisplayed = 1000;
+
+
+    // mainentry
+    this.mainentryDS = new YAHOO.widget.DS_XHR("/cgi-bin/koha/authorities/ysearch.pl", ["\n", "\t"]);
+        this.mainentryDS.scriptQueryAppend = "op=do_search&type=intranet&and_or=and&operator=contains&orderby=HeadingAsc&querytype=mainentry";
+        this.mainentryDS.responseType = YAHOO.widget.DS_XHR.TYPE_FLAT;
+        this.mainentryDS.maxCacheEntries = 60;
+        this.mainentryDS.queryMatchSubset = false;
+
+        var myInput = document.getElementById('value_main');
+        var myContainer = document.getElementById('yvaluecontainermainentry');
+        this.oAutoComp = new YAHOO.widget.AutoComplete(myInput,myContainer,this.mainentryDS);
+        this.oAutoComp.queryDelay = 1;
+        this.oAutoComp.formatResult = this.fnCustomFormatter;
+        this.oAutoComp.maxResultsDisplayed = 1000;
+
+
+    // mainmainentry
+    this.mainentryDS = new YAHOO.widget.DS_XHR("/cgi-bin/koha/authorities/ysearch.pl", ["\n", "\t"]);
+        this.mainentryDS.scriptQueryAppend = "op=do_search&type=intranet&and_or=and&operator=contains&orderby=HeadingAsc&querytype=mainmainentry";
+        this.mainentryDS.responseType = YAHOO.widget.DS_XHR.TYPE_FLAT;
+        this.mainentryDS.maxCacheEntries = 60;
+        this.mainentryDS.queryMatchSubset = false;
+
+        var myInput = document.getElementById('value_mainstr');
+        var myContainer = document.getElementById('yvaluecontainermainmainentry');
+        this.oAutoComp = new YAHOO.widget.AutoComplete(myInput,myContainer,this.mainentryDS);
+        this.oAutoComp.queryDelay = 1;
+        this.oAutoComp.formatResult = this.fnCustomFormatter;
+        this.oAutoComp.maxResultsDisplayed = 1000;
+
+
+}
+});
+//]]>
+</script>
+
+
+<span id="header_search">
 <form name="f" method="get" action="auth_finder.pl">
             <input type="hidden" name="op" value="do_search" />
             <input type="hidden" name="type" value="intranet" />
                         <option value="start">starts with</option>
                         <option value="is">is exactly</option>
                     </select>
-                    <input type="text" name="value_mainstr" value="[% value_mainstr |html %]" />
+                    <input id="value_mainstr" style="width:400px;" type="text" name="value_mainstr" value="[% value_mainstr |html %]" />
+                    <div id="yvaluecontainermainmainentry"></div>
                 </li>
+
                 <li>
                     <label for="mainentry">Main entry</label>
                     <input type="hidden" name="marclist" value="mainentry" />
                         <option value="start">starts with</option>
                         <option value="is">is exactly</option>
                     </select>
-                    <input type="text" name="value_main" value="[% value_main |html %]" />
+                    <input id="value_main" style="width:400px;" type="text" name="value_main" value="[% value_main |html %]" />
+                    <div id="yvaluecontainermainentry"></div>
                 </li>
+
                 <li>
                     <label for="marclist">Anywhere</label>
                     <input type="hidden" name="marclist" value="any" />
                         <option value="start">starts with</option>
                         <option value="is">is exactly</option>
                     </select>
-                    <input type="text" name="value_any" value="[% value_any |html %]" />
+                    <input id="value_any" style="width:400px;" type="text" name="value_any" value="[% value_any |html %]" />
+                    <div id="yvaluecontainermarclist"></div>
                 </li>
                 <li>
                     <label for="marclist">Heading match</label>
                     </select>
                     <input type="text" name="value_match" value="[% value_match |html %]" />
                 </li>
-               <li>
-               <label for="orderby">Sort by </label>
-               <select name="orderby" id="orderby">
-                   <option value="">No order</option>
+        <li>
+        <label for="orderby">Sort by </label>
+        <select name="orderby" id="orderby">
+            <option value="">No order</option>
             <option value="HeadingAsc" selected="selected">Heading Ascendant</option>
             <option value="HeadingDsc">Heading Descendant</option>
         </select>
-               </li></ol></fieldset>
+        </li></ol></fieldset>
             <fieldset class="action"> <input type="submit" value="Start search" class="submit" /> <a class="cancel close" href="#">Cancel</a></fieldset>
 </form>
+</span>
index 1c004ad..4945be4 100644 (file)
@@ -4,6 +4,11 @@
 <style type="text/css">
 #custom-doc { width:51.46em;*width:50.17em;min-width:675px; margin:auto; text-align:left; } 
 </style>
+    <script type="text/javascript" src="[% yuipath %]/utilities/utilities.js"></script>
+    <script type="text/javascript" src="[% yuipath %]/datasource/datasource.js"></script>
+    <script type="text/javascript" src="[% yuipath %]/autocomplete/autocomplete-min.js"></script>
+
+
 </head>
 <body>
 <div id="custom-doc" class="yui-t7">