Jump To:

  1. Disclaimer

Tab Manager

A demonstration and test page for the core TabManager JavaScript class.


Disclaimer

This page is for testing the behavior of the TabManager JavaScript class directly. It does not demonstrate the fully-styled tabs SCSS component. The styles here are minimal and utilitarian, designed only to make the underlying class's functionality visible.

1. Basic Functionality & Keyboard Navigation

Standard horizontal tabs. Test with Arrow Keys, Home, and End.

Panel 1 Content
Panel 2 Content
Panel 3 Content

2a. `orientation: 'vertical'`

Test with Up/Down arrows.

Vertical Panel 1
Vertical Panel 2

2b. `initialIndex: 1`, `allArrows: true`

Should start on Tab B. All arrow keys should work.

Panel A
Panel B
Panel C

3. URL Hash Options

This instance uses { openByUrlHash: true, setUrlHash: true }. Clicking a tab will update the URL. Refreshing the page with a hash (e.g., #url-tab-2) should open the correct tab.

URL Panel 1
URL Panel 2
URL Panel 3

4. API Methods & Callbacks

This instance tests programmatic control and callbacks.

API Panel 1

This panel has extra content to test `equalHeights`.

API Panel 2

API Panel 3

This panel also has extra content to test `equalHeights`.

Some more content.

Status: Waiting for events...

<script>
  document.addEventListener("DOMContentLoaded", () => {
    const { TabManager } = Ulu;

    // --- Test 1: Basic ---
    const basicTablistEl = document.getElementById('basic-tablist');
    const basicTabs = [
      { tab: document.getElementById('basic-tab-1'), panel: document.getElementById('basic-panel-1') },
      { tab: document.getElementById('basic-tab-2'), panel: document.getElementById('basic-panel-2') },
      { tab: document.getElementById('basic-tab-3'), panel: document.getElementById('basic-panel-3') },
    ];
    basicTabs.forEach(item => item.tab.setAttribute('aria-controls', item.panel.id));
    new TabManager(basicTablistEl);

    // --- Test 2a: Vertical ---
    const verticalTablistEl = document.getElementById('vertical-tablist');
    const verticalTabs = [
      { tab: document.getElementById('vert-tab-1'), panel: document.getElementById('vert-panel-1') },
      { tab: document.getElementById('vert-tab-2'), panel: document.getElementById('vert-panel-2') },
    ];
    verticalTabs.forEach(item => item.tab.setAttribute('aria-controls', item.panel.id));
    new TabManager(verticalTablistEl, { orientation: 'vertical' });

    // --- Test 2b: Options ---
    const optionsTablistEl = document.getElementById('options-tablist');
    const optionsTabs = [
      { tab: document.getElementById('opts-tab-1'), panel: document.getElementById('opts-panel-1') },
      { tab: document.getElementById('opts-tab-2'), panel: document.getElementById('opts-panel-2') },
      { tab: document.getElementById('opts-tab-3'), panel: document.getElementById('opts-panel-3') },
    ];
    optionsTabs.forEach(item => item.tab.setAttribute('aria-controls', item.panel.id));
    new TabManager(optionsTablistEl, { initialIndex: 1, allArrows: true });

    // --- Test 3: URL Hash ---
    const urlTablistEl = document.getElementById('url-tablist');
    const urlTabs = [
      { tab: document.getElementById('url-tab-1'), panel: document.getElementById('url-panel-1') },
      { tab: document.getElementById('url-tab-2'), panel: document.getElementById('url-panel-2') },
      { tab: document.getElementById('url-tab-3'), panel: document.getElementById('url-panel-3') },
    ];
    urlTabs.forEach(item => item.tab.setAttribute('aria-controls', item.panel.id));
    new TabManager(urlTablistEl, { openByUrlHash: true, setUrlHash: true });

    // --- Test 4: API & Callbacks ---
    const apiTablistEl = document.getElementById('api-tablist');
    const apiStatusEl = document.getElementById('api-status');
    const apiTabs = [
      { tab: document.getElementById('api-tab-1'), panel: document.getElementById('api-panel-1') },
      { tab: document.getElementById('api-tab-2'), panel: document.getElementById('api-panel-2') },
      { tab: document.getElementById('api-tab-3'), panel: document.getElementById('api-panel-3') },
    ];
    let apiManager;

    const initApiManager = () => {
      apiStatusEl.innerHTML = "Status: Initializing...";
      // Manually add aria-controls to demonstrate class discovering them
      apiTabs.forEach(item => item.tab.setAttribute('aria-controls', item.panel.id));
      
      apiManager = new TabManager(apiTablistEl, {
        equalHeights: true,
        onReady: (instance) => {
          console.log("TabManager Ready:", instance);
          apiStatusEl.innerHTML += "<br>Event: onReady fired. Instance created.";
        },
        onChange: (active, previous) => {
          console.log("TabManager Change:", { active, previous });
          const prevIndex = previous.index > -1 ? previous.index : 'null';
          apiStatusEl.innerHTML += `<br>Event: onChange fired. Active: ${ active.index }, Previous: ${ prevIndex }`;
        }
      });
    };

    initApiManager();

    document.getElementById('api-btn-activate-2').addEventListener('click', () => {
      apiStatusEl.innerHTML = "Action: activate(2)";
      apiManager.activate(2);
    });
    document.getElementById('api-btn-activate-1-id').addEventListener('click', () => {
      apiStatusEl.innerHTML = "Action: activateById('api-tab-1')";
      apiManager.activateById('api-tab-1');
    });
    document.getElementById('api-btn-destroy').addEventListener('click', () => {
      apiStatusEl.innerHTML = "Action: destroy()";
      apiManager.destroy();
      apiStatusEl.innerHTML += "<br>Instance destroyed. Listeners and attributes should be removed.";
    });
    document.getElementById('api-btn-reinit').addEventListener('click', () => {
      initApiManager();
    });
  });
</script>