PageSourceSearch

https://www.oneshotcharlies.net/wp-content/plugins/breakdance/subp…/mini-cart.js?bd_ver=2.8.3

js oneshotcharlies.net collected 2026-10-08 14:10:39 UTC 6,392 bytes, 211 lines download raw bytes

1/* global BREAKDANCE_ADDED_TO_CART */
2(function () {
3  const { mergeObjects, matchMedia } = BreakdanceFrontend.utils;
4
5  class BreakdanceMiniCart {
6    defaultOptions = {
7      full_screen_at: "breakpoint_phone_landscape",
8      style: "dropdown",
9      cart: {
10        open_cart_on_add: false,
11      },
12    };
13
14    constructor(selector, options) {
15      this.open = this.open.bind(this);
16      this.onEnterClick = this.onEnterClick.bind(this);
17      this.onToggleClick = this.onToggleClick.bind(this);
18      this.onCloseClick = this.onCloseClick.bind(this);
19      this.onEscClick = this.onEscClick.bind(this);
20      this.onMaybeClickOutside = this.onMaybeClickOutside.bind(this);
21      this.onFocusOut = this.onFocusOut.bind(this);
22
23      this.selector = selector;
24      this.options = mergeObjects(this.defaultOptions, options);
25      this.activeClass = "bde-mini-cart-offcanvas--active";
26
27      this.init();
28    }
29
30    getScrollBarWidth() {
31      // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
32      const documentWidth = document.documentElement.clientWidth
33      return Math.abs(window.innerWidth - documentWidth)
34    }
35
36    update(options) {
37      this.options = mergeObjects(this.defaultOptions, options);
38      this.destroy();
39      this.init();
40    }
41
42    destroy() {
43      this.unbindListeners();
44    }
45
46    isOpen() {
47      return this.offcanvas.classList.contains(this.activeClass);
48    }
49
50    toggle() {
51      if (this.isOpen()) {
52        this.close();
53      } else {
54        this.open();
55      }
56    }
57
58    open() {
59      if (this.shouldStopScrolling()) {
60        this.setBalancePadding();
61        document.documentElement.classList.add("bde-stop-scrolling");
62      }
63
64      this.offcanvas.classList.add(this.activeClass);
65      document.documentElement.classList.add("is-breakdance-mini-cart-open");
66    }
67
68    close() {
69      if (!this.isOpen()) return;
70
71      this.offcanvas.classList.remove(this.activeClass);
72      document.documentElement.classList.remove("is-breakdance-mini-cart-open");
73
74      // Remove padding after transition to prevent flickering
75      this.offcanvas.addEventListener("transitionend", () => {
76        document.documentElement.classList.remove("bde-stop-scrolling");
77        document.body.style.paddingRight = null;
78      }, { once: true });
79    }
80
81    isFocusWithin() {
82      return this.element.contains(document.activeElement);
83    }
84
85    shouldStopScrolling() {
86      const isFullscreen = matchMedia(this.options.full_screen_at);
87      return isFullscreen || this.options.style === "sidebar";
88    }
89
90    setBalancePadding() {
91      const element = document.body;
92      const scrollbarWidth = this.getScrollBarWidth();
93
94      if (window.innerWidth <= element.clientWidth + scrollbarWidth) {
95        const currPadding = window.getComputedStyle(element).getPropertyValue("padding-right");
96        const currPaddingAsNum = Number.parseFloat(currPadding);
97        const newPadding = currPaddingAsNum + scrollbarWidth;
98
99        // Give padding to element to balance the hidden scrollbar width
100        if (newPadding > 0) element.style.paddingRight = `${newPadding}px`;
101      }
102    }
103
104    focusInside() {
105      const firstNode = this.element.querySelector(".bde-mini-cart-item-thumbnail, .bde-mini-cart-item-title");
106      const container = this.element.querySelector(".bde-mini-cart-offcanvas-body");
107
108      container.addEventListener("transitionend", () => {
109        firstNode?.focus();
110      }, { once: true });
111    }
112
113    focusToggle() {
114      this.toggleButton.focus();
115    }
116
117    onEnterClick(event) {
118      if (!["Enter", " "].includes(event.key)) return;
119      event.preventDefault();
120
121      this.toggle();
122      this.focusInside();
123      this.element.addEventListener("focusout", this.onFocusOut);
124    }
125
126    onToggleClick(event) {
127      event.preventDefault();
128      this.toggle();
129    }
130
131    onCloseClick() {
132      this.close();
133    }
134
135    onEscClick(event) {
136      if (event.key !== "Escape") return;
137      if (!this.isOpen()) return;
138
139      this.close();
140      this.focusToggle();
141    }
142
143    onMaybeClickOutside(event) {
144      if (!this.element.contains(event.target)) {
145        this.close();
146      }
147    }
148
149    onFocusOut(event) {
150      if (!event.relatedTarget) return;
151      if (this.element.contains(event.relatedTarget)) return;
152
153      this.close();
154      this.element.removeEventListener("focusout", this.onFocusOut);
155    }
156
157    bindListeners() {
158      if (!this.toggleButton || !this.closeButton || !this.overlay) {
159        return;
160      }
161
162      this.toggleButton.addEventListener("click", this.onToggleClick);
163      this.toggleButton.addEventListener("keydown", this.onEnterClick);
164      this.closeButton.addEventListener("click", this.onCloseClick);
165      this.overlay.addEventListener("click", this.onCloseClick);
166
167      addEventListener("click", this.onMaybeClickOutside);
168      addEventListener("keydown", this.onEscClick);
169
170      if (this.options.cart.open_cart_on_add) {
171        // Ajax add to cart
172        jQuery(document.body).on("added_to_cart", this.open);
173
174        // Non-ajax add to cart
175        if (typeof BREAKDANCE_ADDED_TO_CART !== "undefined") this.open();
176      }
177    }
178
179    unbindListeners() {
180      if (!this.toggleButton || !this.closeButton || !this.overlay) {
181        return;
182      }
183
184      this.toggleButton.removeEventListener("click", this.onToggleClick);
185      this.toggleButton.removeEventListener("keydown", this.onEnterClick);
186      this.closeButton.removeEventListener("click", this.onCloseClick);
187      this.overlay.removeEventListener("click", this.onToggleClick);
188      this.element.removeEventListener("focusout", this.onFocusOut);
189
190      removeEventListener("click", this.onMaybeClickOutside);
191      removeEventListener("keydown", this.onEscClick);
192
193      jQuery(document.body).off("added_to_cart", this.open);
194    }
195
196    init() {
197      this.element = document.querySelector(this.selector);
198
199      if (!this.element) return;
200
201      this.toggleButton = this.element.querySelector(".bde-mini-cart-toggle");
202      this.closeButton = this.element.querySelector(".bde-mini-cart-offcanvas__close-button");
203      this.offcanvas = this.element.querySelector(".bde-mini-cart-offcanvas");
204      this.overlay = this.element.querySelector(".bde-mini-cart-offcanvas-overlay");
205
206      this.bindListeners();
207    }
208  }
209
210  window.BreakdanceMiniCart = BreakdanceMiniCart;
211})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.