generic-functions/common.js

/**
 * @file Common Utility functions
 * @category Common Utils
 * @module CommonUtils
 */

/**
 * To be used when we want to convert string to pascal case
 * @function toPascalCase
 * @param {string} str - "DAVID"
 * @returns {string} - pascal case string - David
 */
export const toPascalCase = (str) => {
  return str.replace(/(\w)(\w*)/g, function (_, first, rest) {
    return first.toUpperCase() + rest.toLowerCase();
  });
};

/**
 * Injects script into the DOM and runs a callback on load
 * @function injectScript
 * @param {string} url - url for the JS script
 * @param {function} callback - Callback to run once the script is loaded
 */

export const injectScript = (url, callback) => {
  const script = document.createElement("script");
  script.src = url;
  script.async = true;

  script.addEventListener("load", function () {
    if (typeof callback === "function") {
      callback();
    }
  });

  const head = document.head || document.getElementsByTagName("head")[0];
  head.appendChild(script);
};

/**
 * Mutation Observer on URL
 * @function mutationObserverOnURL
 * @param {HTMLElement} observerElement - HTML Node element
 * @param {string} pageUrl - The page URL on which you want the callback to execute on.
 * @param {object} options - observer options
 * @param {object} callback - callback to run once location.href contains the above pageUrl.
 */
export const mutationObserverOnURL = (
  observerElement,
  pageUrl,
  options,
  callback
) => {
  let prevUrl = "";
  new MutationObserver(() => {
    const currUrl = window.location.href;
    if (currUrl !== prevUrl) {
      prevUrl = currUrl;
      const isPreferredPage = currUrl.indexOf(pageUrl) > -1;
      if (isPreferredPage) {
        callback();
      }
    }
  }).observe(observerElement, options);
};

/**
 *  Run callback on exist intent
 * @function observeForExitIntent
 * @param {function} callback - callback to run on exit intent
 */
export const observeForExitIntent = (callback) => {
  try {
    // Desktop
    const isMobile = window.matchMedia("(max-width: 768px)").matches;
    if (!isMobile) {
      let count = 0;
      const maxCount = 100;

      // Wait for body elemnt in DOM
      const waitForElement = setInterval(() => {
        const bodyElement = document.querySelector("body");

        if (bodyElement) {
          clearInterval(waitForElement);

          // Replace all mouse out events on body with exit intent
          bodyElement.onmouseout = function (evt) {
            try {
              const showIntent =
                !evt.toElement && !evt.relatedTarget && evt.clientY < 10;

              if (showIntent) {
                // Stop observing mouse movements
                window.onmouseout = null;

                // Run callback
                callback();
              }
            } catch (err) {
              console.log(err.message);
            }
          };
        }

        if (count > maxCount) {
          clearInterval(waitForElement);
        }
      }, 500);
    }

    // Mobile
    if (isMobile) {
      let lastScrollPosition =
          window.pageYOffset || document.documentElement.scrollTop,
        upwardScroll = 0,
        timer;

      // Observe scrolling on mobile
      const observeScrolling = () => {
        const newScrollPosition =
          window.pageYOffset || document.documentElement.scrollTop;

        // User scrolled, restart the 8 second timer
        restartTimer();

        // Record upward movements
        if (newScrollPosition < lastScrollPosition) {
          upwardScroll++;
        }

        // Show the modal when the user makes 50 individual upward movements
        if (upwardScroll > 50) {
          clearTimeout(timer);
          window.removeEventListener("scroll", observeScrolling, true);
          callback();
        }

        // Store the new scroll position
        lastScrollPosition = newScrollPosition;
      };
      // Start an 8 second timer
      let restartTimer = () => {
        clearTimeout(timer);

        timer = setTimeout(function () {
          // activate when the user hasn't made a touch motion for 4 seconds
          clearTimeout(timer);
          window.removeEventListener("scroll", observeScrolling, true);
          callback();
        }, 4000);
      };

      // Start the timer on page load
      restartTimer();

      // Restart the 8 second timer when the user touches the screen
      window.ontouchstart = restartTimer;

      // Monitor the scrolling behaviour
      window.addEventListener("scroll", observeScrolling, true);
    }
  } catch (error) {
    console.log("observeForExitIntent Error: " + error);
  }
};

/**
 * Wait for Angular elements to be loaded
 * @function waitForAngularRootElements
 * @returns {Promise} - Resolve when angular root elements are loaded
 */
export const waitForAngularRootElements = () => {
  return new Promise((resolve, reject) => {
    const checkFunctionExists = () => {
      if (typeof getAllAngularRootElements === "function") {
        resolve();
      } else {
        setTimeout(checkFunctionExists, 100); // Check again after 100 milliseconds
      }
    };

    checkFunctionExists();
  });
};