[Koha-patches] [PATCH] bug 2991: Request hold on multiple items at one time.

Stephen Edwards sedwards at alloycomputing.com
Thu Mar 5 01:10:03 CET 2009


Updated the results, cart, and shelf pages to include a button
or link to initiate a hold request based on checked items.

Updated the request CGI scripts to handle multiple biblio items.

Updated the reserve confirmation page to display multiple items,
with an optional list of copies for each one.

Turned on warnings in opac/opac-reserve.pl and fixed resulting
warnings.
---
 koha-tmpl/opac-tmpl/prog/en/css/opac.css           |    6 +-
 koha-tmpl/opac-tmpl/prog/en/js/basket.js           |    8 +-
 .../opac-tmpl/prog/en/modules/opac-basket.tmpl     |   19 +-
 .../opac-tmpl/prog/en/modules/opac-reserve.tmpl    |  668 +++++++++++++-------
 .../opac-tmpl/prog/en/modules/opac-results.tmpl    |   59 ++-
 .../opac-tmpl/prog/en/modules/opac-shelves.tmpl    |   24 +
 opac/opac-reserve.pl                               |  533 ++++++++++------
 7 files changed, 868 insertions(+), 449 deletions(-)

diff --git a/koha-tmpl/opac-tmpl/prog/en/css/opac.css b/koha-tmpl/opac-tmpl/prog/en/css/opac.css
index 711eeb5..1a1c13a 100644
--- a/koha-tmpl/opac-tmpl/prog/en/css/opac.css
+++ b/koha-tmpl/opac-tmpl/prog/en/css/opac.css
@@ -1236,7 +1236,7 @@ div#changelanguage li.yuimenuitem a.yuimenuitemlabel {
 	padding : 0;
 }
 
-#cartDetails,#cartUpdate {
+#cartDetails,#cartUpdate,#holdDetails {
 	background-color : #FFF;
 	border: 1px solid #739acf;
 	color : black;
@@ -1772,4 +1772,8 @@ a.p1:active {
 	color : #AAA;
 	text-decoration : none;
 	font-weight : bold;
+}
+
+.copies_row > td:first-child {
+    border-left-style : none;
 }
\ No newline at end of file
diff --git a/koha-tmpl/opac-tmpl/prog/en/js/basket.js b/koha-tmpl/opac-tmpl/prog/en/js/basket.js
index 1eac658..cb49bee 100644
--- a/koha-tmpl/opac-tmpl/prog/en/js/basket.js
+++ b/koha-tmpl/opac-tmpl/prog/en/js/basket.js
@@ -419,12 +419,12 @@ function showCart(){
 		$("#cartDetails").css("position","absolute").css("left",left);
 		$("#cartDetails").fadeIn("fast",function(){
   			$("#cartDetails").dropShadow({left: 3, top: 3, blur: 0,  color: "#000", opacity: 0.1});
-		});	
+        });
 }
 
 function hideCart(){
-		 $(".dropShadow").hide();
-		 $("#cartDetails").fadeOut("fast");
+    $("#cartDetails").removeShadow();
+    $("#cartDetails").fadeOut("fast");
 }
 
 $("#cartDetails").ready(function(){
@@ -437,3 +437,5 @@ $("#cartDetails").ready(function(){
 	});
 	if(basketcount){ updateBasket(basketcount) }
 });
+
+
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-basket.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-basket.tmpl
index 100bf83..f575d7c 100644
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-basket.tmpl
+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-basket.tmpl
@@ -30,7 +30,18 @@
 		);
 	        return false;
 	    });
+        $(".holdsep").text("| ");
+        $(".hold").text("Place Hold");
+
 	});
+    function holdSel() {
+        var items = document.getElementById('records').value;
+        if (items) {
+            document.location = "/cgi-bin/koha/opac-reserve.pl?biblionumbers=" + items;
+        } else {
+            alert(MSG_NO_RECORD_SELECTED);
+        }
+    }
 	//]]>
 	</script>
 	<!-- /TMPL_IF -->
@@ -58,7 +69,9 @@
 <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 --></p><!-- /TMPL_UNLESS -->
+<!-- /TMPL_IF -->
+     <span class="holdsep"></span><a href="#" onclick="holdSel(); return false;"><span class="hold"></span></a>
+</p><!-- /TMPL_UNLESS -->
             <form action="opac-basket.pl" method="get" name="bookbag_form" id="bookbag_form">
     <!-- TMPL_LOOP NAME="BIBLIO_RESULTS" -->
     <h3>
@@ -202,7 +215,9 @@
 <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 --></td></tr><!-- /TMPL_UNLESS -->
+<!-- /TMPL_IF -->
+     <span class="holdsep"></span><a href="#" onclick="holdSel(); return false;"><span class="hold"></span></a>
+</td></tr><!-- /TMPL_UNLESS -->
         <!-- TMPL_LOOP NAME="BIBLIO_RESULTS" -->
             <!-- TMPL_IF NAME="even" -->
                 <tr class="highlight">
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tmpl
index dc5bcfe..2e1bb33 100644
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tmpl
+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-reserve.tmpl
@@ -1,252 +1,458 @@
 <!-- TMPL_INCLUDE NAME="doc-head-open.inc" --><!-- TMPL_VAR NAME="LibraryNameTitle" DEFAULT="Koha Online" --> Catalog &rsaquo;  Reserving <!-- TMPL_VAR NAME="title" escape="html" --> for <!-- TMPL_LOOP NAME="USER_INFO" --><!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --><!-- /TMPL_LOOP -->
 <!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
 <script type="text/javascript">
-// <![CDATA[ 
+// <![CDATA[
+ var MSG_NO_COPY_SELECTED = _("Expecting a specific copy selection.");
+
+ function prefixOf (s, tok) {
+     var index = s.indexOf(tok);
+     return s.substring(0, index);
+ }
+ function suffixOf (s, tok) {
+     var index = s.indexOf(tok);
+     return s.substring(index + 1);
+ }
+
  $(document).ready(function() {
- 	$("#requestany").click(function() {
-		if(this.checked){
-		$("input[@name=checkitem]").each(function() {
-			$(this).attr("checked","");
-		});
-		}
-	});
- 	$("input[@name=checkitem]").click(function() {
-		onechecked = 0;
-		$("input[@name=checkitem]").each(function() {
-			if(this.checked){
-				onechecked = 1;
-			}
-		});
-		if(onechecked == 1){
-			$("#requestany").attr("checked","");
-		} else {
-			$("#requestany").attr("checked","checked");
-		}
-	});
+    var copiesRowId = null;
+    var wasSpecific = false;
+    var lastCopiesRowId = null;
+
+    // Hides all 'specific copy' table rows on load.
+    $(".copiesrow").hide();
+
+    $("#place_on_hdr").show();
+    $(".place_on_type").show();
+
+    // Replace non-JS single-selection with multi-selection capability.
+    $(".reserve_mode").val("multi");
+    $(".confirm_nonjs").remove();
+    $(".confirmjs_hold").each(function(){
+        var bib = $(this).attr("title");
+        var html = "<input type =\"checkbox\" class=\"confirmjs\" checked=\"checked\"";
+        html += "value=\"" + bib + "\"/>";
+        $(this).html(html);
+    });
+    $(".confirmjs_nohold").each(function(){
+        var bib = $(this).attr("title");
+        var html = "<input type =\"checkbox\" class=\"confirmjs\" disabled=\"disabled\"";
+        html += "value=\"" + bib + "\"/>";
+        $(this).html(html);
+    });
+
+    // Make sure a specific item was selected where specified
+    // before moving on to a new item.
+    function changeSelection (newCopiesRowId, isSpecific) {
+        if (copiesRowId && ((copiesRowId != newCopiesRowId) || (wasSpecific != isSpecific))) {
+            var biblioNum = suffixOf(copiesRowId, "_");
+            
+            // If the 'specific copy' radio button was checked
+              if (wasSpecific && (copiesRowId != newCopiesRowId)) {
+                // Find the selected copy
+                var item = $(".checkitem_" + biblioNum + ":checked");
+                if ($(item).size() == 0) {
+                    alert(MSG_NO_COPY_SELECTED);
+                    return false;
+                }
+            }
+        }
+        copiesRowId = newCopiesRowId;
+        wasSpecific = isSpecific;
+        return true;
+    }
+
+    // When 'specific copy' radio button is clicked
+    $(".selectspecific").click(function() {
+
+        // Make sure all other specific copy table rows are hidden
+        biblioNum = suffixOf($(this).attr("id"), "_");
+        newCopiesRowId = "#copiesrow_" + biblioNum;
+
+        if (!changeSelection(newCopiesRowId, true)) {
+            return false;
+        }
+        $(".copiesrow:not(" + newCopiesRowId + ")").hide();
+        
+        // Show the specific copy table for this radio button.
+        $(newCopiesRowId).show();
+    });
+
+
+    // When 'first available' radion button is clicked
+    $(".selectany").click(function() {
+        // Make sure all other specific copy table rows are hidden
+        biblioNum = suffixOf($(this).attr("id"), "_");
+        newCopiesRowId = "#copiesrow_" + biblioNum;
+
+        if (!changeSelection(newCopiesRowId, false)) {
+            return false;
+        }
+
+        // Hide the copies table row
+        $(".copiesrow").hide();
+    });
+
+    // When 'Place Hold' button is clicked
+    $(".placehold").click(function(){
+        var biblionumbers = "";
+        var selections = "";
+
+        if ($(".confirmjs:checked").size() == 0) {
+            alert(MSG_NO_RECORD_SELECTED);
+            return false;
+        }
+
+        // Find the items with the 'Hold' box checked
+        var badBib = null;
+        $(".confirmjs:checked").each(function() {
+            var biblioNum = $(this).val();
+            biblionumbers += biblioNum + "/";
+            selections += biblioNum + "/";
+
+            // If the 'specific copy' radio button is checked
+            if ($("#reqspecific_" + biblioNum + ":checked").size() > 0) {
+                // Find the selected copy
+                var item = $(".checkitem_" + biblioNum + ":checked");
+                if ($(item).size() == 0) {
+                    badBib = biblioNum;
+                    return false;
+                } else {
+                  selections += $(item).val();
+                }
+            }
+            selections += "/";
+
+            // Add the pickup location
+            var branchSel = $("#branch_" + biblioNum);
+            if (branchSel.size() > 0) {
+                selections += $(branchSel).val();
+            }
+            selections += "/";
+            return true;
+        });
+
+        if (badBib) {
+            alert(MSG_NO_COPY_SELECTED);
+            return false;
+        }
+
+        $("#selections").val(selections);
+        $("#biblionumbers").val(biblionumbers);
+
+        return true;
+    });
+
  });
 // ]]>
 </script>
 </head>
+
 <body>
-<div id="doc3" class="yui-t7">
-<!--TMPL_INCLUDE NAME="masthead.inc" -->
-
-   <div id="bd">
-	<div id="yui-g">
-<div id="holds" class="container">
-<!-- TMPL_IF NAME="message" -->
-    <!-- TMPL_IF NAME="GNA" -->
-    <div class="dialog alert">
-        <strong>Sorry</strong>, you cannot place holds because the library doesn't have up-to-date <a href="/cgi-bin/koha/opac-userdetails.pl">contact information</a> on file.
-    </div>
-    <div class="dialog alert">Please contact your librarian, or use the <a href="/cgi-bin/koha/opac-userupdate.pl">online update form</a> to submit current information (<em>Please note:</em> there may be a delay in restoring your account if you submit online)
-    </div>
-    <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="lost" -->
-    <div class="dialog alert">
-        <strong>Sorry</strong>, you cannot place holds because your library card has been marked as lost or stolen.
-    </div>
-    <div class="dialog alert">
-        If this is an error, please take your card to the circulation desk at your local library and the error will be corrected.
-    </div>
-    <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="debarred" -->
-    <div class="dialog alert">
-        <strong>Sorry</strong>, you cannot place holds because your account has been frozen.
-    </div>
-    <div class="dialog alert">Usually the reason for freezing an account is old overdues or damage fees.   If <a href="/cgi-bin/koha/opac-user.pl">your account page</a> shows your account to be clear, please consult a librarian.
-    </div>
-    <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="too_much_oweing" -->
-    <div class="dialog alert">
-        Sorry, you cannot place holds because you owe <!-- TMPL_VAR NAME="too_much_oweing" -->.
-    </div>
-    <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="too_many_reserves" -->
-        <div class="dialog alert">Sorry, you cannot place more than <!-- TMPL_VAR NAME="too_many_reserves" --> holds.
-        </div>
-        <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="already_reserved" -->
-    <div class="dialog alert">
-        You already have a hold placed on this item. <a href="/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->">Return to Item Detail Screen</a>
-    </div>
-    <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="no_items_selected" -->
-    <div class="dialog alert">
-        You must select at least one item.
-    </div>
-    <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="no_branch_selected" -->
-    <div class="dialog alert">
-        You must select a library for pickup.
-    </div>
-    <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="no_biblionumber" -->
-    <div class="dialog alert">ERROR: No biblionumber received.</div>
-    <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="bad_biblionumber" -->
-    <div class="dialog alert">ERROR: No biblio record found for biblionumber <!-- TMPL_VAR NAME="bad_biblionumber" -->.</div>
-    <!-- /TMPL_IF -->
-    <!-- TMPL_IF NAME="none_available" -->
-    <div class="dialog alert">
-        <strong>Sorry</strong>, none of these items can be placed on hold.
-    </div>
-    <!-- /TMPL_IF -->
-</div>
-<!-- /TMPL_IF -->
-
-<!-- TMPL_IF NAME="select_item_types" -->
-    <!-- The first time round you select which bibitems you want -->
-    <form action="/cgi-bin/koha/opac-reserve.pl" method="post">
-        <input type="hidden" name="item_types_selected" value="1" />
-        <input type="hidden" name="biblionumber" value="<!-- TMPL_VAR NAME="biblionumber" -->" />
-        <h3>Place a hold on <a href="/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->"><!-- TMPL_VAR NAME="title" escape="html" --></a><!-- TMPL_IF NAME="author" -->,  by <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF --></h3>
-
-<!-- TMPL_IF NAME="OPACItemHolds" --> <!-- TMPL_LOOP name="bibitemloop" --> 
-            <!-- TMPL_UNLESS NAME="item-level_itypes" -->
-            <p><strong>Item type:</strong> <!-- TMPL_VAR NAME="description" --></p>
-            <!-- /TMPL_UNLESS -->
-            <!-- TMPL_IF NAME="publicationyear" --><p><strong>Publication year:</strong> <!-- TMPL_VAR NAME="publicationyear" --></p><!-- /TMPL_IF -->
-<!-- /TMPL_IF --><!-- /TMPL_LOOP -->
-
-		<fieldset class="rows holds">
-			<ol>
-				<li><span class="label">For:</span> <!-- TMPL_LOOP NAME="USER_INFO" --><!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --> (<!-- TMPL_VAR NAME="cardnumber" -->)
-            <!-- TMPL_IF NAME="singleBranchMode" -->
-             <input type="hidden" name="branch" value="<!-- TMPL_VAR NAME="branchcode" -->"/>
+  <div id="doc3" class="yui-t7">
+    <!--TMPL_INCLUDE NAME="masthead.inc" -->
+    <div id="bd">
+	  <div id="yui-g">
+        <div id="holds" class="container">
+      
+          <!-- TMPL_IF NAME="message" -->
+            <!-- TMPL_IF NAME="GNA" -->
+              <div class="dialog alert">
+                <strong>Sorry</strong>, you cannot place holds because the library doesn't have up-to-date <a href="/cgi-bin/koha/opac-userdetails.pl">contact information</a> on file.
+              </div>
+              <div class="dialog alert">Please contact your librarian, or use the <a href="/cgi-bin/koha/opac-userupdate.pl">online update form</a> to submit current information (<em>Please note:</em> there may be a delay in restoring your account if you submit online)
+              </div>
             <!-- /TMPL_IF -->
-            <!-- /TMPL_LOOP --></li>
-            <li><span class="label">Priority:</span><!-- TMPL_VAR Name="rank" DEFAULT="?" --> out of <!-- TMPL_VAR Name="reservecount" DEFAULT="?" -->
-			</li> 
-            <!-- TMPL_UNLESS NAME="singleBranchMode" -->
-            <li><label for="branch">Pick up from:</label> <select name="branch" id="branch">
-                    <!-- TMPL_LOOP NAME="CGIbranch" -->
-                        <!-- TMPL_IF name="selected" -->
-                            <option value="<!-- TMPL_VAR NAME="value" -->" selected="selected"><!-- TMPL_VAR NAME="branch" --></option>
-                        <!-- TMPL_ELSE -->
-                            <option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branch" --></option>
-                        <!-- /TMPL_IF -->
-                    <!-- /TMPL_LOOP -->
-            </select>
-            </li>
-            <!-- /TMPL_UNLESS -->
-			
-			<!-- TMPL_IF NAME="forloan" -->
-            <!-- TMPL_IF NAME="OPACItemHolds" --><li> <label for="requestany">Place a hold on the next available copy </label>
-            <input type="checkbox" id="requestany" name="request" checked="checked" value="Any" />
-            </li><!-- TMPL_ELSE --><input type="hidden" name="request" value="Any" /><!-- /TMPL_IF -->
-			</ol>
-		</fieldset>
+            <!-- TMPL_IF NAME="lost" -->
+              <div class="dialog alert">
+                <strong>Sorry</strong>, you cannot place holds because your library card has been marked as lost or stolen.
+              </div>
+              <div class="dialog alert">If this is an error, please take your card to the circulation desk at your local library and the error will be corrected.
+              </div>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_IF NAME="debarred" -->
+              <div class="dialog alert">
+                <strong>Sorry</strong>, you cannot place holds because your account has been frozen.
+              </div>
+              <div class="dialog alert">Usually the reason for freezing an account is old overdues or damage fees.   If <a href="/cgi-bin/koha/opac-user.pl">your account page</a> shows your account to be clear, please consult a librarian.
+              </div>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_IF NAME="too_much_oweing" -->
+              <div class="dialog alert">
+                Sorry, you cannot place holds because you owe <!-- TMPL_VAR NAME="too_much_oweing" -->.
+              </div>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_IF NAME="too_many_reserves" -->
+              <div class="dialog alert">Sorry, you cannot place more than <!-- TMPL_VAR NAME="too_many_reserves" --> holds.
+              </div>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_IF NAME="bad_biblionumber" -->
+              <div class="dialog alert">ERROR: No biblio record found for biblionumber <!-- TMPL_VAR NAME="bad_biblionumber" -->.</div>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_IF NAME="no_items_selected" -->
+              <div class="dialog alert">
+                You must select at least one item.
+              </div>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_IF NAME="no_branch_selected" -->
+              <div class="dialog alert">
+                You must select a library for pickup.
+              </div>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_IF NAME="no_biblionumber" -->
+              <div class="dialog alert">ERROR: No biblionumber received.</div>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_IF NAME="bad_data" -->
+              <div class="dialog alert">ERROR: Internal error: incomplete hold request.</div>
+            <!-- /TMPL_IF -->
+            <!-- TMPL_IF NAME="none_available" -->
+              <div class="dialog alert"><strong>Sorry</strong>, none of these items can be placed on hold.
+              </div>
+            <!-- /TMPL_IF -->
+          <!-- /TMPL_IF --><!-- NAME="message" -->
+
+          <!-- TMPL_UNLESS NAME="message" -->
+            <div class="rows holds">
+              <h3>
+                For:
+                <!-- TMPL_LOOP NAME="USER_INFO" -->
+                  <!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --> (<!-- TMPL_VAR NAME="cardnumber" -->)
+                <!-- /TMPL_LOOP -->
+              </h3>
+            </div>
+
+
 
+            <form action="/cgi-bin/koha/opac-reserve.pl" method="post">
+            <input type="hidden" name="place_reserve" value="1"/>
 
-<fieldset class="action">            <input type="hidden" name="biblioitem" value="<!-- TMPL_VAR NAME="biblioitemnumber" -->" />
+            <!-- These values are set dynamically by js -->
+            <input type="hidden" name="biblionumbers" id="biblionumbers"/>
+            <input type="hidden" name="selecteditems" id="selections"/>
 
             <!-- TMPL_IF NAME="none_available" -->
-            <input type="submit" disabled="disabled" value="Place Hold" />
-            <!-- TMPL_ELSE -->
-            <input type="submit" value="Place Hold" />
-            <!-- /TMPL_IF -->
-            <input type="hidden" name="all" value="1" />
-            <input type="hidden" name="place_reserve" value="1" /></fieldset>
-			<!-- /TMPL_IF -->  
-			          
-       <!-- TMPL_IF NAME="OPACItemHolds" --> <!-- TMPL_LOOP name="bibitemloop" -->    
-
-            <table id="requestspecific">
-			<caption>Place a hold on a specific copy</caption>
-            <tr>
-                <th>Hold</th>
-	            <!-- TMPL_IF NAME="item-level_itypes" -->
-                <th>Item Type</th>
-                <!-- /TMPL_IF -->
-                <!-- TMPL_UNLESS NAME="singleBranchMode" -->
-                <th>Home Library</th>
-                <th>Last Location</th>
-                <!-- /TMPL_UNLESS -->
-                <th>Call Number</th>
-                <th>Copy Number</th>
-                <th>Information</th>
-            </tr>
-        <!-- TMPL_LOOP Name="itemloop" -->
-        <tr class="<!-- TMPL_VAR NAME="backgroundcolor" -->">
-            <td>
-            <!-- TMPL_IF NAME="available" -->
-            <input type="radio" name="checkitem" value="<!-- TMPL_VAR NAME="itemnumber" -->" />
+              <input type="submit" disabled="disabled" value="Place Hold" />
             <!-- TMPL_ELSE -->
-            <input disabled="disabled" type="radio" name="checkitem" value="<!-- TMPL_VAR NAME="itemnumber" -->" />
-            <img src="/intranet-tmpl/<!-- TMPL_VAR NAME="theme" -->/img/famfamfam/silk/cross.png" alt="Cannot be put on hold" />
+              <input type="submit" value="Place Hold" class="placehold"/>
             <!-- /TMPL_IF -->
-            </td>
-            <!-- TMPL_IF NAME="item-level_itypes" -->
-            <td>
-            <img src="<!-- TMPL_VAR NAME="imageurl" -->" alt="<!-- TMPL_VAR NAME="description" -->" title="<!-- TMPL_VAR NAME="description" -->" />
-            </td>
-            <!-- /TMPL_IF -->
-            <!-- TMPL_UNLESS NAME="singleBranchMode" -->
-            <td><!-- TMPL_VAR NAME="homebranchname"    --></td>
-            <td><!-- TMPL_VAR NAME="holdingbranchname" --></td>
-            <!-- /TMPL_UNLESS -->
-            <td><!-- TMPL_VAR NAME="itemcallnumber"    --></td>
-            <td><!-- TMPL_IF NAME="copynumber" --><!-- TMPL_VAR NAME="copynumber" --><!-- TMPL_ELSE -->&nbsp;<!-- /TMPL_IF --></td>
-            <td>
-        <!-- TMPL_IF Name="date_due" -->
-            <span class="checkedout">Due <!-- TMPL_VAR NAME="date_due" --></span>
-        <!-- TMPL_ELSIF Name="transfertwhen" -->
-            <span class="intransit">In transit from <!-- TMPL_VAR NAME="transfertfrom" -->,
-            to <!-- TMPL_VAR NAME="transfertto" -->, since <!-- TMPL_VAR NAME="transfertwhen" --></span>
-        <!-- /TMPL_IF -->
-
-        <!-- TMPL_IF Name="message" -->
-            <span class="lost">Unavailable (lost or missing)</span>
-        <!-- /TMPL_IF -->
-
-        <!-- TMPL_IF Name="notforloan" -->
-            <span class="notforloan">Not for loan (<!-- TMPL_VAR NAME="notforloanvalue" -->)</span>
-        <!-- /TMPL_IF -->
-
-            <!-- TMPL_IF NAME="reservedate"-->
-                    <span class="waiting"><!-- TMPL_IF NAME="waitingdate" -->Waiting<!-- TMPL_ELSE -->On hold<!-- /TMPL_IF --> for patron 
-                    <!-- TMPL_IF NAME="waitingdate" -->at<!-- TMPL_ELSE -->expected at<!-- /TMPL_IF --> <!-- TMPL_VAR NAME="ExpectedAtLibrary" -->
-                    since
-                    <!-- TMPL_IF NAME="waitingdate" --><!-- TMPL_VAR NAME="waitingdate" --><!-- TMPL_ELSE --><!-- TMPL_IF name="reservedate" --><!-- TMPL_VAR NAME="reservedate" --><!-- /TMPL_IF --><!-- /TMPL_IF -->.</span>
-            <!-- TMPL_ELSE -->
-                    <span class="notonhold">Not on hold</span>
-            <!-- /TMPL_IF -->&nbsp;
-            </td>
-        </tr>
-        <!-- /TMPL_LOOP --> <!-- itemloop -->
-        </table>
-        <!-- /TMPL_LOOP --> <!-- bibitemloop -->
+
+            <div id="bigloop">
+              <table id="bibitemloop">
+                <caption>Confirm Holds</caption>
+                <tr>
+                  <th>Hold</th>
+                  <th>Item</th>
+                  <!-- TMPL_UNLESS NAME="item-level_itypes" -->
+                    <th>Item Type</th>
+                  <!-- /TMPL_UNLESS -->
+                  <th>Priority</th>
+                  <!-- TMPL_IF NAME="OPACItemHolds" -->
+                    <th id="place_on_hdr" style="display:none">Place On:</th>
+                  <!-- /TMPL_IF -->
+                  <!-- TMPL_UNLESS NAME="singleBranchMode" -->
+                    <th>Pickup Location</th>
+                  <!-- /TMPL_UNLESS -->
+                </tr>
+
+                <!-- TMPL_LOOP name="bibitemloop" -->
+                  <tr>
+                    <td>
+                      <input class="reserve_mode" name="reserve_mode" type="hidden" value="single"/>
+                      <input class="single_bib" name="single_bib" type="hidden" value="<!-- TMPL_VAR NAME="biblionumber" -->"/>
+                      <!-- TMPL_IF NAME="holdable" -->
+                        <span class="confirmjs_hold" title="<!-- TMPL_VAR NAME="biblionumber" -->"></span>
+                        <span class="confirm_nonjs">
+                          <input type="radio" class="confirmbox checkitem checkitem_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                 name="checkitem_<!-- TMPL_VAR NAME="biblionumber" -->" checked="checked"
+                                 id="checkitem_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                 value="any" />
+                          <label class="confirm_label" for="checkitem_<!-- TMPL_VAR NAME="biblionumber" -->">Next available copy</label>
+                        </span>
+                      <!-- TMPL_ELSE -->
+                        <span class="confirmjs_nohold" title="<!-- TMPL_VAR NAME="biblionumber" -->"></span>
+                        <span class="confirm_nonjs">
+                          <input type="radio" class="confirmbox checkitem checkitem_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                 name="checkitem_<!-- TMPL_VAR NAME="biblionumber" -->" disabled="disabled"
+                                 id="checkitem_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                 value="any" />
+                        </span>
+                        <!-- TMPL_IF NAME="already_reserved" -->
+                          <div class="bibmessage">You have already requested this title.</div>
+                        <!-- /TMPL_IF -->
+                        <!-- TMPL_UNLESS NAME="bib_available" -->
+                          <div class="bibmessage">No available items.</div>
+                        <!-- TMPL_ELSE -->
+                          <div class="bibmessage">This title cannot be requested.</div>
+                        <!-- /TMPL_UNLESS -->
+                      <!-- /TMPL_IF -->
+                    </td>
+                    <td>
+                      <a href="/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->"><!-- TMPL_VAR NAME="title" escape="html" --></a>
+                      <!-- TMPL_IF NAME="author" -->,  by <!-- TMPL_VAR NAME="author" --><!-- /TMPL_IF -->
+                    </td>
+                    <!-- TMPL_UNLESS NAME="item-level_itypes" -->
+                      <td>
+                        <img src="<!-- TMPL_VAR NAME="imageurl" -->"
+                             alt="<!-- TMPL_VAR NAME="description" -->"
+                             title="<!-- TMPL_VAR NAME="description" -->" />
+                      </td>
+                    <!-- /TMPL_UNLESS -->
+                    <td><!-- TMPL_VAR name="rank" --> out of <!-- TMPL_VAR NAME="reservecount" --></td>
+                    <!-- TMPL_IF NAME="OPACItemHolds" -->
+                      <td class="place_on_type" style="display:none">
+                        <table>
+                          <tr>
+                            <td>
+                              <!-- TMPL_UNLESS NAME="holdable" -->
+                                <input type="radio" name="reqtype_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                       id="reqany_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                       class="selectany"
+                                       value="Any"
+                                       disabled="disabled"
+                                />
+                              <!-- TMPL_ELSE -->
+                                <input type="radio" name="reqtype_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                       id="reqany_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                       class="selectany"
+                                       value="Any"
+                                       checked="checked"
+                                />
+                              <!-- /TMPL_UNLESS -->
+                              <label for="reqany_<!-- TMPL_VAR NAME="biblionumber" -->">Next available copy</label>
+                            </td>
+                          </tr>
+                          <tr>
+                            <td>
+                              <!-- TMPL_UNLESS NAME="holdable" -->
+                                <input type="radio" name="reqtype_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                       id="reqspecific_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                       class="selectspecific"
+                                       disabled="disabled"
+                                       value="Specific"
+                                />
+                              <!-- TMPL_ELSE -->
+                                <input type="radio" name="reqtype_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                       id="reqspecific_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                       class="selectspecific"
+                                       value="Specific"
+                                />
+                              <!-- /TMPL_UNLESS -->
+                              <label for="reqspecific_<!-- TMPL_VAR NAME="biblionumber"-->">A specific copy</label>
+                            </td>
+                          </tr>
+                        </table>
+                      </td>
+                    <!-- /TMPL_IF -->
+
+                    <!-- TMPL_UNLESS NAME="singleBranchMode" -->
+                      <td>
+                        <select name="branch" id="branch_<!-- TMPL_VAR NAME="biblionumber" -->"
+                          <!-- TMPL_UNLESS NAME="holdable" -->disabled="disabled"<!-- /TMPL_UNLESS --> >
+                          <!-- TMPL_LOOP NAME="branchChoicesLoop" -->
+                            <!-- TMPL_IF name="selected" -->
+                              <option value="<!-- TMPL_VAR NAME="value" -->" selected="selected"><!-- TMPL_VAR NAME="branch" --></option>
+                            <!-- TMPL_ELSE -->
+                              <option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branch" --></option>
+                            <!-- /TMPL_IF -->
+                          <!-- /TMPL_LOOP -->
+                        </select>
+                      </td>
+                    <!-- /TMPL_UNLESS -->
+                  </tr>
+
+                  <!-- TMPL_IF NAME="OPACItemHolds" -->
+                  <!-- TMPL_IF NAME="bib_available" -->
+                    <tr class="copiesrow" id="copiesrow_<!-- TMPL_VAR NAME="biblionumber"-->">
+                      <td colspan="1">
+                      </td>
+                      <td colspan="<!-- TMPL_VAR NAME="itemtable_colspan" -->">
+                        <table>
+                          <caption>Select a specific copy:</caption>
+                          <tr>
+                            <th>Copy</th>
+                            <!-- TMPL_IF NAME="item-level_itypes" -->
+                              <th>Item Type</th>
+                            <!-- /TMPL_IF -->
+                            <th>Barcode</th>
+                            <!-- TMPL_UNLESS NAME="singleBranchMode" -->
+                              <th>Home Library</th>
+                              <th>Last Location</th>
+                            <!-- /TMPL_UNLESS -->
+                            <th>Call Number</th>
+                            <th>Information</th>
+                          </tr>
+
+                          <!-- TMPL_LOOP name="itemLoop" -->
+                            <tr class="<!-- TMPL_VAR NAME="backgroundcolor" -->">
+                              <td>
+                                <!-- TMPL_IF NAME="available" -->
+                                  <input type="radio" class="checkitem checkitem_<!-- TMPL_VAR NAME="biblionumber" -->" name="checkitem_<!-- TMPL_VAR NAME="biblionumber" -->"
+                                         value="<!-- TMPL_VAR NAME="itemnumber" -->" />
+                                <!-- TMPL_ELSE -->
+                                  <input disabled="disabled" type="radio" class="checkitem" name="checkitem" value="<!-- TMPL_VAR NAME="itemnumber" -->" />
+                                  <img src="/intranet-tmpl/<!-- TMPL_VAR NAME="theme" -->/img/famfamfam/silk/cross.png" alt="Cannot be put on hold" />
+                                <!-- /TMPL_IF -->
+                              </td>
+                              <!-- TMPL_IF NAME="item-level_itypes" -->
+                                <td>
+                                  <img src="<!-- TMPL_VAR NAME="imageurl" -->"
+                                       alt="<!-- TMPL_VAR NAME="description" -->"
+                                       title="<!-- TMPL_VAR NAME="description" -->" />
+                                </td>
+                              <!-- /TMPL_IF -->
+                              <td><!-- TMPL_VAR NAME="barcode" --></td>
+                              <!-- TMPL_UNLESS NAME="singleBranchMode" -->
+                                <td><!-- TMPL_VAR NAME="homeBranchName" --></td>
+                                <td><!-- TMPL_VAR NAME="holdingBranchName" --></td>
+                              <!-- /TMPL_UNLESS -->
+                              <td><!-- TMPL_VAR NAME="callNumber" --></td>
+                              <td>
+                                <!-- TMPL_IF NAME="date_due" -->
+                                  <span class="checkedout">Due <!-- TMPL_VAR NAME="date_due" --></span>
+                                <!-- TMPL_ELSIF NAME="transfertwhen" -->
+                                  <span class="intransit">In transit from <!-- TMPL_VAR NAME="transfertfrom" -->,
+                                    to <!-- TMPL_VAR NAME="transfertto" -->, since <!-- TMPL_VAR NAME="transfertwhen" --></span>
+                                <!-- /TMPL_IF -->
+                                <!-- TMPL_IF Name="message" -->
+                                  <span class="lost">Unavailable (lost or missing)</span>
+                                <!-- /TMPL_IF -->
+                                <!-- TMPL_IF Name="notforloan" -->
+                                  <span class="notforloan">Not for loan (<!-- TMPL_VAR NAME="notforloanvalue" -->)</span>
+                                <!-- /TMPL_IF -->
+                                <!-- TMPL_IF NAME="reservedate"-->
+                                  <span class="waiting"><!-- TMPL_IF NAME="waitingdate" -->Waiting<!-- TMPL_ELSE -->On hold<!-- /TMPL_IF --> for patron 
+                                    <!-- TMPL_IF NAME="waitingdate" -->at<!-- TMPL_ELSE -->expected at<!-- /TMPL_IF --> <!-- TMPL_VAR NAME="ExpectedAtLibrary" -->
+                                    since
+                                    <!-- TMPL_IF NAME="waitingdate" --><!-- TMPL_VAR NAME="waitingdate" --><!-- TMPL_ELSE --><!-- TMPL_IF name="reservedate" --><!-- TMPL_VAR NAME="reservedate" --><!-- /TMPL_IF --><!-- /TMPL_IF -->.
+                                  </span>
+                                <!-- TMPL_ELSE -->
+                                  <span class="notonhold">Not on hold</span>
+                                <!-- /TMPL_IF -->&nbsp;
+                              </td>
+                            </tr>
+                          <!-- /TMPL_LOOP -->
+                        </table>
+                      </td>
+                    </tr>
+                  <!-- /TMPL_IF --><!-- bib_available -->
+                  <!-- /TMPL_IF --><!-- OPACItemHolds -->
+                <!-- /TMPL_LOOP -->
+              </table><!-- bibitemloop -->
+            </div><!-- bigloop -->
+
             <!-- TMPL_IF NAME="none_available" -->
             <input type="submit" disabled="disabled" value="Place Hold" />
             <!-- TMPL_ELSE -->
-            <input type="submit" value="Place Hold" />
+            <input type="submit" value="Place Hold" class="placehold" />
             <!-- /TMPL_IF -->
-        </form><!-- /TMPL_IF -->
-    <!-- end of the first form -->
-<!-- /TMPL_IF -->
-
-<!-- TMPL_IF NAME="item_types_selected" -->
-<!-- if the bibitems have already been selected -->
-<form action="/cgi-bin/koha/opac-reserve.pl" method="post">
-<input type="hidden" name="place_reserve" value="1" />
-<input type="hidden" name="biblionumber" value="<!-- TMPL_VAR NAME="biblionumber" -->" /><h3>Confirm Reservation</h3>
-<div class="details">
-    <table>
-        <tr><th>Title: </th><td><span class="title"><!-- TMPL_VAR NAME="title" escape="html" --></span></td></tr>
-
-        <!-- TMPL_IF NAME="singleBranchMode" -->
-        <input type="hidden" name="branch" value="<!-- TMPL_VAR NAME="branch" -->" />
-        <!-- TMPL_ELSE -->
-        <tr><th>Pick up From: </th><td><!-- TMPL_VAR NAME="branchname" --><input type="hidden" name="branch" value="<!-- TMPL_VAR NAME="branch" -->" /></td></tr>
-        <!-- /TMPL_IF -->
-</table>
-</div>
-<p><input type="submit" value="Finish and Place Reservation" class="submit" onclick="this.value='Please wait...'; this.disabled=true; this.form.submit();" /></p>
-
-</form>
-
-<!-- /TMPL_IF -->
-</div></div>
-</div>
+
+            </form>
+
+          <!-- /TMPL_UNLESS --><!-- message -->
+
+        </div><!-- holds -->
+      </div><!-- yui-g -->
+    </div><!-- bd    -->
+  </div><!-- doc3  -->
+
+<div><!-- The following include seems to have an extra "/div" in it... -->
 <!-- TMPL_INCLUDE NAME="opac-bottom.inc"-->
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tmpl
index d23a64f..6faefd0 100644
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tmpl
+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tmpl
@@ -12,6 +12,33 @@
 <script type="text/javascript" src="<!-- TMPL_VAR name="themelang" -->/lib/jquery/plugins/jquery.checkboxes.pack.js"></script>
 <script type="text/javascript">
 //<![CDATA[
+
+function holdMultiple() {
+    var checkedBiblioNums = ""; // Separated by "/"
+    var checkedCount = 0;
+    if(document.bookbag_form.biblionumber.length > 0) {
+        for (var i=0; i < document.bookbag_form.biblionumber.length; i++) {
+            if (document.bookbag_form.biblionumber[i].checked) {
+                checkedBiblioNums += (document.bookbag_form.biblionumber[i].value + "/");
+                checkedCount++;
+            }
+        }
+    }
+
+    if (checkedCount > 0) {
+        holdBiblioNums(checkedBiblioNums);
+    } else {
+        alert(MSG_NO_RECORD_SELECTED);   
+    }
+}
+
+function holdBiblioNums(numList) {
+    // numList: biblio numbers separated by "/"
+    $("#hold_form_biblios").attr("value", numList);
+    $("#hold_form").submit();
+}
+
+
 $(document).ready(function(){
 	var param1 = "<label for=\"addto\">Add to: <\/label><select name=\"addto\" id=\"addto\"><option value=\"\"><\/option>"<!-- TMPL_IF name="opacbookbag" -->+"<option value=\"addtocart\">Cart<\/option>"<!-- /TMPL_IF -->+<!-- TMPL_IF NAME="virtualshelves" --><!-- TMPL_IF NAME="loggedinusername" -->"<optgroup label=\"Your Lists:\">"+<!-- TMPL_IF NAME="addbarshelves" --><!-- TMPL_LOOP NAME="addbarshelvesloop" -->"<option id=\"s<!-- TMPL_VAR NAME="shelfnumber" -->\" value=\"addtolist\"><!-- TMPL_VAR NAME="shelfname" ESCAPE="html"--><\/option>"+<!-- /TMPL_LOOP --><!-- /TMPL_IF -->"<\/optgroup>";
 	param1 += "<optgroup label=\"Public Lists:\">"+<!-- TMPL_IF NAME="addpubshelves" --><!-- TMPL_LOOP NAME="addpubshelvesloop" -->"<option id=\"s<!-- TMPL_VAR NAME="shelfnumber" -->\" value=\"addtolist\"><!-- TMPL_VAR NAME="shelfname" ESCAPE="html"--><\/option>"+<!-- /TMPL_LOOP --><!-- /TMPL_IF -->"<\/optgroup><option value=\"newlist\">[ New List ]<\/option>"+<!-- TMPL_ELSE -->"<optgroup label=\"Public Lists:\">"+<!-- TMPL_IF NAME="addpubshelves" --><!-- TMPL_LOOP NAME="addpubshelvesloop" -->"<option id=\"s<!-- TMPL_VAR NAME="shelfnumber" -->\" value=\"addtolist\"><!-- TMPL_VAR NAME="shelfname" ESCAPE="html"--><\/option>"+<!-- /TMPL_LOOP --><!-- /TMPL_IF -->"<\/optgroup>"+<!-- /TMPL_IF --><!-- /TMPL_IF -->"<\/select> <input type=\"submit\" class=\"submit\" value=\"Save\" />";
@@ -54,7 +81,13 @@ $(document).ready(function(){
     $("#CheckNone").click(function(){
         $("#bookbag_form").unCheckCheckboxes();
         return false;
-    }); 
+    });
+    $("#placehold").html("<input class=\"submit\" type=\"submit\" value=\"Place Hold\"/>");
+	$("#placehold").find("input:submit").click(function(){
+        holdMultiple();
+		return false;
+	});
+    $("#holdDetails").hide();
 	<!-- TMPL_IF NAME="TagsEnabled" -->$(".tagbutton").click(KOHA.Tags.add_tag_button);<!-- /TMPL_IF -->
     <!-- TMPL_IF NAME="GoogleJackets" -->KOHA.Google.GetCoverFromIsbn();<!-- /TMPL_IF -->
 });
@@ -68,7 +101,6 @@ $(document).ready(function(){
 <!--TMPL_INCLUDE NAME="masthead.inc" -->
 
 
-
 	<div id="yui-main">
 	<div class="yui-b">
 	<div class="container">
@@ -164,15 +196,16 @@ $(document).ready(function(){
         <table>
 		<tr><td colspan="5" class="resultscontrol" style="border : 1px solid #e8e8e8;">
 		<div class="resort"> <select id="sort_by" name="sort_by"> <!--TMPL_INCLUDE NAME="resort_form.inc"--> </select> <input type="submit" class="submit clearfix" id="sortsubmit" value="Go" /></div>
-        <!-- TMPL_IF NAME="opacbookbag" -->
-			<div class="cartlist"><span class="checkall"></span>
-			<span class="clearall"></span>
-			<span class="addto"></span></div>
-        <!-- TMPL_ELSIF NAME="virtualshelves" -->
-			<div class="cartlist"><span class="checkall"></span>
-			<span class="clearall"></span>
-			<span class="addto"></span></div>
-		<!-- /TMPL_IF -->
+		<div class="cartlist">
+            <!-- checkall, clearall are now needed for placehold -->
+            <span class="checkall"></span>
+        	<span class="clearall"></span>
+            <!-- TMPL_IF EXPR="opacbookbag || virtualshelves" -->
+    	    	<span class="addto"></span>
+            <!-- /TMPL_IF -->
+		    <span id="placehold"><!-- input class="submit" type="submit" value="Place Hold"/ --></span>
+            <div id="holdDetails"></div>
+        </div>
 
         </td></tr>
             <!-- Actual Search Results -->
@@ -305,6 +338,10 @@ $(document).ready(function(){
                 <!-- /TMPL_LOOP -->
             </table>
     </form>
+    <form id="hold_form" name="hold_form" method="get" action="/cgi-bin/koha/opac-reserve.pl">
+        <!-- The value will be set by holdBiblioNums() in basket.js -->
+        <input id="hold_form_biblios" type="hidden" name="biblionumbers" value=""/>
+    </form>
         </div>
     <!-- /TMPL_IF -->
 	<!-- TMPL_INCLUDE NAME="page-numbers.inc" -->
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-shelves.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-shelves.tmpl
index 9732fdc..be56c78 100644
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-shelves.tmpl
+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-shelves.tmpl
@@ -10,6 +10,21 @@ $.tablesorter.addParser({
     type: 'text' 
 });
 
+function holdSelections() {
+    var checkedBoxes = $(":checkbox:checked");
+    if ($(checkedBoxes).size() == 0) {
+        alert(MSG_NO_RECORD_SELECTED);
+    } else {
+        var bibs = "";
+        $(checkedBoxes).each(function(){
+            var name = $(this).attr("name");
+            bib = name.substr(4);
+            bibs += bib + "/";
+        });
+        document.location = "/cgi-bin/koha/opac-reserve.pl?biblionumbers="+bibs;
+    }
+}
+
        $(function() {
             $("span.clearall").html("<a id=\"CheckNone\" href=\"#\">Clear All</a>");
             $("span.checkall").html("<a id=\"CheckAll\" href=\"#\">Select All</a>");
@@ -33,6 +48,10 @@ $.tablesorter.addParser({
                 return false;
             });
        });
+
+       $(document).ready(function(){
+           $(".hold").html("Place Hold");
+       });
 //]]>
 </script>
 </head>
@@ -97,6 +116,7 @@ $.tablesorter.addParser({
 <input type="hidden" value="1" name="DEL-<!-- TMPL_VAR NAME="shelfnumber" -->"/>
 <input type="submit" class="deleteshelf" value="Delete List" onclick="return confirmDelete(_('Are you sure you want to remove this List?'));"/></form>
 <a href="#" class="send" onClick="open(CGIBIN+'opac-sendshelf.pl?shelfid=<!-- TMPL_VAR NAME="shelfnumber" -->','win_form','dependant=yes,scrollbars=no,resizable=no,height=300,width=450,top=50,left=100')">Send List</a>
+<a href="#" class="hold" onClick="holdSelections();return false;"></a>
 </div><!-- /TMPL_IF -->
     <!-- TMPL_IF NAME="manageshelf" --><form action="/cgi-bin/koha/opac-shelves.pl" method="post" name="myform" class="checkboxed">
         <input type="hidden" name="viewshelf" value="<!-- TMPL_VAR NAME="shelfnumber" -->" />
@@ -338,4 +358,8 @@ $.tablesorter.addParser({
   </div><!-- /TMPL_IF -->
  </div>
 <!-- </div> -->
+
+<!-- DEBUG -->
+<div id="debug"></div>
+
 <!-- TMPL_INCLUDE NAME="opac-bottom.inc" -->
diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl
index 5f22a5a..7719ab3 100755
--- a/opac/opac-reserve.pl
+++ b/opac/opac-reserve.pl
@@ -16,6 +16,7 @@
 # Suite 330, Boston, MA  02111-1307 USA
 
 use strict;
+use warnings;
 use CGI;
 use C4::Biblio;
 use C4::Items;
@@ -55,42 +56,43 @@ my ( $borr ) = GetMemberDetails( $borrowernumber );
 
 # get branches and itemtypes
 my $branches = GetBranches();
-my $itemtypes = GetItemTypes();
-
-# get biblionumber.....
-my $biblionumber = $query->param('biblionumber');
-if (! $biblionumber) {
-	$template->param(message=>1,no_biblionumber=>1);
-	&get_out($query, $cookie, $template->output);
+my $itemTypes = GetItemTypes();
+
+# There are two ways of calling this script, with a single biblio num
+# or multiple biblio nums.
+my $biblionumbers = $query->param('biblionumbers');
+my $reserveMode = $query->param('reserve_mode');
+if ($reserveMode && ($reserveMode eq 'single')) {
+    my $bib = $query->param('single_bib');
+    $biblionumbers = "$bib/";
+}
+if (! $biblionumbers) {
+    $biblionumbers = $query->param('biblionumber');
 }
-$template->param( biblionumber => $biblionumber );
 
-my $bibdata = GetBiblioData($biblionumber);
-if (! $bibdata) {
-	$template->param(message=>1,bad_biblionumber=>$biblionumber);
-	&get_out($query, $cookie, $template->output);
+if ((! $biblionumbers) && (! $query->param('place_reserve'))) {
+    $template->param(message=>1, no_biblionumber=>1);
+    &get_out($query, $cookie, $template->output);
 }
-$template->param($bibdata);		# FIXME: bad form.
 
-# get the rank number....
-my ( $rank, $reserves ) = GetReservesFromBiblionumber( $biblionumber);
-$template->param( reservecount => $rank );
+# Pass the numbers to the page so they can be fed back
+# when the hold is confirmed. TODO: Not necessary?
+$template->param( biblionumbers => $biblionumbers );
 
-foreach my $res (@$reserves) {
-    if ( $res->{'found'} eq 'W' ) {
-        $rank--;
-    }
+# Each biblio number is suffixed with '/', e.g. "1/2/3/"
+my @biblionumbers = split /\//, $biblionumbers;
+if (($#biblionumbers < 0) && (! $query->param('place_reserve'))) {
+    # TODO: New message?
+    $template->param(message=>1, no_biblionumber=>1);
+    &get_out($query, $cookie, $template->output);
 }
 
-$rank++;
-$template->param( rank => $rank );
-
 # pass the pickup branch along....
 my $branch = $query->param('branch');
 $template->param( branch => $branch );
 
 # make sure it's a real branch
-if ( !$branches->{$branch} ) {
+if ( !$branch || !$branches->{$branch} ) {
     $branch = '';
 }
 $template->param( branchname => $branches->{$branch}->{'branchname'} );
@@ -114,262 +116,391 @@ foreach my $branch ( keys %$branches ) {
     }
 }
 @CGIbranchlooparray =
-  sort { $a->{branch} cmp $b->{branch} } @CGIbranchlooparray;
+   sort { $a->{branch} cmp $b->{branch} } @CGIbranchlooparray;
 my $CGIbranchloop = \@CGIbranchlooparray;
 $template->param( CGIbranch => $CGIbranchloop );
 
-my @items = GetItemsInfo($biblionumber);
-
-# an item was previously required to have an itemtype in order to be reserved.
-# this behavior removed to fix bug 1891 .
-# my @items = grep { (C4::Context->preference('item-level_itypes') ? $_->{'itype'} : $_->{'itemtype'} ) } @all_items ;
-
-$template->param( itemcount => scalar(@items) );
-
-my %itemhash;
-my $forloan;
-foreach my $itm (@items) {
-	$debug and warn $itm->{'notforloan'};
-    my $fee = GetReserveFee( undef, $borrowernumber, $itm->{'biblionumber'}, 'a', ( $itm->{'biblioitemnumber'} ) );
-    $itm->{'reservefee'} = sprintf "%.02f", $fee;
-    # pass itype to itemtype for display purposes.  
-    $itm->{'itemtype'} = $itm->{'itype'} if(C4::Context->preference('item-level_itypes')); 	
-	$itemhash{$itm->{'itemnumber'}}=$itm;
-    if (!$itm->{'notforloan'} && !($itm->{'itemnotforloan'} > 0)){
-		$forloan=1;
-	}
+
+#Debug
+#output_html_with_http_headers($query,$cookie,"<html><head></head><body> @biblionumbers </body></html>\n");
+#exit;
+#my %bibdata;
+#my $rank;
+#my $biblionumber;
+#my $bibdata;
+#my %itemhash;
+#my $forloan;
+
+#
+#
+# Build hashes of the requested biblio(item)s and items.
+#
+#
+
+# Hash of biblionumber to biblio/biblioitems record.
+my %biblioDataHash;
+
+# Hash of itemnumber to item info.
+my %itemInfoHash;
+
+foreach my $biblioNumber (@biblionumbers) {
+
+    my $biblioData = GetBiblioData($biblioNumber);
+    $biblioDataHash{$biblioNumber} = $biblioData;
+
+    my @itemInfos = GetItemsInfo($biblioNumber);
+    $biblioData->{itemInfos} = \@itemInfos;
+    foreach my $itemInfo (@itemInfos) {
+        $itemInfoHash{$itemInfo->{itemnumber}} = $itemInfo;
+    }
+
+    # Compute the priority rank.
+    my ( $rank, $reserves ) = GetReservesFromBiblionumber($biblioNumber);
+    $biblioData->{reservecount} = $rank;
+    foreach my $res (@$reserves) {
+        my $found = $res->{'found'};
+        if ( $found && ($found eq 'W') ) {
+            $rank--;
+        }
+    }
+    $rank++;
+    $biblioData->{rank} = $rank;
 }
 
+#
+#
+# If this is the second time through this script, it
+# means we are carrying out the hold request, possibly
+# with a specific item for each biblionumber.
+#
+#
 if ( $query->param('place_reserve') ) {
-    my @bibitems=$query->param('biblioitem');
-    my $notes=$query->param('notes');
-    my $checkitem=$query->param('checkitem');
-    my $found;
-    
-    #if we have an item selectionned, and the pickup branch is the same as the holdingbranch of the document, we force the value $rank and $found.
-    if ($checkitem ne ''){
-        $rank = '0' unless C4::Context->preference('ReservesNeedReturns');
-        my $item = $checkitem;
-        $item = GetItem($item);
-        if ( $item->{'holdingbranch'} eq $branch ){
-            $found = 'W' unless C4::Context->preference('ReservesNeedReturns');
+
+    my $notes = $query->param('notes');
+
+    # List is composed of alternating biblio/item/branch
+    my $selectedItems = $query->param('selecteditems');
+
+    if ($query->param('reserve_mode') eq 'single') {
+        # This indicates non-JavaScript mode, so there was
+        # only a single biblio number selected.
+        my $bib = $query->param('single_bib');
+        my $item = $query->param("checkitem_$bib");
+        if ($item eq 'any') {
+            $item = '';
         }
+        my $branch = $query->param('branch');
+        $selectedItems = "$bib/$item/$branch/";
+    }
+    
+    my @selectedItems = split /\//, $selectedItems;
+
+    # Make sure there is a biblionum/itemnum/branch triplet for each item.
+    # The itemnum can be 'any', meaning next available.
+    my $selectionCount = @selectedItems;
+    if (($selectionCount == 0) || (($selectionCount % 3) != 0)) {
+        $template->param(message=>1, bad_data=>1);
+        &get_out($query, $cookie, $template->output);
     }
+
+    while (@selectedItems) {
+        my $biblioNum = shift(@selectedItems);
+        my $itemNum = shift(@selectedItems);
+        my $branch = shift(@selectedItems); # i.e., branch code, not name
+
+        my $singleBranchMode = $template->param('singleBranchMode');
+        if ($singleBranchMode) {
+            $branch = $borr->{'branchcode'};
+        }
+
+        my $biblioData = $biblioDataHash{$biblioNum};
+        my $found;
         
-        my $count=@bibitems;
-    @bibitems=sort @bibitems;
-    my $i2=1;
-    my @realbi;
-    $realbi[0]=$bibitems[0];
-    for (my $i=1;$i<$count;$i++) {
-        my $i3=$i2-1;
-        if ($realbi[$i3] ne $bibitems[$i]) {
-            $realbi[$i2]=$bibitems[$i];
-            $i2++;
+        # If a specific item was selected and the pickup branch is the same as the
+        # holdingbranch, force the value $rank and $found.
+        my $rank = $biblioData->{rank};
+        if ($itemNum ne ''){
+            $rank = '0' unless C4::Context->preference('ReservesNeedReturns');
+            my $item = GetItem($itemNum);
+            if ( $item->{'holdingbranch'} eq $branch ){
+                $found = 'W' unless C4::Context->preference('ReservesNeedReturns');
+            }
         }
+        else {
+            # Inserts a null into the 'itemnumber' field of 'reserves' table.
+            $itemNum = undef;
+        }
+        
+        # Here we actually do the reserveration. Stage 3.
+        AddReserve($branch, $borrowernumber, $biblioNum, 'a', [$biblioNum], $rank, $notes,
+                   $biblioData->{'title'}, $itemNum, $found);
     }
-    # here we actually do the reserveration. Stage 3.
-    if ($query->param('request') eq 'any'){
-        # place a request on 1st available
-        AddReserve($branch,$borrowernumber,$biblionumber,'a',\@realbi,$rank,$notes,$bibdata->{'title'},$checkitem,$found);
-    } else {
-        AddReserve($branch,$borrowernumber,$biblionumber,'a',\@realbi,$rank,$notes,$bibdata->{'title'},$checkitem, $found);
-    }
+
     print $query->redirect("/cgi-bin/koha/opac-user.pl#opac-user-holds");
+    exit;
 }
-else {
-
-    # Here we check that the borrower can actually make reserves Stage 1.
-    my $noreserves     = 0;
-    my $maxoutstanding = C4::Context->preference("maxoutstanding");
-    $template->param( noreserve => 1 ) unless $maxoutstanding;
-    if ( $borr->{'amountoutstanding'} > $maxoutstanding ) {
-        my $amount = sprintf "\$%.02f", $borr->{'amountoutstanding'};
-        $template->param( message => 1 );
-        $noreserves = 1;
-        $template->param( too_much_oweing => $amount );
-    }
-    if ( $borr->{gonenoaddress} eq 1 ) {
-        $noreserves = 1;
-        $template->param(
-            message => 1,
-            GNA     => 1
-        );
-    }
-    if ( $borr->{lost} eq 1 ) {
-        $noreserves = 1;
-        $template->param(
-            message => 1,
-            lost    => 1
-        );
-    }
-    if ( $borr->{debarred} eq 1 ) {
-        $noreserves = 1;
-        $template->param(
-            message  => 1,
-            debarred => 1
-        );
-    }
-    my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
-    $template->param( RESERVES => \@reserves );
-    if ( scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES ) {
-        $template->param( message => 1 );
-        $noreserves = 1;
-        $template->param( too_many_reserves => scalar(@reserves));
-    }
-    foreach my $res (@reserves) {
+
+#
+#
+# Here we check that the borrower can actually make reserves Stage 1.
+#
+#
+my $noreserves     = 0;
+my $maxoutstanding = C4::Context->preference("maxoutstanding");
+$template->param( noreserve => 1 ) unless $maxoutstanding;
+if ( $borr->{'amountoutstanding'} && ($borr->{'amountoutstanding'} > $maxoutstanding) ) {
+    my $amount = sprintf "\$%.02f", $borr->{'amountoutstanding'};
+    $template->param( message => 1 );
+    $noreserves = 1;
+    $template->param( too_much_oweing => $amount );
+}
+if ( $borr->{gonenoaddress} && ($borr->{gonenoaddress} eq 1) ) {
+    $noreserves = 1;
+    $template->param(
+                     message => 1,
+                     GNA     => 1
+                    );
+}
+if ( $borr->{lost} && ($borr->{lost} eq 1) ) {
+    $noreserves = 1;
+    $template->param(
+                     message => 1,
+                     lost    => 1
+                    );
+}
+if ( $borr->{debarred} && ($borr->{debarred} eq 1) ) {
+    $noreserves = 1;
+    $template->param(
+                     message  => 1,
+                     debarred => 1
+                    );
+}
+
+my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
+$template->param( RESERVES => \@reserves );
+if ( scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES ) {
+    $template->param( message => 1 );
+    $noreserves = 1;
+    $template->param( too_many_reserves => scalar(@reserves));
+}
+foreach my $res (@reserves) {
+    foreach my $biblionumber (@biblionumbers) {
         if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) {
-            $template->param( message => 1 );
-            $noreserves = 1;
-            $template->param( already_reserved => 1 );
+#            $template->param( message => 1 );
+#            $noreserves = 1;
+#            $template->param( already_reserved => 1 );
+            $biblioDataHash{$biblionumber}->{already_reserved} = 1;
         }
     }
-    unless ($noreserves) {
-        $template->param( select_item_types => 1 );
-    }
 }
 
-
-my %itemnumbers_of_biblioitem;
-my @itemnumbers  = @{ get_itemnumbers_of($biblionumber)->{$biblionumber} };
-my $iteminfos_of = GetItemInfosOf(@itemnumbers);
-
-foreach my $itemnumber (@itemnumbers) {
-    my $biblioitemnumber = $iteminfos_of->{$itemnumber}->{biblioitemnumber};
-    push( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} }, $itemnumber );
+unless ($noreserves) {
+    $template->param( select_item_types => 1 );
 }
 
-my @biblioitemnumbers = keys %itemnumbers_of_biblioitem;
 
+#
+#
+# Build the template parameters that will show the info
+# and items for each biblionumber.
+#
+#
 my $notforloan_label_of = get_notforloan_label_of();
-my $biblioiteminfos_of  = GetBiblioItemInfosOf(@biblioitemnumbers);
 
-my @itemtypes;
-foreach my $biblioitemnumber (@biblioitemnumbers) {
-    push @itemtypes, $biblioiteminfos_of->{$biblioitemnumber}{itemtype};
-}
+my $biblioLoop = [];
+my $numBibsAvailable = 0;
+my $itemLevelTypes = C4::Context->preference('item-level_itypes');
+$template->param('item-level_itypes' => $itemLevelTypes);
 
-my @bibitemloop;
+foreach my $biblioNum (@biblionumbers) {
 
-foreach my $biblioitemnumber (@biblioitemnumbers) {
-    my $biblioitem = $biblioiteminfos_of->{$biblioitemnumber};
+    
+    # Init the bib item with the choices for branch pickup
+    my %biblioLoopIter = ( branchChoicesLoop => $CGIbranchloop );
 
-    $biblioitem->{description} =
-      $itemtypes->{ $biblioitem->{itemtype} }{description};
+    # Get relevant biblio data.
+    my $biblioData = $biblioDataHash{$biblioNum};
+    if (! $biblioData) {
+        $template->param(message=>1, bad_biblionumber=>$biblioNum);
+	&get_out($query, $cookie, $template->output);
+    }
 
-    my $num_available = 0;
+    $biblioLoopIter{biblionumber} = $biblioData->{biblionumber};
+    $biblioLoopIter{title} = $biblioData->{title};
+    $biblioLoopIter{author} = $biblioData->{author};
+    $biblioLoopIter{rank} = $biblioData->{rank};
+    $biblioLoopIter{reservecount} = $biblioData->{reservecount};
+    $biblioLoopIter{already_reserved} = $biblioData->{already_reserved};
 
-    foreach
-      my $itemnumber ( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} } )
-    {
-		my $item = $itemhash{$itemnumber};
+    if (!$itemLevelTypes && $biblioData->{itemtype}) {
+        $biblioLoopIter{description} = $itemTypes->{$biblioData->{itemtype}}{description};
+        $biblioLoopIter{imageurl} = getitemtypeimagesrc() . "/". $itemTypes->{$biblioData->{itemtype}}{imageurl};
+    }
 
-        $item->{homebranchname} =
-          $branches->{ $item->{homebranch} }{branchname};
+    foreach my $itemInfo (@{$biblioData->{itemInfos}}) {
+        $debug and warn $itemInfo->{'notforloan'};
 
-        # if the holdingbranch is different than the homebranch, we show the
-        # holdingbranch of the document too
-        if ( $item->{homebranch} ne $item->{holdingbranch} ) {
-            $item->{holdingbranchname} =
-              $branches->{ $item->{holdingbranch} }{branchname};
+        # Get reserve fee.
+        my $fee = GetReserveFee(undef, $borrowernumber, $itemInfo->{'biblionumber'}, 'a',
+                                ( $itemInfo->{'biblioitemnumber'} ) );
+        $itemInfo->{'reservefee'} = sprintf "%.02f", ($fee ? $fee : 0.0);
+        
+        if ($itemLevelTypes && $itemInfo->{itype}) {
+            $itemInfo->{description} = $itemTypes->{$itemInfo->{itype}}{description};
+            $itemInfo->{imageurl} = getitemtypeimagesrc() . "/". $itemTypes->{$itemInfo->{itype}}{imageurl};
         }
         
-# 	add information
-	$item->{itemcallnumber} = $item->{itemcallnumber};
-	
-        # if the item is currently on loan, we display its return date and
-        # change the background color
-        my $issues= GetItemIssue($itemnumber);
+        if (!$itemInfo->{'notforloan'} && !($itemInfo->{'itemnotforloan'} > 0)) {
+            $biblioLoopIter{forloan} = 1;
+	}
+    }
+
+    $biblioLoopIter{itemTypeDescription} =
+      $itemTypes->{$biblioData->{itemtype}}{description};
+    
+
+    $biblioLoopIter{itemLoop} = [];
+    my $numCopiesAvailable = 0;
+    foreach my $itemInfo (@{$biblioData->{itemInfos}}) {
+        my $itemNum = $itemInfo->{itemnumber};
+        my $itemLoopIter = {};
+
+        $itemLoopIter->{itemnumber} = $itemNum;
+        $itemLoopIter->{barcode} = $itemInfo->{barcode};
+        $itemLoopIter->{homeBranchName} = $branches->{$itemInfo->{homebranch}}{branchname};
+        $itemLoopIter->{callNumber} = $itemInfo->{itemcallnumber};
+
+        if ($itemLevelTypes) {
+            $itemLoopIter->{description} = $itemInfo->{description};
+            $itemLoopIter->{imageurl} = $itemInfo->{imageurl};
+        }
+
+        # If the holdingbranch is different than the homebranch, we show the
+        # holdingbranch of the document too.
+        if ( $itemInfo->{homebranch} ne $itemInfo->{holdingbranch} ) {
+            $itemLoopIter->{holdingBranchName} =
+              $branches->{ $itemInfo->{holdingbranch} }{branchname};
+        }
+
+        # If the item is currently on loan, we display its return date and
+        # change the background color.
+        my $issues= GetItemIssue($itemNum);
         if ( $issues->{'date_due'} ) {
-            $item->{date_due} = format_date($issues->{'date_due'});
-            $item->{backgroundcolor} = 'onloan';
+            $itemLoopIter->{dateDue} = format_date($issues->{'date_due'});
+            $itemLoopIter->{backgroundcolor} = 'onloan';
         }
 
         # checking reserve
-        my ($reservedate,$reservedfor,$expectedAt) = GetReservesFromItemnumber($itemnumber);
+        my ($reservedate,$reservedfor,$expectedAt) = GetReservesFromItemnumber($itemNum);
         my $ItemBorrowerReserveInfo = GetMemberDetails( $reservedfor, 0);
 
         if ( defined $reservedate ) {
-            $item->{backgroundcolor} = 'reserved';
-            $item->{reservedate}     = format_date($reservedate);
-            $item->{ReservedForBorrowernumber}     = $reservedfor;
-            $item->{ReservedForSurname}     = $ItemBorrowerReserveInfo->{'surname'};
-            $item->{ReservedForFirstname}     = $ItemBorrowerReserveInfo->{'firstname'};
-            $item->{ExpectedAtLibrary}     = $expectedAt;
-            
+            $itemLoopIter->{backgroundcolor} = 'reserved';
+            $itemLoopIter->{reservedate}     = format_date($reservedate);
+            $itemLoopIter->{ReservedForBorrowernumber}     = $reservedfor;
+            $itemLoopIter->{ReservedForSurname}     = $ItemBorrowerReserveInfo->{'surname'};
+            $itemLoopIter->{ReservedForFirstname}     = $ItemBorrowerReserveInfo->{'firstname'};
+            $itemLoopIter->{ExpectedAtLibrary}     = $expectedAt;
         }
 
+        $itemLoopIter->{notforloan} = $itemInfo->{notforloan};
+        $itemLoopIter->{itemnotforloan} = $itemInfo->{itemnotforloan};
+
         # Management of the notforloan document
-        if ( $item->{notforloan} || $item->{itemnotforloan}) {
-            $item->{backgroundcolor} = 'other';
-            $item->{notforloanvalue} =
-              $notforloan_label_of->{ $item->{notforloan} };
+        if ( $itemLoopIter->{notforloan} || $itemLoopIter->{itemnotforloan}) {
+            $itemLoopIter->{backgroundcolor} = 'other';
+            $itemLoopIter->{notforloanvalue} =
+              $notforloan_label_of->{ $itemLoopIter->{notforloan} };
         }
 
         # Management of lost or long overdue items
-        if ( $item->{itemlost} ) {
+        if ( $itemInfo->{itemlost} ) {
 
             # FIXME localized strings should never be in Perl code
-            $item->{message} =
-                $item->{itemlost} == 1 ? "(lost)"
-              : $item->{itemlost} == 2 ? "(long overdue)"
+            $itemLoopIter->{message} =
+                $itemInfo->{itemlost} == 1 ? "(lost)"
+              : $itemInfo->{itemlost} == 2 ? "(long overdue)"
               : "";
-            $item->{backgroundcolor} = 'other';
+            $itemInfo->{backgroundcolor} = 'other';
         }
 
         # Check of the transfered documents
         my ( $transfertwhen, $transfertfrom, $transfertto ) =
-          GetTransfers($itemnumber);
-
-        if ( $transfertwhen ne '' ) {
-            $item->{transfertwhen} = format_date($transfertwhen);
-            $item->{transfertfrom} =
+          GetTransfers($itemNum);
+        if ( $transfertwhen && ($transfertwhen ne '') ) {
+            $itemLoopIter->{transfertwhen} = format_date($transfertwhen);
+            $itemLoopIter->{transfertfrom} =
               $branches->{$transfertfrom}{branchname};
-            $item->{transfertto} = $branches->{$transfertto}{branchname};
-		$item->{nocancel} = 1;
+            $itemLoopIter->{transfertto} = $branches->{$transfertto}{branchname};
+            $itemLoopIter->{nocancel} = 1;
         }
 
         # If there is no loan, return and transfer, we show a checkbox.
-        $item->{notforloan} = $item->{notforloan} || 0;
+        $itemLoopIter->{notforloan} = $itemLoopIter->{notforloan} || 0;
 
-        my $branchitemrule = GetBranchItemRule( $item->{'homebranch'}, $item->{'itype'} );
+        my $branchitemrule = GetBranchItemRule( $borr->{'branchcode'}, $itemInfo->{'itype'} );
         my $policy_holdallowed = 1;
 
         if ( $branchitemrule->{'holdallowed'} == 0 ||
-                ( $branchitemrule->{'holdallowed'} == 1 && $borr->{'branchcode'} ne $item->{'homebranch'} ) ) {
+                ( $branchitemrule->{'holdallowed'} == 1 && $borr->{'branchcode'} ne $itemInfo->{'homebranch'} ) ) {
             $policy_holdallowed = 0;
         }
 
-        if (IsAvailableForItemLevelRequest($itemnumber) and $policy_holdallowed) {
-            $item->{available} = 1;
-            $num_available++;
+        if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed) {
+            $itemLoopIter->{available} = 1;
+            $numCopiesAvailable++;
         }
 
 	# FIXME: move this to a pm
         my $dbh = C4::Context->dbh;
         my $sth2 = $dbh->prepare("SELECT * FROM reserves WHERE borrowernumber=? AND itemnumber=? AND found='W'");
-        $sth2->execute($item->{ReservedForBorrowernumber},$item->{itemnumber});
+        $sth2->execute($itemLoopIter->{ReservedForBorrowernumber}, $itemNum);
         while (my $wait_hashref = $sth2->fetchrow_hashref) {
-            $item->{waitingdate} = format_date($wait_hashref->{waitingdate});
+            $itemLoopIter->{waitingdate} = format_date($wait_hashref->{waitingdate});
         }
-	$item->{imageurl} = getitemtypeimagelocation( 'opac', $itemtypes->{ $item->{itype} }{imageurl} );
-        push @{ $biblioitem->{itemloop} }, $item;
+	$itemLoopIter->{imageurl} = getitemtypeimagelocation( 'opac', $itemTypes->{ $itemInfo->{itype} }{imageurl} );
+
+        
+        push @{$biblioLoopIter{itemLoop}}, $itemLoopIter;
     }
 
-    if ( $num_available == 0 ) {
-        $template->param( none_available => 1, message => 1 );
+    if ($numCopiesAvailable > 0) {
+        $numBibsAvailable++;
+        $biblioLoopIter{bib_available} = 1;
+        $biblioLoopIter{holdable} = 1;
+    }
+    if ($biblioLoopIter{already_reserved}) {
+        $biblioLoopIter{holdable} = undef;
     }
 
-    push @bibitemloop, $biblioitem;
+    push @$biblioLoop, \%biblioLoopIter;
 }
 
+
+if ( $numBibsAvailable == 0 ) {
+    $template->param( none_available => 1, message => 1 );
+}
+
+
+my $itemTableColspan = 5;
+if (!$template->param('OPACItemHolds')) {
+    $itemTableColspan--;
+}
+if ($template->param('singleBranchMode')) {
+    $itemTableColspan--;
+}
+$template->param(itemtable_colspan => $itemTableColspan);
+
+
+
 # display infos
-$template->param(
-	forloan           => $forloan,
-    bibitemloop       => \@bibitemloop,
-);
+$template->param(bibitemloop => $biblioLoop);
 output_html_with_http_headers $query, $cookie, $template->output;
 
+
+
+
+
 # Local Variables:
 # tab-width: 8
 # End:
-- 
1.5.6.5




More information about the Koha-patches mailing list