package AutoComplete; $VERSION = '0.10'; use strict; use warnings; =head1 NAME AutoComplete - Google Suggest-compatible autocompletion backend =head1 SYNOPSYS package MyAC; use CGI; use base qw(AutoComplete); my @NAMES = qw(alice bob charlie); MyAC->run; sub expand { my ($self, $query) = @_; # do something to expand the query my $re = qr/^\Q$query\E/i; my @names = grep /$re/, @NAMES; (lc $query, \@names, [], []); } =head1 DESCRIPTION This is a base class for implementing an autocomplete server with the same protocol used by Google Suggest ( http://www.google.com/webhp?complete=1&hl=en ). The front-end JavaScript code is discussed in http://serversideguy.blogspot.com/2004/12/google-suggest-dissected.html . This module is used by creating a subclass, which should override the C method, which takes care of searching for the autocompletion results. =head1 METHODS =over =item $class->run(%args) Run the whole autocompletion process in one fell swoop. Prints everything to standard output, including the HTTP headers. The arguments %args are passed to the constructor. =cut sub run { my $class = shift; my $self = $class->new(@_); print $self->header; print($self->no_js), return unless $self->param('js'); my ($query, $names, $values, $prefix) = $self->expand($self->query); print $self->output($query, $names, $values, $prefix); } =item $class->new(%args) Create a new AutoComplete object. Currently the only argument is C, which should provide a L or CGI-compatible object. If none is provided, a new CGI object is created by default. =cut sub new { my ($class, %args) = @_; my $cgi = $args{cgi} || CGI->new; bless { cgi => $cgi, }, shift; } =item $obj->query Returns the string to be expanded. =cut sub query { shift->param('qu'); } =item $obj->cgi Returns the CGI object being used. =cut sub cgi { shift->{cgi} } =item $obj->param($name) Get a CGI parameter. Just delegates the call to $self->cgi. =cut sub param { shift->cgi->param(@_) } =item $obj->header(%args) Return the HTTP headers. By default delegates to $self->cgi, but it uses the UTF-8 encoding by default. =cut sub header { shift->cgi->header( -charset => 'utf-8', @_ ) } =item $obj->output($query, $names, $values, $prefix) Converts the expanded values into JavaScript, as expected by the calling frontend script. $query is a string; all the other parameters are array refs. =cut sub output { my ($self, $query, $names, $values, $prefix) = @_; my $ret = qq{sendRPCDone(frameElement, "$query", }; $ret .= $self->as_array($names). ", "; $ret .= $self->as_array($values). ", "; $ret .= $self->as_array($prefix). ");\n"; $ret; } =item $obj->expand($query) Provide the autocompleted values for the query. Returns a 4-element list: ($query, $names, $values, $prefix). $query is the query as returned to the frontend script (typically converted to lowercase). $names is an array ref of results. $values is an array ref of values that are usually shown on the right-hand side of the drop-down box in the front end; it is used by Google for the estimated result count. The purpose of $prefix is not certain at this time. =cut sub expand { my ($self, $query) = @_; (lc $query, [],[],[]); } =item $obj->as_array(\@arr) Convert an array ref into a JavaScript Array constructor. Returns a string. =cut sub as_array { my ($self, $a) = @_; 'new Array(' . join(", ", map { qq("$_") } @$a) . ')'; } =item $obj->no_js Returns that message that is returned by the Google backend when the C CGI parameter is not true. =cut sub no_js { print < HTML exit; } =back =head1 SEE ALSO http://www.google.com/webhp?complete=1&hl=en http://serversideguy.blogspot.com/2004/12/google-suggest-dissected.html =head1 AUTHOR Ivan Tubert-Brohman Eitub@cpan.orgE =head1 COPYRIGHT Copyright (c) 2004 Ivan Tubert-Brohman. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The original JavaScript frontend code is Copyright (c) 2004 Google, Inc. Use it at your own risk or write or find a free version. =cut 1;