MT 1110 : Balance cart and lists : cart is now in the intranet
authorMatthias Meusburger <matthias.meusburger@biblibre.com>
Wed, 14 Oct 2009 13:04:53 +0000 (15:04 +0200)
committerMatthias Meusburger <matthias.meusburger@biblibre.com>
Wed, 14 Oct 2009 13:04:53 +0000 (15:04 +0200)
12 files changed:
basket/basket.pl [new file with mode: 0755]
basket/downloadcart.pl [new file with mode: 0755]
basket/sendbasket.pl [new file with mode: 0755]
koha-tmpl/intranet-tmpl/prog/en/js/tags.js [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/lib/jquery/plugins/jquery.dropshadow-min.js [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tmpl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/basket/downloadcart.tmpl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasket.tmpl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasketform.tmpl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/tags/tags.tmpl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/img/cart.gif [new file with mode: 0644]
tags/tags.pl [new file with mode: 0755]

diff --git a/basket/basket.pl b/basket/basket.pl
new file mode 100755 (executable)
index 0000000..464c6d5
--- /dev/null
@@ -0,0 +1,125 @@
+#!/usr/bin/perl
+
+# 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., 59 Temple Place,
+# Suite 330, Boston, MA  02111-1307 USA
+
+
+use strict;
+use warnings;
+use CGI;
+use C4::Koha;
+use C4::Biblio;
+use C4::Items;
+use C4::Auth;
+use C4::Output;
+
+my $query = new CGI;
+
+my ( $template, $borrowernumber, $cookie ) = get_template_and_user (
+    {
+        template_name   => "basket/basket.tmpl",
+        query           => $query,
+        type            => "intranet",
+        flagsrequired   => { borrow => 1 },
+    }
+);
+
+my $bib_list     = $query->param('bib_list');
+my $print_basket = $query->param('print');
+my $verbose      = $query->param('verbose');
+
+if ($verbose)      { $template->param( verbose      => 1 ); }
+if ($print_basket) { $template->param( print_basket => 1 ); }
+
+my @bibs = split( /\//, $bib_list );
+my @results;
+
+my $num = 1;
+my $marcflavour = C4::Context->preference('marcflavour');
+if (C4::Context->preference('TagsEnabled')) {
+       $template->param(TagsEnabled => 1);
+       foreach (qw(TagsShowOnList TagsInputOnList)) {
+               C4::Context->preference($_) and $template->param($_ => 1);
+       }
+}
+
+
+foreach my $biblionumber ( @bibs ) {
+    $template->param( biblionumber => $biblionumber );
+
+    my $dat              = &GetBiblioData($biblionumber);
+    my $record           = &GetMarcBiblio($biblionumber);
+    my $marcnotesarray   = GetMarcNotes( $record, $marcflavour );
+    my $marcauthorsarray = GetMarcAuthors( $record, $marcflavour );
+    my $marcsubjctsarray = GetMarcSubjects( $record, $marcflavour );
+    my $marcseriesarray  = GetMarcSeries  ($record,$marcflavour);
+    my $marcurlsarray    = GetMarcUrls    ($record,$marcflavour);
+    my @items            = &GetItemsInfo( $biblionumber, 'opac' );
+
+    my $hasauthors = 0;
+    if($dat->{'author'} || @$marcauthorsarray) {
+      $hasauthors = 1;
+    }
+       
+    my $shelflocations =GetKohaAuthorisedValues('items.location',$dat->{'frameworkcode'}, 'opac');
+    my $collections =  GetKohaAuthorisedValues('items.ccode',$dat->{'frameworkcode'}, 'opac');
+
+       for my $itm (@items) {
+           if ($itm->{'location'}){
+           $itm->{'location_description'} = $shelflocations->{$itm->{'location'} };
+               }
+       }
+       # COinS format FIXME: for books Only
+        my $coins_format;
+        my $fmt = substr $record->leader(), 6,2;
+        my $fmts;
+        $fmts->{'am'} = 'book';
+        $dat->{ocoins_format} = $fmts->{$fmt};
+
+    if ( $num % 2 == 1 ) {
+        $dat->{'even'} = 1;
+    }
+
+    $num++;
+    $dat->{biblionumber} = $biblionumber;
+    $dat->{ITEM_RESULTS}   = \@items;
+    $dat->{MARCNOTES}      = $marcnotesarray;
+    $dat->{MARCSUBJCTS}    = $marcsubjctsarray;
+    $dat->{MARCAUTHORS}    = $marcauthorsarray;
+    $dat->{MARCSERIES}  = $marcseriesarray;
+    $dat->{MARCURLS}    = $marcurlsarray;
+    $dat->{HASAUTHORS}  = $hasauthors;
+
+    if ( C4::Context->preference("BiblioDefaultView") eq "normal" ) {
+        $dat->{dest} = "opac-detail.pl";
+    }
+    elsif ( C4::Context->preference("BiblioDefaultView") eq "marc" ) {
+        $dat->{dest} = "opac-MARCdetail.pl";
+    }
+    else {
+        $dat->{dest} = "opac-ISBDdetail.pl";
+    }
+    push( @results, $dat );
+}
+
+my $resultsarray = \@results;
+
+# my $itemsarray=\@items;
+
+$template->param(
+    BIBLIO_RESULTS => $resultsarray,
+);
+
+output_html_with_http_headers $query, $cookie, $template->output;
diff --git a/basket/downloadcart.pl b/basket/downloadcart.pl
new file mode 100755 (executable)
index 0000000..9733c11
--- /dev/null
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+
+# Copyright 2009 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., 59 Temple Place,
+# Suite 330, Boston, MA  02111-1307 USA
+
+use strict;
+use warnings;
+
+use CGI;
+use Encode qw(encode);
+use Switch;
+
+use C4::Auth;
+use C4::Biblio;
+use C4::Items;
+use C4::Output;
+use C4::VirtualShelves;
+use C4::Record;
+use C4::Ris;
+use C4::Csv;
+use utf8;
+use open qw( :std :utf8);
+my $query = new CGI;
+
+my ( $template, $borrowernumber, $cookie ) = get_template_and_user (
+    {
+        template_name   => "basket/downloadcart.tmpl",
+        query           => $query,
+        type            => "intranet",
+        authnotrequired => 0,
+        flagsrequired   => { borrow => 1 },
+    }
+);
+
+my $bib_list = $query->param('bib_list');
+my $format  = $query->param('format');
+my $dbh     = C4::Context->dbh;
+
+if ($bib_list && $format) {
+
+    my @bibs = split( /\//, $bib_list );
+
+    my $marcflavour         = C4::Context->preference('marcflavour');
+    my $output;
+
+    # retrieve biblios from shelf
+    my $firstpass = 1;
+    foreach my $biblio (@bibs) {
+
+       my $record = GetMarcBiblio($biblio);
+
+       switch ($format) {
+           case "iso2709" { $output .= $record->as_usmarc(); }
+           case "ris"     { $output .= marc2ris($record); }
+           case "bibtex"  { $output .= marc2bibtex($record, $biblio); }
+           # We're in the case of a csv profile (firstpass is used for headers printing) :
+            case /^\d+$/   { $output .= marc2csv($record, $format, $firstpass); }
+       }
+        $firstpass = 0;
+
+    }
+
+    # If it was a CSV export we change the format after the export so the file extension is fine
+    $format = "csv" if ($format =~ m/^\d+$/);
+
+    print $query->header(
+       -type => 'application/octet-stream',
+       -'Content-Transfer-Encoding' => 'binary',
+       -attachment=>"cart.$format");
+    print $output;
+
+} else { 
+    $template->param(csv_profiles => GetCsvProfilesLoop());
+    $template->param(bib_list => $bib_list); 
+    output_html_with_http_headers $query, $cookie, $template->output;
+}
diff --git a/basket/sendbasket.pl b/basket/sendbasket.pl
new file mode 100755 (executable)
index 0000000..6efa6bc
--- /dev/null
@@ -0,0 +1,181 @@
+#!/usr/bin/perl
+
+# 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., 59 Temple Place,
+# Suite 330, Boston, MA  02111-1307 USA
+
+use strict;
+use warnings;
+
+use CGI;
+use Encode qw(encode);
+
+use Mail::Sendmail;
+use MIME::QuotedPrint;
+use MIME::Base64;
+use C4::Biblio;
+use C4::Items;
+use C4::Auth;
+use C4::Output;
+use C4::Biblio;
+
+my $query = new CGI;
+
+my ( $template, $borrowernumber, $cookie ) = get_template_and_user (
+    {
+        template_name   => "basket/sendbasketform.tmpl",
+        query           => $query,
+        type            => "intranet",
+        authnotrequired => 0,
+        flagsrequired   => { borrow => 1 },
+    }
+);
+
+my $bib_list     = $query->param('bib_list');
+my $email_add    = $query->param('email_add');
+my $email_sender = $query->param('email_sender');
+
+my $dbh          = C4::Context->dbh;
+
+if ( $email_add ) {
+    my $email_from = C4::Context->preference('KohaAdminEmailAddress');
+    my $comment    = $query->param('comment');
+    my %mail = (
+        To   => $email_add,
+        From => $email_from
+    );
+
+    my ( $template2, $borrowernumber, $cookie ) = get_template_and_user(
+        {
+            template_name   => "basket/sendbasket.tmpl",
+            query           => $query,
+            type            => "intranet",
+            authnotrequired => 0,
+            flagsrequired   => { borrow => 1 },
+        }
+    );
+
+    my @bibs = split( /\//, $bib_list );
+    my @results;
+    my $iso2709;
+    my $marcflavour = C4::Context->preference('marcflavour');
+    foreach my $biblionumber (@bibs) {
+        $template2->param( biblionumber => $biblionumber );
+
+        my $dat              = GetBiblioData($biblionumber);
+        my $record           = GetMarcBiblio($biblionumber);
+        my $marcnotesarray   = GetMarcNotes( $record, $marcflavour );
+        my $marcauthorsarray = GetMarcAuthors( $record, $marcflavour );
+        my $marcsubjctsarray = GetMarcSubjects( $record, $marcflavour );
+
+        my @items = &GetItemsInfo( $biblionumber, 'opac' );
+
+        my $hasauthors = 0;
+        if($dat->{'author'} || @$marcauthorsarray) {
+          $hasauthors = 1;
+        }
+       
+
+        $dat->{MARCNOTES}      = $marcnotesarray;
+        $dat->{MARCSUBJCTS}    = $marcsubjctsarray;
+        $dat->{MARCAUTHORS}    = $marcauthorsarray;
+        $dat->{HASAUTHORS}     = $hasauthors;
+        $dat->{'biblionumber'} = $biblionumber;
+        $dat->{ITEM_RESULTS}   = \@items;
+
+        $iso2709 .= $record->as_usmarc();
+
+        push( @results, $dat );
+    }
+
+    my $resultsarray = \@results;
+    $template2->param(
+        BIBLIO_RESULTS => $resultsarray,
+        email_sender   => $email_sender,
+        comment        => $comment
+    );
+
+    # Getting template result
+    my $template_res = $template2->output();
+    my $body;
+
+    # Analysing information and getting mail properties
+    if ( $template_res =~ /<SUBJECT>\n(.*)\n<END_SUBJECT>/s ) {
+        $mail{'subject'} = $1;
+    }
+    else { $mail{'subject'} = "no subject"; }
+
+    my $email_header = "";
+    if ( $template_res =~ /<HEADER>\n(.*)\n<END_HEADER>/s ) {
+        $email_header = $1;
+    }
+
+    my $email_file = "basket.txt";
+    if ( $template_res =~ /<FILENAME>\n(.*)\n<END_FILENAME>/s ) {
+        $email_file = $1;
+    }
+
+    if ( $template_res =~ /<MESSAGE>\n(.*)\n<END_MESSAGE>/s ) { $body = encode_qp($1); }
+
+    my $boundary = "====" . time() . "====";
+
+    #     $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\"";
+    #
+    #     $email_header = encode_qp($email_header);
+    #
+    #     $boundary = "--".$boundary;
+    #
+    #     # Writing mail
+    #     $mail{body} =
+    $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\"";
+    my $isofile = encode_base64(encode("UTF-8", $iso2709));
+    $boundary = '--' . $boundary;
+    $mail{body} = <<END_OF_BODY;
+$boundary
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+$email_header
+$body
+$boundary
+Content-Type: application/octet-stream; name="basket.iso2709"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename="basket.iso2709"
+
+$isofile
+$boundary--
+END_OF_BODY
+
+    # Sending mail
+    if ( sendmail %mail ) {
+        # do something if it works....
+        $template->param( SENT      => "1" );
+    }
+    else {
+        # do something if it doesnt work....
+        warn "Error sending mail: $Mail::Sendmail::error \n";
+        $template->param( error => 1 );
+    }
+    $template->param( email_add => $email_add );
+    output_html_with_http_headers $query, $cookie, $template->output;
+}
+else {
+    $template->param( bib_list => $bib_list );
+    $template->param(
+        url            => "/cgi-bin/koha/basket/sendbasket.pl",
+        suggestion     => C4::Context->preference("suggestion"),
+        virtualshelves => C4::Context->preference("virtualshelves"),
+    );
+    output_html_with_http_headers $query, $cookie, $template->output;
+}
diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/tags.js b/koha-tmpl/intranet-tmpl/prog/en/js/tags.js
new file mode 100644 (file)
index 0000000..9c117d0
--- /dev/null
@@ -0,0 +1,158 @@
+if (typeof KOHA == "undefined" || !KOHA) {
+    var KOHA = {};
+}
+
+/**
+* A namespace for Tags related functions.
+* readCookie is expected to already be declared.  That's why the assignment below is unscoped.
+* readCookie should be from basket.js or undefined.
+
+$.ajaxSetup({
+       url: "/cgi-bin/koha/tags/tags.pl",
+       type: "POST",
+       dataType: "script"
+});
+*/
+if (typeof(readCookie) == "undefined") {
+       readCookie = function (name) { // from http://www.quirksmode.org/js/cookies.html
+               var nameEQ = name + "=";
+               var ca = document.cookie.split(';');
+               for (var i=0;i < ca.length;i++) {
+                       var c = ca[i];
+                       while (c.charAt(0)==' '){ c = c.substring(1,c.length); }
+                       if (c.indexOf(nameEQ) == 0){ return c.substring(nameEQ.length,c.length); }
+               }
+               return null;
+       }
+}
+KOHA.Tags = {
+       add_tag_button: function(){
+               var mybibnum = $(this).attr("title");
+               var mynewtag = "newtag" + mybibnum;
+               var mytagid = "#" + mynewtag;
+               var mydata = {CGISESSID: readCookie('CGISESSID')};      // Someday this should be OPACSESSID
+               mydata[mynewtag] = $(mytagid).val();    // need [bracket] for variable property id
+               var response;   // AJAX from server will assign value to response.
+               $.post(
+                       "/cgi-bin/koha/tags/tags.pl",
+                       mydata,
+                       function(data){
+                               // alert("AJAX Response: " + data);
+                               eval(data);
+                               // alert("counts: " + response["added"] + response["deleted"] + response["errors"]);
+                               KOHA.Tags.set_tag_status(
+                                       mytagid + "_status",
+                                       KOHA.Tags.common_status(response["added"], response["deleted"], response["errors"])
+                               );
+                               if (response.alerts) {
+                                       alert(response.alerts.join("\n\n"));
+                               }
+                       },
+                       'script'
+               );
+               return false;
+       },
+       common_status : function(addcount, delcount, errcount) {
+           var cstat = "";
+           if (addcount && addcount > 0) {cstat += _("Added ")   + addcount + (addcount==1 ? _(" tag") : _(" tags")) + ".  " ;}
+           if (delcount && delcount > 0) {cstat += _("Deleted ") + delcount + (delcount==1 ? _(" tag") : _(" tags")) + ".  " ;}
+           if (errcount && errcount > 0) {cstat += (errcount==1 ? _("ERROR") : errcount + _(" ERRORS")) + _(" during operation.");}
+           return cstat;
+       },
+       set_tag_status : function(tagid, newstatus) {
+               $(tagid).html(newstatus);
+               $(tagid).css({display:"inline"});
+       },
+       append_tag_status : function(tagid, newstatus) {
+               $(tagid).append(newstatus);
+               $(tagid).css({display:"inline"});
+       },
+
+       tag_message: {
+       tagsdisabled : function(arg) {return (_("Sorry, tags are not enabled on this system."));},
+       scrubbed_all_bad : function(arg) {return (_("Error! Your tag was entirely markup code.  It was NOT added.  Please try again with plain text."));},
+       badparam : function(arg) {return (_("Error! Illegal parameter '" +arg+ "'."));},
+       scrubbed : function(arg) {return (_("Note: your tag contained markup code that was removed. The tag was added as '" +arg+ "'."));},
+    failed_add_tag : function(arg) {return (_("Error! The add_tag operation failed on '" +arg+ "'.  Note: you can only tag an item with a given term once.  Check 'My Tags' to see your current tags."));},
+    failed_delete  : function(arg) {return (_("Error! You cannot delete the tag '" +arg+ "'.  Note: you can only delete your own tags."));},
+       login : function(arg) {return (_("You must be logged in to add tags."));}
+       },
+
+    // Used to tag multiple items at once.  The main difference
+    // is that status is displayed on a per item basis.
+    add_multitags_button : function(bibarray, tag){
+               var mydata = {CGISESSID: readCookie('CGISESSID')};      // Someday this should be OPACSESSID
+        for (var i = 0; i < bibarray.length; i++) {
+            var mynewtag = "newtag" + bibarray[i];
+            mydata[mynewtag] = tag;
+        }
+               var response;   // AJAX from server will assign value to response.
+               $.post(
+                       "/cgi-bin/koha/tags/tags.pl",
+                       mydata,
+                       function(data){
+                               eval(data);
+                $(".tagstatus").empty();
+                var bibErrors = false;
+
+                // Display the status for each tagged bib
+                for (var i = 0; i < bibarray.length; i++) {
+                    var bib = bibarray[i];
+                    var mytagid = "#newtag" + bib;
+                    var status = "";
+
+                    // Number of tags added.
+                    if (response[bib]) {
+                        var added = response[bib]["added"];
+                        if (added > 0) {
+                            status = "Added " + added + (added == 1 ? " tag" : " tags") + ".  ";
+                                       KOHA.Tags.set_tag_status(mytagid + "_status", status);
+                        }
+
+                        // Show a link that opens an error dialog, if necessary.
+                        var errors = response[bib]["errors"];
+                        if (errors.length > 0) {
+                            bibErrors = true;    
+                            var errid = "tagerr_" + bib;
+                            var errstat = "<a id=\"" + errid + "\" class=\"tagerror\" href=\"#\">";
+                            errstat += "Error" + (errors.length > 1 ? "s" : "") + " adding tag.";
+                            errstat += "</a>";
+                                           KOHA.Tags.append_tag_status(mytagid + "_status", errstat);
+                            var errmsg = "";
+                            for (var e = 0; e < errors.length; e++){
+                                if (e) {
+                                    errmsg += "\n\n";
+                                }
+                                errmsg += errors[e];
+                            }
+                            $("#" + errid).click(function(){
+                                alert(errmsg);
+                            });
+                        }
+                    }
+                }
+
+                if (bibErrors || response["global_errors"]) {
+                    var msg = "";
+                    if (bibErrors) {
+                        msg = "Unable to add one or more tags.";
+                    }
+
+                    // Show global errors in a dialog.
+                    if (response["global_errors"]) {
+                        var global_errors = response["global_errors"];
+                        var msg;
+                        for (var e = 0; e < global_errors.length; e++) {
+                            msg += "\n\n";
+                            msg += response.alerts[global_errors[e]];
+                        }
+                    }
+                    alert(msg);
+                }
+                       },
+                       'script'
+               );
+               return false;
+    }
+};
+
diff --git a/koha-tmpl/intranet-tmpl/prog/en/lib/jquery/plugins/jquery.dropshadow-min.js b/koha-tmpl/intranet-tmpl/prog/en/lib/jquery/plugins/jquery.dropshadow-min.js
new file mode 100644 (file)
index 0000000..9b1b1fb
--- /dev/null
@@ -0,0 +1 @@
+(function(B){var A=1;B.fn.dropShadow=function(C){var D=B.extend({left:4,top:4,blur:2,opacity:0.5,color:"black",swap:false},C);var E=B([]);this.not(".dropShadow").each(function(){var N=B(this);var J=[];var G=(D.blur<=0)?0:D.blur;var M=(G==0)?D.opacity:D.opacity/(G*8);var O=(D.swap)?A:A+1;var F=(D.swap)?A+1:A;var P;if(this.id){P=this.id+"_dropShadow"}else{P="ds"+(1+Math.floor(9999*Math.random()))}B.data(this,"shadowId",P);B.data(this,"shadowOptions",C);N.attr("shadowId",P).css("zIndex",O);if(N.css("position")!="absolute"){N.css({position:"relative",zoom:1})}bgColor=N.css("backgroundColor");if(bgColor=="rgba(0, 0, 0, 0)"){bgColor="transparent"}if(bgColor!="transparent"||N.css("backgroundImage")!="none"||this.nodeName=="SELECT"||this.nodeName=="INPUT"||this.nodeName=="TEXTAREA"){J[0]=B("<div></div>").css("background",D.color)}else{J[0]=N.clone().removeAttr("id").removeAttr("name").removeAttr("shadowId").css("color",D.color)}J[0].addClass("dropShadow").css({height:N.outerHeight(),left:G,opacity:M,position:"absolute",top:G,width:N.outerWidth(),zIndex:F});var L=(8*G)+1;for(K=1;K<L;K++){J[K]=J[0].clone()}var K=1;var I=G;while(I>0){J[K].css({left:I*2,top:0});J[K+1].css({left:I*4,top:I*2});J[K+2].css({left:I*2,top:I*4});J[K+3].css({left:0,top:I*2});J[K+4].css({left:I*3,top:I});J[K+5].css({left:I*3,top:I*3});J[K+6].css({left:I,top:I*3});J[K+7].css({left:I,top:I});K+=8;I--}var H=B("<div></div>").attr("id",P).addClass("dropShadow").css({left:N.position().left+D.left-G,marginTop:N.css("marginTop"),marginRight:N.css("marginRight"),marginBottom:N.css("marginBottom"),marginLeft:N.css("marginLeft"),position:"absolute",top:N.position().top+D.top-G,zIndex:F});for(K=0;K<L;K++){H.append(J[K])}N.after(H);E=E.add(H);B(window).resize(function(){try{H.css({left:N.position().left+D.left-G,top:N.position().top+D.top-G})}catch(Q){}});A+=2});return this.pushStack(E)};B.fn.redrawShadow=function(){this.removeShadow();return this.each(function(){var C=B.data(this,"shadowOptions");B(this).dropShadow(C)})};B.fn.removeShadow=function(){return this.each(function(){var C=B(this).shadowId();B("div#"+C).remove()})};B.fn.shadowId=function(){return B.data(this[0],"shadowId")};B(function(){var C="<style type='text/css' media='print'>";C+=".dropShadow{visibility:hidden;}</style>";B("head").append(C)})})(jQuery);
\ No newline at end of file
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tmpl
new file mode 100644 (file)
index 0000000..23713a0
--- /dev/null
@@ -0,0 +1,436 @@
+<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
+<!-- TMPL_IF NAME="LibraryNameTitle" --><!-- TMPL_VAR NAME="LibraryNameTitle" --><!-- TMPL_ELSE -->Koha Online<!-- /TMPL_IF --> Catalog &rsaquo; Your Cart
+    <!-- TMPL_IF NAME="print_basket" --></title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<link rel="shortcut icon" href="<!-- TMPL_VAR NAME="themelang" -->/includes/favicon.ico" type="image/x-icon" />
+<meta http-equiv="Content-Language" content="en-us" />
+<style type="text/css"> 
+    @import url(<!-- TMPL_VAR NAME="themelang" -->/css/print.css);
+</style>
+    <!-- TMPL_ELSE --><!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
+       <script type="text/javascript" src="<!-- TMPL_VAR name="themelang" -->/lib/jquery/plugins/jquery.checkboxes.min.js"></script>
+       <script type="text/javascript" src="<!-- TMPL_VAR name="themelang" -->/lib/jquery/plugins/jquery.tablesorter.min.js"></script>
+       <script type="text/javascript">
+       //<![CDATA[
+
+$(document).ready(function() 
+    { 
+        $("#itemst").tablesorter({
+                        headers: { 0: { sorter: false }}
+                }); 
+    } 
+); 
+    
+
+function placeHold () {
+    var checkedItems = $("input:checkbox:checked");
+    if ($(checkedItems).size() == 0) {
+        alert(MSG_NO_RECORD_SELECTED);
+        return false;
+    }
+    var bibs = "";
+    var badBibs = false;
+    $(checkedItems).each(function() {
+        var bib = $(this).val();
+        bibs += bib + "/";
+    });
+
+    var newloc = "/cgi-bin/koha/reserve/request.pl?biblionumbers=" + bibs;
+    if ($(checkedItems).size() > 1) { newloc += "&multi_hold=1"; }
+    window.opener.location = newloc;
+    window.close();
+}
+
+
+
+var MSG_NO_TAG_SPECIFIED = _("No tag was specified.");
+
+function tagSelected() {
+    var bibs = document.getElementById('records').value;
+    if (bibs) {
+        $("#tagsel_tag").hide();
+        $("#tag_hides").hide();
+        $("#tagsel_form").show();
+    } else {
+        alert(MSG_NO_RECORD_SELECTED);
+    }
+}
+
+function tagCanceled() {
+    $("#tagsel_form").hide();
+    $("#tagsel_tag").show();
+    $("#tag_hides").show();
+}
+
+function tagAdded() {
+    var checkedBoxes = $("input:checkbox:checked");
+    if (!$(checkedBoxes).size()) {
+        alert(MSG_NO_RECORD_SELECTED);
+        return false;
+    }
+
+    var tag = $("#tagsel_new").val();
+    if (!tag || (tag == "")) {
+        alert(MSG_NO_TAG_SPECIFIED);
+        return false;
+    }
+
+    var bibs = [];
+    for (var i = 0; i < $(checkedBoxes).size(); i++) {
+        var box = $(checkedBoxes).get(i);
+        bibs[i] = $(box).val();
+    }
+
+    KOHA.Tags.add_multitags_button(bibs, tag);
+    return false;
+}
+
+       $(document).ready(function(){
+               $("#CheckAll").click(function(){
+               var checked = [];
+               $("#bookbag_form").checkCheckboxes("*", true).each(
+                   function() {
+                               selRecord(this.value,true); 
+                       }
+               ); 
+               return false;
+           });
+           $("#CheckNone").click(function(){
+           var checked = [];
+               $("#bookbag_form").unCheckCheckboxes("*",true).each(
+                   function() {
+                               selRecord(this.value,false);
+                       }
+               );
+               return false;
+           });
+<!-- TMPL_IF NAME="RequestOnOpac" -->
+        $(".holdsep").text("| ");
+        $(".hold").text(_("Place Hold"));
+<!-- /TMPL_IF -->
+  
+        <!-- TMPL_IF NAME="TagsEnabled" -->
+        <!-- TMPL_IF NAME="TagsInputOnList" -->
+          $(".tagsep").text("| ");
+          $("#tagsel_tag").text(_("Tag"));
+          $("#tagsel_button").click(function(){
+              tagAdded();
+              return false;
+          });
+        <!-- /TMPL_IF -->
+        <!-- /TMPL_IF -->
+       });
+
+   
+       //]]>
+       </script>
+       <!-- /TMPL_IF -->
+</head>
+<!-- TMPL_IF NAME="print_basket" --><body id="basket" onload="print();history.back();"><!-- TMPL_ELSE --><body id="basket"><!-- /TMPL_IF -->
+
+<div id="doc" class="yui-t7">
+<div class="container">
+<!-- TMPL_UNLESS NAME="print_basket" -->
+<h1>Your Cart</h1>
+
+<div id="toolbar">
+<ul class="toolbar">
+       <li>
+           <span id="addchild" class="yui-button yui-link-button"><span class="first-child">
+               <!-- TMPL_IF NAME="verbose" --><a href="opac-basket.pl" class="brief" onclick="showLess(); return false;">Brief Display</a><!-- TMPL_ELSE --><a href="basket.pl" class="detail" onclick="showMore(); return false;">More Details</a><!-- /TMPL_IF -->
+           </span></span>
+       </li>
+       <li>
+           <span id="receive" class="yui-button yui-link-button"><span class="first-child">
+               <a class="send" href="basket.pl" onclick="sendBasket(); return false;">Send</a>
+           </span></span>
+       </li>
+       <li>
+           <span id="savemenuc" class="yui-button yui-link-button"><span class="first-child">
+               <a class="download" href="basket.pl" onclick="downloadBasket(); return false;">Download</a>
+           </span></span>
+       </li>
+       <li>
+           <span id="printmenuc" class="yui-button yui-link-button"><span class="first-child">
+               <a class="print" href="basket.pl" onclick="printBasket(); return false;">Print</a>
+           </span></span>
+       </li>
+       <li>
+           <span id="delete" class="yui-button yui-link-button"><span class="first-child">
+               <a class="empty" href="basket.pl" onclick="delBasket(); return false;">Empty and Close</a>
+           </span></span>
+       </li>
+       <li>
+           <span id="delete" class="yui-button yui-link-button"><span class="first-child">
+               <a class="hide" href="basket.pl" onclick="quit(); return false;">Hide Window</a>
+           </span></span>
+       </li>
+</ul>
+</div>
+        <!-- /TMPL_UNLESS -->
+
+<!-- TMPL_IF NAME="verbose" -->
+       <!-- TMPL_UNLESS NAME="print_basket" --><p style="padding: 7px 0; border-top : 1px solid #E8E8E8;"><a id="CheckAll" href="#">Select All</a> <a id="CheckNone" href="#">Clear All</a> | <b>Selected items :</b>
+<span id="tag_hides">
+<a href="#" onclick="delSelRecords(); return false;">Remove</a>
+
+<!-- TMPL_IF NAME="loggedinusername" -->
+     | <a href="#" onclick="addSelToShelf(); return false;">Add to a list</a>
+<!-- /TMPL_IF -->
+
+<!-- TMPL_IF NAME="CAN_user_reserveforothers" -->
+     | <a href="#" onclick="placeHold(); return false;">Place Hold</a>
+<!-- /TMPL_IF -->
+
+     <span class="tagsep"></span>
+     <a href="#" onclick="tagSelected(); return false;"><span id="tagsel_tag"></span></a>
+</span>
+     <span id="tagsel_form" style="display:none">
+       <label for="tagsel_new" style="display:inline">New&nbsp;Tag:</label>
+       <input name="tagsel_new" id="tagsel_new" maxlength="100" style="display:inline"/>
+       <input id="tagsel_button" name="tagsel_button" class="input tagsel_button" title="tagsel_button"
+           type="submit" value="Add" style="display:inline" />
+       <a href="#" id="tagsel_cancel" onclick="tagCanceled(); return false;" style="display:inline">Cancel</a>
+     </span>
+</p><!-- /TMPL_UNLESS -->
+            <form action="opac-basket.pl" method="get" name="bookbag_form" id="bookbag_form">
+    <!-- TMPL_LOOP NAME="BIBLIO_RESULTS" -->
+    <h3>
+        <!-- TMPL_IF NAME="print_basket" -->
+            <!-- TMPL_VAR NAME="title" -->
+                <!-- TMPL_IF name="subtitle" --> <!-- TMPL_VAR NAME="subtitle" --><!-- /TMPL_IF -->
+                <!-- TMPL_IF name="author" --> <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF -->
+        <!-- TMPL_ELSE -->
+                <input type="checkbox" value="<!-- TMPL_VAR NAME="biblionumber" -->" name="bib<!-- TMPL_VAR NAME="biblionumber" -->" id="bib<!-- TMPL_VAR NAME="biblionumber" -->" onclick="selRecord(value,checked)" />
+                <!-- TMPL_VAR NAME="title" escape="html" -->
+                <!-- TMPL_IF name="subtitle" --> <!-- TMPL_VAR NAME="subtitle" --><!-- /TMPL_IF -->
+                <!-- TMPL_IF name="author" --> <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF -->
+        <!-- /TMPL_IF -->
+    </h3>
+           <!-- COinS / OpenURL -->
+    <span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.au=<!-- TMPL_VAR NAME="author" -->&amp;rft.btitle=<!-- TMPL_VAR NAME="title" ESCAPE="url" -->&amp;rft.date=<!-- TMPL_VAR NAME="publicationyear" -->&amp;rft.tpages=<!-- TMPL_VAR NAME="size" -->&amp;rft.isbn=<!-- TMPL_VAR NAME="isbn"  ESCAPE="url" -->&amp;rft.aucorp=&amp;rft.place=<!-- TMPL_VAR NAME="place" -->&amp;rft.pub=<!-- TMPL_VAR NAME="publisher" ESCAPE="url" -->&amp;rft.edition=<!-- TMPL_VAR NAME="edition" -->&amp;rft.series=<!-- TMPL_VAR NAME="series" -->&amp;rft.genre="></span>
+    <table>
+        <!-- TMPL_IF name="isbn" -->
+        <tr>
+            <th scope="row">ISBN</th>
+            <td><!-- TMPL_VAR NAME="isbn" --></td>
+        </tr>
+        <!-- /TMPL_IF -->
+
+        <!-- TMPL_IF "HASAUTHORS" -->
+        <tr>
+            <th scope="row">Author(s)</th>
+            <td>
+                   <!-- TMPL_IF NAME="author" -->
+                       <p><!-- TMPL_VAR NAME="author" --></p>
+                   <!-- /TMPL_IF -->
+                   <!-- TMPL_IF NAME="MARCAUTHORS" -->
+                       <!-- TMPL_LOOP NAME="MARCAUTHORS" -->
+                       <p> <!-- TMPL_LOOP NAME="MARCAUTHOR_SUBFIELDS_LOOP" -->
+                              <!-- TMPL_VAR NAME="separator" -->
+                                  <!-- TMPL_VAR NAME="value" -->
+                           <!-- /TMPL_LOOP -->
+                       </p>
+                       <!-- /TMPL_LOOP -->
+                   <!-- /TMPL_IF -->
+           </td>
+        </tr>
+        <!-- /TMPL_IF -->
+        
+        <!-- TMPL_IF NAME="publishercode" -->
+            <tr>
+                <th scope="row">Publisher</th>
+                <td><!-- TMPL_VAR NAME="place" --> <!-- TMPL_VAR NAME="publishercode" --> <!-- TMPL_VAR NAME="publicationyear" -->
+                </td>
+            </tr>
+        <!-- /TMPL_IF -->
+        <!-- TMPL_IF NAME="pages" -->
+            <tr>
+                <th scope="row">Details</th>
+                <td><!-- TMPL_VAR NAME="pages" --> <!-- TMPL_VAR NAME="illus" --> <!-- TMPL_VAR NAME="size" --></td>
+            </tr>
+        <!-- /TMPL_IF -->
+        <!-- TMPL_IF name="seriestitle" -->
+        <tr>
+            <th scope="row">Collection</th>
+            <td> <!-- TMPL_VAR NAME="seriestitle" --></td>
+        </tr>
+        <!-- /TMPL_IF -->
+        
+        <!-- TMPL_IF name="MARCSUBJCTS" -->
+        <tr>
+            <th scope="row">Subject(s)</th>
+            <td><!-- TMPL_LOOP NAME="MARCSUBJCTS" -->
+                   <p> <!-- TMPL_LOOP NAME="MARCSUBJECT_SUBFIELDS_LOOP" -->
+                        <!-- TMPL_VAR NAME="separator" --><!-- TMPL_VAR NAME="value" --><!-- /TMPL_LOOP -->
+                   </p>
+                <!-- /TMPL_LOOP --></td>
+        </tr>
+        <!-- /TMPL_IF -->
+    
+        <!-- TMPL_IF name="copyrightdate" -->
+            <tr><th scope="row">Copyright</th>
+                <td> <!-- TMPL_VAR NAME="copyrightdate" --></td>
+            </tr>
+        <!-- /TMPL_IF -->
+    
+        <!-- TMPL_IF name="MARCNOTES" -->
+        <tr>
+            <th scope="row">Notes</th>
+            <td>
+            <!-- TMPL_LOOP NAME="MARCNOTES" -->
+                <p>- <!-- TMPL_VAR NAME="marcnote" --></p>
+            <!-- /TMPL_LOOP --></td>
+        </tr>
+        <!-- /TMPL_IF -->
+    
+        <!-- TMPL_IF name="unititle" -->
+        <tr>
+            <th scope="row">Unified title</th>
+            <td> <!-- TMPL_VAR NAME="unititle" --></td>
+        </tr>
+        <!-- /TMPL_IF -->
+        <!-- TMPL_IF name="serial" -->
+        <tr>
+            <th scope="row">Serial</th>
+            <td><!-- TMPL_VAR NAME="serial" --></td>
+        </tr>
+        <!-- /TMPL_IF -->
+        <!-- TMPL_IF name="dewey" -->
+        <tr>
+            <th scope="row">Dewey</th>
+            <td><!-- TMPL_VAR name="dewey" --></td>
+        </tr>
+        <!-- /TMPL_IF -->
+        <!-- TMPL_IF name="classification" -->
+        <tr>
+            <th scope="row">Classification</th>
+            <td> <!-- TMPL_VAR name="classification" --></td>
+        </tr>
+        <!-- /TMPL_IF -->
+        <!-- TMPL_IF name="lccn" -->
+        <tr>
+            <th scope="row">LCCN</th>
+            <td> <!-- TMPL_VAR name="lccn" --></td>
+        </tr>
+        <!-- /TMPL_IF -->
+               
+        <!-- TMPL_IF name="MARCURLS" -->
+        <tr>
+            <th scope="row">URL(s)</th>
+            <td>
+          <!-- TMPL_LOOP name="MARCURLS" -->
+               <p><!-- TMPL_IF NAME="part" --><!-- TMPL_VAR NAME="part" -->
+                       <br /><!-- /TMPL_IF --> 
+       
+               <!-- TMPL_VAR NAME="MARCURL" -->
+                       <!-- TMPL_IF NAME="notes" --><!-- TMPL_LOOP NAME="notes" --><!-- TMPL_VAR NAME="note" --><br /><!-- /TMPL_LOOP --><!-- /TMPL_IF -->
+            <!-- /TMPL_LOOP --></p></td>
+        </tr><!-- /TMPL_IF -->
+               
+        <tr>
+            <th scope="row">Location(s)</th>
+            <td><!-- TMPL_IF NAME="ITEM_RESULTS" --><!-- TMPL_LOOP NAME="ITEM_RESULTS" -->
+                <p>
+                    <!-- TMPL_VAR NAME="branchname" --> <!-- TMPL_VAR NAME="location_description" -->
+                    <!-- TMPL_IF name="itemcallnumber" -->
+                        (<!-- TMPL_VAR NAME="itemcallnumber" -->)
+                    <!-- /TMPL_IF -->
+                </p>
+                <!-- /TMPL_LOOP --><!-- TMPL_ELSE -->This record has no items.<!-- /TMPL_IF --></td>
+        </tr>
+    </table>
+    <!-- /TMPL_LOOP -->
+            </form>
+
+<!-- TMPL_ELSE -->
+<!-- TMPL_UNLESS NAME="print_basket" -->
+<p style="border-top : 1px solid #E8E8E8;">
+       <form action="/cgi-bin/koha/basket/basket.pl" method="get" name="bookbag_form" id="bookbag_form">
+    <a id="CheckAll" href="#">Select All</a> 
+    <a id="CheckNone" href="#">Clear All</a>
+    | <b>Selected items :</b>
+<span id="tag_hides">                
+<a href="#" onclick="delSelRecords(); return false;">Remove</a>
+
+<!-- TMPL_IF NAME="loggedinusername" -->
+     | <a href="#" onclick="addSelToShelf(); return false;">Add to a list</a>
+<!-- /TMPL_IF -->
+
+<!-- TMPL_IF NAME="CAN_user_reserveforothers" -->
+     | <a href="#" onclick="placeHold(); return false;">Place Hold</a>
+<!-- /TMPL_IF -->
+
+
+     <span class="tagsep"></span><a href="#" onclick="tagSelected(); return false;"><span id="tagsel_tag"></span></a>
+</span>
+     <span id="tagsel_form" style="display:none">
+       <label for="tagsel_new" style="display:inline">New&nbsp;Tag:</label>
+       <input name="tagsel_new" id="tagsel_new" maxlength="100"  style="display:inline"/>
+       <input id="tagsel_button" name="tagsel_button" class="input tagsel_button" title="tagsel_button" type="submit" value="Add"  style="display:inline"/>
+       <a href="#" id="tagsel_cancel" onclick="tagCanceled(); return false;" style="display:inline">Cancel</a>
+     </span>
+<!-- /TMPL_UNLESS -->
+</p>
+    <table id="itemst">
+       <thead><tr>
+           <th>&nbsp;</th>
+           <th>Title</th>
+           <th>Item Type</th>
+           <th>Location</th>
+        </tr></thead>
+
+        <!-- TMPL_LOOP NAME="BIBLIO_RESULTS" -->
+            <!-- TMPL_IF NAME="even" -->
+                <tr class="highlight">
+            <!-- TMPL_ELSE -->
+                <tr>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_UNLESS NAME="print_basket" --><td>
+                        <input type="checkbox" value="<!-- TMPL_VAR NAME="biblionumber" -->" name="bib<!-- TMPL_VAR NAME="biblionumber" -->" id="bib<!-- TMPL_VAR NAME="biblionumber" -->" onclick="selRecord(value,checked);" />
+                   
+                </td> <!-- /TMPL_UNLESS -->
+            <td><a href="#" onclick="openBiblio('<!-- TMPL_VAR name="dest" -->',<!-- TMPL_VAR name="biblionumber" -->)">
+                        <!-- TMPL_VAR NAME="title" escape="html" -->
+                    </a>
+                        <!-- TMPL_VAR NAME="author" -->
+                        <p><!-- TMPL_IF name="publishercode" -->- <!-- TMPL_VAR name="publishercode" -->
+                        <!-- TMPL_IF name="place" --> <!-- TMPL_VAR name="place" --><!-- /TMPL_IF --><!-- /TMPL_IF -->
+                        <!-- TMPL_IF name="pages" --> - <!-- TMPL_VAR name="pages" --><!-- TMPL_IF name="size" --> <!-- TMPL_VAR name="size" -->
+                        <!-- /TMPL_IF -->
+                        <!-- /TMPL_IF --></p>
+                        <!-- TMPL_IF name="notes" -->
+                        <p><!-- TMPL_VAR name="notes" --></p>
+                        <!-- /TMPL_IF -->
+                                                   <!-- COinS / OpenURL -->
+    <span class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.au=<!-- TMPL_VAR NAME="author" -->&amp;rft.btitle=<!-- TMPL_VAR NAME="title" ESCAPE="url" -->&amp;rft.date=<!-- TMPL_VAR NAME="publicationyear" -->&amp;rft.tpages=<!-- TMPL_VAR NAME="size" -->&amp;rft.isbn=<!-- TMPL_VAR NAME="isbn"  ESCAPE="url" -->&amp;rft.aucorp=&amp;rft.place=<!-- TMPL_VAR NAME="place" -->&amp;rft.pub=<!-- TMPL_VAR NAME="publisher" ESCAPE="url" -->&amp;rft.edition=<!-- TMPL_VAR NAME="edition" -->&amp;rft.series=<!-- TMPL_VAR NAME="series" -->&amp;rft.genre="></span>
+    <div id="newtag<!-- TMPL_VAR NAME="biblionumber">_status" class="tagstatus results_summary" style="display:none">Tag status here.</div>
+    
+                                               </td>
+            <td><!-- TMPL_VAR name="description" --></td>
+                <td><!-- TMPL_IF NAME="ITEM_RESULTS" --><!-- TMPL_LOOP NAME="ITEM_RESULTS" -->
+                    <p>
+                        <!-- TMPL_VAR NAME="branchname" --> <!-- TMPL_VAR NAME="location_description" -->
+                        <!-- TMPL_IF name="itemcallnumber" -->
+                            (<!-- TMPL_VAR NAME="itemcallnumber" -->)
+                        <!-- /TMPL_IF -->
+                    </p>
+                    <!-- /TMPL_LOOP --><!-- TMPL_ELSE -->This record has no items.<!-- /TMPL_IF --></td>
+            </tr>
+        <!-- /TMPL_LOOP -->
+    </table></form>
+<!-- /TMPL_IF -->
+
+<!-- TMPL_IF NAME="print_basket" -->
+<a href="#back" class="screen">&lt;&lt; Back to Cart</a>
+<!-- TMPL_ELSE -->
+<form name="myform" action="basket/basket.pl" method="get">
+    <input type="hidden" name="records" id="records" />
+</form>
+<!-- /TMPL_IF -->
+
+</div>
+</div>
+</body>
+</html>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/downloadcart.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/downloadcart.tmpl
new file mode 100644 (file)
index 0000000..d05e2a2
--- /dev/null
@@ -0,0 +1,28 @@
+<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->Download shelf<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
+</head>
+<body>
+<!-- TMPL_IF NAME="format" -->
+    Your Download should automatically start
+<!-- TMPL_ELSE -->
+<div id="export" class="detailtagcell">    <form method="post" action="/cgi-bin/koha/basket/downloadcart.pl">
+       <label for="format">Download cart:</label>
+        <select name="format" id="format">
+           <option value="">-- Choose Format --</option>
+           <option value="iso2709">iso2709</option>
+           <option value="ris">RIS</option>
+           <option value="bibtex">BibTex</option>
+           <!-- TMPL_LOOP NAME="csv_profiles" -->
+           <option value="<!-- TMPL_VAR NAME="export_format_id" -->">CSV - <!-- TMPL_VAR NAME="profile" --></option>
+           <!-- /TMPL_LOOP -->
+
+       </select>
+       <input type="hidden" name="bib_list" value="<!-- TMPL_VAR NAME="bib_list" -->" />
+       <input type="submit" name="save" value="Go" />
+    </form>
+
+    <p><a class="button" href="#" onclick="javascript:window.close()">Close this window</a></p>
+    </div>
+
+<!-- /TMPL_IF -->
+</body>
+</html>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasket.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasket.tmpl
new file mode 100644 (file)
index 0000000..033c4d2
--- /dev/null
@@ -0,0 +1,42 @@
+<SUBJECT>
+Your Cart
+<END_SUBJECT>
+
+<HEADER>
+Hi,
+
+Here is your cart, sent from our online catalog.
+
+Please note that the attached file is a MARC biblographic records file
+which can be imported into a Personal Bibliographic Software like EndNote,
+Reference Manager or ProCite.
+<END_HEADER>
+
+<MESSAGE>
+---------------------------------------------
+<!-- TMPL_IF NAME="comment" -->
+<!-- TMPL_VAR NAME="comment" -->
+<!-- /TMPL_IF -->
+<!-- TMPL_LOOP NAME="BIBLIO_RESULTS" --><!-- TMPL_VAR NAME="title" --><!-- TMPL_IF name="subtitle" --> <!-- TMPL_VAR NAME="subtitle" --><!-- /TMPL_IF --><!-- TMPL_IF "HASAUTHORS" -->
+Author(s): <!-- TMPL_IF NAME="author" --><!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF --><!-- TMPL_IF name="MARCAUTHORS" --><!-- TMPL_IF NAME="author" -->; <!-- /TMPL_IF --><!-- TMPL_LOOP NAME="MARCAUTHORS" --><!-- TMPL_LOOP NAME="MARCAUTHOR_SUBFIELDS_LOOP" --><!-- TMPL_VAR NAME="separator" --><!-- TMPL_VAR NAME="value" --><!-- /TMPL_LOOP --><!-- TMPL_UNLESS NAME="__last__" -->; <!-- TMPL_ELSE --><!-- /TMPL_UNLESS --><!-- /TMPL_LOOP --><!-- /TMPL_IF --><!-- /TMPL_IF --><!-- TMPL_IF name="ISBN" -->
+ISBN: <!-- TMPL_VAR NAME="ISBN" --><!-- /TMPL_IF -->
+<!-- TMPL_IF name="publishercode" -->Published by: <!-- TMPL_VAR NAME="publishercode" --><!-- /TMPL_IF --><!-- TMPL_IF name="publicationyear" --> in <!-- /TMPL_IF --><!-- TMPL_VAR NAME="publicationyear" --><!-- TMPL_IF name="pages" -->, <!-- /TMPL_IF --><!-- TMPL_VAR name="pages" --><!-- TMPL_IF name="size" -->, <!-- /TMPL_IF --><!-- TMPL_VAR name="size" --><!-- TMPL_IF name="collection" -->
+Collection: <!-- TMPL_VAR NAME="seriestitle" --><!-- /TMPL_IF --><!-- TMPL_IF name="subject" -->
+Subject: <!-- TMPL_VAR NAME="subject" --><!-- /TMPL_IF --><!-- TMPL_IF name="copyrightdate" -->
+Copyright year: <!-- TMPL_VAR NAME="copyrightdate" --><!-- /TMPL_IF --><!-- TMPL_IF name="notes" -->
+Notes : <!-- TMPL_VAR NAME="notes" --><!-- /TMPL_IF --><!-- TMPL_IF name="unititle" -->
+Unified title: <!-- TMPL_VAR NAME="unititle" --><!-- /TMPL_IF --><!-- TMPL_IF name="serial" -->
+Serial: <!-- TMPL_VAR NAME="serial" --><!-- /TMPL_IF --><!-- TMPL_IF name="dewey" -->
+Dewey: <!-- TMPL_VAR name="dewey" --><!-- /TMPL_IF --><!-- TMPL_IF name="classification" -->
+Classification: <!-- TMPL_VAR name="classification" --><!-- /TMPL_IF --><!-- TMPL_IF name="lccn" -->
+LCCN: <!-- TMPL_VAR name="lccn" --><!-- /TMPL_IF --><!-- TMPL_IF name="url" -->
+URL : <!-- TMPL_VAR NAME="url" --><!-- /TMPL_IF -->
+In the online catalog:
+<!-- TMPL_VAR NAME="OPACBaseURL" -->/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" escape="url" -->
+Items : <!-- TMPL_LOOP NAME="ITEM_RESULTS" -->
+       <!-- TMPL_VAR NAME="branchname" --> <!-- TMPL_VAR NAME="location" --> <!-- TMPL_IF name="itemcallnumber" -->(<!-- TMPL_VAR NAME="itemcallnumber" -->)<!-- /TMPL_IF --> <!-- TMPL_VAR NAME="barcode" --><!-- /TMPL_LOOP -->
+
+---------------------------------------------
+
+<!-- /TMPL_LOOP -->
+<END_MESSAGE>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasketform.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/sendbasketform.tmpl
new file mode 100644 (file)
index 0000000..9caef3c
--- /dev/null
@@ -0,0 +1,38 @@
+<!-- TMPL_INCLUDE NAME="doc-head-open.inc" --><!-- TMPL_IF NAME="LibraryNameTitle" --><!-- TMPL_VAR NAME="LibraryNameTitle" --><!-- TMPL_ELSE -->Koha Online<!-- /TMPL_IF --> Catalog &rsaquo;  Sending Your Cart
+<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
+</head>
+<body style="padding: 1em;" id="sendbasket">
+<div class="container"><!-- TMPL_IF NAME="email_add" -->
+
+       <!-- TMPL_IF NAME="SENT" -->
+               <h3>Message Sent</h3>
+           <p>The cart was sent to: <!-- TMPL_VAR NAME="email_add" --></p>
+               <p><a class="focus close" href="#">Close window</a></p>
+       <!-- /TMPL_IF  -->
+       <!-- TMPL_IF NAME="error" -->
+       <p>Problem sending the cart...</p>
+       <!-- /TMPL_IF -->
+       
+<!-- TMPL_ELSE -->
+
+<form action="<!-- TMPL_VAR NAME="url" -->" method="post">
+
+<fieldset class="rows"> 
+<legend>Sending your cart</legend>
+<ol>   <li>
+        <label for="email_add">Email Address:</label>
+        <input type="text" id="email_add" name="email_add" size="43" class="focus" />
+    </li>
+    <li>
+            <label for="comment">Comment:</label>
+            <textarea id="comment" name="comment" rows="4" cols="40"></textarea>
+    </li>
+    <li>
+        <input type="hidden" name="bib_list" value="<!-- TMPL_VAR NAME="bib_list" -->" />
+    </li></ol></fieldset>
+       <fieldset class="action"> <input type="submit" value="Send" /> <a class="cancel close" href="#">Cancel</a> </fieldset>
+</form>
+
+<!-- /TMPL_IF --></div>
+</body>
+</html>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tags/tags.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/tags/tags.tmpl
new file mode 100644 (file)
index 0000000..8681a8a
--- /dev/null
@@ -0,0 +1,149 @@
+<!-- TMPL_INCLUDE NAME="doc-head-open.inc" --><!-- TMPL_IF NAME="LibraryNameTitle" --><!-- TMPL_VAR NAME="LibraryNameTitle" --><!-- TMPL_ELSE -->Koha Online<!-- /TMPL_IF --> Catalog &rsaquo; Tags
+<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
+<script type="text/javascript" src="<!-- TMPL_VAR name="themelang" -->/lib/jquery/plugins/jquery.tablesorter.min.js"></script>
+<style type="text/css">
+       fieldset { padding : .3em;margin:.3em 0;}
+       #tagcloud    {background-color: #F3F3F3; text-align: justify;padding:7px;}
+       .tag a       {text-decoration: none;}
+       .tag a:hover {text-decoration: underline;}
+       .tag         {display: block; padding-left: 1em;}
+       .tagcount    {display: none;}
+       .cloudweight {display: none;}
+       .tagweight {
+               display: none;
+               position: relative;
+               bottom: 0.4em;
+               color: red;
+               font-size: 12px;
+       }
+</style>
+<script type="text/javascript">
+//<![CDATA[
+       var fontsizes = new Array (12,14,16,18,20,22,24,26,28,30);
+       var fontcount = fontsizes.length;
+       var maxcloudweight = 1;
+       $(document).ready(function() {
+               // $('#tagcloud').css('background-color','lightgrey');
+               // $('#tagcloud .tag').css('border','1px solid black');
+               $('#tagcloud .tag').each(function() {
+                       if (maxcloudweight < this.title) { maxcloudweight = this.title; }
+                       // have to run through the set of tags once to get the max: cannot be combined w/ 2nd pass
+               });
+               $('#tagcloud .tag').each(function(i) {
+                       var pos = this.id;
+                       var weight = this.title;        // "cloudweight"
+                       weight = (! weight) ? 1 : (weight > maxcloudweight) ? maxcloudweight : weight ;
+                       var index = Math.round(fontcount * weight/maxcloudweight) - 1;
+                       index  = (! index ) ? 0 : ( index > fontcount     ) ? fontcount      : index  ;
+                       var newsize = fontsizes[index];
+                       // alert(pos+ " (" +i+ ") weight = " +weight+ " of " +maxcloudweight+ ", fontsize[" +index+ " of " +fontcount+ "] = " +newsize);
+                       $('#' + pos).css({"font-size":(newsize + 'px'), display:"inline"});
+               });
+               $("#mytagst").tablesorter({<!-- TMPL_IF EXPR="dateformat eq 'metric'" -->
+    dateFormat: 'uk',<!-- /TMPL_IF -->
+            widgets : ['zebra'],
+                       headers: { 3: { sorter: false }},
+            sortList: [[2,0]]
+        });
+       });
+//]]>
+</script>
+</head>
+<!-- TMPL_IF NAME="loggedinusername" --><body id="opac-usertags"><!-- TMPL_ELSE --><body id="opac-tags"><!-- /TMPL_IF -->
+<!-- TMPL_IF EXPR="OpacNav||loggedinusername" --><div id="doc3" class="yui-t1"><!-- TMPL_ELSE --><div id="doc3" class="yui-t7"><!-- /TMPL_IF -->
+<div id="bd">
+<!-- TMPL_INCLUDE NAME="masthead.inc" -->
+
+<div id="yui-main">
+  <div class="yui-b"><div class="yui-g">
+       <div class="container">
+       <!-- TMPL_IF NAME="ERRORS" -->
+       <!-- TMPL_LOOP NAME="ERRORS" -->
+               <div class="dialog alert">There was a problem with this operation:
+               <!-- TMPL_IF NAME="tagsdisabled" -->Sorry, tags are not enabled on this system.
+               <!-- TMPL_ELSIF NAME="badparam" -->ERROR: illegal parameter <!-- TMPL_VAR NAME="badparam" -->
+               <!-- TMPL_ELSIF NAME="login"    -->ERROR: You must log in to complete that action.
+               <!-- TMPL_ELSIF NAME="failed_delete" -->ERROR: You cannot delete the tag <!-- TMPL_VAR NAME="failed_delete" -->.
+                                       <br />Note: you can only delete your own tags.
+               <!-- TMPL_ELSIF NAME="scrubbed" -->Note: your tag contained markup code that was removed. 
+                                       <br />The tag was added as &quot;<!-- TMPL_VAR NAME="scrubbed" -->&quot;.
+               <!-- TMPL_ELSIF NAME="scrubbed_all_bad" -->Note: your tag was entirely markup code.  It was NOT added.
+                                       <br />Please try again with plain text.
+               <!-- TMPL_ELSE -->Unrecognized error.
+               <!-- /TMPL_IF -->
+               </div>
+       <!-- /TMPL_LOOP -->
+       <!-- /TMPL_IF -->
+       <h1>All Tags</h1>
+       
+               <form method="get" action="opac-tags.pl">
+               <fieldset>Show up to <input name="limit" style="text-align: right;" maxlength="4" size="4" value="<!-- TMPL_VAR NAME="limit" DEFAULT="100" -->" />
+                       tags from other users.
+                        <!-- TMPL_IF NAME="hidemytags" -->
+                       <input type="hidden" name="hidemytags" value="1" />
+                        <!-- /TMPL_IF -->
+                       <input type="submit" value="OK" />
+                        <!-- TMPL_UNLESS NAME="loggedinusername" -->
+                          <a href="/cgi-bin/koha/opac-user.pl">Log in</a> to see your own saved tags.
+                        <!-- TMPL_ELSE -->
+                          <!-- TMPL_IF NAME="hidemytags" --><a class="hidemytags" href="/cgi-bin/koha/opac-tags.pl?limit=<!-- TMPL_VAR NAME="limit" DEFAULT="100" -->">Show my tags</a>
+                          <!-- TMPL_ELSE --><a class="hidemytags" href="/cgi-bin/koha/opac-tags.pl?limit=<!-- TMPL_VAR NAME="limit" DEFAULT="100" -->&amp;hidemytags=1">Hide my tags</a>
+                          <!-- /TMPL_IF -->
+                        <!-- /TMPL_UNLESS --></fieldset>
+               </form>
+       
+       <!-- TMPL_IF NAME="TAGLOOP" -->
+       <div id="tagcloud">
+       <!-- TMPL_LOOP NAME="TAGLOOP" -->
+       <span class="tag" id="tag<!-- TMPL_VAR NAME="__counter__" -->" title="<!-- TMPL_VAR NAME="cloudweight" -->">
+               <a href="/cgi-bin/koha/opac-search.pl?tag=<!-- TMPL_VAR NAME="term" ESCAPE="URL" -->&amp;q=<!-- TMPL_VAR NAME="term" ESCAPE="URL" -->">
+               <!-- TMPL_VAR NAME="term" ESCAPE="HTML" --></a>
+                       <span class="tagweight"><!-- TMPL_VAR NAME="weight_total" --></span>
+       </span>
+       <!-- /TMPL_LOOP -->
+       </div>
+       <!-- /TMPL_IF -->
+       <!-- TMPL_IF NAME="add_op" -->
+         <!-- TMPL_IF NAME="added_count" -->
+               <div class="dialog message"><!-- TMPL_VAR NAME="added_count" --> <!-- TMPL_IF EXPR="added_count ==1" --> tag<!-- TMPL_ELSE -->tags<!-- /TMPL_IF --> successfully added.</div>
+         <!-- /TMPL_IF -->
+         <!-- TMPL_IF NAME="deleted_count" -->
+               <div class="dialog message"><!-- TMPL_VAR NAME="deleted_count" --><!-- TMPL_IF EXPR="deleted_count ==1" --> tag<!-- TMPL_ELSE -->tags<!-- /TMPL_IF --> successfully deleted.</div>
+         <!-- /TMPL_IF -->
+       <!-- /TMPL_IF -->
+
+       <!-- TMPL_UNLESS NAME="hidemytags" -->
+       <!-- TMPL_IF NAME="MY_TAGS" -->
+               <form method="post" action="opac-tags.pl">
+               <h2>My Tags</h2>
+               <table id="mytagst">
+               <thead><tr><th>Term</th><th>Title</th><th>Date Added</th><th>Delete</th>
+               </tr></thead>
+       <tbody><!-- TMPL_LOOP NAME="MY_TAGS" -->
+               <tr><td><a href="/cgi-bin/koha/opac-search.pl?tag=<!-- TMPL_VAR NAME="term" ESCAPE="URL" -->&amp;q=<!-- TMPL_VAR NAME="term" ESCAPE="URL" -->">
+                               <!-- TMPL_VAR NAME="term" ESCAPE="HTML" --></a>
+                       </td>
+                       <td><a href="/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->">
+                               <!-- TMPL_VAR NAME="bib_summary" ESCAPE="HTML" --></a></td>
+                       <td><!-- TMPL_VAR NAME="date_created_display" --></td>
+                       <td><input type="submit" name="del<!-- TMPL_VAR NAME="tag_id" -->" value="Delete" /></td>
+               </tr>
+       <!-- /TMPL_LOOP --></tbody>
+               </table>
+               </form>
+       <!-- /TMPL_IF -->
+       <!-- /TMPL_UNLESS -->
+
+</div>
+</div>
+</div>
+</div>
+<!-- TMPL_IF EXPR="OpacNav||loggedinusername" -->
+<div class="yui-b"><div class="container">
+<!--TMPL_INCLUDE NAME="navigation.inc" -->
+<!--TMPL_INCLUDE NAME="usermenu.inc" -->
+</div></div>
+<!-- /TMPL_IF -->
+</div>
+<!-- TMPL_INCLUDE NAME="opac-bottom.inc" -->
+
diff --git a/koha-tmpl/intranet-tmpl/prog/img/cart.gif b/koha-tmpl/intranet-tmpl/prog/img/cart.gif
new file mode 100644 (file)
index 0000000..560cc28
Binary files /dev/null and b/koha-tmpl/intranet-tmpl/prog/img/cart.gif differ
diff --git a/tags/tags.pl b/tags/tags.pl
new file mode 100755 (executable)
index 0000000..bfce9cc
--- /dev/null
@@ -0,0 +1,327 @@
+#!/usr/bin/perl
+
+# Copyright 2000-2002 Katipo Communications
+#
+# 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., 59 Temple Place,
+# Suite 330, Boston, MA  02111-1307 USA
+
+
+=head1 
+
+TODO :: Description here
+
+C4::Scrubber is used to remove all markup content from the sumitted text.
+
+=cut
+
+use strict;
+use warnings;
+use CGI;
+use CGI::Cookie; # need to check cookies before having CGI parse the POST request
+
+use C4::Auth qw(:DEFAULT check_cookie_auth);
+use C4::Context;
+use C4::Debug;
+use C4::Output 3.02 qw(:html :ajax pagination_bar);
+use C4::Dates qw(format_date);
+use C4::Scrubber;
+use C4::Biblio;
+use C4::Tags qw(add_tag get_approval_rows get_tag_rows remove_tag);
+
+my %newtags = ();
+my @deltags = ();
+my %counts  = ();
+my @errors  = ();
+my $perBibResults = {};
+
+# Indexes of @errors that do not apply to a particular biblionumber.
+my @globalErrorIndexes = ();
+
+sub ajax_auth_cgi ($) {     # returns CGI object
+       my $needed_flags = shift;
+       my %cookies = fetch CGI::Cookie;
+       my $input = CGI->new;
+       my $sessid = $cookies{'CGISESSID'}->value || $input->param('CGISESSID');
+       my ($auth_status, $auth_sessid) = check_cookie_auth($sessid, $needed_flags);
+       $debug and
+       print STDERR "($auth_status, $auth_sessid) = check_cookie_auth($sessid," . Dumper($needed_flags) . ")\n";
+       if ($auth_status ne "ok") {
+               output_with_http_headers $input, undef,
+               "window.alert('Your CGI session cookie ($sessid) is not current.  " .
+               "Please refresh the page and try again.');\n", 'js';
+               exit 0;
+       }
+       $debug and print STDERR "AJAX request: " . Dumper($input),
+               "\n(\$auth_status,\$auth_sessid) = ($auth_status,$auth_sessid)\n";
+       return $input;
+}
+
+# The trick here is to support multiple tags added to multiple bilbios in one POST.
+# The HTML might not use this, but it makes it more web-servicey from the start.
+# So the name of param has to have biblionumber built in.
+# For lack of anything more compelling, we just use "newtag[biblionumber]"
+# We split the value into tags at comma and semicolon
+
+my $is_ajax = is_ajax();
+my $openadds = C4::Context->preference('TagsModeration') ? 0 : 1;
+my $query = ($is_ajax) ? &ajax_auth_cgi({}) : CGI->new();
+unless (C4::Context->preference('TagsEnabled')) {
+       push @errors, {+ tagsdisabled=>1 };
+    push @globalErrorIndexes, $#errors;
+} else {
+       foreach ($query->param) {
+               if (/^newtag(.*)/) {
+                       my $biblionumber = $1;
+                       unless ($biblionumber =~ /^\d+$/) {
+                               $debug and warn "$_ references non numerical biblionumber '$biblionumber'";
+                               push @errors, {+'badparam' => $_ };
+                push @globalErrorIndexes, $#errors;
+                               next;
+                       }
+                       $newtags{$biblionumber} = $query->param($_);
+               } elsif (/^del(\d+)$/) {
+                       push @deltags, $1;
+               }
+       }
+}
+
+my $add_op = (scalar(keys %newtags) + scalar(@deltags)) ? 1 : 0;
+my ($template, $loggedinuser, $cookie);
+if ($is_ajax) {
+       $loggedinuser = C4::Context->userenv->{'id'};  # must occur AFTER auth
+       $debug and print STDERR "op: $loggedinuser\n";
+} else {
+       ($template, $loggedinuser, $cookie) = get_template_and_user({
+               template_name   => "tags/tags.tmpl",
+               query           => $query,
+               type            => "intranet",
+               authnotrequired => ($add_op ? 0 : 1),   # auth required to add tags
+               debug           => 1,
+       });
+}
+
+if ($add_op) {
+       unless ($loggedinuser) {
+               push @errors, {+'login' => 1 };
+        push @globalErrorIndexes, $#errors;
+               %newtags=();    # zero out any attempted additions
+               @deltags=();    # zero out any attempted deletions
+       }
+}
+
+my $scrubber;
+my @newtags_keys = (keys %newtags);
+if (scalar @newtags_keys) {
+       $scrubber = C4::Scrubber->new();
+       foreach my $biblionumber (@newtags_keys) {
+        my $bibResults = {adds=>0, errors=>[]};
+               my @values = split /[;,]/, $newtags{$biblionumber};
+               foreach (@values) {
+                       s/^\s*(.+)\s*$/$1/;
+                       my $clean_tag = $scrubber->scrub($_);
+                       unless ($clean_tag eq $_) {
+                               if ($clean_tag =~ /\S/) {
+                                       push @errors, {scrubbed=>$clean_tag};
+                                       push @{$bibResults->{errors}}, {scrubbed=>$clean_tag};
+                               } else {
+                                       push @errors, {scrubbed_all_bad=>1};
+                                       push @{$bibResults->{errors}}, {scrubbed_all_bad=>1};
+                                       next;   # we don't add it if there's nothing left!
+                               }
+                       }
+                       my $result = ($openadds) ?
+                               add_tag($biblionumber,$clean_tag,$loggedinuser,$loggedinuser) : # pre-approved
+                               add_tag($biblionumber,$clean_tag,$loggedinuser)   ;
+                       if ($result) {
+                               $counts{$biblionumber}++;
+                $bibResults->{adds}++;
+                       } else {
+                               push @errors, {failed_add_tag=>$clean_tag};
+                               push @{$bibResults->{errors}}, {failed_add_tag=>$clean_tag};
+                               $debug and warn "add_tag($biblionumber,$clean_tag,$loggedinuser...) returned bad result (" . (defined $result ? $result : 'UNDEF') .")";
+                       }
+               }
+        $perBibResults->{$biblionumber} = $bibResults;
+       }
+}
+my $dels = 0;
+foreach (@deltags) {
+       if (remove_tag($_,$loggedinuser)) {
+               $dels++;
+       } else {
+               push @errors, {failed_delete=>$_};
+       }
+}
+
+if ($is_ajax) {
+       my $sum = 0;
+       foreach (values %counts) {$sum += $_;}
+       my $js_reply = sprintf("response = {\n\tadded: %d,\n\tdeleted: %d,\n\terrors: %d",$sum,$dels,scalar @errors);
+
+    # If no add attempts were made, flag global errors.
+    if (@globalErrorIndexes) {
+        $js_reply .= ",\n\tglobal_errors: [";
+        my $first = 1;
+        foreach (@globalErrorIndexes) {
+            $js_reply .= "," unless $first;
+            $first = 0;
+            $js_reply .= "\n\t\t$_";
+        }
+        $js_reply .= "\n\t]";
+    }
+    
+       my $err_string = '';
+       if (scalar @errors) {
+               $err_string = ",\n\talerts: ["; # open response_function
+               my $i = 1;
+               foreach (@errors) {
+                       my $key = (keys %$_)[0];
+                       $err_string .= "\n\t\t KOHA.Tags.tag_message.$key(\"" . $_->{$key} . '")';
+                       if($i < scalar @errors){ $err_string .= ","; }
+                       $i++;
+               }
+               $err_string .= "\n\t]\n";       # close response_function
+       }
+
+    # Add per-biblionumber results for use on results page
+    my $js_perbib = "";
+    for my $bib (keys %$perBibResults) {
+        my $bibResult = $perBibResults->{$bib};
+        my $js_bibres = ",\n\t$bib: {\n\t\tadded: $bibResult->{adds}";
+        $js_bibres .= ",\n\t\terrors: [";
+        my $i = 0;
+        foreach (@{$bibResult->{errors}}) {
+            $js_bibres .= "," if ($i);
+                       my $key = (keys %$_)[0];
+                       $js_bibres .= "\n\t\t\t KOHA.Tags.tag_message.$key(\"" . $_->{$key} . '")';
+            $i++;
+        }
+        $js_bibres .= "\n\t\t]\n\t}";
+        $js_perbib .= $js_bibres;
+    }
+
+       output_with_http_headers($query, undef, "$js_reply\n$err_string\n$js_perbib\n};", 'js');
+       exit;
+}
+
+my $results = [];
+my $my_tags = [];
+
+if ($loggedinuser) {
+       $my_tags = get_tag_rows({borrowernumber=>$loggedinuser});
+       foreach (@$my_tags) {
+               my $biblio = GetBiblioData($_->{biblionumber});
+               $_->{bib_summary} = $biblio->{title}; 
+               ($biblio->{author}) and $_->{bib_summary} .= " by " . $biblio->{author};
+               my $date = $_->{date_created} || '';
+               $date =~ /\s+(\d{2}\:\d{2}\:\d{2})/;
+               $_->{time_created_display} = $1;
+               $_->{date_created_display} = format_date($_->{date_created});
+       }
+}
+
+$template->param(tagsview => 1,
+dateformat => C4::Context->preference("dateformat"));
+
+if ($add_op) {
+       my $adds = 0;
+       for (values %counts) {$adds += $_;}
+       $template->param(
+               add_op => 1,
+               added_count => $adds,
+               deleted_count => $dels,
+       );
+} else {
+       my ($arg,$limit,$mine);
+       my $hardmax = 100;      # you might disagree what this value should be, but there definitely should be a max
+       $limit = $query->param('limit') || $hardmax;
+    $mine =  $query->param('mine') || 0; # set if the patron want to see only his own tags.
+       ($limit =~ /^\d+$/ and $limit <= $hardmax) or $limit = $hardmax;
+       $template->param(limit => $limit);
+       my $arghash = {approved=>1, limit=>$limit, 'sort'=>'-weight_total'};
+    $arghash->{'borrowernumber'} = $loggedinuser if $mine;
+       # ($openadds) or $arghash->{approved} = 1;
+       if ($arg = $query->param('tag')) {
+               $arghash->{term} = $arg;
+       } elsif ($arg = $query->param('biblionumber')) {
+               $arghash->{biblionumber} = $arg;
+       }
+       $results = get_approval_rows($arghash);
+
+       my $count = scalar @$results;
+       $template->param(TAGLOOP_COUNT => $count, mine => $mine);
+       # Here we make a halfhearted attempt to separate the tags into "strata" based on weight_total
+       # FIXME: code4lib probably has a better algorithm, iirc
+       # FIXME: when we get a better algorithm, move to C4
+       my $maxstrata = 5;
+       my $strata = 1;
+       my $previous = 0;
+       my $chunk = ($count/$maxstrata)/2;
+       my $total = 0;
+       my %cloud;
+       foreach (reverse @$results) {
+               my $current = $_->{weight_total};
+               $total++;
+               $cloud{$strata}++;
+               if ($current == $previous) {
+                       $_->{cloudweight} = $strata;
+                       next;
+               } 
+               if ($strata < $maxstrata and 
+                       ($cloud{$strata} > $chunk or 
+                       $count-$total <= $maxstrata-$strata)) {
+                       $strata++;
+               }
+               $_->{cloudweight} = $strata;
+               $previous = $current;
+       }
+}
+(scalar @errors  ) and $template->param(ERRORS  => \@errors);
+my @orderedresult = sort { $a->{'term'} cmp $b->{'term'} } @$results;
+(scalar @$results) and $template->param(TAGLOOP => \@orderedresult );
+(scalar @$my_tags) and $template->param(MY_TAGS => $my_tags);
+
+output_html_with_http_headers $query, $cookie, $template->output;
+__END__
+
+=head1 EXAMPLE AJAX POST PARAMETERS
+
+CGISESSID      7c6288263107beb320f70f78fd767f56
+newtag396      fire,+<a+href="foobar.html">foobar</a>,+<img+src="foo.jpg"+/>
+
+So this request is trying to add 3 tags to biblio #396.  The CGISESSID is the same as that the browser would
+typically communicate using cookies.  If it is valid, the server will split the value of "newtag396" and 
+process the components for addition.  In this case the intended tags are:
+       fire
+       <a+href="foobar.html">foobar</a>
+       <img src="foo.jpg" />
+
+The first tag is acceptable.  The second will be scrubbed of markup, resulting in the tag "foobar".  
+The third tag is all markup, and will be rejected.  
+
+=head1 EXAMPLE AJAX JSON response
+
+response = {
+       added: 2,
+       deleted: 0,
+       errors: 2,
+       alerts: [
+                KOHA.Tags.tag_message.scrubbed("foobar"),
+                KOHA.Tags.tag_message.scrubbed_all_bad("1"),
+       ],
+};
+
+=cut
+