Hello I’m using shrine pro (not the most recent one) and when I add to cart I need to reload to see the product added (also I use it as a drawer and that’s how I want it to be), I would like that when I click add to cart it appears the drawer on the right side, also when I delete any product in my cart I need to reload to see the changes i’ve tried asking chat gpt but had no luck, I can share whatever info you like to know
Hey @Lucas_Miranda,
Shrine Pro is known for being not very developer friendly.
I tried to reverse engineer their uglified main.js a little and came up with this little controller to open/close/update the cart drawer.
cart-controller.js
/**
* Cart Drawer Controller
*
* This script provides a global interface to control the cart drawer
* functionality from anywhere in your Shopify theme.
*/
// Create a global namespace for cart drawer controls
window.CartDrawerController = (function() {
// Private variables
let cartDrawer = null;
let cartDrawerItems = null;
// Initialize references to the cart drawer elements
function init() {
cartDrawer = document.querySelector('cart-drawer');
cartDrawerItems = document.querySelector('cart-drawer-items');
if (!cartDrawer) {
console.error('Cart drawer element not found. Make sure your theme includes a cart-drawer custom element.');
return false;
}
return true;
}
/**
* Open the cart drawer
* @return {Boolean} Success status
*/
function openCartDrawer() {
if (!init()) return false;
cartDrawer.open();
return true;
}
/**
* Close the cart drawer
* @return {Boolean} Success status
*/
function closeCartDrawer() {
if (!init()) return false;
cartDrawer.close();
return true;
}
/**
* Update cart drawer contents by fetching the latest cart data
* @return {Promise} A promise that resolves when the cart is updated
*/
function updateCartContents() {
if (!init()) return Promise.reject('Cart drawer not initialized');
return fetch('/cart.js')
.then(response => response.json())
.then(cartData => {
// If cart is empty, make sure we reflect that state
if (cartData.item_count === 0) {
cartDrawer.classList.add('is-empty');
} else {
cartDrawer.classList.remove('is-empty');
}
// Fetch sections to get the rendered HTML
return fetch('/cart?sections=cart-drawer,cart-icon-bubble', {
method: 'GET'
});
})
.then(response => response.json())
.then(sections => {
// Check if we have the expected sections in the response
if (!sections || (typeof sections !== 'object')) {
throw new Error('Invalid response format from cart sections');
}
// Now we have the rendered HTML for the cart drawer
// Make sure we match the structure expected by renderContents
try {
cartDrawer.renderContents({
sections: sections
});
} catch (e) {
console.error('Error in renderContents:', e);
// Alternative approach - directly update the innerHTML
if (sections['cart-drawer']) {
const drawerInner = cartDrawer.querySelector('.drawer__inner');
if (drawerInner) {
const parser = new DOMParser();
const parsedHtml = parser.parseFromString(sections['cart-drawer'], 'text/html');
const drawerContent = parsedHtml.querySelector('.drawer__inner');
if (drawerContent) {
drawerInner.innerHTML = drawerContent.innerHTML;
}
}
}
// Update cart count bubble if available
if (sections['cart-icon-bubble']) {
const iconBubble = document.getElementById('cart-icon-bubble');
if (iconBubble) {
const parser = new DOMParser();
const parsedHtml = parser.parseFromString(sections['cart-icon-bubble'], 'text/html');
const newBubble = parsedHtml.getElementById('cart-icon-bubble');
if (newBubble) {
iconBubble.innerHTML = newBubble.innerHTML;
}
}
}
}
return sections;
})
.catch(error => {
console.error('Error updating cart drawer:', error);
throw error;
});
}
/**
* Add an item to the cart and open the drawer
* @param {Number} variantId - The variant ID to add
* @param {Number} quantity - The quantity to add (default: 1)
* @param {Object} properties - Line item properties (optional)
* @return {Promise} A promise that resolves when the item is added
*/
function addItemAndOpenDrawer(variantId, quantity = 1, properties = {}) {
if (!init()) return Promise.reject('Cart drawer not initialized');
// Ensure variantId is valid
if (!variantId || isNaN(Number(variantId))) {
return Promise.reject('Invalid variant ID');
}
// Ensure quantity is valid
quantity = Math.max(1, parseInt(quantity) || 1);
// Prepare the request payload
const data = {
items: [{
id: variantId,
quantity: quantity
}]
};
// Add properties if they exist
if (Object.keys(properties).length > 0) {
data.items[0].properties = properties;
}
// Add the item to the cart
return fetch('/cart/add.js', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
// If the server responds with an error status
return response.json().then(data => {
throw new Error(data.description || 'Error adding item to cart');
});
}
return response.json();
})
.then(addResult => {
// Now update the cart drawer contents
return updateCartContents();
})
.then(() => {
// Open the cart drawer
openCartDrawer();
return true;
})
.catch(error => {
console.error('Error adding item to cart:', error);
throw error;
});
}
/**
* Update the quantity of an item in the cart
* @param {Number} lineItem - The line item to update (1-based index)
* @param {Number} quantity - The new quantity
* @return {Promise} A promise that resolves when the cart is updated
*/
function updateItemQuantity(lineItem, quantity) {
if (!init() || !cartDrawerItems) return Promise.reject('Cart drawer not initialized');
// Call the updateQuantity method on the cart-drawer-items element
return new Promise((resolve, reject) => {
try {
cartDrawerItems.updateQuantity(lineItem, quantity);
resolve(true);
} catch (error) {
reject(error);
}
});
}
/**
* Clear the cart
* @return {Promise} A promise that resolves when the cart is cleared
*/
function clearCart() {
if (!init() || !cartDrawerItems) return Promise.reject('Cart drawer not initialized');
// Call the clearCart method on the cart-drawer-items element
return new Promise((resolve, reject) => {
try {
cartDrawerItems.clearCart();
resolve(true);
} catch (error) {
reject(error);
}
});
}
/**
* Debugging utility to help troubleshoot cart drawer issues
* @return {Object} Diagnostic information about the cart drawer
*/
function debug() {
const diagnostics = {
cartDrawerFound: !!document.querySelector('cart-drawer'),
cartItemsFound: !!document.querySelector('cart-drawer-items'),
cartIconFound: !!document.getElementById('cart-icon-bubble'),
drawerMethods: {}
};
// Check drawer methods
if (cartDrawer) {
diagnostics.drawerMethods = {
open: typeof cartDrawer.open === 'function',
close: typeof cartDrawer.close === 'function',
renderContents: typeof cartDrawer.renderContents === 'function',
getSectionsToRender: typeof cartDrawer.getSectionsToRender === 'function'
};
// Check if drawer has required properties
diagnostics.drawerProperties = {
classList: !!cartDrawer.classList,
querySelector: typeof cartDrawer.querySelector === 'function',
drawerInner: !!cartDrawer.querySelector('.drawer__inner')
};
}
// Check cart items methods
if (cartDrawerItems) {
diagnostics.cartItemsMethods = {
updateQuantity: typeof cartDrawerItems.updateQuantity === 'function',
clearCart: typeof cartDrawerItems.clearCart === 'function'
};
}
return diagnostics;
}
// Public API
return {
open: openCartDrawer,
close: closeCartDrawer,
update: updateCartContents,
addItem: addItemAndOpenDrawer,
updateQuantity: updateItemQuantity,
clear: clearCart,
debug: debug
};
})();
You then are able to use this controller to open, close, update, …
// Open the cart drawer
CartDrawerController.open();
// Add an item with custom properties
CartDrawerController.addItem(variantId, quantity, {
'Gift Wrap': 'Yes',
'Engraving': 'Happy Birthday'
})
.then(() => console.log('Added with properties!'));
// Update the quantity of an item
CartDrawerController.updateQuantity(lineItemNumber, newQuantity);
// Clear the entire cart
CartDrawerController.clear();
// Manually update the cart drawer contents
CartDrawerController.update();
// Debug cart drawer issues
console.log(CartDrawerController.debug());
Hope this helps,
Kevin
1 Like