A Step-by-Step Guide to Implementing Touch-Swipe Tab Navigation with jQuery

In today's mobile-first world, providing a seamless user experience is crucial. One way to enhance the user experience is by implementing swipe navigation for tabs. In this guide, we'll walk you through a simple yet effective jQuery code snippet that allows users to navigate through tabs by swiping left or right on touch devices.

window.isOptionSwipe = false;

jQuery(document).ready(function($) {
    var tabsWrapper = document.querySelector('[id^="_tabs-"]');
    var tabsContentsWrapper = document.querySelector('[id^="_tabs_contents-"]');
    var touchTimer, touchDuration;
    const holdDuration = 200; // time in milliseconds to consider as a hold

    if (tabsWrapper && tabsContentsWrapper) {
        var tabs = tabsWrapper.querySelectorAll('.oxy-tab');
        var tabContents = tabsContentsWrapper.querySelectorAll('.oxy-tab-content');
        var startX = 0;
        var distance = 0;
        var threshold = window.innerWidth * 0.3; // 30% of screen width
        var isOptionSwipe = false;

        tabsContentsWrapper.addEventListener('touchstart', function(e) {
            console.log("Touch Start Triggered");
            startX = e.touches[0].clientX;
            touchDuration = null;

            touchTimer = setTimeout(function() {
                touchDuration = 'long';
            }, holdDuration);
        }, false);

        tabsContentsWrapper.addEventListener('touchmove', function(e) {
            console.log("Touch Move Triggered");
            distance = e.touches[0].clientX - startX;
        }, false);

        tabsContentsWrapper.addEventListener('touchend', function() {
            clearTimeout(touchTimer);
            var activeClassPattern = /tabs-\d+-tab-active/;
            var activeTabIndex = Array.from(tabs).findIndex(function(tab) {
                return tab.className.match(activeClassPattern);
            });

            if (window.isOptionSwipe) { // <-- Check the flag here
                window.isOptionSwipe = false; // Reset the flag
                return; // Return early to prevent tab change
            }

            if (isOptionSwipe) { // Add this condition
                isOptionSwipe = false; // Reset the flag
                return;
            }

            if (touchDuration !== 'long') {
                window.isOptionSwipe = false;
                return;
            }

            if (distance < -threshold && activeTabIndex < tabs.length - 1) {
                changeTab(activeTabIndex + 1);
            } else if (distance > threshold && activeTabIndex > 0) {
                changeTab(activeTabIndex - 1);
            }
            distance = 0;
        }, false);

        $(tabs).on('click', function() {
            scrollToActiveTab();
        });

        function changeTab(index) {
            var activeClassPattern = /tabs-\d+-tab-active/;
            var activeClass = Array.from(tabs).find(function(tab) {
                return tab.className.match(activeClassPattern);
            }).className.match(activeClassPattern)[0];

            tabs.forEach(function(tab) {
                tab.classList.remove(activeClass);
            });
            tabContents.forEach(function(content) {
                content.classList.add('oxy-tabs-contents-content-hidden');
            });

            tabs[index].classList.add(activeClass);
            tabContents[index].classList.remove('oxy-tabs-contents-content-hidden');
            scrollToActiveTab();
        }

        function scrollToActiveTab() {
            var activeClassPattern = /tabs-\d+-tab-active/;
            var activeClass = Array.from(tabs).find(function(tab) {
                return tab.className.match(activeClassPattern);
            }).className.match(activeClassPattern)[0];
            var activeTab = $('.oxy-tab.' + activeClass);
            var tabsWrapperJQ = $(tabsWrapper);
            var scrollPosition = activeTab.position().left + tabsWrapperJQ.scrollLeft() - (tabsWrapperJQ.width() / 2) + (activeTab.width() / 2);
            tabsWrapperJQ.animate({
                scrollLeft: scrollPosition
            }, 300);
        }
    } else {
        console.warn('Tabs or tab contents not found');
    }
});

What Does the Code Do?

The code snippet provided enables swipe navigation for tabs. Users can swipe left to go to the next tab and swipe right to go to the previous tab. This functionality is especially useful for mobile users, providing an intuitive way to navigate through content.

Code Breakdown

Event Listeners: Three event listeners are added to the `tabsContentsWrapper` to detect touch events:

  • touchstart: Captures the starting X-coordinate of the touch.
  • touchmove: Calculates the distance swiped by subtracting the starting X-coordinate from the current X-coordinate.
  • touchend: Determines the swipe direction and triggers the tab change if the swipe distance is significant.

Changing Tabs: The changeTab function is responsible for switching tabs. It removes the active class from the current tab and adds it to the new tab, while also hiding and showing the corresponding tab content.

function changeTab(index) {
        var activeClassPattern = /tabs-\d+-tab-active/;
        var activeClass = Array.from(tabs).find(tab => tab.className.match(activeClassPattern)).className.match(activeClassPattern)[0];

        tabs.forEach(tab => tab.classList.remove(activeClass));
        tabContents.forEach(content => content.classList.add('oxy-tabs-contents-content-hidden'));

        tabs[index].classList.add(activeClass);
        tabContents[index].classList.remove('oxy-tabs-contents-content-hidden');

        // Scroll to the active tab
        scrollToActiveTab();
    }

How to Implement

Step 1: Copy and paste the provided code snippet into your JavaScript file or Code Block.

Step 2: Apply necessary CSS styling to the tabs and content to achieve the desired appearance.

For a seamless user experience, consider integrating this with your existing option swipe navigation. Both scripts work in harmony to enhance your site's interactivity.

Jump to Option Swipe Implementation

Share this post