// 自行加入的JS請寫在這裡 $(function () { $('.radio_grp').each(function (index, el) { $(this) .find('input') .focus(function (event) { $(this).parent('label').siblings().removeClass('active'); $(this).parent('label').addClass('active'); }); $(this) .find('input') .blur(function (event) { $(this).parent('label').siblings().removeClass('active'); $(this).parent('label').removeClass('active'); }); }); // lazyload $('img').lazyload({ effect: 'fadeIn' }); // slider 定義初始化無障礙功能 $(document).ready(function () { var isEn = $('html').attr('lang') && $('html').attr('lang').toLowerCase().indexOf('en') > -1; var i18n = { pause: isEn ? 'Pause' : '暫停', play: isEn ? 'Play' : '播放', next: isEn ? 'Next' : '下一張', prev: isEn ? 'Previous' : '前一張', link: isEn ? 'Link' : '連結', }; function enhanceSlickAccessibility(sliderEl, sliderName) { var $slider = $(sliderEl); // --- 動態加入暫停/播放按鈕 --- var $controls = $('
'); var $pauseBtn = $(''); if (!$slider.parent().find('.slick-pause-btn').length) { $slider.parent().prepend($controls); $controls.append($pauseBtn); } $pauseBtn.on('click', function () { if ($(this).hasClass('is-paused')) { $slider.slick('slickPlay'); $(this) .removeClass('is-paused') .text(i18n.pause) .attr('aria-label', i18n.pause + ' ' + sliderName); } else { $slider.slick('slickPause'); $(this) .addClass('is-paused') .text(i18n.play) .attr('aria-label', i18n.play + ' ' + sliderName); } }); $slider.on('init afterChange breakpoint', function (event, slick, currentSlide) { var slickObj = slick || $slider.slick('getSlick'); var current = currentSlide || 0; // slick-dots 的無障礙屬性 (隱藏 dots 避免 Tab 選取) var $dots = $slider.find('.slick-dots'); if ($dots.length) { $dots.attr('aria-hidden', 'true'); $dots.find('li, button').attr({ tabindex: '-1', 'aria-hidden': 'true', }); } var nextIndex = (current + 1) % slickObj.slideCount; var prevIndex = (current - 1 + slickObj.slideCount) % slickObj.slideCount; var nextTitle = slickObj.$slides.eq(nextIndex).find('.caption').text().trim() || slickObj.$slides.eq(nextIndex).find('a').attr('title') || slickObj.$slides.eq(nextIndex).find('img').attr('alt') || (isEn ? 'Next slide' : '下一張'); var prevTitle = slickObj.$slides.eq(prevIndex).find('.caption').text().trim() || slickObj.$slides.eq(prevIndex).find('a').attr('title') || slickObj.$slides.eq(prevIndex).find('img').attr('alt') || (isEn ? 'Previous slide' : '前一張'); // 只設定 title,並強制移除 slick 自動產生的 aria-label 屬性避免重複報讀 $slider .find('.slick-next') .attr('title', i18n.next + ': ' + nextTitle) .removeAttr('aria-label'); $slider .find('.slick-prev') .attr('title', i18n.prev + ': ' + prevTitle) .removeAttr('aria-label'); slickObj.$slides.attr('aria-hidden', 'true').find('a, button').attr('tabindex', '-1'); slickObj.$slides.eq(current).attr('aria-hidden', 'false').find('a, button').attr('tabindex', '0'); }); if ($slider.hasClass('slick-initialized')) { $slider.trigger('afterChange', [$slider.slick('getSlick'), $slider.slick('slickCurrentSlide')]); } } // --- mpSlider (首頁輪播) --- $('.mpSlider').each(function () { $(this).slick({ dots: true, arrows: true, infinite: true, speed: 2000, autoplay: true, fade: true, pauseOnFocus: true, pauseOnHover: true, cssEase: 'ease', accessibility: true, }); enhanceSlickAccessibility(this, isEn ? 'Main Slider' : '首頁輪播'); }); // --- event_slider (活動輪播) --- $('.event_slider').each(function () { $(this).slick({ dots: true, arrows: true, infinite: true, speed: 500, autoplay: true, fade: true, pauseOnFocus: true, pauseOnHover: true, cssEase: 'ease', accessibility: true, }); enhanceSlickAccessibility(this, isEn ? 'Event Slider' : '活動輪播'); }); // --- adSlider (廣告輪播) --- $('.adSlider').each(function () { $(this).slick({ dots: false, // 廣告通常不顯示 dots,若要顯示改 true,程式會自動處理隱藏屬性 infinite: true, speed: 300, slidesToShow: 5, slidesToScroll: 1, autoplay: true, arrows: true, accessibility: true, responsive: [ { breakpoint: 1024, settings: { slidesToShow: 4, slidesToScroll: 4, }, }, { breakpoint: 768, settings: { slidesToShow: 3, slidesToScroll: 3, }, }, { breakpoint: 575, settings: { slidesToShow: 2, slidesToScroll: 2, }, }, ], }); enhanceSlickAccessibility(this, isEn ? 'Ad Slider' : '廣告輪播'); }); }); //燈箱slick+lightBox組合 $('.cp_slider').slick({ dots: true, infinite: true, speed: 500, slidesToShow: 4, slidesToScroll: 1, autoplay: false, autoplaySpeed: 1500, pauseOnHover: true, pauseOnFocus: true, focusOnSelect: true, accessibility: true, responsive: [ { breakpoint: 768, settings: { slidesToShow: 2, slidesToScroll: 2, infinite: true, dots: true, }, }, { breakpoint: 545, settings: { arrows: true, slidesToShow: 2, slidesToScroll: 2, }, }, { breakpoint: 480, settings: { arrows: true, slidesToShow: 1, slidesToScroll: 1, arrows: false, }, }, ], }); $('.cp_slider').slickLightbox({ caption: 'caption', useHistoryApi: 'true', lazy: true, }); // 相簿內容頁面專用 $('.Slider-for').on('init reInit afterChange', function (event, slick, currentSlide) { var i = (currentSlide ? currentSlide : 0) + 1; $('.controls').html(i + '/' + slick.slideCount); }); $('.Slider-for').slick({ slidesToShow: 1, slidesToScroll: 1, arrows: true, fade: true, asNavFor: '.Slider-nav', autoplay: true, autoplaySpeed: 2000, infinite: true, }); $('.Slider-nav').slick({ slidesToShow: 3, slidesToScroll: 1, asNavFor: '.Slider-for', dots: true, arrows: true, focusOnSelect: true, infinite: true, }); //不同語系 var weblang = $('html').attr('lang'); if (weblang.substring(0, 2) == 'zh') { // console.log("中文"); $('.slick-prev').attr('title', '上一筆'); $('.slick-next').attr('title', '下一筆'); $('header').find('.accesskey').attr('title', '上方功能區塊'); $('.main').find('.accesskey').attr('title', '中央內容區塊'); $('footer').find('.accesskey').attr('title', '下方功能區塊'); $('.search').find('.accesskey').attr('title', '關鍵字搜尋:文章關鍵字搜尋'); } else if (weblang.substring(0, 2) == 'en') { // console.log("英文"); $('.slick-prev').attr('title', 'previous'); $('.slick-next').attr('title', 'next'); $('header').find('.accesskey').attr('title', 'header'); $('.main').find('.accesskey').attr('title', 'content'); $('footer').find('.accesskey').attr('title', 'footer'); $('.search').find('.accesskey').attr('title', 'search'); } else if (weblang.substring(0, 2) == 'vi') { // console.log("越南"); $('.slick-prev').attr('title', 'Trước'); $('.slick-next').attr('title', 'kế tiếp'); } else if (weblang.substring(0, 2) == 'id') { // console.log("印尼"); $('.slick-prev').attr('title', 'sebelumnya'); $('.slick-next').attr('title', 'berikutnya'); } else if (weblang.substring(0, 2) == 'km') { // console.log("柬埔寨"); $('.slick-prev').attr('title', 'មុន'); $('.slick-next').attr('title', 'បន្ទាប់'); } else if (weblang.substring(0, 2) == 'th') { // console.log("泰文"); $('.slick-prev').attr('title', 'ก่อน'); $('.slick-next').attr('title', 'ต่อไป'); } else { // console.log("沒有判斷"); $('.slick-prev').attr('title', 'previous'); $('.slick-next').attr('title', 'next'); $('.slick-prev').attr('title', '上一筆'); $('.slick-next').attr('title', '下一筆'); $('header').find('.accesskey').attr('title', '上方功能區塊'); $('.main').find('.accesskey').attr('title', '中央內容區塊'); $('footer').find('.accesskey').attr('title', '下方功能區塊'); $('.search').find('.accesskey').attr('title', '關鍵字搜尋:文章關鍵字搜尋'); } }); /*------------------------------------------------*/ ///////////// 修正表單無障礙 (WCAG 3.3.2) ///////////// /*------------------------------------------------*/ $(document).ready(function () { $('input[placeholder], textarea[placeholder]').each(function () { var pText = $(this).attr('placeholder'); if (!$(this).attr('aria-label')) { $(this).attr('aria-label', pText); } }); $('label[for]').each(function () { var targetId = $(this).attr('for'); var $input = $(this).siblings('input, textarea'); if ($input.length > 0 && !$input.attr('id')) { $input.attr('id', targetId); } }); }); // tab順序 document.addEventListener('DOMContentLoaded', function () { // ------------------------------------------------------------------------- // 1. 定義 DOM 元素 (根據您的描述假設 class 名稱,請依實際 HTML 調整) // ------------------------------------------------------------------------- const h1 = document.querySelector('h1 a'); // 搜尋相關 const searchCtrl = document.querySelector('.searchCtrl'); const mSearch = document.querySelector('.m_search'); // 搜尋區塊容器 const mSearchInput = mSearch ? mSearch.querySelector('input') : null; // 側邊欄相關 const sidebarCtrl = document.querySelector('.sidebarCtrl'); const sidebar = document.querySelector('.sidebar'); const sidebarClose = document.querySelector('.sidebarClose'); // 側邊欄內的關閉按鈕 // ------------------------------------------------------------------------- // 2. 初始化設定 (H1 可聚焦 & ARIA 屬性) // ------------------------------------------------------------------------- // if (h1) { // h1.setAttribute('tabindex', '4'); // 讓 H1 可以被 Tab 選中 // // 確保 H1 是順序上的優先項目,通常放在 HTML 結構最前即可 // } // 初始化 ARIA 狀態 // if (searchCtrl) searchCtrl.setAttribute('aria-expanded', 'false'); // if (sidebarCtrl) sidebarCtrl.setAttribute('aria-expanded', 'false'); // ------------------------------------------------------------------------- // 3. 搜尋區塊邏輯 (m_search) // ------------------------------------------------------------------------- if (searchCtrl && mSearch) { // 點擊或 Enter 開啟搜尋 searchCtrl.addEventListener('click', function (e) { e.preventDefault(); toggleSearch(true); }); // 取得搜尋區塊內所有可聚焦元素 const searchFocusables = mSearch.querySelectorAll('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])'); if (searchFocusables.length > 0) { const lastSearchItem = searchFocusables[searchFocusables.length - 1]; // 監聽最後一個項目的 Tab 事件 lastSearchItem.addEventListener('keydown', function (e) { if (e.key === 'Tab' && !e.shiftKey) { // 如果是 Tab (非 Shift+Tab),收合搜尋並回到按鈕 e.preventDefault(); toggleSearch(false); searchCtrl.focus(); // 焦點還給按鈕 } }); } } function toggleSearch(show) { if (show) { mSearch.classList.add('open'); // 假設 open class 控制顯示 searchCtrl.setAttribute('aria-expanded', 'true'); if (mSearchInput) mSearchInput.focus(); // 展開後焦點跳到 input } else { mSearch.classList.remove('open'); searchCtrl.setAttribute('aria-expanded', 'false'); } } // ------------------------------------------------------------------------- // 4. 側邊欄邏輯 (Sidebar) - 包含特殊循環需求 // ------------------------------------------------------------------------- if (sidebarCtrl && sidebar && sidebarClose) { // 用來判斷是否已經完成了一次「選單循環」 let sidebarExitReady = false; // 開啟側邊欄 sidebarCtrl.addEventListener('click', function (e) { e.preventDefault(); openSidebar(); }); // 關閉按鈕本身的點擊事件 (滑鼠或 Enter) sidebarClose.addEventListener('click', function (e) { e.preventDefault(); closeSidebar(); sidebarCtrl.focus(); }); // 取得側邊欄內所有可聚焦元素 (選單項目) // 這裡假設選單項目在 sidebarClose 之後 const sidebarFocusables = sidebar.querySelectorAll('a, button, input, [tabindex]:not([tabindex="-1"])'); // 過濾掉 sidebarClose 本身,找出最後一個選單項目 let menuItems = Array.from(sidebarFocusables).filter((el) => el !== sidebarClose); let lastMenuItem = menuItems.length > 0 ? menuItems[menuItems.length - 1] : null; // --- 邏輯 A: 關閉按鈕的 Tab 行為 --- sidebarClose.addEventListener('keydown', function (e) { if (e.key === 'Tab' && !e.shiftKey) { // 如果是 Tab 鍵 if (sidebarExitReady) { // 如果已經從下面繞回來了,再次按 Tab 則收合並離開 e.preventDefault(); closeSidebar(); sidebarCtrl.focus(); // 回到觸發按鈕,使用者再按一下 Tab 就會到「下一個項目」 } else { // 如果是剛打開,保持預設行為 (往下聚焦到第一個選單 li) // 這裡不需要 preventDefault } } else if (e.key === 'Tab' && e.shiftKey) { // Shift+Tab 往回 (離開 Sidebar 回到上一層),重置狀態 sidebarExitReady = false; } }); // --- 邏輯 B: 最後一個選單項目的 Tab 行為 --- if (lastMenuItem) { lastMenuItem.addEventListener('keydown', function (e) { if (e.key === 'Tab' && !e.shiftKey) { // 在最後一項按 Tab -> 跳回 Close 按鈕 e.preventDefault(); sidebarClose.focus(); // **關鍵**: 設定標記,告訴 Close 按鈕「下次按 Tab 要關閉選單」 sidebarExitReady = true; } }); } // 輔助函式:開啟 function openSidebar() { sidebar.classList.add('open'); sidebarCtrl.setAttribute('aria-expanded', 'true'); sidebarClose.focus(); // 依需求:先跳到 sidebarClose sidebarExitReady = false; // 重置狀態:剛進來時按 Tab 應該是要進入選單 } // 輔助函式:關閉 function closeSidebar() { sidebar.classList.remove('open'); sidebarCtrl.setAttribute('aria-expanded', 'false'); sidebarExitReady = false; } // 監聽 Esc 鍵 (無障礙通用規範) sidebar.addEventListener('keydown', function (e) { if (e.key === 'Escape') { closeSidebar(); sidebarCtrl.focus(); } }); } }); // 手機版searchCtrl // $(function () { // var _searchCtrl = $('.searchCtrl'); // var _mSearch = $('.m_search'); // // 抓取搜尋區塊內最後一個可聚焦的元素 (這裡是 submit input) // var _lastFocusItem = _mSearch.find('input[type="submit"], button').last(); // var search_mode = false; // // 初始化無障礙屬性 (因不可修改 HTML,故由 JS 動態加入) // _searchCtrl.attr('aria-expanded', 'false'); // // 開啟搜尋功能的函式 // function openSearch() { // _mSearch.stop(true, false).slideDown('400', 'easeOutQuint', function () { // // 動畫結束後,將焦點移至第一個輸入框 // $(this).find('input[type="text"]').first().focus(); // }); // _searchCtrl.attr('aria-expanded', 'true'); // search_mode = true; // } // // 關閉搜尋功能的函式 // function closeSearch() { // _mSearch.stop(true, false).slideUp('400', 'easeOutQuint'); // _searchCtrl.attr('aria-expanded', 'false'); // // 關閉後,焦點必須回到原本的觸發按鈕,符合 WCAG 路徑邏輯 // _searchCtrl.focus(); // search_mode = false; // } // // 觸發按鈕點擊事件 (包含鍵盤 Enter/Space 觸發) // _searchCtrl.off().on('click', function (e) { // e.preventDefault(); // if (!search_mode) { // openSearch(); // } else { // closeSearch(); // } // }); // // 監聽最後一個項目的鍵盤事件 (關鍵修改) // _lastFocusItem.on('keydown', function (e) { // // 如果按下的是 Tab 鍵 (keyCode 9) 且沒有按 Shift (表示是往下 Tab) // if (e.which === 9 && !e.shiftKey) { // e.preventDefault(); // 阻止瀏覽器預設跳到下一個未知元素的行為 // closeSearch(); // 收合選單並將焦點帶回 searchCtrl // } // }); // // ESC 鍵關閉 (WCAG 建議:提供 ESC 關閉浮動視窗的功能) // _mSearch.on('keydown', function (e) { // if (e.which === 27) { // // ESC // closeSearch(); // } // }); // // 點擊外部區域關閉 (維持原有邏輯) // $('.main') // .off() // .on('click touchend', function (e) { // // 確保點擊的不是 searchCtrl 或 m_search 內部才關閉 // if (!_searchCtrl.is(e.target) && _searchCtrl.has(e.target).length === 0 && !_mSearch.is(e.target) && _mSearch.has(e.target).length === 0 && search_mode) { // closeSearch(); // } // }); // }); $(function () { var _searchCtrl = $('.searchCtrl'); // 搜尋開關按鈕 var _mSearch = $('.m_search'); // 搜尋容器 var search_mode = false; _searchCtrl.attr('aria-expanded', 'false'); // 更新焦點清單的函式 (包含所有 input, button 和 keywordHot 內的 a) function getFocusableItems() { return _mSearch.find('input, button, a').filter(':visible'); } function openSearch() { _mSearch.stop(true, false).slideDown('400', 'easeOutQuint', function () { // 開啟後,焦點移至第一個輸入框 getFocusableItems().first().focus(); }); _searchCtrl.attr('aria-expanded', 'true'); search_mode = true; } function closeSearch(backToCtrl) { _mSearch.stop(true, false).slideUp('400', 'easeOutQuint'); _searchCtrl.attr('aria-expanded', 'false'); if (backToCtrl) { _searchCtrl.focus(); } search_mode = false; } // 1. 處理搜尋按鈕 (searchCtrl) 的 Tab 行為 _searchCtrl.on('keydown', function (e) { if (search_mode && e.which === 9) { // 如果選單已開啟且按下 Tab if (!e.shiftKey) { // [正向 Tab]: 從開關跳出,關閉選單,讓焦點自然移到下一個區塊 (內容區) closeSearch(false); } else { // [反向 Shift+Tab]: 回到搜尋區塊內的最後一個連結 e.preventDefault(); getFocusableItems().last().focus(); } } }); // 點擊觸發 _searchCtrl.off('click').on('click', function (e) { e.preventDefault(); if (!search_mode) { openSearch(); } else { closeSearch(true); } }); // 2. 處理搜尋區塊內部 (m_search) 的鍵盤邏輯 _mSearch.on('keydown', function (e) { var _focusable = getFocusableItems(); var _firstItem = _focusable.first(); var _lastItem = _focusable.last(); if (e.which === 9) { // 按下 Tab if (e.shiftKey) { // [反向 Shift+Tab] if (document.activeElement === _firstItem[0]) { e.preventDefault(); _searchCtrl.focus(); // 從第一個元素往回跳到開關 } } else { // [正向 Tab] if (document.activeElement === _lastItem[0]) { e.preventDefault(); _searchCtrl.focus(); // 從最後一個連結跳回開關 } } } if (e.which === 27) { // ESC 鍵 closeSearch(true); } }); // 點擊外部關閉 $('.main').on('click touchend', function (e) { if (!_searchCtrl.is(e.target) && _searchCtrl.has(e.target).length === 0 && !_mSearch.is(e.target) && _mSearch.has(e.target).length === 0 && search_mode) { closeSearch(false); } }); }); // 手機版漢堡選單 // $(function () { // var _sidebar = $('.sidebar'); // var _sidebarCtrl = $('.sidebarCtrl'); // var _mArea = $('.m_area'); // var _sidebarClose = $('.sidebarClose'); // var sidebar_mode = false; // // 初始化 ARIA // _sidebarCtrl.attr('aria-expanded', 'false'); // // 開啟側欄 // function openSidebar() { // _sidebar.show(); // // 這裡假設是移動 margin-left 或是直接顯示,依據原本 CSS 邏輯 // _mArea.show().css('display', 'block'); // 確保容器可見 // _mArea.stop(true, false).animate({ marginLeft: 0 }, 400, 'easeOutQuint', function () { // // 動畫結束後,焦點移至選單的第一個連結,這樣才能「往下 Tab」 // // 若找不到任何連結,則直接聚焦在關閉按鈕 // var firstItem = _mArea.find('a[href], input, button').not('.sidebarClose').first(); // if (firstItem.length) { // firstItem.focus(); // } else { // _sidebarClose.focus(); // } // }); // _sidebarCtrl.attr('aria-expanded', 'true'); // sidebar_mode = true; // } // // 關閉側欄 // function closeSidebar() { // // 假設隱藏是移出畫面或 hide // _mArea.stop(true, false).animate({ marginLeft: '-280px' }, 400, 'easeOutQuint', function () { // _mArea.hide(); // _sidebar.hide(); // }); // _sidebarCtrl.attr('aria-expanded', 'false'); // _sidebarCtrl.focus(); // 焦點回歸觸發按鈕 // sidebar_mode = false; // } // // 觸發按鈕點擊 // _sidebarCtrl.off().on('click', function (e) { // e.preventDefault(); // if (!sidebar_mode) { // openSidebar(); // } else { // closeSidebar(); // } // }); // // 關閉按鈕點擊 // _sidebarClose.off().on('click', function (e) { // closeSidebar(); // }); // // 關鍵邏輯:在 Close 按鈕上按 Tab 離開時收合 // _sidebarClose.on('keydown', function (e) { // // 按下 Tab (keyCode 9) 且沒有按 Shift (代表是順向 Tab 離開) // if (e.which === 9 && !e.shiftKey) { // e.preventDefault(); // 阻止瀏覽器預設跳轉 // closeSidebar(); // 執行關閉 // } // }); // // ESC 鍵關閉支援 // _sidebar.on('keydown', function (e) { // if (e.which === 27) { // // ESC // closeSidebar(); // } // }); // // 點擊遮罩層 (sidebar 本體) 關閉 // _sidebar.off().on('click', function (e) { // // 確保點擊的不是 m_area 內部的東西 // if ($(e.target).is(_sidebar) && !_mArea.is(e.target) && _mArea.has(e.target).length === 0) { // closeSidebar(); // } // }); // }); // 手機版漢堡選單 $(function () { var _sidebar = $('.sidebar'); var _sidebarCtrl = $('.sidebarCtrl'); var _mArea = $('.m_area'); var _sidebarClose = $('.sidebarClose'); var sidebar_mode = false; var justOpened = false; _sidebarCtrl.attr('aria-expanded', 'false'); // 開啟側欄 function openSidebar() { _sidebar.show(); _mArea.show().css('display', 'block'); justOpened = true; // 設定狀態:剛打開 _mArea.stop(true, false).animate({ marginLeft: 0 }, 400, 'easeOutQuint', function () { // 確保抓取畫面上第一個關閉按鈕 _sidebarClose.first().focus(); }); _sidebarCtrl.attr('aria-expanded', 'true'); sidebar_mode = true; } // 關閉側欄 function closeSidebar() { _mArea.stop(true, false).animate({ marginLeft: '-280px' }, 400, 'easeOutQuint', function () { _mArea.hide(); _sidebar.hide(); }); _sidebarCtrl.attr('aria-expanded', 'false'); _sidebarCtrl.focus(); sidebar_mode = false; justOpened = false; } // 觸發按鈕點擊 _sidebarCtrl.off('click').on('click', function (e) { e.preventDefault(); if (!sidebar_mode) { openSidebar(); } else { closeSidebar(); } }); // 關閉按鈕點擊 _sidebarClose.off('click').on('click', function (e) { closeSidebar(); }); _sidebar.off('keydown').on('keydown', function (e) { if (e.which === 27) { // ESC 鍵 closeSidebar(); return; } if (e.which === 9) { // Tab 鍵 var focusables = _mArea.find('a[href], input, button, select, textarea, [tabindex]:not([tabindex="-1"])').filter(':visible'); if (focusables.length === 0) return; var closeBtn = focusables.filter('.sidebarClose')[0] || _sidebarClose[0]; var menuItems = focusables.not('.sidebarClose'); var firstItem = menuItems.length > 0 ? menuItems[0] : null; var lastItem = menuItems.length > 0 ? menuItems[menuItems.length - 1] : null; var activeEl = document.activeElement; if (!e.shiftKey) { // 【順向 Tab 往下跳】 if (activeEl === closeBtn) { if (justOpened) { // 剛打開時,從關閉按鈕 -> 跳到第一個選單項目 e.preventDefault(); justOpened = false; if (firstItem) firstItem.focus(); } else { // 已經繞完一圈回來時,在關閉按鈕按 Tab -> 執行關閉 e.preventDefault(); closeSidebar(); } } else if (activeEl === lastItem) { // 在最後一個選單項目時 -> 強制阻斷預設行為,跳回關閉按鈕! e.preventDefault(); if (closeBtn) closeBtn.focus(); } } else { // 【逆向 Shift + Tab 往回跳】 if (activeEl === closeBtn) { // 在關閉按鈕往回跳 -> 跳到最後一個選單項目 e.preventDefault(); justOpened = false; if (lastItem) lastItem.focus(); } else if (activeEl === firstItem) { // 在第一個選單項目往回跳 -> 退回關閉按鈕,並重新設定為剛打開狀態 e.preventDefault(); justOpened = true; if (closeBtn) closeBtn.focus(); } } } }); // 點擊遮罩層關閉 _sidebar.off('click').on('click', function (e) { if ($(e.target).is(_sidebar) && !_mArea.is(e.target) && _mArea.has(e.target).length === 0) { closeSidebar(); } }); });