PageSourceSearch

https://menstherapyhub.co.uk/wp-content/plugins/bdthemes-element-pack/assets/js/common/helper.js?ver=8.2.1

js menstherapyhub.co.uk collected 2026-09-29 00:56:21 UTC 9,262 bytes, 311 lines download raw bytes

1var debounce = function (func, wait, immediate) {
2  // 'private' variable for instance
3  // The returned function will be able to reference this due to closure.
4  // Each call to the returned function will share this common timer.
5  var timeout;
6
7  // Calling debounce returns a new anonymous function
8  return function () {
9    // reference the context and args for the setTimeout function
10    var context = this,
11      args = arguments;
12
13    // Should the function be called now? If immediate is true
14    //   and not already in a timeout then the answer is: Yes
15    var callNow = immediate && !timeout;
16
17    // This is the basic debounce behaviour where you can call this
18    //   function several times, but it will only execute once
19    //   [before or after imposing a delay].
20    //   Each time the returned function is called, the timer starts over.
21    clearTimeout(timeout);
22
23    // Set the new timeout
24    timeout = setTimeout(function () {
25      // Inside the timeout function, clear the timeout variable
26      // which will let the next execution run when in 'immediate' mode
27      timeout = null;
28
29      // Check if the function already ran with the immediate flag
30      if (!immediate) {
31        // Call the original function with apply
32        // apply lets you define the 'this' object as well as the arguments
33        //    (both captured before setTimeout)
34        func.apply(context, args);
35      }
36    }, wait);
37
38    // Immediate mode and no wait timer? Execute the function..
39    if (callNow) func.apply(context, args);
40  };
41};
42
43function epObserveTarget(target, callback) {
44  var options =
45    arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
46  // Set the rootMargin to trigger when the target is 10% past the viewport
47  options.rootMargin = options.rootMargin || "10% 0px 0px 0px";
48  var observer = new IntersectionObserver(function (entries, observer) {
49    entries.forEach(function (entry) {
50      if (entry.isIntersecting) {
51        callback(entry);
52
53        if (!options.loop) observer.unobserve(entry.target); // Unobserve after the first intersection
54      }
55    });
56  }, options);
57  observer.observe(target);
58}
59
60/**
61 * Safe HTML
62 */
63function EP_SAFE_HTML(input) {
64  /**
65   * Expanded list of allowed tags and attributes for a more flexible sanitization
66   */
67  const allowedTags = {
68    'img': ['src', 'alt', 'title', 'width', 'height', 'style'],
69    'a': ['href', 'title', 'target', 'rel'],
70    'p': ['class', 'style', 'id'],
71    'b': ['class', 'style'],
72    'i': ['class', 'style'],
73    'u': ['class', 'style'],
74    'strong': ['class', 'style'],
75    'em': ['class', 'style'],
76    'br': [],
77    'hr': ['class', 'style'],
78    'ul': ['class', 'style'],
79    'ol': ['class', 'style'],
80    'li': ['class', 'style'],
81    'div': ['class', 'style', 'id'],
82    'span': ['class', 'style', 'id'],
83    'blockquote': ['cite', 'class', 'style'],
84    'code': ['class', 'style'],
85    'pre': ['class', 'style'],
86    'h1': ['class', 'style', 'id'],
87    'h2': ['class', 'style', 'id'],
88    'h3': ['class', 'style', 'id'],
89    'h4': ['class', 'style', 'id'],
90    'h5': ['class', 'style', 'id'],
91    'h6': ['class', 'style', 'id'],
92    'table': ['class', 'style', 'id'],
93    'thead': ['class', 'style'],
94    'tbody': ['class', 'style'],
95    'tfoot': ['class', 'style'],
96    'tr': ['class', 'style'],
97    'th': ['class', 'style', 'scope'],
98    'td': ['class', 'style', 'colspan', 'rowspan'],
99  };
100
101  /**
102   * Main sanitization process
103   */
104  const tagPattern = /<\/?([a-zA-Z0-9]+)([^>]*)>/g;
105  input = input.replace(tagPattern, (match, tagName, attributes) => {
106    tagName = tagName.toLowerCase();
107
108    /**
109     * Remove the tag if it's not allowed
110     */
111    if (!allowedTags.hasOwnProperty(tagName)) {
112      return '';
113    }
114
115    /**
116     * Filter attributes for allowed tags only
117     */
118    const allowedAttributes = allowedTags[tagName];
119    const filteredAttributes = attributes.replace(/([a-zA-Z0-9-]+)\s*=\s*("[^"]*"|'[^']*'|[^\s>]*)/g, (match, attrName, attrValue) => {
120      attrName = attrName.toLowerCase();
121
122      /**
123       * Only keep attributes in the allowed list and ignore any "on" events or disallowed protocols
124       */
125      if (!allowedAttributes.includes(attrName) || attrName.startsWith("on") || /^javascript:/i.test(attrValue)) {
126        return '';
127      }
128
129      return `${attrName}=${attrValue}`;
130    });
131
132    return `<${tagName}${filteredAttributes}>`;
133  });
134
135  return input;
136}
137/**
138 * /Safe HTML
139 */
140
141/**
142 * Start Crypto Currency
143 */
144
145function returnCurrencySymbol(currency = null) {
146  if (currency === null) return "";
147  let currency_symbols = {
148    USD: "$", // US Dollar
149    EUR: "€", // Euro
150    CRC: "₡", // Costa Rican Colón
151    GBP: "£", // British Pound Sterling
152    ILS: "₪", // Israeli New Sheqel
153    INR: "₹", // Indian Rupee
154    JPY: "Â¥", // Japanese Yen
155    KRW: "₩", // South Korean Won
156    NGN: "₦", // Nigerian Naira
157    PHP: "₱", // Philippine Peso
158    PLN: "zł", // Polish Zloty
159    PYG: "₲", // Paraguayan Guarani
160    THB: "฿", // Thai Baht
161    UAH: "₴", // Ukrainian Hryvnia
162    VND: "₫", // Vietnamese Dong
163  };
164  if (currency_symbols[currency] !== undefined) {
165    return currency_symbols[currency];
166  } else {
167    return ""; // this is means there is not any
168  }
169}
170
171/**
172 * End Crypto Currency
173 */
174
175(function ($) {
176
177  /**
178   * Open Offcanvas on Mini Cart Update
179   */          
180  $(document).ajaxComplete(function(event, request, settings) {
181      if (request.responseJSON && 
182          typeof request.responseJSON.cart_hash !== "undefined" && 
183          request.responseJSON.cart_hash) {
184          
185          var isCartUpdate = false;
186          
187          if (settings.url && 
188              (settings.url.indexOf('wc-ajax=add_to_cart') > -1)) {
189              isCartUpdate = true;
190          }
191          
192          if (settings.data && 
193              (settings.data.indexOf('action=add_to_cart') > -1)) {
194              isCartUpdate = true;
195          }
196          
197          if (isCartUpdate && $(".bdt-offcanvas").hasClass("__update_cart")) {
198              let id = $(".bdt-offcanvas.__update_cart").attr("id");
199              bdtUIkit.util.ready(function() {
200                  bdtUIkit.offcanvas("#" + id).show();
201              });
202          }
203      }
204  });
205
206  /**
207   * /Open Offcanvas on Mini Cart Update
208   */
209
210  jQuery(document).ready(function () {
211    /**
212     * Start used on Social Share
213     */
214
215    jQuery(".bdt-ss-link").on("click", function () {
216      var $temp = jQuery("<input>");
217      jQuery("body").append($temp);
218      $temp.val(jQuery(this).data("url")).select();
219      document.execCommand("copy");
220      $temp.remove();
221
222      // Update the text to indicate that it has been copied
223      jQuery(this)
224        .find(".bdt-social-share-title")
225        .html(jQuery(this).data("copied"));
226
227      // Reset the text after a delay (e.g., 5 seconds)
228      setTimeout(() => {
229        jQuery(this)
230          .find(".bdt-social-share-title")
231          .html(jQuery(this).data("orginal"));
232      }, 5000);
233    });
234
235    /**
236     * end Social Share
237     */
238
239    /**
240     * Open In a New Tab Feature
241     */
242    const element = {
243      "elementor-widget-bdt-post-grid-tab": {
244        selectors: [
245          ".bdt-post-grid-desc-inner a",
246          ".bdt-post-grid-tab-readmore",
247        ],
248      },
249      "elementor-widget-bdt-post-grid": {
250        selectors: [".bdt-post-grid-title a", ".bdt-post-grid-readmore"],
251      },
252      "elementor-widget-bdt-post-card": {
253        selectors: [".bdt-post-card-title a", ".bdt-post-card-button"],
254      },
255      "elementor-widget-bdt-post-block": {
256        selectors: [".bdt-post-block-title a", ".bdt-post-block-read-more"],
257      },
258      "elementor-widget-bdt-post-block-modern": {
259        selectors: [
260          ".bdt-post-block-modern-title a",
261          ".bdt-post-block-modern-read-more",
262        ],
263      },
264      "elementor-widget-bdt-post-gallery": {
265        selectors: [".bdt-post-gallery-title-link", ".bdt-gallery-item-link"],
266      },
267      "elementor-widget-bdt-post-list": {
268        selectors: [".bdt-title a", ".bdt-image a"],
269      },
270      "elementor-widget-bdt-post-slider": {
271        selectors: [".bdt-post-slider-title-wrap a", ".bdt-post-slider-button"],
272      },
273    };
274
275    Object.keys(element).forEach(function (key) {
276      if (jQuery("." + key).length > 0) {
277        if (
278          jQuery("." + key).data("settings") !== undefined &&
279          jQuery("." + key).data("settings").bdt_link_new_tab === "yes"
280        ) {
281          element[key].selectors.forEach(function (selector) {
282            jQuery(selector).attr("target", "_blank");
283          });
284        }
285      }
286    });
287    /**
288     * /Open In a New Tab Feature
289     */
290
291    /** Toggle Pass */
292
293    jQuery(".bdt-pass-input-wrapper")
294      .find("i")
295      .on("click", function () {
296        if (jQuery(this).hasClass("fa-eye")) {
297          jQuery(this).toggleClass("fa-eye-slash");
298        }
299        let input = jQuery(this)
300          .closest(".bdt-pass-input-wrapper")
301          .find("input");
302        if (input.attr("type") == "password") {
303          jQuery(input).attr("type", "text");
304        } else {
305          jQuery(input).attr("type", "password");
306        }
307      });
308
309    /** /Toggle Pass */
310  });
311})(jQuery);

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.