Bug 7400: Add auto-completion on auth_finder

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>
This commit is contained in:
Matthias Meusburger 2012-01-04 15:11:03 +01:00 committed by Paul Poulain
parent c548761bc1
commit 1e7437bbae
6 changed files with 195 additions and 29 deletions

View 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

View File

@ -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,

71
authorities/ysearch.pl Executable file
View File

@ -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";
}

View File

@ -24,11 +24,10 @@
=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) ;
}

View 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" />
@ -17,8 +83,10 @@
<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" />
@ -29,8 +97,10 @@
<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" />
@ -41,7 +111,8 @@
<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>
@ -55,13 +126,14 @@
</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>

View 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">