|  | var shop = { | 
        
          |  | // (A) HELPER - AJAX FETCH | 
        
          |  | fetch : (data, after) => { | 
        
          |  | // (A1) FORM DATA | 
        
          |  | let form; | 
        
          |  | if (data instanceof FormData) { form = data; } | 
        
          |  | else { | 
        
          |  | form = new FormData(); | 
        
          |  | for (let [k, v] of Object.entries(data)) { form.append(k, v); } | 
        
          |  | } | 
        
          |  |  | 
        
          |  | // (A2) FETCH | 
        
          |  | fetch("1-lib.php", { method : "post", body : form }) | 
        
          |  | .then(res => res.text()) | 
        
          |  | .then(txt => after(txt)) | 
        
          |  | .catch(err => console.error(err)); | 
        
          |  | }, | 
        
          |  |  | 
        
          |  | // (B) PROPERTIES | 
        
          |  | hPdt : null, // html products | 
        
          |  | hCart : null, // html cart | 
        
          |  | hCCart : null, // html cart count | 
        
          |  | hCO : null, // html checkout wrapper | 
        
          |  | hCOF : null, // html checkout form | 
        
          |  | products : null, // products list | 
        
          |  | cart : null, // cart items | 
        
          |  | qty : 0, // cart total item quantity | 
        
          |  | total : 0, // cart total amount | 
        
          |  |  | 
        
          |  | // (C) INITIALIZE | 
        
          |  | init : () => { | 
        
          |  | // (C1) GET HTML ELEMENTS | 
        
          |  | shop.hPdt = document.getElementById("products"); | 
        
          |  | shop.hCart = document.getElementById("cart"); | 
        
          |  | shop.hCCart = document.getElementById("cCart"); | 
        
          |  | shop.hCO = document.getElementById("checkout"); | 
        
          |  | shop.hCOF = document.querySelector("#checkout form"); | 
        
          |  |  | 
        
          |  | // (C2) CLICK TO TOGGLE CART | 
        
          |  | document.getElementById("iCart").onclick = () => { | 
        
          |  | document.getElementById("wCart").classList.toggle("show"); | 
        
          |  | }; | 
        
          |  |  | 
        
          |  | // (C3) RESTORE CART | 
        
          |  | shop.cart = localStorage.getItem("cart"); | 
        
          |  | if (shop.cart == null) { shop.cart = {}; } | 
        
          |  | else { shop.cart = JSON.parse(shop.cart); } | 
        
          |  |  | 
        
          |  | // (C4) LOAD PRODUCTS > DRAW HTML | 
        
          |  | shop.fetch({"req": "get"}, data => { | 
        
          |  | // (C4-1) PARSE DATA INTO JS OBJECT | 
        
          |  | shop.products = JSON.parse(data); | 
        
          |  |  | 
        
          |  | // (C4-2) DRAW HTML PRODUCTS | 
        
          |  | for (let [id, pdt] of Object.entries(shop.products)) { | 
        
          |  | let row = document.createElement("div"); | 
        
          |  | row.className = "pCell"; | 
        
          |  | row.innerHTML = `<img class="pImg" src="${pdt.i}"> | 
        
          |  | <div class="pDetails"> | 
        
          |  | <div class="pName">${pdt.n}</div> | 
        
          |  | <div class="pPrice">$${pdt.p.toFixed(2)}</div> | 
        
          |  | <input class="pAdd button" type="button" value="Add To Cart" onclick="shop.add(${id})"> | 
        
          |  | </div>`; | 
        
          |  | shop.hPdt.appendChild(row); | 
        
          |  | } | 
        
          |  |  | 
        
          |  | // (C4-3) DRAW CART ITEMS | 
        
          |  | shop.drawcart(); | 
        
          |  | }); | 
        
          |  | }, | 
        
          |  |  | 
        
          |  | // (D) SAVE CART ITEMS INTO LOCALSTORAGE | 
        
          |  | save : () => localStorage.setItem("cart", JSON.stringify(shop.cart)), | 
        
          |  |  | 
        
          |  | // (E) DRAW CART ITEMS | 
        
          |  | drawcart : () => { | 
        
          |  | // (E1) RESET | 
        
          |  | let row; | 
        
          |  | shop.qty = 0; | 
        
          |  | shop.total = 0; | 
        
          |  | shop.hCart.innerHTML = ""; | 
        
          |  |  | 
        
          |  | // (E2) EMPTY CART | 
        
          |  | if (Object.keys(shop.cart).length==0) { | 
        
          |  | row = document.createElement("div"); | 
        
          |  | row.className = "cCell empty"; | 
        
          |  | row.innerHTML = `Cart is empty`; | 
        
          |  | shop.hCart.appendChild(row); | 
        
          |  | shop.hCCart.innerHTML = 0; | 
        
          |  | } | 
        
          |  |  | 
        
          |  | // (E3) DRAW ITEMS | 
        
          |  | else { | 
        
          |  | for (let [i, q] of Object.entries(shop.cart)) { | 
        
          |  | // (E3-1) CALCULATE SUBTOTAL | 
        
          |  | let subtotal = q * shop.products[i]["p"]; | 
        
          |  | shop.total += subtotal; | 
        
          |  | shop.qty += parseInt(q); | 
        
          |  |  | 
        
          |  | // (E3-2) ITEM ROW | 
        
          |  | row = document.createElement("div"); | 
        
          |  | row.className = "cCell"; | 
        
          |  | row.innerHTML = `<input class="cQty" type="number" value="${q}" | 
        
          |  | min="0" max="99" onchange="shop.change(${i}, this.value)"> | 
        
          |  | <div class="cInfo"> | 
        
          |  | <div class="cName">${shop.products[i]["n"]}</div> | 
        
          |  | <div class="cPrice">$${subtotal.toFixed(2)}</div> | 
        
          |  | </div> | 
        
          |  | <input class="cDel button" type="button" value="X" onclick="shop.remove(${i})">`; | 
        
          |  | shop.hCart.appendChild(row); | 
        
          |  | } | 
        
          |  |  | 
        
          |  | // (E3-3) CART TOTAL | 
        
          |  | row = document.createElement("div"); | 
        
          |  | row.className = "cCell"; | 
        
          |  | row.innerHTML = `<input class="cDel button" type="button" value="X" onclick="shop.empty()"> | 
        
          |  | <div class="cInfo"> | 
        
          |  | <div class="cName">Total</div> | 
        
          |  | <div class="cPrice">$${shop.total.toFixed(2)}</div> | 
        
          |  | </div> | 
        
          |  | <input class="cDel button" type="button" value=">" onclick="shop.togcf(true)">`; | 
        
          |  | shop.hCart.appendChild(row); | 
        
          |  |  | 
        
          |  | // (E3-4) TOTAL QUANTITY | 
        
          |  | shop.hCCart.innerHTML = shop.qty; | 
        
          |  | } | 
        
          |  | }, | 
        
          |  |  | 
        
          |  | // (F) ADD PRODUCT TO CART | 
        
          |  | add : id => { | 
        
          |  | if (shop.cart[id]==undefined) { shop.cart[id] = 1; } | 
        
          |  | else { shop.cart[id]++; } | 
        
          |  | shop.save(); shop.drawcart(); | 
        
          |  | }, | 
        
          |  |  | 
        
          |  | // (G) CHANGE QUANTITY IN CART | 
        
          |  | change : (id, qty) => { | 
        
          |  | if (qty <= 0) { shop.remove(id) } | 
        
          |  | else { shop.cart[id] = qty; } | 
        
          |  | shop.save(); shop.drawcart(); | 
        
          |  | }, | 
        
          |  |  | 
        
          |  | // (H) REMOVE PRODUCT FROM CART | 
        
          |  | remove : id => { | 
        
          |  | delete shop.cart[id]; | 
        
          |  | shop.save(); shop.drawcart(); | 
        
          |  | }, | 
        
          |  |  | 
        
          |  | // (I) EMPTY CART | 
        
          |  | empty : () => { if (confirm("Empty cart?")) { | 
        
          |  | shop.cart = {}; | 
        
          |  | shop.save(); shop.drawcart(); | 
        
          |  | }}, | 
        
          |  |  | 
        
          |  | // (J) TOGGLE CHECKOUT FORM | 
        
          |  | togcf : show => { | 
        
          |  | if (show) { shop.hCO.className = "show"; } | 
        
          |  | else { shop.hCO.className = ""; } | 
        
          |  | }, | 
        
          |  |  | 
        
          |  | // (K) CHECKOUT | 
        
          |  | checkout : () => { | 
        
          |  | // (K1) FORM DATA | 
        
          |  | let form = new FormData(shop.hCOF); | 
        
          |  | form.append("req", "checkout"); | 
        
          |  | form.append("cart", JSON.stringify(shop.cart)); | 
        
          |  |  | 
        
          |  | // (K2) AJAX PROCESS | 
        
          |  | shop.fetch(form, res => { | 
        
          |  | if (res=="OK") { | 
        
          |  | shop.cart = {}; | 
        
          |  | shop.save(); | 
        
          |  | shop.drawcart(); | 
        
          |  | shop.togcf(false); | 
        
          |  | alert("CHECKOUT OK. DO SOMETHING - REDIRECT TO THANK YOU?"); | 
        
          |  | } else { alert(res); } | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | // (K3) PREVENT FORM SUBMIT | 
        
          |  | return false; | 
        
          |  | } | 
        
          |  | }; | 
        
          |  | window.onload = shop.init; |