Bug 6483 - Paging in opac-detail when coming from a search
authorSalvador Zaragoza Rubio <salvazm@masmedios.com>
Fri, 27 May 2011 09:12:52 +0000 (11:12 +0200)
committerChris Cormack <chrisc@catalyst.net.nz>
Thu, 20 Oct 2011 15:57:09 +0000 (04:57 +1300)
Add paging in opac-detail when coming from a search to be
able to continue viewing the previous and next register
from the detail without returning to the results.
The partial list pagination can be showed to increase forwarding
or rewinding in the pagination.
It's implemented for Zebra search and not build_grouped_results.

The param busc with all the information from the search is stored
on the session when running opac-search and opac-detail, outside these
pages the busc param is removed from the session.

A list of the biblionumbers inside the OPACnumSearchResults range
is passed to avoid repeating the searching everytime we see the
previous or next biblio. The searching will be run again when
we are going to exceed the list and a new one will be calculated
from the new search.

Signed-off-by: Magnus Enger <magnus@enger.priv.no>
Signed-off-by: Frédéric Demians <f.demians@tamil.fr>
Signed-off-by: Ian Walls <ian.walls@bywatersolutions.com>
Signed-off-by: Chris Cormack <chrisc@catalyst.net.nz>
C4/Auth.pm [changed mode: 0644->0755]
koha-tmpl/opac-tmpl/prog/en/css/opac.css [changed mode: 0644->0755]
koha-tmpl/opac-tmpl/prog/en/includes/opac-facets.inc [changed mode: 0644->0755]
koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt [changed mode: 0644->0755]
koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt [changed mode: 0644->0755]
koha-tmpl/opac-tmpl/prog/images/ico_b_results.gif [new file with mode: 0644]
opac/opac-detail.pl
opac/opac-search.pl

old mode 100644 (file)
new mode 100755 (executable)
index 2aac678..e360e10
@@ -398,6 +398,11 @@ sub get_template_and_user {
         my $LibraryNameTitle = C4::Context->preference("LibraryName");
         $LibraryNameTitle =~ s/<(?:\/?)(?:br|p)\s*(?:\/?)>/ /sgi;
         $LibraryNameTitle =~ s/<(?:[^<>'"]|'(?:[^']*)'|"(?:[^"]*)")*>//sg;
+        # clean up the busc param in the session if the page is not opac-detail
+        if ($in->{'template_name'} =~ /opac-(.+)\.(?:tt|tmpl)$/ && $1 !~ /^(?:MARC|ISBD)?detail$/) {
+            my $sessionSearch = get_session($sessionID || $in->{'query'}->cookie("CGISESSID"));
+            $sessionSearch->clear(["busc"]) if ($sessionSearch->param("busc"));
+        }
         # variables passed from CGI: opac_css_override and opac_search_limits.
         my $opac_search_limit = $ENV{'OPAC_SEARCH_LIMIT'};
         my $opac_limit_override = $ENV{'OPAC_LIMIT_OVERRIDE'};
old mode 100644 (file)
new mode 100755 (executable)
index 14236c8..11c434f
@@ -1902,7 +1902,7 @@ table#items th {
        padding : 2px;
 }
 #action {
-       margin-top: 0;
+       /*margin-top: 0;*/
 }
 #similars h4 {
        text-align : left;
@@ -2065,3 +2065,163 @@ a.koha_url {
     text-decoration:none;
     color: #666666;
 }
+/* pagination */
+.pagination {
+    position: absolute;
+    top:32px;
+    left: -1px;
+    width: 100%;
+    height:auto;
+    border: 1px solid #D0D0D0;
+    display: none;
+       background-color:#F3F3F3;
+       padding-bottom:10px;
+}
+
+
+/* nav */
+.nav .close_pagination {
+    padding-right: 10px;
+    position: absolute;
+    right: 3px;
+    top: -25px;
+}
+.nav .close_pagination a {
+    text-decoration:none!important;
+}
+
+.nav ul {
+    padding-top: 10px;
+}
+
+.nav li {
+       list-style:none;
+       float:left;
+       padding:4px;
+       color:#999;
+}
+
+.nav li a {
+       text-decoration:none!important;
+}
+
+.nav li a:hover {
+       text-decoration:underline;
+}
+
+.nav li ul {
+       float:left;
+}
+
+.back {
+       float:right;
+}
+
+.back input{
+       background:none!important;
+       color:#999!important;
+}
+
+.pagination_list {
+       float:bottom;
+}
+.pagination_list ul {
+    padding-top: 40px;
+       padding-left:0px;
+}
+.pagination_list li {
+       list-style:none;
+       float:bottom;
+       padding:4px;
+       color:#999;
+   /* border-bottom : 1px solid #DDDDDD;*/
+}
+.pagination_list li.highlight {
+   background-color : #F3F3F3;
+   border-top : 1px solid #DDDDDD;
+   border-bottom : 1px solid #DDDDDD;
+}
+.pagination_list span.li_pag_index {
+   color: #999999;
+    float: left;
+    font-size: 15px;
+    font-weight: bold;
+    padding-right: 10px;
+    text-align: right;
+    width: 13px;
+       
+}
+
+.pagination_list li a {padding-left:0px;}
+
+
+.nav_results {
+    background-color: #F3F3F3;
+    border: 1px solid #D0D0D0;
+    margin-top: 0.5em;
+       position:relative;
+}
+
+.nav_results .l_Results a {
+    background:#E1E1E1 url("../../images/ico_b_results.gif") 14px 13px no-repeat;
+    color:#006699;
+    display:block;
+    padding:8px 28px;
+    text-decoration:none;
+}
+.nav_results .l_Results a:hover {
+    background-color:#D9D9D9;
+}
+.nav_results ul.pg_menu {
+    height:25px;
+    border-top: 1px solid #D0D0D0;
+}
+.nav_results ul.pg_menu li {
+    color:#B2B2B2;
+    display:block;
+    float:left;
+    padding:5px 0;
+    list-style:none;
+    text-align:center;
+}
+.nav_results ul.pg_menu li.back_results {
+    padding:5px 0px;
+    width:45%;
+    border-left: 1px solid #D0D0D0;
+    border-right: 1px solid #D0D0D0;
+}
+.nav_results ul.pg_menu li a {
+    text-decoration:none;
+    font-weight:normal;
+    color:#4D4D4D;
+}
+.nav_results ul.pg_menu li a:hover {
+    color:#006699;
+}
+.nav_results ul.pg_menu li.left_results {
+    margin-right:10px;
+}
+.nav_results ul.pg_menu li.right_results {
+    margin-left:10px;
+}
+
+.nav_results #listResults{
+    line-height: 0.7em;
+}
+
+.nav_results  #listResults li  {
+    background-color:#999999;
+    color:#C5C5C5;
+    font-weight:normal;
+       display:block;
+       margin-right:1px;
+       font-size:0.9em;
+       padding:5px 0px;
+       text-align:center;
+       min-width:20px;
+}
+
+.nav_results  #listResults li:hover  {background-color:#006699;}
+
+.nav_results  #listResults li a { color:#FFFFFF; font-weight:normal;}
+
old mode 100644 (file)
new mode 100755 (executable)
index a42ceea..8cba98b
@@ -3,6 +3,17 @@
 <script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.tablesorter.min.js"></script>
 <script type="text/JavaScript" language="JavaScript">
 //<![CDATA[
+    [% IF ( busc ) %]
+        var arrPagination = new Array();
+        var pag_index_ini = [% indexPag %];
+        [% IF ( listResults ) %]
+            [% FOREACH listResult IN listResults %]
+                arrPagination[[% listResult.index %]] = {url:"[% listResult.url %]", title:"[% listResult.title|html %]", author:"[% listResult.author|html %]", biblionumber:[% listResult.biblionumber %]};
+           [% END %]
+        [% END %]
+    [% END %]
+
+
      $(document).ready(function() { 
         $('#bibliodescriptions > ul').tabs();
 [% IF ( opacuserlogin ) %][% IF ( loggedinusername ) %][% IF ( TagsEnabled ) %]$("#tagform").hide();
         [% END %]
        [% IF ( opacuserlogin ) %][% IF ( loggedinusername ) %][% IF ( TagsEnabled ) %]
         $(".tagbutton").click(KOHA.Tags.add_tag_button);[% END %][% END %][% END %]
+        [% IF ( busc ) %]
+        if (arrPagination.length > 0) {
+            renderPagIndexList(pag_index_ini, $("#listResults"));
+        }
+        $("#a_listResults").click(function(e) {
+            if (arrPagination.length > 0) {
+                e.preventDefault();
+                var navigation = $(".pagination");
+                if (navigation.css("display") == 'none') {
+                    navigation.show();
+                    var newtitle = $(this).attr('title').replace('Show', 'Hide')
+                    $(this).attr('title',newtitle);
+                    renderPagination(pag_index_ini, arrPagination.length - 1, $("#ul_pagination_list"), false);
+                } else {
+                    navigation.hide();
+                    var newtitle = $(this).attr('title').replace('Hide', 'Show')
+                    $(this).attr('title',newtitle);
+                }
+            }
+        });
+        $("#close_pagination").click(function(e) {
+            e.preventDefault();
+            var navigation = $(".pagination");
+            navigation.hide();
+        });
+        [% END %]
 
 });
 
+
+[% IF ( busc ) %]
+
+var timeoutRFW;
+var totalPagItemList = 10;
+
+function rewindList()
+{
+    var ul = $("#listResults");
+    var li_ini = ul.children(':first').next();
+    var index_ini = pag_index_ini;
+    if (li_ini) {
+        index_ini = parseInt(li_ini.attr("class").substring(7), 10);
+    }
+    var li_end = ul.children(':last').prev();
+    var index_end = arrPagination.length - 1;
+    if (li_end) {
+        index_end = parseInt(li_end.attr("class").substring(7), 10);
+    }
+    if (index_ini > pag_index_ini) {
+        renderPagIndexList(index_ini - 1, ul, false);
+        renderPagination(index_ini - 1, arrPagination.length - 1, $("#ul_pagination_list"), true);
+    }
+}//rewindList
+
+function forwardList()
+{
+    var ul = $("#listResults");
+    var li_ini = ul.children(':first').next();
+    var index_ini = pag_index_ini;
+    if (li_ini) {
+        index_ini = parseInt(li_ini.attr("class").substring(7), 10);
+    }
+    var li_end = ul.children(':last').prev();
+    var index_end = arrPagination.length - 1;
+    if (li_end) {
+        index_end = parseInt(li_end.attr("class").substring(7), 10);
+    }
+    if (index_end < arrPagination.length - 1) {
+        renderPagIndexList(index_ini + 1, ul, false);
+        renderPagination(index_ini + 1, arrPagination.length - 1, $("#ul_pagination_list"), true);
+    }
+}//forwardList
+
+function renderPagIndexList(index, ul)
+{
+    var $kids = ul.children("li");
+    if ($kids.length > 0) {
+        $kids.each(function() {
+            $(this).remove();
+        });
+    }
+    var li;
+    var html = "";
+    var ini = index - 1;
+    var end = ini + totalPagItemList - 1;
+    li = $("<li />");
+    html = (index > pag_index_ini)?"<a href='#' id='rew_list_index' onclick='rewindList()' title='Click to rewind the list to " + ini + " - " + end + "'>&laquo;</a>":"&laquo;";
+    li.html(html);
+    ul.append(li);
+    var title = "";
+    for (var i=index; i < arrPagination.length && i < index + totalPagItemList; i++) {
+        if (arrPagination[i] == undefined) continue;
+        var li = $("<li />");
+        if (arrPagination[i].url != "") {
+            title = "See biblio &quot;" + arrPagination[i].title + "&quot; ";
+            if (arrPagination[i].author != "") title += " by &quot;" + arrPagination[i].author + "&quot;";
+            title += " with biblionumber " + arrPagination[i].biblionumber;
+            html = "<a href='" + arrPagination[i].url + "' title='" + title + "' class='a_pag' id='a_pag_" + i + "'";
+            html += " onmouseover='renderPagination(" + i + ", " + (arrPagination.length - 1) + ", $(\"#ul_pagination_list\"), true)'";
+            html += ">" + i + "</a>";
+        } else html = i;
+        li.html(html);
+        li.attr("class", "li_pag_" + i);
+        ul.append(li);
+    }
+    li = $("<li />");
+    ini = index + 1;
+    end = (arrPagination.length > index + totalPagItemList)?index + totalPagItemList:arrPagination.length - 1;
+    html = (end <= arrPagination.length - 1 && (end - index) >= totalPagItemList)?"<a href='#' id='fw_list_index' onclick='forwardList()' title='Click to forward the list to " + ini + " - " + end + "'>&raquo;</a>":"&raquo;";
+    li.html(html);
+    ul.append(li);
+}//renderPagIndexList
+
+
+function renderPagination(index, total, ul, highlIndex)
+{
+    for (var i = pag_index_ini; i <= total; i++) {
+        if (arrPagination[i] == undefined || arrPagination[i].url == "") continue;
+        $("#li_pag_" + i).remove();
+    }
+    var j = 0;
+    for (var i = index; i <= total && j < totalPagItemList; i++) {
+        if (arrPagination[i] == undefined || arrPagination[i].url == "") continue;
+        var li = $("<li id='li_pag_" + i + "' " + ((j % 2 == 0)?"class='highlight'":"")  + " title='Go to detail' />");
+        var html = "<span class='li_pag_index'>" + i + "</span><a href='" + arrPagination[i].url + "'>" + arrPagination[i].title + "</a>";
+        if (arrPagination[i].author) html += "<br /> by " + arrPagination[i].author;
+        li.html(html);
+        if (highlIndex && i == index) li.css("backgroundColor", "#DDDDDD");
+        ul.append(li);
+        j++;
+    }
+    for (i = pag_index_ini; i < index && j < totalPagItemList; i++) {
+        if (arrPagination[i] == undefined || arrPagination[i].url == "") continue;
+        $("#li_pag_" + i).remove();
+        var li = $("<li id='li_pag_" + i + "' " + ((j % 2 == 0)?"class='highlight'":"")  + " title='Go to detail' />");
+        var html = "<span class='li_pag_index'>" + i + "</span><a href='" + arrPagination[i].url + "'>" + arrPagination[i].title + "</a>";
+        if (arrPagination[i].author) html += "<br /> by " + arrPagination[i].author;
+        li.html(html);
+        ul.append(li);
+        j++;
+    }
+}//renderPagination
+[% END %]
+
+
 YAHOO.util.Event.onContentReady("furtherm", function () {
     $("#furtherm").css("display","block").css("visibility","hidden");
        $("#furthersearches").parent().show();
@@ -825,6 +978,7 @@ YAHOO.util.Event.onContentReady("furtherm", function () {
 [% END %]
 [% END %]
 
+
 </div>
 [% IF ( NovelistSelectProfile ) %][% IF ( NovelistSelectView == 'below' ) %]
 <div id="NovelistSelect">
@@ -835,8 +989,30 @@ YAHOO.util.Event.onContentReady("furtherm", function () {
 </div>
 </div>
 
+
 <div class="yui-u">
 <div id="ulactioncontainer" class="container">
+[% IF ( busc ) %]
+    <div class="nav_results">
+        <div class="l_Results">[% IF ( listResults ) %]<a href="#" id="a_listResults" title="Show pagination list ([% indexPag %]-[% indexPagEnd %] / [% totalPag %])">Browse results</a>[% ELSE %]Browse results[% END %]</div>
+        <ul class="pg_menu">
+            <li class="left_results">[% IF ( previous ) %]<a href="[% previous %]" title="See: [% IF ( previousTitle ) %][% previousTitle |html %][% ELSE %]previous biblio[% END %]">&laquo; Previous</a>[% ELSE %]Previous[% END %]</li>
+            <li class="back_results"><a href="opac-search.pl?[% busc %]" title="Back to the results search list">Back to results</a></li>
+            <li class="right_results">[% IF ( next ) %]<a href="[% next %]" title="See: [% IF ( nextTitle ) %][% nextTitle |html %][% ELSE %]next biblio[% END %]">Next &raquo;</a>[% ELSE %]Next[% END %]</li>
+        </ul>
+        [% IF ( listResults ) %]
+        <div class="pagination">
+            <div class="nav">
+                <span class="close_pagination"><a href="#" id="close_pagination">Close</a></span>
+                <ul id="listResults"></ul>
+            </div>
+            <div class="pagination_list">
+                <ul id="ul_pagination_list"></ul>
+            </div>
+        </div>
+        [% END %]
+    </div>
+[% END %]
 <ul id="action">
 
 [% UNLESS ( norequests ) %]
diff --git a/koha-tmpl/opac-tmpl/prog/images/ico_b_results.gif b/koha-tmpl/opac-tmpl/prog/images/ico_b_results.gif
new file mode 100644 (file)
index 0000000..3db88f2
Binary files /dev/null and b/koha-tmpl/opac-tmpl/prog/images/ico_b_results.gif differ
index 0301a5a..d3c7e2a 100755 (executable)
@@ -23,7 +23,7 @@ use strict;
 use warnings;
 
 use CGI;
-use C4::Auth;
+use C4::Auth qw(:DEFAULT get_session);
 use C4::Branch;
 use C4::Koha;
 use C4::Serials;    #uses getsubscriptionfrom biblionumber
@@ -66,6 +66,288 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
 
 my $biblionumber = $query->param('biblionumber') || $query->param('bib');
 
+# We look for the busc param to build the simple paging from the search
+my $session = get_session($query->cookie("CGISESSID"));
+my %paging = (previous => {}, next => {});
+if ($session->param('busc')) {
+    use C4::Search;
+
+    # Rebuild the string to store on session
+    sub rebuildBuscParam
+    {
+        my $arrParamsBusc = shift;
+
+        my $pasarParams = '';
+        my $j = 0;
+        for (keys %$arrParamsBusc) {
+            if ($_ =~ /^(?:query|listBiblios|newlistBiblios|query_type|simple_query|total|offset|offsetSearch|next|previous|count|expand|scan)/) {
+                if (defined($arrParamsBusc->{$_})) {
+                    $pasarParams .= '&amp;' if ($j);
+                    $pasarParams .= $_ . '=' . $arrParamsBusc->{$_};
+                    $j++;
+                }
+            } else {
+                for my $value (@{$arrParamsBusc->{$_}}) {
+                    $pasarParams .= '&amp;' if ($j);
+                    $pasarParams .= $_ . '=' . $value;
+                    $j++;
+                }
+            }
+        }
+        return $pasarParams;
+    }#rebuildBuscParam
+
+    # Search given the current values from the busc param
+    sub searchAgain
+    {
+        my ($arrParamsBusc, $offset, $results_per_page) = @_;
+
+        my $expanded_facet = $arrParamsBusc->{'expand'};
+        my $branches = GetBranches();
+        my @servers;
+        @servers = @{$arrParamsBusc->{'server'}} if $arrParamsBusc->{'server'};
+        @servers = ("biblioserver") unless (@servers);
+        my $default_sort_by = C4::Context->preference('OPACdefaultSortField')."_".C4::Context->preference('OPACdefaultSortOrder') if (C4::Context->preference('OPACdefaultSortField') && C4::Context->preference('OPACdefaultSortOrder'));
+        my @sort_by = @{$arrParamsBusc->{'sort_by'}} if $arrParamsBusc->{'sort_by'};
+        $sort_by[0] = $default_sort_by if !$sort_by[0] && defined($default_sort_by);
+        my ($error, $results_hashref, $facets);
+        eval {
+            ($error, $results_hashref, $facets) = getRecords($arrParamsBusc->{'query'},$arrParamsBusc->{'simple_query'},\@sort_by,\@servers,$results_per_page,$offset,$expanded_facet,$branches,$arrParamsBusc->{'query_type'},$arrParamsBusc->{'scan'});
+        };
+        my $hits;
+        my @newresults;
+        for (my $i=0;$i<@servers;$i++) {
+            my $server = $servers[$i];
+            $hits = $results_hashref->{$server}->{"hits"};
+            @newresults = searchResults('opac', '', $hits, $results_per_page, $offset, $arrParamsBusc->{'scan'}, @{$results_hashref->{$server}->{"RECORDS"}},, C4::Context->preference('hidelostitems'));
+        }
+        return \@newresults;
+    }#searchAgain
+
+    # Build the current list of biblionumbers in this search
+    sub buildListBiblios
+    {
+        my ($newresultsRef, $results_per_page) = @_;
+
+        my $listBiblios = '';
+        my $j = 0;
+        foreach (@$newresultsRef) {
+            my $bibnum = ($_->{biblionumber})?$_->{biblionumber}:0;
+            $listBiblios .= $bibnum . ',';
+            $j++;
+            last if ($j == $results_per_page);
+        }
+        chop $listBiblios if ($listBiblios =~ /,$/);
+        return $listBiblios;
+    }#buildListBiblios
+
+    my $busc = $session->param("busc");
+    my @arrBusc = split(/\&(?:amp;)?/, $busc);
+    my ($key, $value);
+    my %arrParamsBusc = ();
+    for (@arrBusc) {
+        ($key, $value) = split(/=/, $_, 2);
+        if ($key =~ /^(?:query|listBiblios|newlistBiblios|query_type|simple_query|next|previous|total|offset|offsetSearch|count|expand|scan)/) {
+            $arrParamsBusc{$key} = $value;
+        } else {
+            unless (exists($arrParamsBusc{$key})) {
+                $arrParamsBusc{$key} = [];
+            }
+            push @{$arrParamsBusc{$key}}, $value;
+        }
+    }
+    my $searchAgain = 0;
+    my $count = C4::Context->preference('OPACnumSearchResults') || 20;
+    my $results_per_page = ($arrParamsBusc{'count'} && $arrParamsBusc{'count'} =~ /^[0-9]+?/)?$arrParamsBusc{'count'}:$count;
+    $arrParamsBusc{'count'} = $results_per_page;
+    my $offset = ($arrParamsBusc{'offset'} && $arrParamsBusc{'offset'} =~ /^[0-9]+?/)?$arrParamsBusc{'offset'}:0;
+    # The value OPACnumSearchResults has changed and the search has to be rebuild
+    if ($count != $results_per_page) {
+        if (exists($arrParamsBusc{'listBiblios'}) && $arrParamsBusc{'listBiblios'} =~ /^[0-9]+(?:,[0-9]+)*$/) {
+            my $indexBiblio = 0;
+            my @arrBibliosAux = split(',', $arrParamsBusc{'listBiblios'});
+            for (@arrBibliosAux) {
+                last if ($_ == $biblionumber);
+                $indexBiblio++;
+            }
+            $indexBiblio += $offset;
+            $offset = int($indexBiblio / $count) * $count;
+            $arrParamsBusc{'offset'} = $offset;
+        }
+        $arrParamsBusc{'count'} = $count;
+        $results_per_page = $count;
+        my $newresultsRef = searchAgain(\%arrParamsBusc, $offset, $results_per_page);
+        $arrParamsBusc{'listBiblios'} = buildListBiblios($newresultsRef, $results_per_page);
+        delete $arrParamsBusc{'previous'} if (exists($arrParamsBusc{'previous'}));
+        delete $arrParamsBusc{'next'} if (exists($arrParamsBusc{'next'}));
+        delete $arrParamsBusc{'offsetSearch'} if (exists($arrParamsBusc{'offsetSearch'}));
+        delete $arrParamsBusc{'newlistBiblios'} if (exists($arrParamsBusc{'newlistBiblios'}));
+        my $newbusc = rebuildBuscParam(\%arrParamsBusc);
+        $session->param("busc" => $newbusc);
+        @arrBusc = split(/\&(?:amp;)?/, $newbusc);
+    } else {
+        my $modifyListBiblios = 0;
+        # We come from a previous click
+        if (exists($arrParamsBusc{'previous'})) {
+            $modifyListBiblios = 1 if ($biblionumber == $arrParamsBusc{'previous'});
+            delete $arrParamsBusc{'previous'};
+        } elsif (exists($arrParamsBusc{'next'})) { # We come from a next click
+            $modifyListBiblios = 2 if ($biblionumber == $arrParamsBusc{'next'});
+            delete $arrParamsBusc{'next'};
+        }
+        if ($modifyListBiblios) {
+            if (exists($arrParamsBusc{'newlistBiblios'})) {
+                my $listBibliosAux = $arrParamsBusc{'listBiblios'};
+                $arrParamsBusc{'listBiblios'} = $arrParamsBusc{'newlistBiblios'};
+                my @arrAux = split(',', $listBibliosAux);
+                $arrParamsBusc{'newlistBiblios'} = $listBibliosAux;
+                if ($modifyListBiblios == 1) {
+                    $arrParamsBusc{'next'} = $arrAux[0];
+                    $paging{'next'}->{biblionumber} = $arrAux[0];
+                }else {
+                    $arrParamsBusc{'previous'} = $arrAux[$#arrAux];
+                    $paging{'previous'}->{biblionumber} = $arrAux[$#arrAux];
+                }
+            } else {
+                delete $arrParamsBusc{'listBiblios'};
+            }
+            my $offsetAux = $arrParamsBusc{'offset'};
+            $arrParamsBusc{'offset'} = $arrParamsBusc{'offsetSearch'};
+            $arrParamsBusc{'offsetSearch'} = $offsetAux;
+            $offset = $arrParamsBusc{'offset'};
+            my $newbusc = rebuildBuscParam(\%arrParamsBusc);
+            $session->param("busc" => $newbusc);
+            @arrBusc = split(/\&(?:amp;)?/, $newbusc);
+        }
+    }
+    my $buscParam = '';
+    my $j = 0;
+    # Rebuild the query for the button "back to results"
+    for (@arrBusc) {
+        unless ($_ =~ /^(?:query|listBiblios|newlistBiblios|query_type|simple_query|next|previous|total|count|offsetSearch)/) {
+            $buscParam .= '&amp;' unless ($j == 0);
+            $buscParam .= $_;
+            $j++;
+        }
+    }
+    $template->param('busc' => $buscParam);
+    my $offsetSearch;
+    my @arrBiblios;
+    # We are inside the list of biblios and we don't have to search
+    if (exists($arrParamsBusc{'listBiblios'}) && $arrParamsBusc{'listBiblios'} =~ /^[0-9]+(?:,[0-9]+)*$/) {
+        @arrBiblios = split(',', $arrParamsBusc{'listBiblios'});
+        if (@arrBiblios) {
+            # We are at the first item of the list
+            if ($arrBiblios[0] == $biblionumber) {
+                if (@arrBiblios > 1) {
+                    for (my $j = 1; $j < @arrBiblios; $j++) {
+                        next unless ($arrBiblios[$j]);
+                        $paging{'next'}->{biblionumber} = $arrBiblios[$j];
+                        last;
+                    }
+                }
+                # search again if we are not at the first searching list
+                if ($offset && !$arrParamsBusc{'previous'}) {
+                    $searchAgain = 1;
+                    $offsetSearch = $offset - $results_per_page;
+                }
+            # we are at the last item of the list
+            } elsif ($arrBiblios[$#arrBiblios] == $biblionumber) {
+                for (my $j = $#arrBiblios - 1; $j >= 0; $j--) {
+                    next unless ($arrBiblios[$j]);
+                    $paging{'previous'}->{biblionumber} = $arrBiblios[$j];
+                    last;
+                }
+                if (!$offset) {
+                    # search again if we are at the first list and there is more results
+                    $searchAgain = 1 if (!$arrParamsBusc{'next'} && $arrParamsBusc{'total'} != @arrBiblios);
+                } else {
+                    # search again if we aren't at the first list and there is more results
+                    $searchAgain = 1 if (!$arrParamsBusc{'next'} && $arrParamsBusc{'total'} > ($offset + @arrBiblios));
+                }
+                $offsetSearch = $offset + $results_per_page if ($searchAgain);
+            } else {
+                for (my $j = 1; $j < $#arrBiblios; $j++) {
+                    if ($arrBiblios[$j] == $biblionumber) {
+                        for (my $z = $j - 1; $z >= 0; $z--) {
+                            next unless ($arrBiblios[$z]);
+                            $paging{'previous'}->{biblionumber} = $arrBiblios[$z];
+                            last;
+                        }
+                        for (my $z = $j + 1; $z < @arrBiblios; $z++) {
+                            next unless ($arrBiblios[$z]);
+                            $paging{'next'}->{biblionumber} = $arrBiblios[$z];
+                            last;
+                        }
+                        last;
+                    }
+                }
+            }
+        }
+        $offsetSearch = 0 if (defined($offsetSearch) && $offsetSearch < 0);
+    }
+    if ($searchAgain) {
+        my $newresultsRef = searchAgain(\%arrParamsBusc, $offsetSearch, $results_per_page);
+        my @newresults = @$newresultsRef;
+        # build the new listBiblios
+        my $listBiblios = buildListBiblios(\@newresults, $results_per_page);
+        unless (exists($arrParamsBusc{'listBiblios'})) {
+            $arrParamsBusc{'listBiblios'} = $listBiblios;
+            @arrBiblios = split(',', $arrParamsBusc{'listBiblios'});
+        } else {
+            $arrParamsBusc{'newlistBiblios'} = $listBiblios;
+        }
+        # From the new list we build again the next and previous result
+        if (@arrBiblios) {
+            if ($arrBiblios[0] == $biblionumber) {
+                for (my $j = $#newresults; $j >= 0; $j--) {
+                    next unless ($newresults[$j]);
+                    $paging{'previous'}->{biblionumber} = $newresults[$j]->{biblionumber};
+                    $arrParamsBusc{'previous'} = $paging{'previous'}->{biblionumber};
+                    $arrParamsBusc{'offsetSearch'} = $offsetSearch;
+                   last;
+                }
+            } elsif ($arrBiblios[$#arrBiblios] == $biblionumber) {
+                for (my $j = 0; $j < @newresults; $j++) {
+                    next unless ($newresults[$j]);
+                    $paging{'next'}->{biblionumber} = $newresults[$j]->{biblionumber};
+                    $arrParamsBusc{'next'} = $paging{'next'}->{biblionumber};
+                    $arrParamsBusc{'offsetSearch'} = $offsetSearch;
+                    last;
+                }
+            }
+        }
+        # build new busc param
+        my $newbusc = rebuildBuscParam(\%arrParamsBusc);
+        $session->param("busc" => $newbusc);
+    }
+    my ($previous, $next, $dataBiblioPaging);
+    # Previous biblio
+    if ($paging{'previous'}->{biblionumber}) {
+        $previous = 'opac-detail.pl?biblionumber=' . $paging{'previous'}->{biblionumber};
+        $dataBiblioPaging = GetBiblioData($paging{'previous'}->{biblionumber});
+        $template->param('previousTitle' => $dataBiblioPaging->{'title'}) if ($dataBiblioPaging);
+    }
+    # Next biblio
+    if ($paging{'next'}->{biblionumber}) {
+        $next = 'opac-detail.pl?biblionumber=' . $paging{'next'}->{biblionumber};
+        $dataBiblioPaging = GetBiblioData($paging{'next'}->{biblionumber});
+        $template->param('nextTitle' => $dataBiblioPaging->{'title'}) if ($dataBiblioPaging);
+    }
+    $template->param('previous' => $previous, 'next' => $next);
+    # Partial list of biblio results
+    my @listResults;
+    for (my $j = 0; $j < @arrBiblios; $j++) {
+        next unless ($arrBiblios[$j]);
+        $dataBiblioPaging = GetBiblioData($arrBiblios[$j]) if ($arrBiblios[$j] != $biblionumber);
+        push @listResults, {index => $j + 1 + $offset, biblionumber => $arrBiblios[$j], title => ($arrBiblios[$j] == $biblionumber)?'':$dataBiblioPaging->{title}, author => ($arrBiblios[$j] != $biblionumber && $dataBiblioPaging->{author})?$dataBiblioPaging->{author}:'', url => ($arrBiblios[$j] == $biblionumber)?'':'opac-detail.pl?biblionumber=' . $arrBiblios[$j]};
+    }
+    $template->param('listResults' => \@listResults) if (@listResults);
+    $template->param('indexPag' => 1 + $offset, 'totalPag' => $arrParamsBusc{'total'}, 'indexPagEnd' => scalar(@arrBiblios) + $offset);
+}
+
+
+
 $template->param( 'AllowOnShelfHolds' => C4::Context->preference('AllowOnShelfHolds') );
 $template->param( 'ItemsIssued' => CountItemsIssued( $biblionumber ) );
 
index ff437da..716b164 100755 (executable)
@@ -272,6 +272,21 @@ my $params = $cgi->Vars;
 my $tag;
 $tag = $params->{tag} if $params->{tag};
 
+
+# String with params with the search criteria for the paging in opac-detail
+my $pasarParams = '';
+my $j = 0;
+for (keys %$params) {
+    my @pasarParam = split("\0", $params->{$_});
+    for my $paramValue(@pasarParam) {
+        $pasarParams .= '&amp;' if ($j > 0);
+        $pasarParams .= $_ . '=' . $paramValue;
+        $j++;
+    }
+}
+#
+
+
 # Params that can have more than one value
 # sort by is used to sort the query
 # in theory can have more than one but generally there's just one
@@ -434,6 +449,10 @@ elsif (C4::Context->preference('NoZebra')) {
         ($error, $results_hashref, $facets) = C4::Search::pazGetRecords($query,$simple_query,\@sort_by,\@servers,$results_per_page,$offset,$expanded_facet,$branches,$query_type,$scan);
     };
 } else {
+    $pasarParams .= '&amp;query=' . $query;
+    $pasarParams .= '&amp;count=' . $results_per_page;
+    $pasarParams .= '&amp;simple_query=' . $simple_query;
+    $pasarParams .= '&amp;query_type=' . $query_type if ($query_type);
     eval {
         ($error, $results_hashref, $facets) = getRecords($query,$simple_query,\@sort_by,\@servers,$results_per_page,$offset,$expanded_facet,$branches,$query_type,$scan);
     };
@@ -555,6 +574,24 @@ for (my $i=0;$i<@servers;$i++) {
             exit;
         }
         if ($hits) {
+            if (!C4::Context->preference('NoZebra') && !$build_grouped_results) {
+                # We build the encrypted list of first OPACnumSearchResults biblios to pass with the search criteria for paging on opac-detail
+                $pasarParams .= '&amp;listBiblios=';
+                my $j = 0;
+                foreach (@newresults) {
+                    my $bibnum = ($_->{biblionumber})?$_->{biblionumber}:0;
+                    $pasarParams .= $bibnum . ',';
+                    $j++;
+                    last if ($j == $results_per_page);
+                }
+                chop $pasarParams if ($pasarParams =~ /,$/);
+                $pasarParams .= '&amp;total=' . int($total) if ($pasarParams !~ /total=(?:[0-9]+)?/);
+                if ($pasarParams) {
+                    my $session = get_session($cgi->cookie("CGISESSID"));
+                    $session->param('busc' => $pasarParams);
+                }
+                #
+            }
             $template->param(total => $hits);
             my $limit_cgi_not_availablity = $limit_cgi;
             $limit_cgi_not_availablity =~ s/&limit=available//g if defined $limit_cgi_not_availablity;