tabs.js

I’ll create a strong inc/js/tabs.js for RX Theme that works for normal tabs, nested tabs, URL hash tabs, keyboard accessibility, auto tabs, vertical tabs, AJAX-ready hooks, and WordPress-friendly initialization.

My dear friend, create this file:

rx-theme/inc/js/tabs.js

Then paste this full code.

/*!
 * RX Theme Tabs JS
 * File: inc/js/tabs.js
 * Theme: RX Theme
 * Description:
 * Advanced accessible tabs system for WordPress theme.
 * Supports:
 * - Click tabs
 * - Keyboard navigation
 * - URL hash support
 * - Nested tabs
 * - Auto-rotating tabs
 * - Vertical tabs
 * - Mobile accordion mode
 * - LocalStorage active tab memory
 * - Deep linking
 * - Lazy loading content
 * - AJAX-ready re-initialization
 * - Custom events
 */

(function () {
  "use strict";

  const RX_TABS = {
    selector: ".rx-tabs",
    tabSelector: ".rx-tab",
    panelSelector: ".rx-tab-panel",
    navSelector: ".rx-tabs-nav",
    activeClass: "is-active",
    disabledClass: "is-disabled",
    initializedClass: "rx-tabs-initialized",
    hiddenClass: "is-hidden",
    mobileClass: "is-mobile-tabs",
    accordionActiveClass: "is-accordion-active",
    storagePrefix: "rx_theme_active_tab_",
    resizeTimer: null,

    defaults: {
      activeIndex: 0,
      remember: true,
      hash: true,
      keyboard: true,
      autoRotate: false,
      autoRotateDelay: 5000,
      pauseOnHover: true,
      mobileAccordion: true,
      mobileBreakpoint: 768,
      lazy: true,
      scrollToTab: false,
      scrollOffset: 80,
      animation: true,
      animationDuration: 250,
      closeOtherMobilePanels: true
    },

    init: function (context) {
      const root = context || document;
      const tabGroups = root.querySelectorAll(this.selector);

      if (!tabGroups.length) {
        return;
      }

      tabGroups.forEach((tabs, index) => {
        if (tabs.classList.contains(this.initializedClass)) {
          return;
        }

        this.setupTabs(tabs, index);
      });

      this.bindGlobalEvents();
    },

    setupTabs: function (tabs, groupIndex) {
      const settings = this.getSettings(tabs);
      const nav = tabs.querySelector(this.navSelector);
      const tabButtons = Array.from(tabs.querySelectorAll(":scope > .rx-tabs-nav .rx-tab"));
      const panels = Array.from(tabs.querySelectorAll(":scope > .rx-tabs-content > .rx-tab-panel"));

      if (!nav || !tabButtons.length || !panels.length) {
        return;
      }

      tabs.classList.add(this.initializedClass);

      if (!tabs.id) {
        tabs.id = "rx-tabs-" + Date.now() + "-" + groupIndex;
      }

      tabs._rxTabsSettings = settings;
      tabs._rxTabsButtons = tabButtons;
      tabs._rxTabsPanels = panels;
      tabs._rxTabsAutoTimer = null;
      tabs._rxTabsPaused = false;

      this.setupARIA(tabs, tabButtons, panels);
      this.setupInitialState(tabs, tabButtons, panels, settings);
      this.bindTabEvents(tabs, tabButtons, panels, settings);

      if (settings.keyboard) {
        this.bindKeyboardEvents(tabs, tabButtons, panels, settings);
      }

      if (settings.autoRotate) {
        this.startAutoRotate(tabs);
      }

      if (settings.mobileAccordion) {
        this.checkMobileMode(tabs);
      }

      this.dispatchEvent(tabs, "rxTabsReady", {
        tabs: tabs,
        buttons: tabButtons,
        panels: panels,
        settings: settings
      });
    },

    getSettings: function (tabs) {
      const data = tabs.dataset || {};

      return {
        activeIndex: this.toInt(data.activeIndex, this.defaults.activeIndex),
        remember: this.toBool(data.remember, this.defaults.remember),
        hash: this.toBool(data.hash, this.defaults.hash),
        keyboard: this.toBool(data.keyboard, this.defaults.keyboard),
        autoRotate: this.toBool(data.autoRotate, this.defaults.autoRotate),
        autoRotateDelay: this.toInt(data.autoRotateDelay, this.defaults.autoRotateDelay),
        pauseOnHover: this.toBool(data.pauseOnHover, this.defaults.pauseOnHover),
        mobileAccordion: this.toBool(data.mobileAccordion, this.defaults.mobileAccordion),
        mobileBreakpoint: this.toInt(data.mobileBreakpoint, this.defaults.mobileBreakpoint),
        lazy: this.toBool(data.lazy, this.defaults.lazy),
        scrollToTab: this.toBool(data.scrollToTab, this.defaults.scrollToTab),
        scrollOffset: this.toInt(data.scrollOffset, this.defaults.scrollOffset),
        animation: this.toBool(data.animation, this.defaults.animation),
        animationDuration: this.toInt(data.animationDuration, this.defaults.animationDuration),
        closeOtherMobilePanels: this.toBool(data.closeOtherMobilePanels, this.defaults.closeOtherMobilePanels)
      };
    },

    setupARIA: function (tabs, tabButtons, panels) {
      const nav = tabs.querySelector(this.navSelector);

      if (nav) {
        nav.setAttribute("role", "tablist");

        if (tabs.dataset.orientation === "vertical") {
          nav.setAttribute("aria-orientation", "vertical");
          tabs.classList.add("rx-tabs-vertical");
        } else {
          nav.setAttribute("aria-orientation", "horizontal");
        }
      }

      tabButtons.forEach((button, index) => {
        const panel = panels[index];

        if (!button.id) {
          button.id = tabs.id + "-tab-" + index;
        }

        if (panel && !panel.id) {
          panel.id = tabs.id + "-panel-" + index;
        }

        button.setAttribute("role", "tab");
        button.setAttribute("aria-selected", "false");
        button.setAttribute("tabindex", "-1");

        if (panel) {
          button.setAttribute("aria-controls", panel.id);
        }

        if (button.classList.contains(this.disabledClass) || button.disabled) {
          button.setAttribute("aria-disabled", "true");
          button.setAttribute("tabindex", "-1");
        } else {
          button.setAttribute("aria-disabled", "false");
        }

        if (panel) {
          panel.setAttribute("role", "tabpanel");
          panel.setAttribute("aria-hidden", "true");
          panel.setAttribute("tabindex", "0");
          panel.setAttribute("aria-labelledby", button.id);
        }
      });
    },

    setupInitialState: function (tabs, tabButtons, panels, settings) {
      let activeIndex = settings.activeIndex;

      const hashIndex = this.getIndexFromHash(tabButtons, panels);
      const storedIndex = this.getStoredIndex(tabs);

      if (settings.hash && hashIndex !== null) {
        activeIndex = hashIndex;
      } else if (settings.remember && storedIndex !== null) {
        activeIndex = storedIndex;
      }

      if (!tabButtons[activeIndex] || this.isDisabled(tabButtons[activeIndex])) {
        activeIndex = this.getFirstEnabledIndex(tabButtons);
      }

      if (activeIndex < 0) {
        activeIndex = 0;
      }

      tabButtons.forEach((button, index) => {
        const panel = panels[index];

        if (index === activeIndex) {
          this.activateButton(button);
          this.showPanel(panel, false);
        } else {
          this.deactivateButton(button);
          this.hidePanel(panel, false);
        }
      });

      tabs._rxTabsActiveIndex = activeIndex;
    },

    bindTabEvents: function (tabs, tabButtons, panels, settings) {
      tabButtons.forEach((button, index) => {
        button.addEventListener("click", (event) => {
          event.preventDefault();

          if (this.isDisabled(button)) {
            return;
          }

          this.activateTab(tabs, index, true);
        });

        button.addEventListener("mouseenter", () => {
          if (settings.autoRotate && settings.pauseOnHover) {
            this.pauseAutoRotate(tabs);
          }
        });

        button.addEventListener("mouseleave", () => {
          if (settings.autoRotate && settings.pauseOnHover) {
            this.resumeAutoRotate(tabs);
          }
        });

        button.addEventListener("focus", () => {
          if (settings.autoRotate && settings.pauseOnHover) {
            this.pauseAutoRotate(tabs);
          }
        });

        button.addEventListener("blur", () => {
          if (settings.autoRotate && settings.pauseOnHover) {
            this.resumeAutoRotate(tabs);
          }
        });
      });

      panels.forEach((panel) => {
        panel.addEventListener("mouseenter", () => {
          if (settings.autoRotate && settings.pauseOnHover) {
            this.pauseAutoRotate(tabs);
          }
        });

        panel.addEventListener("mouseleave", () => {
          if (settings.autoRotate && settings.pauseOnHover) {
            this.resumeAutoRotate(tabs);
          }
        });
      });
    },

    bindKeyboardEvents: function (tabs, tabButtons, panels, settings) {
      tabButtons.forEach((button, index) => {
        button.addEventListener("keydown", (event) => {
          if (this.isDisabled(button)) {
            return;
          }

          const key = event.key;
          let newIndex = null;

          const isVertical = tabs.classList.contains("rx-tabs-vertical");

          if (key === "ArrowRight" && !isVertical) {
            newIndex = this.getNextEnabledIndex(tabButtons, index);
          }

          if (key === "ArrowLeft" && !isVertical) {
            newIndex = this.getPreviousEnabledIndex(tabButtons, index);
          }

          if (key === "ArrowDown" && isVertical) {
            newIndex = this.getNextEnabledIndex(tabButtons, index);
          }

          if (key === "ArrowUp" && isVertical) {
            newIndex = this.getPreviousEnabledIndex(tabButtons, index);
          }

          if (key === "Home") {
            newIndex = this.getFirstEnabledIndex(tabButtons);
          }

          if (key === "End") {
            newIndex = this.getLastEnabledIndex(tabButtons);
          }

          if (key === "Enter" || key === " ") {
            event.preventDefault();
            this.activateTab(tabs, index, true);
            return;
          }

          if (newIndex !== null && newIndex >= 0) {
            event.preventDefault();
            tabButtons[newIndex].focus();
            this.activateTab(tabs, newIndex, true);
          }
        });
      });
    },

    activateTab: function (tabs, index, userAction) {
      const tabButtons = tabs._rxTabsButtons || [];
      const panels = tabs._rxTabsPanels || [];
      const settings = tabs._rxTabsSettings || this.defaults;

      const button = tabButtons[index];
      const panel = panels[index];

      if (!button || !panel || this.isDisabled(button)) {
        return;
      }

      const oldIndex = typeof tabs._rxTabsActiveIndex === "number" ? tabs._rxTabsActiveIndex : 0;

      if (oldIndex === index) {
        if (tabs.classList.contains(this.mobileClass)) {
          this.toggleMobilePanel(tabs, index);
        }
        return;
      }

      this.dispatchEvent(tabs, "rxTabsBeforeChange", {
        tabs: tabs,
        oldIndex: oldIndex,
        newIndex: index,
        oldButton: tabButtons[oldIndex],
        newButton: button,
        oldPanel: panels[oldIndex],
        newPanel: panel
      });

      tabButtons.forEach((tabButton, tabIndex) => {
        if (tabIndex === index) {
          this.activateButton(tabButton);
        } else {
          this.deactivateButton(tabButton);
        }
      });

      panels.forEach((tabPanel, panelIndex) => {
        if (panelIndex === index) {
          this.showPanel(tabPanel, settings.animation);
        } else {
          this.hidePanel(tabPanel, settings.animation);
        }
      });

      tabs._rxTabsActiveIndex = index;

      if (settings.lazy) {
        this.lazyLoadPanel(panel);
      }

      if (settings.remember) {
        this.storeIndex(tabs, index);
      }

      if (settings.hash && userAction) {
        this.updateHash(button, panel);
      }

      if (settings.scrollToTab && userAction) {
        this.scrollToElement(tabs, settings.scrollOffset);
      }

      this.dispatchEvent(tabs, "rxTabsAfterChange", {
        tabs: tabs,
        oldIndex: oldIndex,
        newIndex: index,
        activeButton: button,
        activePanel: panel
      });
    },

    activateButton: function (button) {
      if (!button) return;

      button.classList.add(this.activeClass);
      button.setAttribute("aria-selected", "true");
      button.setAttribute("tabindex", "0");
    },

    deactivateButton: function (button) {
      if (!button) return;

      button.classList.remove(this.activeClass);
      button.setAttribute("aria-selected", "false");

      if (!this.isDisabled(button)) {
        button.setAttribute("tabindex", "-1");
      }
    },

    showPanel: function (panel, animate) {
      if (!panel) return;

      panel.classList.add(this.activeClass);
      panel.classList.remove(this.hiddenClass);
      panel.removeAttribute("hidden");
      panel.setAttribute("aria-hidden", "false");

      if (animate) {
        panel.style.display = "block";
        panel.style.opacity = "0";
        panel.style.transform = "translateY(8px)";

        requestAnimationFrame(() => {
          panel.style.transition = "opacity 250ms ease, transform 250ms ease";
          panel.style.opacity = "1";
          panel.style.transform = "translateY(0)";
        });

        window.setTimeout(() => {
          panel.style.transition = "";
          panel.style.opacity = "";
          panel.style.transform = "";
        }, 270);
      } else {
        panel.style.display = "";
      }
    },

    hidePanel: function (panel, animate) {
      if (!panel) return;

      panel.classList.remove(this.activeClass);
      panel.classList.add(this.hiddenClass);
      panel.setAttribute("aria-hidden", "true");
      panel.setAttribute("hidden", "hidden");

      if (animate) {
        panel.style.display = "none";
      } else {
        panel.style.display = "";
      }
    },

    toggleMobilePanel: function (tabs, index) {
      const panels = tabs._rxTabsPanels || [];
      const tabButtons = tabs._rxTabsButtons || [];
      const settings = tabs._rxTabsSettings || this.defaults;

      const panel = panels[index];
      const button = tabButtons[index];

      if (!panel || !button) return;

      const isOpen = panel.classList.contains(this.accordionActiveClass);

      if (settings.closeOtherMobilePanels) {
        panels.forEach((p, i) => {
          p.classList.remove(this.accordionActiveClass);
          if (tabButtons[i]) {
            tabButtons[i].setAttribute("aria-expanded", "false");
          }
        });
      }

      if (!isOpen) {
        panel.classList.add(this.accordionActiveClass);
        button.setAttribute("aria-expanded", "true");
      } else {
        panel.classList.remove(this.accordionActiveClass);
        button.setAttribute("aria-expanded", "false");
      }
    },

    checkMobileMode: function (tabs) {
      const settings = tabs._rxTabsSettings || this.defaults;
      const tabButtons = tabs._rxTabsButtons || [];

      if (window.innerWidth <= settings.mobileBreakpoint) {
        tabs.classList.add(this.mobileClass);

        tabButtons.forEach((button) => {
          button.setAttribute("aria-expanded", button.classList.contains(this.activeClass) ? "true" : "false");
        });
      } else {
        tabs.classList.remove(this.mobileClass);

        tabButtons.forEach((button) => {
          button.removeAttribute("aria-expanded");
        });
      }
    },

    startAutoRotate: function (tabs) {
      const settings = tabs._rxTabsSettings || this.defaults;

      this.stopAutoRotate(tabs);

      tabs._rxTabsAutoTimer = window.setInterval(() => {
        if (tabs._rxTabsPaused) {
          return;
        }

        const tabButtons = tabs._rxTabsButtons || [];
        const currentIndex = tabs._rxTabsActiveIndex || 0;
        const nextIndex = this.getNextEnabledIndex(tabButtons, currentIndex);

        if (nextIndex !== null && nextIndex >= 0) {
          this.activateTab(tabs, nextIndex, false);
        }
      }, settings.autoRotateDelay);
    },

    stopAutoRotate: function (tabs) {
      if (tabs._rxTabsAutoTimer) {
        window.clearInterval(tabs._rxTabsAutoTimer);
        tabs._rxTabsAutoTimer = null;
      }
    },

    pauseAutoRotate: function (tabs) {
      tabs._rxTabsPaused = true;
    },

    resumeAutoRotate: function (tabs) {
      tabs._rxTabsPaused = false;
    },

    lazyLoadPanel: function (panel) {
      if (!panel || panel.dataset.loaded === "true") {
        return;
      }

      const lazyImages = panel.querySelectorAll("img[data-src]");
      const lazyIframes = panel.querySelectorAll("iframe[data-src]");
      const lazyBackgrounds = panel.querySelectorAll("[data-bg]");

      lazyImages.forEach((img) => {
        img.src = img.dataset.src;
        img.removeAttribute("data-src");

        if (img.dataset.srcset) {
          img.srcset = img.dataset.srcset;
          img.removeAttribute("data-srcset");
        }
      });

      lazyIframes.forEach((iframe) => {
        iframe.src = iframe.dataset.src;
        iframe.removeAttribute("data-src");
      });

      lazyBackgrounds.forEach((element) => {
        element.style.backgroundImage = "url(" + element.dataset.bg + ")";
        element.removeAttribute("data-bg");
      });

      panel.dataset.loaded = "true";
    },

    getIndexFromHash: function (tabButtons, panels) {
      const hash = window.location.hash;

      if (!hash) {
        return null;
      }

      const cleanHash = hash.replace("#", "");

      for (let i = 0; i < tabButtons.length; i++) {
        const button = tabButtons[i];
        const panel = panels[i];

        if (!button || !panel) continue;

        if (
          button.id === cleanHash ||
          panel.id === cleanHash ||
          button.dataset.tab === cleanHash ||
          panel.dataset.tabPanel === cleanHash
        ) {
          return i;
        }
      }

      return null;
    },

    updateHash: function (button, panel) {
      const target = button.dataset.hash || panel.id || button.id;

      if (!target) {
        return;
      }

      if (history.pushState) {
        history.pushState(null, "", "#" + target);
      } else {
        window.location.hash = target;
      }
    },

    getStoredIndex: function (tabs) {
      try {
        const key = this.storagePrefix + tabs.id;
        const stored = localStorage.getItem(key);

        if (stored === null) {
          return null;
        }

        const value = parseInt(stored, 10);

        return isNaN(value) ? null : value;
      } catch (error) {
        return null;
      }
    },

    storeIndex: function (tabs, index) {
      try {
        const key = this.storagePrefix + tabs.id;
        localStorage.setItem(key, String(index));
      } catch (error) {
        return false;
      }
    },

    isDisabled: function (button) {
      if (!button) return true;

      return (
        button.disabled ||
        button.classList.contains(this.disabledClass) ||
        button.getAttribute("aria-disabled") === "true"
      );
    },

    getFirstEnabledIndex: function (buttons) {
      for (let i = 0; i < buttons.length; i++) {
        if (!this.isDisabled(buttons[i])) {
          return i;
        }
      }

      return -1;
    },

    getLastEnabledIndex: function (buttons) {
      for (let i = buttons.length - 1; i >= 0; i--) {
        if (!this.isDisabled(buttons[i])) {
          return i;
        }
      }

      return -1;
    },

    getNextEnabledIndex: function (buttons, currentIndex) {
      if (!buttons.length) {
        return -1;
      }

      let index = currentIndex;

      for (let i = 0; i < buttons.length; i++) {
        index = (index + 1) % buttons.length;

        if (!this.isDisabled(buttons[index])) {
          return index;
        }
      }

      return -1;
    },

    getPreviousEnabledIndex: function (buttons, currentIndex) {
      if (!buttons.length) {
        return -1;
      }

      let index = currentIndex;

      for (let i = 0; i < buttons.length; i++) {
        index = (index - 1 + buttons.length) % buttons.length;

        if (!this.isDisabled(buttons[index])) {
          return index;
        }
      }

      return -1;
    },

    scrollToElement: function (element, offset) {
      const rect = element.getBoundingClientRect();
      const top = rect.top + window.pageYOffset - offset;

      window.scrollTo({
        top: top,
        behavior: "smooth"
      });
    },

    bindGlobalEvents: function () {
      if (this._globalEventsBound) {
        return;
      }

      this._globalEventsBound = true;

      window.addEventListener("resize", () => {
        window.clearTimeout(this.resizeTimer);

        this.resizeTimer = window.setTimeout(() => {
          document.querySelectorAll(this.selector + "." + this.initializedClass).forEach((tabs) => {
            if (tabs._rxTabsSettings && tabs._rxTabsSettings.mobileAccordion) {
              this.checkMobileMode(tabs);
            }
          });
        }, 150);
      });

      window.addEventListener("hashchange", () => {
        document.querySelectorAll(this.selector + "." + this.initializedClass).forEach((tabs) => {
          const tabButtons = tabs._rxTabsButtons || [];
          const panels = tabs._rxTabsPanels || [];
          const settings = tabs._rxTabsSettings || this.defaults;

          if (!settings.hash) {
            return;
          }

          const index = this.getIndexFromHash(tabButtons, panels);

          if (index !== null && index >= 0) {
            this.activateTab(tabs, index, false);
          }
        });
      });

      document.addEventListener("rxAjaxContentLoaded", (event) => {
        this.init(event.detail && event.detail.context ? event.detail.context : document);
      });

      document.addEventListener("DOMContentLoaded", () => {
        this.init(document);
      });
    },

    refresh: function (context) {
      const root = context || document;

      root.querySelectorAll(this.selector).forEach((tabs) => {
        tabs.classList.remove(this.initializedClass);
        this.stopAutoRotate(tabs);
      });

      this.init(root);
    },

    destroy: function (tabs) {
      if (!tabs) {
        return;
      }

      const tabButtons = tabs._rxTabsButtons || [];
      const panels = tabs._rxTabsPanels || [];

      this.stopAutoRotate(tabs);

      tabs.classList.remove(this.initializedClass);
      tabs.classList.remove(this.mobileClass);

      tabButtons.forEach((button) => {
        button.classList.remove(this.activeClass);
        button.removeAttribute("role");
        button.removeAttribute("aria-selected");
        button.removeAttribute("aria-controls");
        button.removeAttribute("aria-disabled");
        button.removeAttribute("aria-expanded");
        button.removeAttribute("tabindex");
      });

      panels.forEach((panel) => {
        panel.classList.remove(this.activeClass);
        panel.classList.remove(this.hiddenClass);
        panel.classList.remove(this.accordionActiveClass);
        panel.removeAttribute("role");
        panel.removeAttribute("aria-hidden");
        panel.removeAttribute("aria-labelledby");
        panel.removeAttribute("tabindex");
        panel.removeAttribute("hidden");
        panel.style.display = "";
        panel.style.opacity = "";
        panel.style.transform = "";
        panel.style.transition = "";
      });

      delete tabs._rxTabsSettings;
      delete tabs._rxTabsButtons;
      delete tabs._rxTabsPanels;
      delete tabs._rxTabsAutoTimer;
      delete tabs._rxTabsPaused;
      delete tabs._rxTabsActiveIndex;
    },

    toBool: function (value, fallback) {
      if (typeof value === "undefined") {
        return fallback;
      }

      if (value === true || value === "true" || value === "1" || value === "yes") {
        return true;
      }

      if (value === false || value === "false" || value === "0" || value === "no") {
        return false;
      }

      return fallback;
    },

    toInt: function (value, fallback) {
      const number = parseInt(value, 10);
      return isNaN(number) ? fallback : number;
    },

    dispatchEvent: function (element, name, detail) {
      const event = new CustomEvent(name, {
        bubbles: true,
        cancelable: true,
        detail: detail || {}
      });

      element.dispatchEvent(event);
    }
  };

  window.RX_TABS = RX_TABS;

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", function () {
      RX_TABS.init(document);
    });
  } else {
    RX_TABS.init(document);
  }
})();

Add this in functions.php or your enqueue file:

function rx_theme_enqueue_tabs_script() {
    wp_enqueue_script(
        'rx-tabs',
        get_template_directory_uri() . '/inc/js/tabs.js',
        array(),
        wp_get_theme()->get( 'Version' ),
        true
    );
}
add_action( 'wp_enqueue_scripts', 'rx_theme_enqueue_tabs_script' );

Example HTML structure:

<div class="rx-tabs"
     data-active-index="0"
     data-remember="true"
     data-hash="true"
     data-keyboard="true"
     data-mobile-accordion="true"
     data-auto-rotate="false">

  <div class="rx-tabs-nav">
    <button class="rx-tab" data-hash="overview">Overview</button>
    <button class="rx-tab" data-hash="symptoms">Symptoms</button>
    <button class="rx-tab" data-hash="treatment">Treatment</button>
  </div>

  <div class="rx-tabs-content">
    <div class="rx-tab-panel" id="overview">
      Overview content here.
    </div>

    <div class="rx-tab-panel" id="symptoms">
      Symptoms content here.
    </div>

    <div class="rx-tab-panel" id="treatment">
      Treatment content here.
    </div>
  </div>
</div>

Important options you can use:

data-active-index="0"
data-remember="true"
data-hash="true"
data-keyboard="true"
data-auto-rotate="true"
data-auto-rotate-delay="5000"
data-pause-on-hover="true"
data-mobile-accordion="true"
data-mobile-breakpoint="768"
data-lazy="true"
data-scroll-to-tab="true"
data-scroll-offset="80"
data-animation="true"
data-animation-duration="250"
data-close-other-mobile-panels="true"
data-orientation="vertical"

This file is advanced and safe for RX Theme. It does not need jQuery. It is pure JavaScript and WordPress friendly.

Leave a Reply

Your email address will not be published. Required fields are marked *