'js'
This commit is contained in:
parent
7ae3e05c24
commit
b69db30a4e
|
|
@ -789,38 +789,37 @@
|
|||
// 延遲執行確保圖片與動態內容已渲染
|
||||
setTimeout(fixImageAccessibility, 500);
|
||||
});
|
||||
function removeEmptyTitles() {
|
||||
// 定義所有需要檢查的 class
|
||||
const targetClasses = [
|
||||
'.w-annc__widget-title',
|
||||
'.widget-title',
|
||||
'.show-title',
|
||||
'.event-annc-title',
|
||||
'.annc-title',
|
||||
'.sitemenu-title',
|
||||
'.widget-link__widget-title'
|
||||
];
|
||||
function removeEmptyTitles() {
|
||||
// 定義所有需要檢查的 class
|
||||
const targetClasses = [
|
||||
'.w-annc__widget-title',
|
||||
'.widget-title',
|
||||
'.show-title',
|
||||
'.event-annc-title',
|
||||
'.annc-title',
|
||||
'.sitemenu-title',
|
||||
'.widget-link__widget-title'
|
||||
];
|
||||
|
||||
// 將陣列轉換為 jQuery 選擇器字串
|
||||
const selector = targetClasses.join(', ');
|
||||
// 將陣列轉換為 jQuery 選擇器字串
|
||||
const selector = targetClasses.join(', ');
|
||||
|
||||
$(selector).each(function() {
|
||||
// 使用 $.trim 移除空格、換行符號
|
||||
// 然後檢查裡面是否完全沒有文字
|
||||
const textContent = $.trim($(this).text());
|
||||
$(selector).each(function() {
|
||||
// 使用 $.trim 移除空格、換行符號
|
||||
// 然後檢查裡面是否完全沒有文字
|
||||
const textContent = $.trim($(this).text());
|
||||
|
||||
if (textContent === "") {
|
||||
// 如果沒有文字,則將整個元素刪除
|
||||
$(this).remove();
|
||||
console.log('已移除空標題元素:', this.className);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (textContent === "") {
|
||||
// 如果沒有文字,則將整個元素刪除
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 執行 function
|
||||
$(document).ready(function() {
|
||||
removeEmptyTitles();
|
||||
});
|
||||
// 執行 function
|
||||
$(document).ready(function() {
|
||||
removeEmptyTitles();
|
||||
});
|
||||
$(".w-annc__img-wrap a").each(function () {
|
||||
var $this = $(this);
|
||||
// 確保 <a> 內沒有文字節點 (避免重複添加)
|
||||
|
|
@ -880,105 +879,99 @@ $(document).ready(function() {
|
|||
$button.attr('aria-label', '播放驗證碼語音');
|
||||
}
|
||||
});
|
||||
//有連結目的之所有a標籤加上aria-label和title
|
||||
$(function() {
|
||||
/**
|
||||
* 無障礙 AA 級補強最終整合版 (人工檢測完全合格)
|
||||
* 1. 修正語言選單:Tab 到達時顯示「在本視窗開啟語言選單」。
|
||||
* 2. 智慧 Title 策略:
|
||||
* - 長文字:僅保留動作提示 (如: (在本視窗開啟)),避免重複讀取。
|
||||
* - 短文字/標籤:組合 [文字內容] + [動作提示],增強目的識別。
|
||||
* 3. 圖文並存處理:符合 HM1240402E,當有文字時,圖片 alt 設為空值。
|
||||
* 4. 清理無效描述:攔截「這是一張圖片」等不合格內容。
|
||||
*/
|
||||
function fixAccessibilityAll() {
|
||||
// --- Part 1: 語言選單修正 (Language Button) ---
|
||||
var $langBtn = $('#languagebutton');
|
||||
if ($langBtn.length > 0) {
|
||||
$langBtn.attr('title', '在本視窗開啟語言選單');
|
||||
$langBtn.removeAttr('aria-label');
|
||||
//有連結目的之所有a標籤的無障礙處理
|
||||
$(function() {
|
||||
|
||||
/**
|
||||
* 全站無障礙 AA 級補強 (多語系偵測版)
|
||||
* 支援功能:語系自動偵測、HM1240404E 修正、檔案預知類型、圖片替代文字
|
||||
*/
|
||||
function fixAccessibilityAll() {
|
||||
// 1. 偵測目前頁面語系 (優先抓取 html lang,若無則預設為 zh-Hant)
|
||||
var pageLang = $('html').attr('lang') || 'zh-Hant';
|
||||
var isEn = pageLang.toLowerCase().startsWith('en');
|
||||
|
||||
// 2. 定義語系對應字典
|
||||
var i18n = {
|
||||
langBtn: isEn ? 'Open language menu in this window' : '在本視窗開啟語言選單',
|
||||
newWin: isEn ? '(Open in new window)' : '(在新視窗開啟)',
|
||||
selfWin: isEn ? '(Open in this window)' : '(在本視窗開啟)',
|
||||
link: isEn ? 'Link' : '連結'
|
||||
};
|
||||
|
||||
// --- Part 1: 語言選單修正 ---
|
||||
var $langBtn = $('#languagebutton');
|
||||
if ($langBtn.length > 0) {
|
||||
$langBtn.attr('title', i18n.langBtn);
|
||||
$langBtn.removeAttr('aria-label');
|
||||
}
|
||||
|
||||
// --- Part 2: 全站連結與檔案類型自動標示 ---
|
||||
$('a').each(function() {
|
||||
var $a = $(this);
|
||||
var href = ($a.attr('href') || '').toLowerCase();
|
||||
if (!href || href.startsWith('javascript:')) return;
|
||||
|
||||
var linkText = $a.text().replace(/\u00a0/g, '').trim();
|
||||
var $img = $a.find('img');
|
||||
var currentTitle = ($a.attr('title') || '').trim();
|
||||
|
||||
// A. 視窗動作規範 (動態語系)
|
||||
var isNewWindow = ($a.attr('target') === '_blank');
|
||||
var windowTask = isNewWindow ? i18n.newWin : i18n.selfWin;
|
||||
|
||||
// B. 偵測檔案類型
|
||||
var fileExt = "";
|
||||
var fileMatches = href.match(/\.(pdf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odp|zip|rar|jpg|png|csv)$/);
|
||||
if (fileMatches) {
|
||||
fileExt = fileMatches[1].toLowerCase();
|
||||
}
|
||||
|
||||
// C. 智慧修正與標題補充 (解決 HM1240404E 不明符號問題)
|
||||
// 檢查是否包含括號 () 或 中英文的另開視窗關鍵字
|
||||
var hasBadSymbol = currentTitle.includes('()') ||
|
||||
currentTitle.includes('另開新視窗') ||
|
||||
currentTitle.includes('Open in new window');
|
||||
|
||||
if (linkText === "" && $img.length > 0) {
|
||||
// 【純圖片連結】
|
||||
var rawAlt = ($img.attr('alt') || '').trim();
|
||||
var forbidden = ['這是一張圖片', '圖片', 'image', 'photo', '图', ''];
|
||||
var imgAlt = forbidden.some(function(txt) { return rawAlt.toLowerCase() === txt; })
|
||||
? ($a.attr('aria-label') || i18n.link) : rawAlt;
|
||||
|
||||
var fileInfo = fileExt ? '[' + fileExt.toUpperCase() + '] ' : '';
|
||||
$a.attr('title', (fileInfo + windowTask).trim());
|
||||
$img.attr('alt', imgAlt);
|
||||
}
|
||||
else if (linkText !== "") {
|
||||
// 【有文字連結】
|
||||
if (fileExt !== "" || hasBadSymbol || currentTitle === "") {
|
||||
var isTag = $a.hasClass('label') || $a.hasClass('tag') || $a.find('[class*="tag"]').length > 0;
|
||||
|
||||
if (fileExt !== "") {
|
||||
// 檔案下載:連結文字 + .副檔名 + 動作 (語系化)
|
||||
$a.attr('title', linkText + " ." + fileExt + " " + windowTask);
|
||||
} else if (linkText.length <= 6 || isTag) {
|
||||
// 短文字:補充完整語意
|
||||
$a.attr('title', linkText + " " + windowTask);
|
||||
} else {
|
||||
// 長文字:僅動作提示
|
||||
$a.attr('title', windowTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// D. 最終清理
|
||||
$a.removeAttr('aria-label');
|
||||
if (linkText !== "" && $img.length > 0) { $img.attr('alt', ''); }
|
||||
});
|
||||
}
|
||||
|
||||
// --- Part 2: 全站連結補強 (Links) ---
|
||||
$('a').each(function() {
|
||||
var $a = $(this);
|
||||
var href = $a.attr('href');
|
||||
|
||||
// 基礎攔截
|
||||
if (!href || href.startsWith('javascript:')) return;
|
||||
|
||||
// 1. 獲取內容資訊
|
||||
var linkText = $a.text().replace(/\u00a0/g, '').trim();
|
||||
var $img = $a.find('img');
|
||||
var rawAlt = ($img.length > 0) ? ($img.attr('alt') || '').trim() : '';
|
||||
var forbiddenTexts = ['這是一張圖片', '圖片', 'image', 'photo', '圖示'];
|
||||
var imgAlt = forbiddenTexts.includes(rawAlt) ? '' : rawAlt;
|
||||
|
||||
var hasSrOnly = $a.find('.sr-only').length > 0 && $a.find('.sr-only').text().trim().length > 0;
|
||||
var srOnlyText = hasSrOnly ? $a.find('.sr-only').text().trim() : '';
|
||||
|
||||
// 2. 移除空連結
|
||||
if (linkText === '' && $img.length === 0 && !hasSrOnly && !($a.attr('aria-label'))) {
|
||||
$a.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 準備視窗提示
|
||||
let windowTask = ($a.attr('target') === '_blank') ? '(在新視窗開啟)' : '(在本視窗開啟)';
|
||||
|
||||
// 4. 核心邏輯判定
|
||||
|
||||
// 【情況 A:純圖片連結 (無文字)】
|
||||
if (linkText === "" && !hasSrOnly) {
|
||||
if (imgAlt !== "") {
|
||||
// 名字讓圖片 alt 說,title 只放動作提示 (避免重複)
|
||||
$a.attr('title', windowTask);
|
||||
$img.attr('alt', imgAlt);
|
||||
} else {
|
||||
let fallback = $a.attr('aria-label') || '連結';
|
||||
$a.attr('title', (fallback + ' ' + windowTask).trim());
|
||||
$img.attr('alt', fallback);
|
||||
}
|
||||
}
|
||||
|
||||
// 【情況 B:有文字連結】
|
||||
else {
|
||||
/**
|
||||
* 智慧 Title 判斷:
|
||||
* 1. 如果是標籤 (Class 含 label 或 tag) 或文字很短 (<= 6 字)
|
||||
* -> Title 顯示:[文字內容] (動作提示)
|
||||
* 2. 如果是長文章標題或一般長連結
|
||||
* -> Title 僅顯示:(動作提示) 以避免重複朗讀
|
||||
*/
|
||||
var isTag = $a.hasClass('label') || $a.hasClass('tag') || $a.find('[class*="tag"]').length > 0 || $a.find('[class*="label"]').length > 0;
|
||||
|
||||
if (linkText.length <= 6 || isTag) {
|
||||
// 短文字或標籤:補全語意
|
||||
$a.attr('title', linkText + " " + windowTask);
|
||||
} else {
|
||||
// 長文字:精簡語意
|
||||
$a.attr('title', windowTask);
|
||||
}
|
||||
|
||||
// 符合規範:圖文並存時,圖片 alt 應為空值
|
||||
// if ($img.length > 0) {
|
||||
// $img.attr('alt', '');
|
||||
// }
|
||||
}
|
||||
|
||||
// 5. 最終清理
|
||||
$a.removeAttr('aria-label');
|
||||
$a.removeAttr('alt'); // a 標籤不應有 alt
|
||||
|
||||
if ($img.length > 0 && forbiddenTexts.includes($img.attr('alt'))) {
|
||||
$img.attr('alt', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 延遲執行
|
||||
setTimeout(fixAccessibilityAll, 500);
|
||||
});
|
||||
setTimeout(function() {
|
||||
fixAccessibilityAll();
|
||||
}, 600);
|
||||
});
|
||||
|
||||
// if (location.href.search('editmode=on') === -1) {
|
||||
// // 1. 處理圖片 alt 重複問題 (保持原邏輯但優化)
|
||||
|
|
@ -1205,6 +1198,154 @@ $(function() {
|
|||
|
||||
// 執行 function
|
||||
removeHiddenElementsInsideBrand();
|
||||
//修正 Alt+M 定位點位置
|
||||
$(function() {
|
||||
function fixAccessKeyM() {
|
||||
var $accessKeyM = $('#accesskey_menu');
|
||||
var $navbarHeader = $('.navbar-header');
|
||||
|
||||
if ($accessKeyM.length > 0 && $navbarHeader.length > 0) {
|
||||
$accessKeyM.insertBefore($navbarHeader);
|
||||
$accessKeyM.css({
|
||||
'display': 'inline-block',
|
||||
'position': 'relative',
|
||||
'float': 'left', // 靠左對齊
|
||||
});
|
||||
// $accessKeyM.attr('title', '中央內容區塊導覽列 (Alt+M)');
|
||||
}
|
||||
}
|
||||
setTimeout(fixAccessKeyM, 500);
|
||||
});
|
||||
//公告頁籤無障礙
|
||||
$(function() {
|
||||
function fixTabLinearOrder() {
|
||||
var $tabs = $('.filter_tab');
|
||||
var $anncList = $('.w-annc__list');
|
||||
|
||||
// --- 1. 順向遊走:標籤 -> 對應內容 ---
|
||||
$tabs.on('keydown', function(e) {
|
||||
// 當在標籤按下 Tab (排除 Shift+Tab)
|
||||
if (e.which === 9 && !e.shiftKey) {
|
||||
var category = $(this).data('category');
|
||||
var $visibleItems = $('.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 處理標籤的 Enter/Space 切換
|
||||
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 category = $currentItem.data('category');
|
||||
var $visibleItems = $('.w-annc__item[data-category="' + category + '"]:visible');
|
||||
|
||||
// 如果是目前內容的第一個連結,按下 Shift+Tab 應回到對應標籤
|
||||
if (e.which === 9 && e.shiftKey) {
|
||||
if ($currentLink.is($visibleItems.find('a').first())) {
|
||||
e.preventDefault();
|
||||
$('.filter_tab[data-category="' + category + '"]').focus();
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是目前內容的最後一個連結,按下 Tab 應跳往「下一個標籤」
|
||||
if (e.which === 9 && !e.shiftKey) {
|
||||
if ($currentLink.is($visibleItems.find('a').last())) {
|
||||
var $nextTab = $('.filter_tab[data-category="' + category + '"]').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 $prevTab = $(this).prev('.filter_tab');
|
||||
if ($prevTab.length > 0) {
|
||||
var prevCategory = $prevTab.data('category');
|
||||
|
||||
// 先切換到上一個分頁
|
||||
$prevTab.click();
|
||||
|
||||
// 找出上一個分頁最後一個可見連結
|
||||
var $prevItems = $('.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');
|
||||
|
||||
$navItems.each(function() {
|
||||
const $li = $(this);
|
||||
const $toggle = $li.children('a');
|
||||
const $subMenu = $li.children('ul');
|
||||
|
||||
// 判斷是否有子選單
|
||||
if ($subMenu.length > 0) {
|
||||
// 1. 初始化屬性
|
||||
// aria-haspopup="true" 表示有點擊後彈出選單的功能
|
||||
// aria-expanded="false" 預設為摺疊
|
||||
$toggle.attr({
|
||||
'aria-haspopup': 'true',
|
||||
'aria-expanded': 'false'
|
||||
});
|
||||
|
||||
// 如果 href 是 javascript:void(0);,建議補上 role="button" 讓語音讀出它是按鈕
|
||||
if ($toggle.attr('href').indexOf('javascript') !== -1) {
|
||||
$toggle.attr('role', 'button');
|
||||
}
|
||||
|
||||
// 2. 焦點移入事件 (Focus)
|
||||
$toggle.on('focus', function() {
|
||||
// 這裡假設你的選單是用 CSS 或其他 JS 控制顯示,
|
||||
// 當焦點進入時,將狀態改為 true
|
||||
$(this).attr('aria-expanded', 'true');
|
||||
// 如果需要透過 JS 強制顯示選單可在此加上:$subMenu.addClass('show'); (視你的 CSS 而定)
|
||||
});
|
||||
|
||||
// 3. 處理失焦事件 (Focusout)
|
||||
// 使用 focusout 並檢查焦點是否移出了整個 li 區塊
|
||||
$li.on('focusout', function(e) {
|
||||
// 使用 setTimeout 確保能抓到下一個獲焦元素
|
||||
setTimeout(function() {
|
||||
if (!$li.is(':focus-within')) {
|
||||
$toggle.attr('aria-expanded', 'false');
|
||||
// 如果有 class 控制顯示:$subMenu.removeClass('show');
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// 執行修正
|
||||
fixNavMenuA11y();
|
||||
}
|
||||
forFreeGo();
|
||||
|
||||
|
|
@ -1863,118 +2004,188 @@ $(function() {
|
|||
init();
|
||||
});
|
||||
|
||||
//orbitbar無障礙js
|
||||
$(document).ready(function() {
|
||||
const isEnglish = document.documentElement.lang === 'en';
|
||||
|
||||
if (isEnglish) {
|
||||
$('.navbar-toggle').attr({
|
||||
title: 'menu',
|
||||
'aria-label': 'menu'
|
||||
});
|
||||
$('label[for="open-orbit-nav"]').attr({
|
||||
title: 'Site search and language menu',
|
||||
'aria-label': 'Site search and language menu'
|
||||
});
|
||||
$('.mobile-button').attr({
|
||||
title: 'Language menu',
|
||||
'aria-label': 'Language menu'
|
||||
});
|
||||
} else {
|
||||
$('label[for="open-orbit-nav"]').attr({
|
||||
title: '全站収尋及語言切換選單',
|
||||
'aria-label': '全站収尋及語言切換選單'
|
||||
});
|
||||
$('.mobile-button').attr({
|
||||
title: '語言切換選單',
|
||||
'aria-label': '語言切換選單'
|
||||
});
|
||||
}
|
||||
|
||||
// 1. OrbitBar 基礎與搜尋選單邏輯
|
||||
$(document).ready(function() {
|
||||
const isEn = document.documentElement.lang === 'en';
|
||||
const $orbitLabel = $('label[for="open-orbit-nav"]');
|
||||
const $searchArea = $('.orbit-bar-search-sign-language');
|
||||
const $firstInput = $('#q'); // 搜尋框通常是選單內第一個獲焦元素
|
||||
|
||||
$('label[for="open-orbit-login"]').removeAttr('tabindex');
|
||||
$('#orbit-bar').find('li').each(function() {
|
||||
var $li = $(this);
|
||||
// 初始化屬性
|
||||
if (isEn) {
|
||||
$orbitLabel.attr({ title: 'Site search and language menu', 'aria-label': 'Site search and language menu' });
|
||||
} else {
|
||||
$orbitLabel.attr({ title: '全站搜尋及語言切換選單', 'aria-label': '全站搜尋及語言切換選單' });
|
||||
}
|
||||
$orbitLabel.attr({ 'role': 'button', 'aria-haspopup': 'true', 'aria-expanded': 'false', 'tabindex': '0' });
|
||||
|
||||
// 如果 <li> 中没有 <a> 元素,则为 <li> 设置 tabindex="0"
|
||||
if ($li.children('a').length === 0) {
|
||||
$li.attr('tabindex', '0');
|
||||
} else {
|
||||
// 如果 <li> 中有 <a> 元素,则确保 <a> 有 tabindex="0"
|
||||
$li.find('a').attr('tabindex', '0');
|
||||
|
||||
// 确保 <li> 不影响焦点管理,移除 <li> 的 tabindex
|
||||
$li.removeAttr('tabindex');
|
||||
|
||||
// 如果 <li> 被聚焦,自动跳转到 <a> 元素
|
||||
$li.on('focus', function() {
|
||||
$(this).find('a').focus();
|
||||
});
|
||||
}
|
||||
});
|
||||
$('label[for="open-orbit-nav"]').attr('tabindex', '0');
|
||||
// 当屏幕宽度小于 768px 时,将 .orbit-bar-search-sign-language 移动到 <label for="open-orbit-nav"> 后面
|
||||
function moveSearchSignLanguage() {
|
||||
if ($(window).width() < 767) {
|
||||
$('.orbit-bar-search-sign-language').insertAfter('label[for="open-orbit-nav"]');
|
||||
// --- 【修正重點 1】處理 Label 的焦點與按鍵行為 ---
|
||||
$orbitLabel.on('focusin', function(e) {
|
||||
var relatedTarget = e.relatedTarget;
|
||||
// 如果是從選單內部退回來的 (Shift+Tab)
|
||||
if (relatedTarget && ($searchArea.find(relatedTarget).length > 0)) {
|
||||
$searchArea.removeClass('show');
|
||||
$(this).attr('aria-expanded', 'false');
|
||||
} else {
|
||||
// 屏幕宽度大于等于 768px 时,恢复原位置
|
||||
$('.orbit-bar-search-sign-language').appendTo('.orbit-bar-inner');
|
||||
// 正向進入
|
||||
$searchArea.addClass('show');
|
||||
$(this).attr('aria-expanded', 'true');
|
||||
}
|
||||
});
|
||||
|
||||
// 強制偵測:在 Label 上按下 Shift+Tab 代表要離開這整塊,立即收合
|
||||
$orbitLabel.on('keydown', function(e) {
|
||||
if (e.shiftKey && e.keyCode === 9) { // Shift + Tab
|
||||
$searchArea.removeClass('show');
|
||||
$searchArea.find('ul').removeClass('show');
|
||||
$(this).attr('aria-expanded', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
// --- 【修正重點 2】處理選單內第一個元素的 Shift+Tab ---
|
||||
$firstInput.on('keydown', function(e) {
|
||||
if (e.shiftKey && e.keyCode === 9) { // 在第一個輸入框按 Shift + Tab
|
||||
// 讓它自然回到 Label,Label 的 focusin 會接手處理收合
|
||||
// 這裡不做額外動作,交給上面的 focusin 邏輯
|
||||
}
|
||||
});
|
||||
|
||||
// --- 【修正重點 3】處理離開大區塊(往後 Tab)的狀態清除 ---
|
||||
$searchArea.on('focusout', function() {
|
||||
var $thisArea = $(this);
|
||||
setTimeout(function() {
|
||||
if (!$thisArea.is(':focus-within') && !$(document.activeElement).is($orbitLabel)) {
|
||||
$thisArea.removeClass('show');
|
||||
$thisArea.find('ul').removeClass('show');
|
||||
$orbitLabel.attr('aria-expanded', 'false');
|
||||
$('#languagebutton').attr('aria-expanded', 'false');
|
||||
}
|
||||
}, 150);
|
||||
});
|
||||
|
||||
// 點擊行為
|
||||
$orbitLabel.on('click', function() {
|
||||
var isOpen = $searchArea.hasClass('show');
|
||||
$searchArea.toggleClass('show', !isOpen);
|
||||
$(this).attr('aria-expanded', !isOpen);
|
||||
});
|
||||
|
||||
// RWD 位置搬移
|
||||
function moveSearch() {
|
||||
if ($(window).width() < 767) {
|
||||
$searchArea.insertAfter('label[for="open-orbit-nav"]');
|
||||
} else {
|
||||
$searchArea.appendTo('.orbit-bar-inner');
|
||||
}
|
||||
}
|
||||
|
||||
moveSearchSignLanguage();
|
||||
$(window).resize(function() {
|
||||
moveSearchSignLanguage();
|
||||
});
|
||||
// 当 <label for="open-orbit-nav"> 被选中时,显示 .orbit-bar-search-sign-language
|
||||
$('label[for="open-orbit-nav"]').on('focus', function() {
|
||||
$('.orbit-bar-search-sign-language').addClass('show');
|
||||
})
|
||||
$('#languagebutton').on('focus', function() {
|
||||
$('#language-li ul').addClass('show');
|
||||
});
|
||||
moveSearch();
|
||||
$(window).resize(moveSearch);
|
||||
});
|
||||
|
||||
// 监听 #language 元素被 Tab 键选中时
|
||||
$('#language-li-ul li').on('focus', function() {
|
||||
// 给 #language 内部的 ul 元素添加 show 类
|
||||
$(this).find('ul').addClass('show');
|
||||
});
|
||||
$('#language-li-ul li ul > li:last-child>a').on('blur', function() {
|
||||
$('#language-li-ul li ul').removeClass('show');
|
||||
});
|
||||
$('.orbit-bar-title a').on('focus', function() {
|
||||
$('#language-li-ul li ul').removeClass('show');
|
||||
});
|
||||
|
||||
|
||||
$('#language-li').on('focus', function() {
|
||||
// 给 #language 内部的 ul 元素添加 show 类
|
||||
$(this).find('ul').addClass('show');
|
||||
});
|
||||
$('#language-li ul > li:last-child>a').on('blur', function() {
|
||||
$('#language-li ul').removeClass('show');
|
||||
$('.orbit-bar-search-sign-language').removeClass('show');
|
||||
});
|
||||
$('label[for="open-orbit-login"]').on('blur', function() {
|
||||
$('.orbit-bar-search-sign-language').removeClass('show');
|
||||
});
|
||||
$('#gotocenter').on('focus', function() {
|
||||
// 当 #gotocenter 被选中时,移除 .orbit-bar-search-sign-language 上的 show 类
|
||||
$('.orbit-bar-search-sign-language').removeClass('show');
|
||||
});
|
||||
$('label[for="open-orbit-nav"]').on('click', function() {
|
||||
// 切換 .orbit-bar-search-sign-language 的 .show 類別
|
||||
$('.orbit-bar-search-sign-language').removeClass('show');
|
||||
});
|
||||
$('li[tabindex="0"]').each(function () {
|
||||
const $li = $(this);
|
||||
if ($li.find('input').length > 0) {
|
||||
$li.removeAttr('tabindex');
|
||||
// 2. 語言按鈕與手機版選單補強
|
||||
$(function() {
|
||||
function fixLanguageA11y() {
|
||||
var $desktopBtn = $('#languagebutton');
|
||||
if ($desktopBtn.length > 0) {
|
||||
$desktopBtn.attr({ 'aria-expanded': 'false', 'role': 'button', 'aria-haspopup': 'true' });
|
||||
$desktopBtn.on('focus', function() {
|
||||
$(this).closest('#language-li').find('ul').addClass('show');
|
||||
$(this).attr('aria-expanded', 'true');
|
||||
$('.orbit-bar-search-sign-language').addClass('show');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var $mobileBtn = $('.mobile-button');
|
||||
if ($mobileBtn.length > 0) {
|
||||
$mobileBtn.attr({ 'role': 'button', 'tabindex': '0', 'aria-haspopup': 'true', 'aria-expanded': 'false' });
|
||||
$mobileBtn.on('focus', function() {
|
||||
$(this).closest('li').find('ul').addClass('show');
|
||||
$(this).attr('aria-expanded', 'true');
|
||||
});
|
||||
$mobileBtn.on('keydown', function(e) {
|
||||
if (e.which === 13 || e.which === 32) {
|
||||
e.preventDefault();
|
||||
var $ul = $(this).closest('li').find('ul');
|
||||
$ul.toggleClass('show');
|
||||
$(this).attr('aria-expanded', $ul.hasClass('show') ? 'true' : 'false');
|
||||
}
|
||||
});
|
||||
$('#language-li-ul').on('focusout', function() {
|
||||
var $container = $(this);
|
||||
setTimeout(function() {
|
||||
if (!$container.is(':focus-within')) {
|
||||
$container.find('ul').removeClass('show');
|
||||
$mobileBtn.attr('aria-expanded', 'false');
|
||||
}
|
||||
}, 150);
|
||||
});
|
||||
}
|
||||
|
||||
// 強制鎖定 Title
|
||||
var target = document.getElementById('languagebutton');
|
||||
if (target) {
|
||||
var isEn = document.documentElement.lang === 'en';
|
||||
var correctTitle = isEn ? 'Open language menu' : '在本視窗開啟語言選單';
|
||||
var observer = new MutationObserver(function() {
|
||||
if (target.getAttribute('title') !== correctTitle) target.setAttribute('title', correctTitle);
|
||||
});
|
||||
observer.observe(target, { attributes: true });
|
||||
}
|
||||
}
|
||||
setTimeout(fixLanguageA11y, 600);
|
||||
});
|
||||
// rwd左上選單無障礙
|
||||
$(function() {
|
||||
/**
|
||||
* 修正:當焦點離開整個區塊(含語言選單最後一項)時,關閉大選單
|
||||
*/
|
||||
function fixSearchMenuFocusOut() {
|
||||
var $searchArea = $('.orbit-bar-search-sign-language');
|
||||
var $orbitLabel = $('label[for="open-orbit-nav"]');
|
||||
var $langBtn = $('#languagebutton');
|
||||
|
||||
// 使用 focusout 監聽整個搜尋/語言區域
|
||||
$searchArea.on('focusout', function(e) {
|
||||
// 關鍵:使用 setTimeout 讓 document.activeElement 抓到下一個獲焦元素
|
||||
setTimeout(function() {
|
||||
// 如果目前的焦點不在 $searchArea 裡面,也不是回到觸發的 $orbitLabel 上
|
||||
if (!$searchArea.is(':focus-within') && !$(document.activeElement).is($orbitLabel)) {
|
||||
|
||||
// 1. 移除大區塊顯示
|
||||
$searchArea.removeClass('show');
|
||||
|
||||
// 2. 移除子層語言選單顯示
|
||||
$searchArea.find('ul').removeClass('show');
|
||||
|
||||
// 3. 狀態重置為「折疊」供語音報讀
|
||||
$orbitLabel.attr('aria-expanded', 'false');
|
||||
$langBtn.attr('aria-expanded', 'false');
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
|
||||
// 桌面版 Language 按鈕特殊處理:焦點移入時
|
||||
$langBtn.on('focus', function() {
|
||||
// 確保父層搜尋區塊是顯示的 (針對從別處直接 tab 過來的情況)
|
||||
$searchArea.addClass('show');
|
||||
$(this).attr('aria-expanded', 'true');
|
||||
});
|
||||
|
||||
// 針對手機版 mobile-button (span) 同理處理
|
||||
$('.mobile-button').on('focusout', function() {
|
||||
var $mobileParent = $('#language-li-ul');
|
||||
setTimeout(function() {
|
||||
if (!$mobileParent.is(':focus-within')) {
|
||||
$mobileParent.find('ul').removeClass('show');
|
||||
$('.mobile-button').attr('aria-expanded', 'false');
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(fixSearchMenuFocusOut, 600);
|
||||
});
|
||||
//萬用表格查詢按鈕翻中英
|
||||
$(document).ready(function () {
|
||||
const lang = $('html').attr('lang');
|
||||
|
|
@ -2203,60 +2414,7 @@ $(document).ready(function() {
|
|||
// 執行修復功能
|
||||
fixVideoPosterAlt();
|
||||
});
|
||||
//導覽選單與語言按鈕無障礙補強 (人工檢測完全合格版)
|
||||
$(function() {
|
||||
/**
|
||||
* 語言按鈕無障礙補強 (MutationObserver 鎖定版)
|
||||
* 目的:防止導覽套件在 Focus/Click 時將 Title 抽換為「按下關閉語言選單」
|
||||
*/
|
||||
function forceFixLanguageButton() {
|
||||
var $langBtn = $('#languagebutton');
|
||||
var target = document.getElementById('languagebutton'); // 原生 DOM 用於 Observer
|
||||
|
||||
if ($langBtn.length > 0 && target) {
|
||||
|
||||
// 1. 定義修正行為的函數
|
||||
var enforceA11y = function(el) {
|
||||
var correctTitle = '在本視窗開啟語言選單';
|
||||
if (el.getAttribute('title') !== correctTitle) {
|
||||
el.setAttribute('title', correctTitle);
|
||||
}
|
||||
// 同步確保其它屬性正確
|
||||
if (el.getAttribute('role') !== 'button') {
|
||||
el.setAttribute('role', 'button');
|
||||
el.setAttribute('aria-haspopup', 'true');
|
||||
}
|
||||
};
|
||||
|
||||
// 2. 初始執行一次
|
||||
enforceA11y(target);
|
||||
if (!$langBtn.attr('aria-expanded')) {
|
||||
$langBtn.attr('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
// 3. 使用 MutationObserver 進行「即時監修」
|
||||
// 這是為了解決套件在 focus 或 click 時偷偷改掉 title 的問題
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(mutation) {
|
||||
if (mutation.attributeName === 'title') {
|
||||
enforceA11y(target);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 開始監聽屬性變動
|
||||
observer.observe(target, { attributes: true });
|
||||
|
||||
// 4. 事件補強:針對點擊與聚焦再次確保 (雙重保險)
|
||||
$langBtn.on('click focusin', function() {
|
||||
enforceA11y(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 延遲 600ms 執行,確保避開大部份套件的初始載入時間
|
||||
setTimeout(forceFixLanguageButton, 600);
|
||||
});
|
||||
//修正無超連結目的之連結
|
||||
$(function() {
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
a[accesskey] {
|
||||
position: absolute;
|
||||
margin-left: -0.9375em;
|
||||
color: transparent !important;
|
||||
color: transparent ;
|
||||
}
|
||||
|
||||
#orbit-bar a[accesskey] {
|
||||
|
|
|
|||
Loading…
Reference in New Issue