From de767dbdbfeac9fe8bbec5844da34641bd8252dc Mon Sep 17 00:00:00 2001
From: Chris Hallberg <crhallberg@gmail.com>
Date: Tue, 15 Mar 2016 15:52:52 -0400
Subject: [PATCH] Convert Cart to a namespaced object.

---
 themes/bootstrap3/js/cart.js                  | 350 +++++++++---------
 .../bootstrap3/templates/layout/layout.phtml  |   8 +-
 2 files changed, 189 insertions(+), 169 deletions(-)

diff --git a/themes/bootstrap3/js/cart.js b/themes/bootstrap3/js/cart.js
index a387bd7b02c..f38be38128c 100644
--- a/themes/bootstrap3/js/cart.js
+++ b/themes/bootstrap3/js/cart.js
@@ -1,169 +1,212 @@
-/*global bulkActionSubmit, cartCookieDomain, Cookies, Lightbox, refreshPageForLogin, VuFind */
+/*global Cookies, VuFind */
 
-var _CART_COOKIE = 'vufind_cart';
-var _CART_COOKIE_SOURCES = 'vufind_cart_src';
-var _CART_COOKIE_DELIM = "\t";
+VuFind.cart = (function() {
+  var _COOKIE = 'vufind_cart';
+  var _COOKIE_SOURCES = 'vufind_cart_src';
+  var _COOKIE_DELIM = "\t";
+  var _COOKIE_DOMAIN = false;
 
-var currentId,currentSource;
-var lastCartSubmit = false;
+  var setDomain = function(domain) {
+    _COOKIE_DOMAIN = domain;
+  }
 
-function getCartItems() {
-  var items = Cookies.getItem(_CART_COOKIE);
-  if(items) {
-    return items.split(_CART_COOKIE_DELIM);
+  var _uniqueArray = function(op) {
+    var ret = [];
+    for(var i=0;i<op.length;i++) {
+      if(ret.indexOf(op[i]) < 0) {
+        ret.push(op[i]);
+      }
+    }
+    return ret;
   }
-  return [];
-}
-function getCartSources() {
-  var items = Cookies.getItem(_CART_COOKIE_SOURCES);
-  if(items) {
-    return items.split(_CART_COOKIE_DELIM);
+
+  var _getItems = function() {
+    var items = Cookies.getItem(_COOKIE);
+    if(items) {
+      return items.split(_COOKIE_DELIM);
+    }
+    return [];
   }
-  return [];
-}
-function getFullCartItems() {
-  var items = getCartItems();
-  var sources = getCartSources();
-  var full = [];
-  if(items.length == 0) {
+  var _getSources = function() {
+    var items = Cookies.getItem(_COOKIE_SOURCES);
+    if(items) {
+      return items.split(_COOKIE_DELIM);
+    }
     return [];
   }
-  for(var i=items.length;i--;) {
-    full[full.length] = sources[items[i].charCodeAt(0)-65]+'|'+items[i].substr(1);
+  var getFullItems = function() {
+    var items = _getItems();
+    var sources = _getSources();
+    var full = [];
+    if(items.length == 0) {
+      return [];
+    }
+    for(var i=items.length;i--;) {
+      full[full.length] = sources[items[i].charCodeAt(0)-65]+'|'+items[i].substr(1);
+    }
+    return full;
   }
-  return full;
-}
 
-function updateCartCount() {
-  var items = getCartItems();
-  $('#cartItems strong').html(items.length);
-}
-
-function addItemToCart(id,source) {
-  if(!source) {
-    source = VuFind.defaultSearchBackend;
-  }
-  var cartItems = getCartItems();
-  var cartSources = getCartSources();
-  var sIndex = cartSources.indexOf(source);
-  if(sIndex < 0) {
-    // Add source to source cookie
-    cartItems[cartItems.length] = String.fromCharCode(65+cartSources.length) + id;
-    cartSources[cartSources.length] = source;
-    Cookies.setItem(_CART_COOKIE_SOURCES, cartSources.join(_CART_COOKIE_DELIM), false, '/', cartCookieDomain);
-  } else {
-    cartItems[cartItems.length] = String.fromCharCode(65+sIndex) + id;
+  var updateCount = function() {
+    var items = _getItems();
+    $('#cartItems strong').html(items.length);
   }
-  Cookies.setItem(_CART_COOKIE, $.unique(cartItems).join(_CART_COOKIE_DELIM), false, '/', cartCookieDomain);
-  updateCartCount();
-  return true;
-}
-function uniqueArray(op) {
-  var ret = [];
-  for(var i=0;i<op.length;i++) {
-    if(ret.indexOf(op[i]) < 0) {
-      ret.push(op[i]);
+
+  var addItem = function(id,source) {
+    if(!source) {
+      source = VuFind.defaultSearchBackend;
     }
+    var cartItems = _getItems();
+    var cartSources = _getSources();
+    var sIndex = cartSources.indexOf(source);
+    if(sIndex < 0) {
+      // Add source to source cookie
+      cartItems[cartItems.length] = String.fromCharCode(65+cartSources.length) + id;
+      cartSources[cartSources.length] = source;
+      Cookies.setItem(_COOKIE_SOURCES, cartSources.join(_COOKIE_DELIM), false, '/', _COOKIE_DOMAIN);
+    } else {
+      cartItems[cartItems.length] = String.fromCharCode(65+sIndex) + id;
+    }
+    Cookies.setItem(_COOKIE, $.unique(cartItems).join(_COOKIE_DELIM), false, '/', _COOKIE_DOMAIN);
+    updateCount();
+    return true;
   }
-  return ret;
-}
-function removeItemFromCart(id,source) {
-  var cartItems = getCartItems();
-  var cartSources = getCartSources();
-  // Find
-  var cartIndex = cartItems.indexOf(String.fromCharCode(65+cartSources.indexOf(source))+id);
-  if(cartIndex > -1) {
-    var sourceIndex = cartItems[cartIndex].charCodeAt(0)-65;
-    var cartItem = cartItems[cartIndex];
-    var saveSource = false;
-    for(var i=cartItems.length;i--;) {
-      if(i==cartIndex) {
-        continue;
+  var removeItem = function(id,source) {
+    var cartItems = _getItems();
+    var cartSources = _getSources();
+    // Find
+    var cartIndex = cartItems.indexOf(String.fromCharCode(65+cartSources.indexOf(source))+id);
+    if(cartIndex > -1) {
+      var sourceIndex = cartItems[cartIndex].charCodeAt(0)-65;
+      var cartItem = cartItems[cartIndex];
+      var saveSource = false;
+      for(var i=cartItems.length;i--;) {
+        if(i==cartIndex) {
+          continue;
+        }
+        // If this source is shared by another, keep it
+        if(cartItems[i].charCodeAt(0)-65 == sourceIndex) {
+          saveSource = true;
+          break;
+        }
       }
-      // If this source is shared by another, keep it
-      if(cartItems[i].charCodeAt(0)-65 == sourceIndex) {
-        saveSource = true;
-        break;
+      cartItems.splice(cartIndex,1);
+      // Remove unused sources
+      if(!saveSource) {
+        var oldSources = cartSources.slice(0);
+        cartSources.splice(sourceIndex,1);
+        // Adjust source index characters
+        for(var j=cartItems.length;j--;) {
+          var si = cartItems[j].charCodeAt(0)-65;
+          var ni = cartSources.indexOf(oldSources[si]);
+          cartItems[j] = String.fromCharCode(65+ni)+cartItems[j].substring(1);
+        }
       }
-    }
-    cartItems.splice(cartIndex,1);
-    // Remove unused sources
-    if(!saveSource) {
-      var oldSources = cartSources.slice(0);
-      cartSources.splice(sourceIndex,1);
-      // Adjust source index characters
-      for(var j=cartItems.length;j--;) {
-        var si = cartItems[j].charCodeAt(0)-65;
-        var ni = cartSources.indexOf(oldSources[si]);
-        cartItems[j] = String.fromCharCode(65+ni)+cartItems[j].substring(1);
+      if(cartItems.length > 0) {
+        Cookies.setItem(_COOKIE, _uniqueArray(cartItems).join(_COOKIE_DELIM), false, '/', _COOKIE_DOMAIN);
+        Cookies.setItem(_COOKIE_SOURCES, _uniqueArray(cartSources).join(_COOKIE_DELIM), false, '/', _COOKIE_DOMAIN);
+      } else {
+        Cookies.removeItem(_COOKIE, '/', _COOKIE_DOMAIN);
+        Cookies.removeItem(_COOKIE_SOURCES, '/', _COOKIE_DOMAIN);
       }
+      updateCount();
+      return true;
     }
-    if(cartItems.length > 0) {
-      Cookies.setItem(_CART_COOKIE, uniqueArray(cartItems).join(_CART_COOKIE_DELIM), false, '/', cartCookieDomain);
-      Cookies.setItem(_CART_COOKIE_SOURCES, uniqueArray(cartSources).join(_CART_COOKIE_DELIM), false, '/', cartCookieDomain);
-    } else {
-      Cookies.removeItem(_CART_COOKIE, '/', cartCookieDomain);
-      Cookies.removeItem(_CART_COOKIE_SOURCES, '/', cartCookieDomain);
-    }
-    updateCartCount();
-    return true;
+    return false;
   }
-  return false;
-}
 
-var cartNotificationTimeout = false;
-function registerUpdateCart($form) {
-  if($form) {
-    $("#updateCart, #bottom_updateCart").unbind('click').click(function(){
-      var elId = this.id;
-      var selectedBoxes = $("input[name='ids[]']:checked", $form);
-      var selected = [];
-      $(selectedBoxes).each(function(i) {
-        selected[i] = this.value;
-      });
-      if (selected.length > 0) {
-        var inCart = 0;
-        var msg = "";
-        var orig = getFullCartItems();
-        $(selected).each(function(i) {
-          for (var x in orig) {
-            if (this == orig[x]) {
-              inCart++;
-              return;
+  var _cartNotificationTimeout = false;
+  var _registerUpdate = function($form) {
+    if($form) {
+      $("#updateCart, #bottom_updateCart").unbind('click').click(function(){
+        var elId = this.id;
+        var selectedBoxes = $("input[name='ids[]']:checked", $form);
+        var selected = [];
+        $(selectedBoxes).each(function(i) {
+          selected[i] = this.value;
+        });
+        if (selected.length > 0) {
+          var inCart = 0;
+          var msg = "";
+          var orig = getFullItems();
+          $(selected).each(function(i) {
+            for (var x in orig) {
+              if (this == orig[x]) {
+                inCart++;
+                return;
+              }
             }
+            var data = this.split('|');
+            addItem(data[1], data[0]);
+          });
+          var updated = getFullItems();
+          var added = updated.length - orig.length;
+          msg += added + " " + VuFind.translate('itemsAddBag');
+          if (inCart > 0 && orig.length > 0) {
+            msg += "<br/>" + inCart + " " + VuFind.translate('itemsInBag');
           }
-          var data = this.split('|');
-          addItemToCart(data[1], data[0]);
-        });
-        var updated = getFullCartItems();
-        var added = updated.length - orig.length;
-        msg += added + " " + VuFind.translate('itemsAddBag');
-        if (inCart > 0 && orig.length > 0) {
-          msg += "<br/>" + inCart + " " + VuFind.translate('itemsInBag');
+          if (updated.length >= VuFind.translate('bookbagMax')) {
+            msg += "<br/>" + VuFind.translate('bookbagFull');
+          }
+          $('#'+elId).data('bs.popover').options.content = msg;
+          $('#cartItems strong').html(updated.length);
+        } else {
+          $('#'+elId).data('bs.popover').options.content = VuFind.translate('bulk_noitems_advice');
         }
-        if (updated.length >= VuFind.translate('bookbagMax')) {
-          msg += "<br/>" + VuFind.translate('bookbagFull');
+        $('#'+elId).popover('show');
+        if (_cartNotificationTimeout !== false) {
+          clearTimeout(_cartNotificationTimeout);
         }
-        $('#'+elId).data('bs.popover').options.content = msg;
-        $('#cartItems strong').html(updated.length);
+        _cartNotificationTimeout = setTimeout(function() {
+          $('#'+elId).popover('hide');
+        }, 5000);
+        return false;
+      });
+    }
+  }
+
+  // Reveal
+  return {
+    // Methods
+    addItem: addItem,
+    removeItem: removeItem,
+    getFullItems: getFullItems,
+    updateCount: updateCount,
+    setDomain: setDomain,
+    // Lightbox handler
+    // Setup
+    ready: function() {
+      // Record buttons
+      var $cartId = $('.cartId');
+      if($cartId.length > 0) {
+        $cartId.each(function() {
+          var cartId = this.value.split('|');
+          var currentId = cartId[1];
+          var currentSource = cartId[0];
+          var $parent = $(this).parent();
+          $parent.find('.cart-add.correct,.cart-remove.correct').removeClass('correct hidden');
+          $parent.find('.cart-add').click(function() {
+            addItem(currentId,currentSource);
+            $parent.find('.cart-add,.cart-remove').toggleClass('hidden');
+          });
+          $parent.find('.cart-remove').click(function() {
+            removeItem(currentId,currentSource);
+            $parent.find('.cart-add,.cart-remove').toggleClass('hidden');
+          });
+        });
       } else {
-        $('#'+elId).data('bs.popover').options.content = VuFind.translate('bulk_noitems_advice');
-      }
-      $('#'+elId).popover('show');
-      if (cartNotificationTimeout !== false) {
-        clearTimeout(cartNotificationTimeout);
+        // Search results
+        var $form = $('form[name="bulkActionForm"]');
+        _registerUpdate($form);
       }
-      cartNotificationTimeout = setTimeout(function() {
-        $('#'+elId).popover('hide');
-      }, 5000);
-      return false;
-    });
-  }
-}
+      $("#updateCart, #bottom_updateCart").popover({content:'', html:true, trigger:'manual'});
+    }
+  };
+})();
 
 // Building an array and checking indexes prevents a race situation
 // We want to prioritize empty over printing
-function cartFormHandler(event, data) {
+var cartFormHandler = function(event, data) {
   var keys = [];
   for (var i in data) {
     keys.push(data[i].name);
@@ -176,31 +219,6 @@ function cartFormHandler(event, data) {
   }
 }
 
-document.addEventListener('VuFind.lightbox.closed', updateCartCount, false);
+document.addEventListener('VuFind.lightbox.closed', VuFind.cart.updateCount, false);
 
-$(document).ready(function() {
-  // Record buttons
-  var $cartId = $('.cartId');
-  if($cartId.length > 0) {
-    $cartId.each(function() {
-      var cartId = this.value.split('|');
-      currentId = cartId[1];
-      currentSource = cartId[0];
-      var $parent = $(this).parent();
-      $parent.find('.cart-add.correct,.cart-remove.correct').removeClass('correct hidden');
-      $parent.find('.cart-add').click(function() {
-        addItemToCart(currentId,currentSource);
-        $parent.find('.cart-add,.cart-remove').toggleClass('hidden');
-      });
-      $parent.find('.cart-remove').click(function() {
-        removeItemFromCart(currentId,currentSource);
-        $parent.find('.cart-add,.cart-remove').toggleClass('hidden');
-      });
-    });
-  } else {
-    // Search results
-    var $form = $('form[name="bulkActionForm"]');
-    registerUpdateCart($form);
-  }
-  $("#updateCart, #bottom_updateCart").popover({content:'', html:true, trigger:'manual'});
-});
+$(document).ready(VuFind.cart.ready);
diff --git a/themes/bootstrap3/templates/layout/layout.phtml b/themes/bootstrap3/templates/layout/layout.phtml
index 25ab54c4eab..94ca7c20b52 100644
--- a/themes/bootstrap3/templates/layout/layout.phtml
+++ b/themes/bootstrap3/templates/layout/layout.phtml
@@ -66,9 +66,11 @@
           $this->headScript()->appendFile("vendor/cookies.js");
           $this->headScript()->appendFile("cart.js");
           $domain = $cart->getCookieDomain();
-          $this->headScript()->appendScript(
-            'var cartCookieDomain = ' . (!empty($domain) ? "'$domain'" : 'false') . ';'
-          );
+          if (!empty($domain)) {
+            $this->headScript()->appendScript(
+              'VuFind.cart.setDomain("' . $domain . '");'
+            );
+          }
           $this->jsTranslations()->addStrings(
             array(
               'addBookBag' => 'Add to Book Bag',
-- 
GitLab