From 68a0f1fe2e4907b09797befbb6afe670974351ca Mon Sep 17 00:00:00 2001 From: ken Date: Wed, 24 Jun 2026 19:14:48 +0800 Subject: [PATCH] js --- assets/javascripts/app.js | 593 +++++++++++++++++++++++--------------- 1 file changed, 365 insertions(+), 228 deletions(-) diff --git a/assets/javascripts/app.js b/assets/javascripts/app.js index a2b1076..0186583 100644 --- a/assets/javascripts/app.js +++ b/assets/javascripts/app.js @@ -630,7 +630,7 @@ } }); if (document.documentElement.lang === 'zh_tw') { - document.documentElement.lang = 'zh-Hant-TW'; + document.documentElement.lang = 'zh-Hant'; } //tab鍵按下 $(document).on('keydown', function(e) { @@ -924,6 +924,15 @@ // 有連結目的之所有a標籤的無障礙處理 $(function() { + // Bootstrap 會把原始 title 搬到 data-bs-original-title,先還原回來 + $('a[data-bs-original-title]').each(function() { + var $a = $(this); + var originalTitle = $a.attr('data-bs-original-title'); + if (originalTitle && originalTitle.trim() !== '') { + $a.attr('title', originalTitle); + } + }); + /** * 全站無障礙 AA 級補強 (整合 HM1240400C 與 HM1240401C 規範) */ @@ -937,13 +946,13 @@ $(function() { //├─ 文字是路徑/空 → 補隱藏 span //├─ 圖片+文字共存 → 圖片 alt 清空 //├─ 無 title → 自動產出 title - //├─ 有 title 但與連結文字重複 → 只保留開窗提示 + //├─ 有 title 但與連結文字或圖片 alt 重複 → 只保留開窗提示 //├─ 有 title 出現空括號 () → 清除並補上正確開窗提示 //└─ 移除 aria-label var urlParams = new URLSearchParams(window.location.search); var isEditMode = urlParams.get('editmode') === 'on'; - var pageLang = $('html').attr('lang') || 'zh-Hant-TW'; + var pageLang = $('html').attr('lang') || 'zh-Hant'; var isEn = pageLang.toLowerCase().startsWith('en'); var i18n = { @@ -983,6 +992,9 @@ $(function() { var $img = $a.find('img'); var $icons = $a.find('i, svg'); var currentTitle = ($a.attr('title') || '').trim(); + + // ✅ 在 D 區塊清空 alt 之前,先記錄圖片原始 alt + var imgAltOriginal = $img.length > 0 ? ($img.attr('alt') || '').trim() : ''; // --- 【修正 1:隱藏空連結】 --- if (!isEditMode && linkText === "" && $img.length === 0 && $icons.length === 0) { @@ -1100,13 +1112,10 @@ $(function() { .replace('另開新視窗', '') .trim(); - // ✅ 取得圖片原始 alt(D 區塊清空前的值) - var imgAltOriginal = $img.length > 0 ? ($img.data('originalAlt') || $img.attr('alt') || '').trim() : ''; - - // ✅ 修正:title 去掉開窗字串後,若與連結文字或圖片 alt 相同,則只保留開窗提示 + // ✅ title 去掉開窗字串後,若與連結文字或圖片原始 alt 相同,則只保留開窗提示 if ( (titleWithoutWindow === linkText && linkText !== i18n.link) || - (imgAltOriginal !== '' && titleWithoutWindow === imgAltOriginal) // ✅ 新增:與圖片 alt 重複也觸發 + (imgAltOriginal !== '' && titleWithoutWindow === imgAltOriginal) ) { $a.attr('title', windowTask); } @@ -1122,12 +1131,29 @@ $(function() { // F. 最終清理:移除冗餘 label,避免螢幕閱讀器唸兩次 $a.removeAttr('aria-label'); }); + + // ✅ G. 補強特定連結(須在迴圈外,因為 javascript: 連結被迴圈跳過) + $('.btn-o a').each(function() { + var $a = $(this); + if (!$a.attr('target')) { + $a.attr('target', '_blank'); + $a.attr('rel', 'noopener noreferrer'); + } + $a.attr('title', isEn ? 'Share to X Open in new window' : '分享至 X 在新視窗開啟'); + }); + + $('.print-button a').each(function() { + var $a = $(this); + if (!$a.attr('title') || $a.attr('title').trim().toLowerCase() === 'print') { + $a.attr('title', isEn ? 'Print this page' : '列印此頁'); + } + }); + $('a.i-archive__file-name').each(function () { var $a = $(this); var isNewWindow = ($a.attr('target') === '_blank'); $a.attr('title', isNewWindow ? i18n.newWin : i18n.selfWin); }); - } // ✅ 延遲 800ms 確保所有其他 function 執行完畢後才處理 @@ -1136,103 +1162,133 @@ $(function() { }, 800); }); - // if (location.href.search('editmode=on') === -1) { - // // 1. 處理圖片 alt 重複問題 (保持原邏輯但優化) - // $('a').has('img').each(function () { - // const $link = $(this); - // const linkText = $link.text().trim(); + +$(function() { + function smartFixIcons() { + var isEn = $('html').attr('lang') === 'en'; - // $link.find('img').each(function () { - // const $img = $(this); - // const altText = $img.attr('alt')?.trim(); + var labels = { + calendar : isEn ? 'Date: ' : '日期:', + user : isEn ? 'Author: ' : '發布者:', + tag : isEn ? 'Tag: ' : '標籤:', + clock : isEn ? 'Time: ' : '時間:', + location : isEn ? 'Location: ' : '地點:', + phone : isEn ? 'Phone: ' : '電話:', + envelope : isEn ? 'Email: ' : '信箱:', + folder : isEn ? 'Category: ' : '分類:', + eye : isEn ? 'Views: ' : '瀏覽次數:', + download : isEn ? 'Download: ' : '下載檔案:', + search : isEn ? 'Search' : '搜尋', + bars : isEn ? 'Menu' : '選單', + print : isEn ? 'Print this page' : '列印此頁', + share : isEn ? 'Share' : '分享至社群', + close : isEn ? 'Close window' : '關閉視窗', + closePopup : isEn ? 'Close announcement' : '關閉公告視窗', + closeGallery: isEn ? 'Close gallery' : '關閉相簿', + toggleDesc : isEn ? 'Show or hide image description' : '顯示或隱藏圖片說明', + themeSwitch : isEn ? 'Switch gallery theme': '切換相簿主題', + showOriginal: isEn ? 'Show original image' : '顯示原始圖片' + }; - // if (altText && altText === linkText) { - // $img.attr('alt', ''); - // } - // }); - // }); - // } - $(function() { - function smartFixIcons() { - var isEn = $('html').attr('lang') === 'en'; + $('i').each(function() { + var $icon = $(this); + var $parent = $icon.parent(); - var labels = { - calendar : isEn ? 'Date: ' : '日期:', - user : isEn ? 'Author: ' : '發布者:', - tag : isEn ? 'Tag: ' : '標籤:', - clock : isEn ? 'Time: ' : '時間:', - location : isEn ? 'Location: ' : '地點:', - phone : isEn ? 'Phone: ' : '電話:', - envelope : isEn ? 'Email: ' : '信箱:', - folder : isEn ? 'Category: ' : '分類:', - eye : isEn ? 'Views: ' : '瀏覽次數:', - download : isEn ? 'Download: ' : '下載檔案:', - search : isEn ? 'Search' : '搜尋', - bars : isEn ? 'Menu' : '選單', - print : isEn ? 'Print this page': '列印此頁', - share : isEn ? 'Share' : '分享至社群', - close : isEn ? 'Close' : '關閉視窗' - }; + // 1. 所有圖示先對螢幕閱讀器隱藏 + $icon.attr('aria-hidden', 'true'); - $('i').each(function() { - var $icon = $(this); - var $parent = $icon.parent(); - - // 1. 所有圖示先對螢幕閱讀器隱藏 - $icon.attr('aria-hidden', 'true'); - - // 特判:.close-screen-btn 內的圖示,移除無關的 sr-only 並設正確 aria-label - if ($parent.hasClass('close-screen-btn')) { - $parent.find('.sr-only').remove(); - $parent.attr('aria-label', '關閉公告視窗'); - return; + // 特判:.close-screen-btn 內的圖示,移除無關的 sr-only 並設正確 aria-label + if ($parent.hasClass('close-screen-btn')) { + $parent.find('.sr-only').remove(); + $parent.attr('aria-label', labels.closePopup); + if ($icon.next('.sr-only').length === 0) { + $icon.after('' + labels.closePopup + ''); } + return; + } - // 2. 已有 aria-label 或 sr-only 就不重複處理 - if ($icon.attr('aria-label') || $icon.next('.sr-only').length > 0 || $parent.find('.sr-only').length > 0) { - return; + // 特判:.gallery-close 內的圖示,移除錯誤的 sr-only 並補正確說明 + if ($parent.closest('.gallery-close').length > 0) { + $parent.closest('.gallery-close').find('.sr-only').remove(); + $parent.closest('.gallery-close').attr('aria-label', labels.closeGallery); + $parent.closest('.gallery-close').attr('role', 'button'); + $parent.closest('.gallery-close').attr('tabindex', '0'); + if ($icon.next('.sr-only').length === 0) { + $icon.after('' + labels.closeGallery + ''); } + return; + } - var cls = ($icon.attr('class') || '').toLowerCase(); - var labelText = ''; - - // --- 策略 A:常見資訊型圖示 --- - if (cls.includes('calendar')) labelText = labels.calendar; - else if (cls.includes('user') || cls.includes('male')) labelText = labels.user; - else if (cls.includes('tag')) labelText = labels.tag; - else if (cls.includes('clock') || cls.includes('time')) labelText = labels.clock; - else if (cls.includes('map-marker') || cls.includes('location')) labelText = labels.location; - else if (cls.includes('phone')) labelText = labels.phone; - else if (cls.includes('envelope') || cls.includes('mail')) labelText = labels.envelope; - else if (cls.includes('folder')) labelText = labels.folder; - else if (cls.includes('eye')) labelText = labels.eye; - else if (cls.includes('download')) labelText = labels.download; - - // --- 策略 B:功能性按鈕 --- - var $container = $icon.closest('a, button'); - if ($container.length > 0 && $container.text().trim() === '') { - var btnTitle = $container.attr('title'); - if (btnTitle) labelText = btnTitle; - else if (cls.includes('search')) labelText = labels.search; - else if (cls.includes('bars') || cls.includes('navicon')) labelText = labels.bars; - else if (cls.includes('print')) labelText = labels.print; - else if (cls.includes('share')) labelText = labels.share; - else if (cls.includes('close') || cls.includes('times')) labelText = labels.close; + // 特判:.gallery-toggle-desc 補說明 + if ($parent.closest('.gallery-toggle-desc').length > 0) { + var $toggleBtn = $parent.closest('.gallery-toggle-desc'); + if (!$toggleBtn.attr('aria-label')) { + $toggleBtn.attr('aria-label', labels.toggleDesc); + $toggleBtn.attr('role', 'button'); + $toggleBtn.attr('tabindex', '0'); } - - // --- 3. 執行補強 --- - if (labelText !== '') { - if ($container.length > 0 && $container.text().trim() === '') { - $container.attr('aria-label', labelText); - } else { - $icon.after('' + labelText + ''); - } + if ($icon.next('.sr-only').length === 0) { + $icon.after('' + labels.toggleDesc + ''); } - }); - } + return; + } - setTimeout(smartFixIcons, 500); - }); + // 特判:.gallery-theme-switch 補說明 + if ($parent.closest('.gallery-theme-switch').length > 0) { + var $themeBtn = $parent.closest('.gallery-theme-switch'); + if (!$themeBtn.attr('aria-label')) { + $themeBtn.attr('aria-label', labels.themeSwitch); + $themeBtn.attr('role', 'button'); + $themeBtn.attr('tabindex', '0'); + } + if ($icon.next('.sr-only').length === 0) { + $icon.after('' + labels.themeSwitch + ''); + } + return; + } + + // 2. 已有 aria-label 或 sr-only 就不重複處理 + if ($icon.attr('aria-label') || $icon.next('.sr-only').length > 0 || $parent.find('.sr-only').length > 0) { + return; + } + + var cls = ($icon.attr('class') || '').toLowerCase(); + var labelText = ''; + + // --- 策略 A:常見資訊型圖示 --- + if (cls.includes('calendar')) labelText = labels.calendar; + else if (cls.includes('user') || cls.includes('male')) labelText = labels.user; + else if (cls.includes('tag')) labelText = labels.tag; + else if (cls.includes('clock') || cls.includes('time')) labelText = labels.clock; + else if (cls.includes('map-marker') || cls.includes('location')) labelText = labels.location; + else if (cls.includes('phone')) labelText = labels.phone; + else if (cls.includes('envelope') || cls.includes('mail')) labelText = labels.envelope; + else if (cls.includes('folder')) labelText = labels.folder; + else if (cls.includes('eye')) labelText = labels.eye; + else if (cls.includes('download')) labelText = labels.download; + + // --- 策略 B:功能性按鈕 --- + var $container = $icon.closest('a, button'); + if ($container.length > 0 && $container.text().trim() === '') { + var btnTitle = $container.attr('title'); + if (btnTitle) labelText = btnTitle; + else if (cls.includes('search')) labelText = labels.search; + else if (cls.includes('bars') || cls.includes('navicon')) labelText = labels.bars; + else if (cls.includes('print')) labelText = labels.print; + else if (cls.includes('share')) labelText = labels.share; + else if (cls.includes('close') || cls.includes('times')) labelText = labels.close; + else if (cls.includes('image') || cls.includes('photo')) labelText = labels.showOriginal; + } + + // --- 3. 執行補強 --- + if (labelText !== '') { + $icon.after('' + labelText + ''); + } + }); + } + + setTimeout(smartFixIcons, 500); +}); // 刪除banner-slide的空連結和空連結目標 for(var i=0;i<$('.w-ba-banner__slide a').length;i++){ if($('.w-ba-banner__slide a').eq(i).attr('href')=="") @@ -1457,92 +1513,7 @@ $(function() { resizeTimer = setTimeout(fixAccessKeyM, 150); }); }); - //公告頁籤無障礙 - $(function() { - function fixTabLinearOrder() { - // 只處理內部含有 .tab_nav 的 .w-annc - var $targetAnnc = $('.w-annc').filter(function() { - return $(this).find('.tab_nav').length > 0; - }); - // 若頁面上沒有符合條件的 .w-annc,直接離開 - if ($targetAnnc.length === 0) return; - - var $tabs = $targetAnnc.find('.filter_tab'); - var $anncList = $targetAnnc.find('.w-annc__list'); - - // --- 1. 順向遊走:標籤 -> 對應內容 --- - $tabs.on('keydown', function(e) { - if (e.which === 9 && !e.shiftKey) { - var category = $(this).data('category'); - var $scope = $(this).closest('.w-annc'); // 限定在同一個 .w-annc - var $visibleItems = $scope.find('.w-annc__item[data-category="' + category + '"]:visible'); - - if ($visibleItems.length > 0) { - var $firstLink = $visibleItems.find('a').first(); - if ($firstLink.length > 0) { - e.preventDefault(); - $firstLink.focus(); - } - } - } - if (e.which === 13 || e.which === 32) { - e.preventDefault(); - $(this).click(); - } - }); - - // --- 2. 反向遊走:內容 -> 對應標籤 --- - $anncList.on('keydown', '.w-annc__item a', function(e) { - var $currentLink = $(this); - var $currentItem = $currentLink.closest('.w-annc__item'); - var $scope = $currentLink.closest('.w-annc'); // 限定在同一個 .w-annc - var category = $currentItem.data('category'); - var $visibleItems = $scope.find('.w-annc__item[data-category="' + category + '"]:visible'); - - if (e.which === 9 && e.shiftKey) { - if ($currentLink.is($visibleItems.find('a').first())) { - e.preventDefault(); - $scope.find('.filter_tab[data-category="' + category + '"]').focus(); - } - } - - if (e.which === 9 && !e.shiftKey) { - if ($currentLink.is($visibleItems.find('a').last())) { - var $currentTab = $scope.find('.filter_tab[data-category="' + category + '"]'); - var $nextTab = $currentTab.next('.filter_tab'); - if ($nextTab.length > 0) { - e.preventDefault(); - $nextTab.focus(); - $nextTab.click(); - } - } - } - }); - - // --- 3. 反向遊走:標籤 -> 上一個標籤的內容最後一個連結 --- - $tabs.on('keydown', function(e) { - if (e.which === 9 && e.shiftKey) { - var $scope = $(this).closest('.w-annc'); // 限定在同一個 .w-annc - var $prevTab = $(this).prev('.filter_tab'); - if ($prevTab.length > 0) { - var prevCategory = $prevTab.data('category'); - $prevTab.click(); - - var $prevItems = $scope.find('.w-annc__item[data-category="' + prevCategory + '"]:visible'); - var $lastLink = $prevItems.find('a').last(); - - if ($lastLink.length > 0) { - e.preventDefault(); - $lastLink.focus(); - } - } - } - }); - } - - fixTabLinearOrder(); - }); //導覽選單子選單無障礙狀態修正 (支援多層級) function fixNavMenuA11y() { const $navItems = $('#main-nav li'); @@ -1608,62 +1579,222 @@ $(function() { // 延遲執行,確保動態產生的選單也能被補強 setTimeout(fixEmptyHref, 500); }); - //頁籤無障礙 - $(function() { - /** - * 頁籤導覽 (Tab Navigation) 無障礙補強 - * 1. 容器加入 role="tablist" - * 2. 項目加入 role="tab" - * 3. 動態切換 aria-selected="true/false" - * 4. 確保 Enter 鍵可以觸發切換 (針對 tabindex="0" 的優化) - */ - function fixTabAccessibility() { - var $tabNav = $('.tab_nav'); - var $tabs = $tabNav.find('.filter_tab'); +//公告頁籤無障礙 +$(function() { + function fixTabLinearOrder() { + var $targetAnnc = $('.w-annc').filter(function() { + return $(this).find('.tab_nav').length > 0; + }); - // --- 1. 初始化結構語意 --- - $tabNav.attr('role', 'tablist'); + if ($targetAnnc.length === 0) return; - $tabs.each(function() { - var $this = $(this); - var isActive = $this.hasClass('active'); + var $tabs = $targetAnnc.find('.filter_tab'); + var $anncList = $targetAnnc.find('.w-annc__list'); - // 加入頁籤角色與選取狀態 - $this.attr({ - 'role': 'tab', - 'aria-selected': isActive ? 'true' : 'false' - }); - - // 修正 Title:讓使用者知道這是切換頁籤 - var tabName = $this.text().trim(); - $this.attr('title', '切換至 ' + tabName); - }); + // 智慧判斷:偵測 filter_tab 用哪個屬性來分類 + // 優先用 data-tags(若有值),否則用 data-category + function getTabKey($tab) { + var tags = $tab.data('tags'); + if (tags && tags !== '') return { attr: 'data-tags', value: tags }; + var category = $tab.data('category'); + if (category && category !== '') return { attr: 'data-category', value: category }; + return null; + } - // --- 2. 監聽切換事件 (點擊或鍵盤) --- - // 假設原本已有切換邏輯,我們在此「補強」屬性的變更 - $tabs.on('click', function() { - var $clickedTab = $(this); + // 根據 key 找對應的可見 w-annc__item + function getVisibleItems($scope, key) { + if (!key) return $(); + return $scope.find('.w-annc__item[' + key.attr + '="' + key.value + '"]:visible'); + } - // 先將所有頁籤設為未選取 - $tabs.attr('aria-selected', 'false'); + // 根據 w-annc__item 反查對應的 filter_tab + function getTabFromItem($item, $scope) { + var tags = $item.data('tags'); + if (tags && tags !== '') { + var $tab = $scope.find('.filter_tab[data-tags="' + tags + '"]'); + if ($tab.length) return $tab; + } + var category = $item.data('category'); + if (category && category !== '') { + var $tab = $scope.find('.filter_tab[data-category="' + category + '"]'); + if ($tab.length) return $tab; + } + return $(); + } - // 將當前點擊的頁籤設為已選取 - $clickedTab.attr('aria-selected', 'true'); - }); + $tabs.on('keydown', function(e) { + var $scope = $(this).closest('.w-annc'); + var key = getTabKey($(this)); + + // 順向 Tab:頁籤 -> 對應內容第一個連結 + if (e.which === 9 && !e.shiftKey) { + var $visibleItems = getVisibleItems($scope, key); + if ($visibleItems.length > 0) { + var $firstLink = $visibleItems.find('a').first(); + if ($firstLink.length > 0) { + e.preventDefault(); + $firstLink.focus(); + } + } + } + + // 反向 Shift+Tab:頁籤 -> 上一個頁籤的內容最後一個連結 + if (e.which === 9 && e.shiftKey) { + var $prevTab = $(this).prev('.filter_tab'); + if ($prevTab.length > 0) { + var prevKey = getTabKey($prevTab); + $prevTab.click(); + + var $prevItems = getVisibleItems($scope, prevKey); + var $lastLink = $prevItems.find('a').last(); + + if ($lastLink.length > 0) { + e.preventDefault(); + $lastLink.focus(); + } + } + } + + // Enter / Space:切換頁籤並移焦點到內容第一個連結 + if (e.which === 13 || e.which === 32) { + e.preventDefault(); + $(this).click(); + + var $visibleItems = getVisibleItems($scope, key); + var $firstLink = $visibleItems.find('a').first(); + if ($firstLink.length > 0) { + setTimeout(function() { $firstLink.focus(); }, 50); + } + } + }); + + // 反向遊走:內容 -> 對應標籤;Tab 到最後一個連結跳下一個頁籤 + $anncList.on('keydown', '.w-annc__item a', function(e) { + var $currentLink = $(this); + var $currentItem = $currentLink.closest('.w-annc__item'); + var $scope = $currentLink.closest('.w-annc'); + + // 找出當前 item 對應的 filter_tab + var $currentTab = getTabFromItem($currentItem, $scope); + if (!$currentTab.length) return; + + // 找出同類別的所有可見 item + var key = getTabKey($currentTab); + var $visibleItems = getVisibleItems($scope, key); + + // Shift+Tab:若是第一個連結,跳回對應頁籤 + if (e.which === 9 && e.shiftKey) { + if ($currentLink.is($visibleItems.find('a').first())) { + e.preventDefault(); + $currentTab.focus(); + } + } + + // Tab:若是最後一個連結,跳到下一個頁籤並切換 + if (e.which === 9 && !e.shiftKey) { + if ($currentLink.is($visibleItems.find('a').last())) { + var $nextTab = $currentTab.next('.filter_tab'); + if ($nextTab.length > 0) { + e.preventDefault(); + $nextTab.focus(); + $nextTab.click(); + } + } + } + }); + } + + setTimeout(fixTabLinearOrder, 500); +}); + +//頁籤無障礙 +$(function () { + function fixTabAccessibility() { + + // 各自獨立處理每組 .tab_nav,避免多組時跨區塊操作問題 + $('.tab_nav').each(function() { + var $tabNav = $(this); + var $tabs = $tabNav.find('li'); + + // --- 1. 初始化結構語意 --- + $tabNav.attr('role', 'tablist'); + + $tabs.each(function () { + var $this = $(this); + var isActive = $this.hasClass('active'); + + $this.attr({ + 'role': 'tab', + 'aria-selected': isActive ? 'true' : 'false', + 'tabindex': isActive ? '0' : '-1' + }); + + var tabName = $this.text().trim(); + $this.attr('title', '切換至 ' + tabName); + }); + + // --- 2. 點擊事件:更新 aria-selected 與 tabindex --- + $tabs.on('click', function () { + var $clickedTab = $(this); + + $tabs.attr('aria-selected', 'false').attr('tabindex', '-1'); + $clickedTab.attr('aria-selected', 'true').attr('tabindex', '0'); + }); + + // --- 3. 鍵盤操作補強 --- + $tabs.on('keydown', function (e) { + var $current = $(this); + var currentIndex = $tabs.index($current); + var lastIndex = $tabs.length - 1; + var $target = null; + + switch (e.which) { + case 13: // Enter + case 32: // Space + e.preventDefault(); + $current.trigger('click'); + break; + + case 37: // ← 左方向鍵:移到前一個頁籤 + case 38: // ↑ 上方向鍵 + e.preventDefault(); + $target = currentIndex > 0 + ? $tabs.eq(currentIndex - 1) + : $tabs.eq(lastIndex); + break; + + case 39: // → 右方向鍵:移到下一個頁籤 + case 40: // ↓ 下方向鍵 + e.preventDefault(); + $target = currentIndex < lastIndex + ? $tabs.eq(currentIndex + 1) + : $tabs.eq(0); + break; + + case 36: // Home:跳到第一個頁籤 + e.preventDefault(); + $target = $tabs.eq(0); + break; + + case 35: // End:跳到最後一個頁籤 + e.preventDefault(); + $target = $tabs.eq(lastIndex); + break; + } + + // 移動焦點並觸發點擊切換 + if ($target && $target.length) { + $tabs.attr('tabindex', '-1'); + $target.attr('tabindex', '0').focus().trigger('click'); + } + }); + }); + } + + setTimeout(fixTabAccessibility, 500); +}); - // --- 3. 鍵盤操作補強 (針對 tabindex="0" 的非按鈕元素) --- - $tabs.on('keydown', function(e) { - // 當按下 Enter (13) 或 Space (32) 時觸發點擊 - if (e.which === 13 || e.which === 32) { - e.preventDefault(); - $(this).trigger('click'); - } - }); - } - // 延遲執行確保頁籤元件已渲染 - setTimeout(fixTabAccessibility, 500); - }); //移除 accesskey="W" 之後的 | 符號 $(function() { function removeSeparatorAfterAccesskeyW() { @@ -1688,6 +1819,12 @@ $(function() { if ($('#language-li').is(':empty') || $('#language-li').html().trim() === '') { $('#language-li').remove(); }; + $('.header-nav').each(function() { + const cleaned = $(this).text().replace(/[\s|]/g, ''); + if (cleaned === '') { + $(this).remove(); + } + }); } forFreeGo();