This commit is contained in:
parent
cb076cec58
commit
68a0f1fe2e
|
|
@ -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('<span class="sr-only">' + labels.closePopup + '</span>');
|
||||
}
|
||||
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('<span class="sr-only">' + labels.closeGallery + '</span>');
|
||||
}
|
||||
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('<span class="sr-only">' + labelText + '</span>');
|
||||
}
|
||||
if ($icon.next('.sr-only').length === 0) {
|
||||
$icon.after('<span class="sr-only">' + labels.toggleDesc + '</span>');
|
||||
}
|
||||
});
|
||||
}
|
||||
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('<span class="sr-only">' + labels.themeSwitch + '</span>');
|
||||
}
|
||||
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('<span class="sr-only">' + labelText + '</span>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue