From d586d9df007a99c3b69e1b01cb1b75944a4ff7b9 Mon Sep 17 00:00:00 2001 From: MichaelDaum Date: Mon, 13 May 2013 14:51:01 +0000 Subject: [PATCH] Item12497: * implemented jquery.autosuggest * removed nonfunctional term sugestion rest handler * removed support for deprecated old autocomplete library * added size parameter to mapToIconFileName * don't remove newlines from stringified texts git-svn-id: http://svn.foswiki.org/trunk/SolrPlugin@16721 0b4bb1d4-4e5a-0410-9cc4-b2b747904278 --- lib/Foswiki/Plugins/SolrPlugin.pm | 19 +- lib/Foswiki/Plugins/SolrPlugin/Autosuggest.pm | 43 ++++ lib/Foswiki/Plugins/SolrPlugin/Base.pm | 10 +- lib/Foswiki/Plugins/SolrPlugin/Config.spec | 8 + lib/Foswiki/Plugins/SolrPlugin/Index.pm | 2 +- lib/Foswiki/Plugins/SolrPlugin/MANIFEST | 3 + lib/Foswiki/Plugins/SolrPlugin/Search.pm | 232 ++++++++++-------- pub/System/SolrPlugin/Makefile | 4 +- .../jquery.autosuggest.uncompressed.css | 60 +++++ .../jquery.autosuggest.uncompressed.js | 113 +++++++++ 10 files changed, 375 insertions(+), 119 deletions(-) create mode 100644 lib/Foswiki/Plugins/SolrPlugin/Autosuggest.pm create mode 100644 pub/System/SolrPlugin/jquery.autosuggest.uncompressed.css create mode 100644 pub/System/SolrPlugin/jquery.autosuggest.uncompressed.js diff --git a/lib/Foswiki/Plugins/SolrPlugin.pm b/lib/Foswiki/Plugins/SolrPlugin.pm index ac1a731..6d53add 100644 --- a/lib/Foswiki/Plugins/SolrPlugin.pm +++ b/lib/Foswiki/Plugins/SolrPlugin.pm @@ -1,6 +1,6 @@ # Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/ # -# Copyright (C) 2009-2012 Michael Daum http://michaeldaumconsulting.com +# Copyright (C) 2009-2013 Michael Daum http://michaeldaumconsulting.com # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -18,8 +18,8 @@ use Foswiki::Func (); use Foswiki::Plugins (); use Error qw(:try); -our $VERSION = '1.10'; -our $RELEASE = '1.10'; +our $VERSION = '1.20'; +our $RELEASE = '1.20'; our $SHORTDESCRIPTION = 'Enterprise Search Engine for Foswiki based on [[http://lucene.apache.org/solr/][Solr]]'; our $NO_PREFS_IN_TOPIC = 1; our $baseWeb; @@ -79,29 +79,28 @@ sub initPlugin { }); - Foswiki::Func::registerRESTHandler('terms', sub { + Foswiki::Func::registerRESTHandler('similar', sub { my $session = shift; my $web = $session->{webName}; my $topic = $session->{topicName}; - return getSearcher($session)->restSOLRTERMS($web, $topic); + return getSearcher($session)->restSOLRSIMILAR($web, $topic); }); - - Foswiki::Func::registerRESTHandler('similar', sub { + Foswiki::Func::registerRESTHandler('autocomplete', sub { my $session = shift; my $web = $session->{webName}; my $topic = $session->{topicName}; - return getSearcher($session)->restSOLRSIMILAR($web, $topic); + return getSearcher($session)->restSOLRAUTOCOMPLETE($web, $topic); }); - Foswiki::Func::registerRESTHandler('autocomplete', sub { + Foswiki::Func::registerRESTHandler('autosuggest', sub { my $session = shift; my $web = $session->{webName}; my $topic = $session->{topicName}; - return getSearcher($session)->restSOLRAUTOCOMPLETE($web, $topic); + return getSearcher($session)->restSOLRAUTOSUGGEST($web, $topic); }); diff --git a/lib/Foswiki/Plugins/SolrPlugin/Autosuggest.pm b/lib/Foswiki/Plugins/SolrPlugin/Autosuggest.pm new file mode 100644 index 0000000..984e3db --- /dev/null +++ b/lib/Foswiki/Plugins/SolrPlugin/Autosuggest.pm @@ -0,0 +1,43 @@ +# Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/ +# +# Copyright (C) 2013 Michael Daum http://michaeldaumconsulting.com +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +package Foswiki::Plugins::SolrPlugin::Autosuggest; + +use strict; +use warnings; + +use Foswiki::Plugins::JQueryPlugin::Plugin (); +our @ISA = qw( Foswiki::Plugins::JQueryPlugin::Plugin ); + +sub new { + my $class = shift; + + my $this = bless( + $class->SUPER::new( + name => 'Autosuggest', + version => '1.10', + author => 'Michael Daum', + homepage => 'http://foswiki.org/Extensions/SolrPlugin', + css => ['jquery.autosuggest.css'], + javascript => ['jquery.autosuggest.js', ], + puburl => '%PUBURLPATH%/%SYSTEMWEB%/SolrPlugin', + dependencies => ['ui::autocomplete', 'tmpl', 'blockUI'], + ), + $class + ); + + return $this; +} + +1; + diff --git a/lib/Foswiki/Plugins/SolrPlugin/Base.pm b/lib/Foswiki/Plugins/SolrPlugin/Base.pm index 45cf158..566e8f8 100644 --- a/lib/Foswiki/Plugins/SolrPlugin/Base.pm +++ b/lib/Foswiki/Plugins/SolrPlugin/Base.pm @@ -1,6 +1,6 @@ # Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/ # -# Copyright (C) 2009-2012 Michael Daum http://michaeldaumconsulting.com +# Copyright (C) 2009-2013 Michael Daum http://michaeldaumconsulting.com # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -351,7 +351,9 @@ sub putBackBlocks { ############################################################################## sub mapToIconFileName { - my ($this, $type) = @_; + my ($this, $type, $size) = @_; + + $size ||= 16; my $pubUrlPath = $Foswiki::cfg{PubUrlPath}.'/'.$Foswiki::cfg{SystemWebName}.'/FamFamFamSilkIcons/'; @@ -361,7 +363,7 @@ sub mapToIconFileName { if (Foswiki::Func::getContext()->{MimeIconPluginEnabled}) { require Foswiki::Plugins::MimeIconPlugin; - my ($iconName, $iconPath) = Foswiki::Plugins::MimeIconPlugin::getIcon($type, "oxygen", 16); + my ($iconName, $iconPath) = Foswiki::Plugins::MimeIconPlugin::getIcon($type, "oxygen", $size); return $iconPath; } @@ -430,6 +432,7 @@ sub getTopicSummary { my $charset = $Foswiki::cfg{Site}{CharSet}; $summary = Encode::decode($charset, $summary); $summary = $this->plainify($summary, $web, $topic, 1); + $summary =~ s/\n/ /g; $summary = Encode::encode($charset, $summary); return $summary; @@ -514,7 +517,6 @@ sub plainify { $text =~ s/#+//g; $text =~ s/\$perce?nt//g; $text =~ s/\$dollar//g; - $text =~ s/\n/ /g; $text =~ s/~~~/ /g; $text =~ s/^$//gs; diff --git a/lib/Foswiki/Plugins/SolrPlugin/Config.spec b/lib/Foswiki/Plugins/SolrPlugin/Config.spec index 1d6dbff..7113506 100644 --- a/lib/Foswiki/Plugins/SolrPlugin/Config.spec +++ b/lib/Foswiki/Plugins/SolrPlugin/Config.spec @@ -116,4 +116,12 @@ $Foswiki::cfg{SolrPlugin}{SupportedLanguages} = { 'uk' => 'detect', }; +# ---++ JQueryPlugin +# ---+++ Extra plugins +# **STRING** +$Foswiki::cfg{JQueryPlugin}{Plugins}{Autosuggest}{Module} = 'Foswiki::Plugins::SolrPlugin::Autosuggest'; + +# **BOOLEAN** +$Foswiki::cfg{JQueryPlugin}{Plugins}{Autosuggest}{Enabled} = 1; + 1; diff --git a/lib/Foswiki/Plugins/SolrPlugin/Index.pm b/lib/Foswiki/Plugins/SolrPlugin/Index.pm index 60c8f9f..05d1781 100644 --- a/lib/Foswiki/Plugins/SolrPlugin/Index.pm +++ b/lib/Foswiki/Plugins/SolrPlugin/Index.pm @@ -556,7 +556,7 @@ sub indexTopic { if (!defined $thumbnail && $attachment->{isthumbnail}) { $thumbnail = $name; } - if (!defined $firstImage && $name =~ /(png|jpe?g|gif|bmp$)/i) { + if (!defined $firstImage && $name =~ /\.(png|jpe?g|gif|bmp|svg)$/i) { $firstImage = $name; } diff --git a/lib/Foswiki/Plugins/SolrPlugin/MANIFEST b/lib/Foswiki/Plugins/SolrPlugin/MANIFEST index bd3e1ec..6214d08 100644 --- a/lib/Foswiki/Plugins/SolrPlugin/MANIFEST +++ b/lib/Foswiki/Plugins/SolrPlugin/MANIFEST @@ -29,6 +29,7 @@ lib/WebService/Solr/Field.pm 0644 lib/WebService/Solr.pm 0644 lib/WebService/Solr/Query.pm 0644 lib/WebService/Solr/Response.pm 0644 +lib/Foswiki/Plugins/SolrPlugin/Autosuggest.pm 0644 locale/SolrPlugin/de.po 0644 locale/SolrPlugin/Foswiki.pot 0644 pub/System/SolrPlugin/ajax-solr/ASL-LICENSE 0644 @@ -64,6 +65,8 @@ pub/System/SolrPlugin/ajax-solr-widgets.js.gz 0644 pub/System/SolrPlugin/ajax-solr-widgets.uncompressed.js 0644 pub/System/SolrPlugin/ajax-solr/widgets/yui/ParameterYUIStore.js 0644 pub/System/SolrPlugin/Makefile 0644 +pub/System/SolrPlugin/jquery.autosuggest.uncompressed.css 0644 +pub/System/SolrPlugin/jquery.autosuggest.uncompressed.js 0644 pub/System/SolrPlugin/pattern.css 0644 pub/System/SolrPlugin/pattern.css.gz 0644 pub/System/SolrPlugin/pattern.uncompressed.css 0644 diff --git a/lib/Foswiki/Plugins/SolrPlugin/Search.pm b/lib/Foswiki/Plugins/SolrPlugin/Search.pm index 3823c23..3098b02 100644 --- a/lib/Foswiki/Plugins/SolrPlugin/Search.pm +++ b/lib/Foswiki/Plugins/SolrPlugin/Search.pm @@ -1,6 +1,6 @@ # Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/ # -# Copyright (C) 2009-2011 Michael Daum http://michaeldaumconsulting.com +# Copyright (C) 2009-2013 Michael Daum http://michaeldaumconsulting.com # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -22,6 +22,7 @@ use Foswiki::Plugins (); use Foswiki::Plugins::JQueryPlugin (); use POSIX (); use Error qw(:try); +use JSON (); use constant DEBUG => 0; # toggle me #use Data::Dumper (); @@ -255,7 +256,7 @@ HERE } my $itemFormat = 'attachment'; - $itemFormat = 'image' if $type =~ /^(gif|jpe?g|png|bmp)$/i; + $itemFormat = 'image' if $type =~ /^(gif|jpe?g|png|bmp|svg)$/i; $itemFormat = 'topic' if $type eq 'topic'; $itemFormat = 'comment' if $type eq 'comment'; $line =~ s/\$format/$itemFormat/g; @@ -660,6 +661,128 @@ sub getFirstUrl { return $url; } +############################################################################## +sub restSOLRAUTOSUGGEST { + my ($this, $theWeb, $theTopic) = @_; + + return '' unless defined $this->{solr}; + my $query = Foswiki::Func::getCgiQuery(); + + my $theQuery = $query->param('term') || '*'; + $theQuery .= '*' if $theQuery !~ /\*$/ && $theQuery !~ /:/; + + my $theRaw = Foswiki::Func::isTrue($query->param('raw')); + + my $theLimit = $query->param('limit'); + $theLimit = 5 unless defined $theLimit; + + my $theFields = $query->param('fields'); + $theFields = "name,web,topic,container_title,title,thumbnail,url,score,type" unless defined $theFields; + + my $wikiUser = Foswiki::Func::getWikiName(); + + my @filter = (); + + push @filter, "-web:_*"; # SMELL + + push(@filter, "(access_granted:$wikiUser OR access_granted:all)") + unless Foswiki::Func::isAnAdmin($wikiUser); + + my $userForm = $Foswiki::cfg{PersonDataForm} || $Foswiki::cfg{Ldap}{PersonDataForm} || 'UserForm'; + + my $personTopicFilter = "form:*$userForm"; + my $topicFilter = "-form:*$userForm type:topic"; + my $attachmentFilter = "-type:topic"; + + my %params = ( + q => $theQuery, + qt => "edismax", + indent => "true", + group => "true", + fl => $theFields, + "group.sort" => "score desc", + "group.limit" => $theLimit, + "group.query" => [ + $personTopicFilter, + $topicFilter, + $attachmentFilter, + ], + fq => @filter, + ); + + my $theQueryFields = $query->param('queryfields'); + $params{qf} = [split(/\s*,\s*/, $theQueryFields)] + if defined $theQueryFields; + + my $response = $this->solrSearch($theQuery, \%params); + + my $result = ''; + my $status = 200; + my $contentType = "application/json; charset=$Foswiki::cfg{Site}{CharSet}"; + + try { + if ($theRaw) { + $result = $response->raw_response->content(); + } else { + $result = $response->content(); + } + } catch Error::Simple with { + $result = "Error parsing response: ".$response->raw_response->content(); + $status = 500; + $contentType = "text/plain"; + }; + + if ($status == 200 && !$theRaw) { + my @autoSuggestions = (); + + # person topics + if (defined $result->{grouped}{$personTopicFilter}) { + foreach my $doc (@{$result->{grouped}{$personTopicFilter}{doclist}{docs}}) { + $doc->{thumbnail} = $Foswiki::cfg{PubUrlPath}."/".$Foswiki::cfg{SystemWebName}."/JQueryPlugin/images/nobody.gif" + unless defined $doc->{thumbnail}; + $doc->{_section} = 'persons'; + $doc->{value} = $doc->{title}; # TODO + push @autoSuggestions, $doc; + } + } + + # normal topics + if (defined $result->{grouped}{$topicFilter}) { + foreach my $doc (@{$result->{grouped}{$topicFilter}{doclist}{docs}}) { + $doc->{thumbnail} = $this->mapToIconFileName("unknown", 48) + unless defined $doc->{thumbnail}; + $doc->{_section} = 'topics'; + $doc->{value} = $doc->{title}; # TODO + push @autoSuggestions, $doc; + } + } + + # attachments + if (defined $result->{grouped}{$attachmentFilter}) { + foreach my $doc (@{$result->{grouped}{$attachmentFilter}{doclist}{docs}}) { + unless (defined $doc->{thumbnail}) { + if ($doc->{type} =~ /^(gif|jpe?g|png|bmp|svg)$/i) { + $doc->{thumbnail} = $doc->{name}; + } else { + my $ext = $doc->{name}; + $ext =~ s/^.*\.([^\.]+)$/$1/g; + $doc->{thumbnail} = $this->mapToIconFileName($ext, 48); + } + } + $doc->{_section} = 'attachments'; + $doc->{value} = $doc->{title}; # TODO + push @autoSuggestions, $doc; + } + } + + $result = JSON::to_json(\@autoSuggestions, {utf8=>1, pretty=>1}); + } + + $this->{session}->{response}->status($status); + $this->{session}->{response}->header(-type=>$contentType); + + return $result; +} ############################################################################## sub restSOLRAUTOCOMPLETE { @@ -668,10 +791,8 @@ sub restSOLRAUTOCOMPLETE { return '' unless defined $this->{solr}; my $query = Foswiki::Func::getCgiQuery(); - my $isNewAutocomplete = ($Foswiki::Plugins::JQueryPlugin::RELEASE > 4.10)?1:0; - my $theRaw = Foswiki::Func::isTrue($query->param('raw')); - my $theQuery = $query->param($isNewAutocomplete?'term':'q') || ''; + my $theQuery = $query->param('term') || ''; my $theFilter = $query->param('filter'); my $theEllipsis = Foswiki::Func::isTrue($query->param('ellipsis')); my $thePrefix; @@ -683,7 +804,6 @@ sub restSOLRAUTOCOMPLETE { unless Foswiki::Func::isAnAdmin($wikiUser); # tokenize here as well to separate query and prefix - $theQuery =~ s/[\!"ยง\$%&\/\(\)=\?{}\[\]\*\+~#',\.;:\-_]/ /g; $theQuery =~ s/([$Foswiki::regex{lowerAlpha}])([$Foswiki::regex{upperAlpha}$Foswiki::regex{numeric}]+)/$1 $2/go; $theQuery =~ s/([$Foswiki::regex{numeric}])([$Foswiki::regex{upperAlpha}])/$1 $2/go; @@ -741,22 +861,13 @@ sub restSOLRAUTOCOMPLETE { $title =~ s/$thePrefix $theQuery/.../; } my $line; - if ($isNewAutocomplete) { - # jquery-ui's autocomplete takes a json - $line = "{\"value\":\"$key\", \"label\":\"$title\", \"frequency\":$freq}"; - } else { - # old jquery.autocomplete takes proprietary format - $line = "$key|$title|$freq"; - } + + $line = "{\"value\":\"$key\", \"label\":\"$title\", \"frequency\":$freq}"; push(@result, $line); } } - if ($isNewAutocomplete) { - return "[\n".join(",\n ", @result)."\n]"; - } else { - return join("\n", @result)."\n\n"; - } + return "[\n".join(",\n ", @result)."\n]"; } ############################################################################## @@ -868,91 +979,6 @@ sub doSimilar { return $this->solrRequest('mlt', $solrParams); } -############################################################################## -sub restSOLRTERMS { - my ($this, $theWeb, $theTopic) = @_; - - return '' unless defined $this->{solr}; - my $query = Foswiki::Func::getCgiQuery(); - - my $theRaw = Foswiki::Func::isTrue($query->param('raw')); - - # TODO: distinguish new and old autocomplete - my $isNewAutocomplete = ($Foswiki::Plugins::JQueryPlugin::RELEASE > 4.10)?1:0; - my $theQuery = $query->param($isNewAutocomplete?'term':'q') || ''; - - my $theFields = $query->param('fields') || ''; - my $theField = $query->param('field'); - my $theEllipsis = Foswiki::Func::isTrue($query->param('ellipsis')); - my $theLength = $query->param('length') || 0; - - if (defined $theLength) { - $theLength =~ s/[^\d]//g; - } - $theLength ||= 0; - - my @fields = split(/\s*,\s*/, $theFields); - push(@fields, $theField) if defined $theField; - push(@fields, 'catchall') unless @fields; - - my $wikiUser = Foswiki::Func::getWikiName(); - my $solrParams = { - "terms" => 'true', - "terms.fl" => \@fields, - "terms.mincount" => 1, - "terms.limit" => ($query->param('limit') || 10), - "terms.lower" => $theQuery, - "terms.prefix" => $theQuery, - "terms.lower.incl" => 'false', - "indent" => 'true', - }; - - $solrParams->{"fq"} = "(access_granted:$wikiUser OR access_granted:all)" - unless Foswiki::Func::isAnAdmin($wikiUser); - - my $response = $this->solrRequest('terms', $solrParams); - #$this->log($response->raw_response->content()) if DEBUG; - - my %struct = (); - try { - %struct = @{$response->content->{terms}}; - } catch Error::Simple with { - # ignore - }; - my @result = (); - foreach my $field (keys %struct) { - while (my $term = shift @{$struct{$field}}) { - my $freq = shift @{$struct{$field}}; - my $title = $term; - - my $strip = $theQuery; - my $hilite = $theQuery; - if ($theLength) { - $strip = substr($theQuery, 0, -$theLength); - $hilite = substr($theQuery, -$theLength); - } - $title =~ s/$strip/.../ if $theEllipsis; - - # TODO: use different formats for new and old autocomplete library - my $line = "$term|$title|$hilite|$freq"; - push(@result, $line); - } - } - if ($theRaw) { - my $result = ''; - try { - $result = $response->raw_response->content(); - $result = toSiteCharSet($result); - } catch Error::Simple with { - # - }; - return $result."\n\n"; - } - - return join("\n", @result)."\n\n"; -} - - ############################################################################## sub doSearch { my ($this, $query, $params) = @_; diff --git a/pub/System/SolrPlugin/Makefile b/pub/System/SolrPlugin/Makefile index aad02b1..fd0eef5 100644 --- a/pub/System/SolrPlugin/Makefile +++ b/pub/System/SolrPlugin/Makefile @@ -8,7 +8,9 @@ TARGET=\ pattern.css \ solr-searchbox.js \ wikiusers.js \ - wikiusers.css + wikiusers.css \ + jquery.autosuggest.js \ + jquery.autosuggest.css -include $(FOSWIKI_ROOT)/pub/System/JQueryPlugin/Makefile.include diff --git a/pub/System/SolrPlugin/jquery.autosuggest.uncompressed.css b/pub/System/SolrPlugin/jquery.autosuggest.uncompressed.css new file mode 100644 index 0000000..acd33d2 --- /dev/null +++ b/pub/System/SolrPlugin/jquery.autosuggest.uncompressed.css @@ -0,0 +1,60 @@ +.ui-autosuggest { + max-height:445px; + max-width:400px; + border-top:0; + position: absolute; + cursor: default; + overflow-y:auto; + overflow-x:hidden; +} +.ui-autosuggest-loading { + background-image:url(../JQueryPlugin/images/spinner.gif) !important; + background-position:right center !important; + background-repeat:no-repeat !important; +} +.ui-autosuggest.ui-menu .ui-menu-item a.ui-state-hover, +.ui-autosuggest.ui-menu .ui-menu-item a.ui-state-active { + background-color:#E1F3FD; + text-shadow:#F2F9FD; + border-color:#F2F9FD; + color:inherit; +} +.ui-autosuggest .ui-menu-item table { + table-layout:fixed; + height:48px; + width:100%; +} +.ui-autosuggest .ui-menu-item th { + width:48px; +} +.ui-autosuggest .ui-menu-item th div { + height:48px; + overflow:hidden; +} +.ui-autosuggest .ui-menu-item.ui-widget-header { + padding:5px; + border-top:1px solid #ddd; + font-weight:bold; +} + +.ui-autosuggest .ui-widget-header .ui-autosuggest-more { + float:right; + font-weight:normal; + margin-right:15px; + padding:0; + color:#7B7E81; +} +.ui-autosuggest .ui-widget-header .ui-autosuggest-more:hover { + text-decoration:underline; + background-color:transparent; +} +.ui-autosuggest .ui-menu-item .thumbnail.dummy { + background-color:#f8f8f8; + border:1px solid #ddd; +} +.ui-autosuggest .ui-menu-item td { + padding:0px 5px 0px 10px; + overflow:hidden; + white-space:nowrap; +} + diff --git a/pub/System/SolrPlugin/jquery.autosuggest.uncompressed.js b/pub/System/SolrPlugin/jquery.autosuggest.uncompressed.js new file mode 100644 index 0000000..6c63216 --- /dev/null +++ b/pub/System/SolrPlugin/jquery.autosuggest.uncompressed.js @@ -0,0 +1,113 @@ +// (c)opyright 2013 Michael Daum http://michaeldaumconsulting.com + +(function($) { + + $.widget( "solr.autosuggest", $.ui.autocomplete, { + options: { + source: foswiki.getPreference("SCRIPTURL") + '/rest/SolrPlugin/autosuggest', + thumbnailUrl: foswiki.getPreference("SCRIPTURL") + "/rest/ImagePlugin/resize?size=48&crop=north", + delay: 500, + minLength: 3, + position: { + my: "right top", + at: "right bottom", + collision: "none" + }, + + locales: { + persons: 'Persons', + topics: 'Topics', + attachments: 'Attachments', + more: "show more »", + loading: "Loading ..." + }, + + itemTemplate: "
  • ${name}
    ${title}
    ${description}
  • ", + headerTemplate: "
  • ${more}${title}
  • ", + + focus: function() { + return false; + }, + + select: function(event, data) { + var self = $(this).data("autosuggest"); + + if (typeof(data.item.url) !== 'undefined') { + $.blockUI({message:"

    "+self.options.locales.loading+"

    "}); + window.location.href = data.item.url; + } + + return false; + } + }, + + _init: function() { + var elem = this.menu.element; + + elem.addClass("ui-autosuggest").removeClass("ui-autocomplete"); + }, + + _renderMenu: function(ul, items) { + var self = this, + sections = {}; + + $.each(items, function(index, item) { + if (typeof(sections[item._section]) === 'undefined') { + sections[item._section] = []; + } + sections[item._section].push(item); + }); + + $.each(sections, function(key, section) { + + $.tmpl(self.options.headerTemplate, { + key: key, + title: self.options.locales[key] || key, + more: self.options.locales.more, + moreUrl: foswiki.getPreference("SCRIPTURLPATH")+"/System/WebHome" + }).appendTo(ul); + + ul.find("a.ui-autosuggest-more").click(function() { + window.location.href = $(this).attr("href"); + $.blockUI({message:"

    "+self.options.locales.loading+"

    "}); + return false; + }); + + $.each(section, function(index, item) { + self._renderItem(ul, item); + }); + }); + }, + + _renderItem: function(ul, item) { + var self = this, thumbnailUrl, $row, imgClass; + + if (typeof(item.thumbnail) !== 'undefined') { + imgClass = "thumbnail"; + if (/^(\/|http:)/.test(item.thumbnail)) { + thumbnailUrl = item.thumbnail; + } else { + thumbnailUrl = self.options.thumbnailUrl + '&topic=' + item.web + '.' + item.topic + '&file=' + item.thumbnail; + } + } else { + imgClass = "thumbnail dummy"; + thumbnailUrl = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='; + } + + $row = $.tmpl(self.options.itemTemplate, { + url: item.url, + thumbnailUrl: thumbnailUrl, + imgClass: imgClass, + name: item.name, + title: item._section === 'attachments' ? item.name : item.title, + description: typeof(item.container_title) !== 'undefined' ? item.container_title : '' + }); + + return $row.data("item.autocomplete", item).appendTo(ul); + }, + _normalize: function( items ) { + return items; // don't normalize + } + }); + +})(jQuery);