Advertisement
codex23

miniCartActions DIY tests

Jun 13th, 2025
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 14.17 KB | Source Code | 0 0
  1.     /* ***TESTING stateSetter()*** */
  2.  
  3.     function stateSetter(element, off, on) {
  4.         /**
  5.         * stateSetter
  6.         * Toggles the class state of a given element by removing an "off" state and adding an "on" state.
  7.         *
  8.         * @param {HTMLElement} element - The element to update.
  9.         * @param {string} off - The class name representing the "off" state.
  10.         * @param {string} on - The class name representing the "on" state.
  11.         * @returns {HTMLElement} - The updated element.
  12.         */
  13.         element.classList.remove(off);
  14.         element.classList.add(on);
  15.         console.log('stateSetter(): ', element.classList);
  16.         return element;
  17.     }
  18.    
  19.    
  20.     const variable = document.querySelector('.menu-icon');
  21.    
  22.     stateSetter(variable, '.menu-icon', '.new-icon');
  23.  
  24.  
  25.  
  26.        
  27.  
  28.     /* ***TESTING stateControl()*** */
  29.  
  30.  
  31.  
  32.     function stateControl(trigger, element) {
  33.         /**
  34.         * stateControl
  35.         * Binds a click event listener to the trigger element. When clicked, it toggles
  36.         * the state (active/inactive) of the target element.
  37.         *
  38.         * @param {HTMLElement} trigger - The element that triggers the state change.
  39.         * @param {HTMLElement} element - The target element whose state is toggled.
  40.         */
  41.         console.log('stateControl() trigger: ', trigger);
  42.         console.log('stateControl() element: ', element);
  43.         trigger.addEventListener('click', () => {
  44.             if (element.classList.contains('cart_inactive')) {
  45.                 //this.stateSetter(element, 'cart_inactive', 'cart_active');
  46.                 element.classList.replace('cart_inactive', 'cart_active');
  47.                 return element;
  48.             } else if(element.classList.contains('cart_active')) {
  49.                 //this.stateSetter(element, 'cart_active', 'cart_inactive');
  50.                 element.classList.replace('cart_active', 'cart_inactive');
  51.                 return element;
  52.             } else {
  53.                 return;
  54.             }
  55.         });
  56.     }
  57.    
  58.     const variable4 = document.querySelector('.widget_shopping_cart_content');
  59.     const variable5 = document.querySelector('#cart-icon');
  60.     stateControl(variable5, variable4);    
  61.    
  62.  
  63.  
  64.  
  65.     /* ***TESTING closeWhenOutside()*** */
  66.  
  67.  
  68.     function closeWhenOutside(entity) {
  69.         /**
  70.         * closeWhenOutside
  71.         * Binds a click event listener to an external entity (like the document) that closes the mini-cart
  72.         * if the click occurs outside the cart icon and mini cart.
  73.         *
  74.         * @param {HTMLElement} entity - The element to listen for clicks (typically document).
  75.         */
  76.         if (!entity) {
  77.             console.error('closeWhenOutside: No entity provided');
  78.             return;
  79.         }
  80.        
  81.         const miniCart = document.querySelector('.widget_shopping_cart_content');
  82.         const miniCartIcon = document.querySelector('#cart-icon');
  83.         const entityObject = document.querySelector(entity);
  84.        
  85.         if (!miniCart || !miniCartIcon) {
  86.             console.error('closeWhenOutside: Required elements not found');
  87.             return;
  88.         }
  89.    
  90.         console.log('Setting up outside click handler');
  91.        
  92.         entityObject.addEventListener('click', (event) => {
  93.             // Only close if mini cart is currently active
  94.             if (miniCart.classList.contains('cart_active')) {
  95.                 const clickedInsideCart = miniCart.contains(event.target);
  96.                 const clickedInsideIcon = miniCartIcon.contains(event.target);
  97.                
  98.                 if (!clickedInsideCart && !clickedInsideIcon) {
  99.                     console.log('Clicked outside, closing mini cart');
  100.                     this.stateSetter(miniCart, 'cart_active', 'cart_inactive');
  101.                 }
  102.             }
  103.         });
  104.     }
  105.    
  106.     closeWhenOutside('body');
  107.  
  108.  
  109.    
  110. /* ***TESTING THE ENTIRE CLASS*** */   
  111.    
  112.    
  113. class MiniCartActions {
  114.     'use strict';
  115.  
  116.     constructor(uiBody, miniCartSelector) {
  117.    
  118.         /*
  119.        
  120.             Wat ek al probeer het:
  121.                 * Log mini_cart in elke betrokke funksie.
  122.                 * Voeg .cart_inactive by tot die klaslys van widget_shopping_cart_content in class-wc-widget-cart.php.
  123.                 * Bring die 'selector' van index.js se kant in (miniCartSelector).
  124.        
  125.         */
  126.        
  127.         //Properties
  128.         this.body = document.querySelector(uiBody);
  129.         if (!this.body) {
  130.             console.error(`Element with selector '${uiBody}' not found.`);
  131.         }
  132.        
  133.         this.sidebar = this.body.querySelector('.sidebar');
  134.         this.shopping_menu = this.body.querySelector('.shopping-menu-wrapper .shopping-menu');
  135.        
  136.         //mini cart and mini cart icon
  137.         this.mini_cart = this.findMiniCart(miniCartSelector);
  138.         this.cart_icon = this.findCartIcon();
  139.        
  140.         this.cart_items = this.shopping_menu.querySelectorAll('.woocommerce-mini-cart-item');
  141.        
  142.         //mini cart counter
  143.         this.mini_cart_counter = this.findMiniCartCounter();
  144.        
  145.         this.p_add_to_cart = this.shopping_menu.querySelectorAll('.product-actions .add_to_cart_button');
  146.        
  147.         //close mini cart
  148.         this.close_mini_cart = this.mini_cart.querySelector('#close-container');
  149.        
  150.         console.log('mini-cart classlist (constructor): ', this.mini_cart);
  151.         console.log('cart_icon classlist (constructor): ', this.cart_icon);
  152.        
  153.         //Methods
  154.         this.miniCartActivator();
  155.        
  156.     }
  157.    
  158.     findMiniCart(selector) {
  159.         /**
  160.         * Finds the mini-cart container element in the DOM.
  161.         * Searches first in the mobile sidebar's actionsWrapper, then falls back
  162.         * to the desktop shopping-menu container.
  163.         *
  164.         * @returns {HTMLElement|null} The mini-cart container element (.widget_shopping_cart_content)
  165.         *                            or null if not found in either location
  166.         */
  167.        
  168.         let miniCart = null;
  169.        
  170.         if (this.sidebar) {
  171.             miniCart = this.sidebar.querySelector(`.actionsWrapper ${selector}`);
  172.         }
  173.        
  174.         if (!miniCart && this.shopping_menu) {
  175.             miniCart = this.shopping_menu.querySelector(`${selector}`);
  176.         }
  177.         console.log('findMiniCart(): ', miniCart);
  178.         return miniCart;
  179.     }
  180.    
  181.     findCartIcon() {
  182.         /**
  183.         * Finds the cart icon element in the DOM.
  184.         * Searches first in the mobile sidebar's actionsWrapper, then falls back
  185.         * to the desktop shopping-menu container.
  186.         *
  187.         * @returns {HTMLElement|null} The cart icon element (#cart-icon)
  188.         *                            or null if not found in either location
  189.         */
  190.        
  191.         let cartIcon = null;
  192.         console.log('findCartIcon() (sidebar): ', cartIcon);
  193.         if (this.sidebar) {
  194.             cartIcon = this.sidebar.querySelector('.actionsWrapper .shop-icons #cart-icon');
  195.            
  196.         }
  197.        
  198.         if (!cartIcon && this.shopping_menu) {
  199.             cartIcon = this.shopping_menu.querySelector('.shop-icons #cart-icon');
  200.            
  201.         }
  202.         console.log('findCartIcon() (shopping_menu): ', cartIcon);
  203.         return cartIcon;
  204.     }
  205.    
  206.     findMiniCartCounter() {
  207.         /**
  208.         * Finds the mini-cart counter element in the DOM.
  209.         * Searches first in the mobile sidebar's actionsWrapper, then falls back
  210.         * to the desktop shopping-menu container.
  211.         *
  212.         * @returns {HTMLElement|null} The mini-cart counter element (.mini_cart_counter)
  213.         *                            or null if not found in either location
  214.         */
  215.        
  216.         let counter = null;
  217.        
  218.         if (this.sidebar) {
  219.             counter = this.sidebar.querySelector('.actionsWrapper .mini_cart_counter');
  220.         }
  221.        
  222.         if (!counter && this.shopping_menu) {
  223.             counter = this.shopping_menu.querySelector('.mini_cart_counter');
  224.         }
  225.         console.log('findMiniCartCounter(): ', counter);
  226.         return counter;
  227.     }
  228.    
  229.     initializeContainer(container) {
  230.         /**
  231.         * Initializes the mini-cart to its default inactive state.
  232.         * Removes any 'active' class and adds 'inactive' class to ensure
  233.         * the mini-cart starts hidden when the page loads or reloads.
  234.         *
  235.         * @returns {void}
  236.         */
  237.         if (!container) {
  238.             console.error('Cannot initialize mini cart - element not found');
  239.             return;
  240.         }
  241.        
  242.         // Remove all state classes first
  243.         //this.mini_cart.classList.remove('cart_active', 'cart_inactive');
  244.         console.log('Mini cart initial classes: ', container.classList.toString());
  245.         // Add inactive class
  246.         container.classList.add('cart_inactive');
  247.        
  248.         console.log('Mini cart initialized as inactive. Classes: ', container.classList.toString());
  249.        
  250.         // Force a reflow to ensure the class is applied
  251.         container.offsetHeight;
  252.     }
  253.    
  254.     stateSetter(element, off, on) {
  255.         /**
  256.         * stateSetter
  257.         * Toggles the class state of a given element by removing an "off" state and adding an "on" state.
  258.         *
  259.         * @param {HTMLElement} element - The element to update.
  260.         * @param {string} off - The class name representing the "off" state.
  261.         * @param {string} on - The class name representing the "on" state.
  262.         * @returns {HTMLElement} - The updated element.
  263.         */
  264.         element.classList.remove(off);
  265.         element.classList.add(on);
  266.         console.log('stateSetter(): ', element.classList);
  267.         return element;
  268.     }
  269.    
  270.     stateControl(trigger, element) {
  271.         /**
  272.         * stateControl
  273.         * Binds a click event listener to the trigger element. When clicked, it toggles
  274.         * the state (active/inactive) of the target element.
  275.         *
  276.         * @param {HTMLElement} trigger - The element that triggers the state change.
  277.         * @param {HTMLElement} element - The target element whose state is toggled.
  278.         */
  279.         console.log('stateControl() trigger: ', trigger);
  280.         console.log('stateControl() element: ', element);
  281.         trigger.addEventListener('click', () => {
  282.             if (element.classList.contains('cart_inactive')) {
  283.                 //this.stateSetter(element, 'cart_inactive', 'cart_active');
  284.                 element.classList.replace('cart_inactive', 'cart_active');
  285.                 return element;
  286.             } else if(element.classList.contains('cart_active')) {
  287.                 //this.stateSetter(element, 'cart_active', 'cart_inactive');
  288.                 element.classList.replace('cart_active', 'cart_inactive');
  289.                 return element;
  290.             } else {
  291.                 return;
  292.             }
  293.         });
  294.     }
  295.            
  296.     closeMiniCart(container, closeToggle) {
  297.         if (!container || !closeToggle) {
  298.             console.error('closeMiniCart: Missing container or closeToggle');
  299.             return;
  300.         }
  301.        
  302.         console.log('Setting up close mini cart listener');
  303.        
  304.         closeToggle.addEventListener('click', (event) => {
  305.             event.preventDefault();
  306.             event.stopPropagation();
  307.             console.log('Close button clicked');
  308.             this.stateSetter(container, 'cart_active', 'cart_inactive');
  309.         });
  310.        
  311.         return container;
  312.     }
  313.    
  314.     appendElem(trigger, element) {
  315.         /**
  316.         * appendElem
  317.         * Appends a given element to the trigger element.
  318.         *
  319.         * @param {HTMLElement} trigger - The parent element where the element should be appended.
  320.         * @param {HTMLElement} element - The element to append.
  321.         * @returns {HTMLElement} - The appended element.
  322.         */
  323.         if (!trigger || !element) {
  324.             console.error('appendElem: Missing trigger or element');
  325.             return null;
  326.         }
  327.        
  328.         const appended = trigger.appendChild(element);
  329.        
  330.         return appended;
  331.     }
  332.    
  333.    
  334.     activateCounter(counter) {
  335.         /**
  336.         * activateCounter
  337.         * Updates the mini-cart counter state from inactive to active.
  338.         *
  339.         * @returns {HTMLElement|undefined} - The updated mini cart counter, if updated.
  340.         */
  341.         if (!this.mini_cart_counter) {
  342.             return;
  343.         }
  344.        
  345.         if (counter.classList.contains('counter_inactive')) {
  346.             this.stateSetter(counter, 'counter_inactive', 'counter_active');
  347.             return counter;
  348.         }
  349.     }
  350.    
  351.     buttonHandler(buttons, counter) {
  352.         /**
  353.         * buttonHandler
  354.         * Attaches a click event listener to each add-to-cart button, triggering the counter activation.
  355.         *
  356.         * @param {NodeList|Array} buttons - A collection of add-to-cart button elements.
  357.         * @returns {NodeList|Array} - The collection of buttons with event listeners attached.
  358.         */
  359.         if (!buttons || buttons.length === 0) {
  360.             return buttons;
  361.         }
  362.        
  363.         buttons.forEach(button => {
  364.             button.addEventListener('click', () => {
  365.                 this.activateCounter(counter); // Fixed: was missing 'this.'
  366.             });
  367.         });
  368.        
  369.         return buttons;
  370.     }
  371.    
  372.    
  373.     closeWhenOutside(entity) {
  374.         /**
  375.         * closeWhenOutside
  376.         * Binds a click event listener to an external entity (like the document) that closes the mini-cart
  377.         * if the click occurs outside the cart icon and mini cart.
  378.         *
  379.         * @param {HTMLElement} entity - The element to listen for clicks (typically document).
  380.         */
  381.        
  382.         const targetEntity = document.querySelector(entity);
  383.        
  384.         if (!targetEntity) {
  385.             console.error('closeWhenOutside: No entity provided');
  386.             return;
  387.         }
  388.        
  389.         if (!this.mini_cart || !this.cart_icon) {
  390.             console.error('closeWhenOutside: Required elements not found');
  391.             return;
  392.         }
  393.    
  394.         console.log('Setting up outside click handler');
  395.        
  396.         targetEntity.addEventListener('click', (event) => {
  397.             // Only close if mini cart is currently active
  398.             if (this.mini_cart.classList.contains('cart_active')) {
  399.                 const clickedInsideCart = this.mini_cart.contains(event.target);
  400.                 const clickedInsideIcon = this.cart_icon.contains(event.target);
  401.                
  402.                 if (!clickedInsideCart && !clickedInsideIcon) {
  403.                     console.log('Clicked outside, closing mini cart');
  404.                     this.stateSetter(this.mini_cart, 'cart_active', 'cart_inactive');
  405.                 }
  406.             }
  407.         });
  408.     }
  409.    
  410.     miniCartActivator() {
  411.         /**
  412.         * miniCartActivator
  413.         * Ties all mini-cart related behaviors together:
  414.         * cartState - Binds state control to the cart icon for toggling the mini-cart.
  415.         * buttonState - Attaches event listeners to add-to-cart buttons.
  416.         * closeWhenOutside - Sets up the event listener to close the mini-cart when clicking outside.
  417.         * appendMenu - Appends the mini-cart counter to the shopping menu.
  418.         *
  419.         * @returns {object} - An object containing the activated actions.
  420.         */
  421.        
  422.         console.log('this is events (mini_cart_actions)');
  423.         console.log('this is events(): ', this.close_mini_cart);
  424.        
  425.         if(this.mini_cart) {
  426.             // Initialize state as inactive.
  427.             this.initializeContainer(this.mini_cart);
  428.            
  429.             // Set the mini-cart state accordingly.
  430.             this.stateControl(this.cart_icon, this.mini_cart);
  431.            
  432.             // Set the mini-cart state as inactive when clicking outside it.
  433.             this.closeWhenOutside('body');
  434.         }
  435.        
  436.         if(this.shopping_menu || this.sidebar) {
  437.             // Increase the cart item count when clicking on the add-to-cart button.
  438.             this.buttonHandler(this.p_add_to_cart, this.mini_cart_counter);
  439.            
  440.             // Append the cart counter to the shopping menu.
  441.             this.appendElem(this.shopping_menu, this.mini_cart_counter);   
  442.            
  443.         }
  444.  
  445.     }  
  446. }
  447.  
  448.  
  449. const miniCartActions = new MiniCartActions('body', '.widget_shopping_cart_content');
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement