This commit is contained in:
ken 2026-04-22 16:54:21 +08:00
parent b69db30a4e
commit e64d5ffc4f
1 changed files with 202 additions and 175 deletions

View File

@ -729,97 +729,37 @@
$this.attr('title', '按鈕');
}
});
//img無障礙
$(function() {
/**
* 圖片無障礙 AA 級補強 (人工檢測優化版)
* 1. 處理裝飾性圖片清空 alt 並移除 title
* 2. 解決資訊冗餘 alt title 內容相同移除 title避免重複朗讀
* 3. 自動補強缺失 alt從父層 title 或鄰近標題文字擷取
*/
function fixImageAccessibility() {
$('img').each(function() {
var $img = $(this);
var currentAlt = ($img.attr('alt') || '').trim();
var currentTitle = ($img.attr('title') || '').trim();
// --- 1. 處理「裝飾性圖片」標註 (最高優先權) ---
if (currentAlt === "裝飾圖片" || currentTitle === "裝飾圖片") {
$img.attr('alt', '');
$img.removeAttr('title');
return; // 跳過此圖
}
function removeEmptyTitles() {
// 定義所有需要檢查的 class
const targetClasses = [
'.w-annc__widget-title',
'.widget-title',
'.show-title',
'.event-annc-title',
'.annc-title',
'.sitemenu-title',
'.widget-link__widget-title'
];
// --- 2. 解決【alt 與 title 相同】的問題 (人工檢測重點) ---
// 只要兩者內容一致且不為空,就移除 title保留 alt
if (currentAlt !== '' && currentAlt === currentTitle) {
$img.removeAttr('title');
// 重新更新變數值供後續邏輯使用
currentTitle = '';
}
// 將陣列轉換為 jQuery 選擇器字串
const selector = targetClasses.join(', ');
// --- 3. 處理「缺失 alt」或「空的 alt」補強邏輯 ---
if (currentAlt === '') {
let finalAlt = "";
$(selector).each(function() {
// 使用 $.trim 移除空格、換行符號
// 然後檢查裡面是否完全沒有文字
const textContent = $.trim($(this).text());
// A. 嘗試從父層 (如 <a>) 的 title 抓取描述
var parentTitle = $img.parent().attr('title');
// B. 嘗試抓取同區域內的標題文字
var nearbyTitle = $img.closest('a').find('h1, h2, h3, h4, h5, h6').first().text().trim();
if (parentTitle && parentTitle.trim() !== '') {
finalAlt = parentTitle.trim();
} else if (nearbyTitle !== '') {
finalAlt = nearbyTitle;
}
// 寫入最終 alt 結果
// 如果 finalAlt 仍為空,則設為 "" (符合 AA 規範,視為裝飾圖)
$img.attr('alt', finalAlt);
// --- 4. 二次清理:補強後的 alt 如果又跟原本的 title 一樣,則移除 title ---
if (currentTitle !== '' && currentTitle === finalAlt) {
$img.removeAttr('title');
}
}
});
}
// 延遲執行確保圖片與動態內容已渲染
setTimeout(fixImageAccessibility, 500);
if (textContent === "") {
// 如果沒有文字,則將整個元素刪除
$(this).remove();
}
});
}
// 執行 function
$(document).ready(function() {
removeEmptyTitles();
});
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(', ');
$(selector).each(function() {
// 使用 $.trim 移除空格、換行符號
// 然後檢查裡面是否完全沒有文字
const textContent = $.trim($(this).text());
if (textContent === "") {
// 如果沒有文字,則將整個元素刪除
$(this).remove();
}
});
}
// 執行 function
$(document).ready(function() {
removeEmptyTitles();
});
$(".w-annc__img-wrap a").each(function () {
var $this = $(this);
// 確保 <a> 內沒有文字節點 (避免重複添加)
@ -879,99 +819,181 @@
$button.attr('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;
// img無障礙
$(function() {
/**
* 圖片無障礙 AA 級補強 (人工檢測優化版)
*/
function fixImageAccessibility() {
$('img').each(function() {
var $img = $(this);
var $parentA = $img.closest('a'); // 取得父層連結
var currentAlt = ($img.attr('alt') || '').trim();
var currentTitle = ($img.attr('title') || '').trim();
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;
// 判定該連結是否「僅靠圖片傳達目的」(連結內無文字)
var isLinkImage = $parentA.length > 0 && $parentA.text().replace(/\u00a0/g, '').trim() === "";
// --- 1. 處理「裝飾性圖片」標註 ---
if (currentAlt === "裝飾圖片" || currentTitle === "裝飾圖片") {
$img.attr('alt', '');
$img.removeAttr('title');
return;
}
// --- 2. 解決【alt 與 title 相同】的問題 ---
if (currentAlt !== '' && currentAlt === currentTitle) {
$img.removeAttr('title');
currentTitle = '';
}
// --- 3. 處理「缺失 alt」或「空的 alt」補強邏輯 ---
// 修改點若是具有連結用途的圖片alt 不可為空
if (currentAlt === '') {
let finalAlt = "";
// A. 優先嘗試從父層 (<a>) 的 title 抓取
var parentATitle = $parentA.attr('title');
if (fileExt !== "") {
// 檔案下載:連結文字 + .副檔名 + 動作 (語系化)
$a.attr('title', linkText + " ." + fileExt + " " + windowTask);
} else if (linkText.length <= 6 || isTag) {
// 短文字:補充完整語意
$a.attr('title', linkText + " " + windowTask);
} else {
// 長文字:僅動作提示
$a.attr('title', windowTask);
// B. 嘗試抓取同區域內的標題文字
var nearbyTitle = $parentA.find('h1, h2, h3, h4, h5, h6').first().text().trim();
if (parentATitle && parentATitle.trim() !== '') {
// 移除 title 內的視窗提示字眼,只取純文字作為 alt
finalAlt = parentATitle.replace(/\(在本視窗開啟\)|\(在新視窗開啟\)/g, '').trim();
} else if (nearbyTitle !== '') {
finalAlt = nearbyTitle;
} else if (isLinkImage) {
// 如果是連結圖片且都抓不到文字,給予預設值「連結」避免檢測失敗
finalAlt = "連結";
}
$img.attr('alt', finalAlt);
// --- 4. 二次清理 ---
if (currentTitle !== '' && currentTitle === finalAlt) {
$img.removeAttr('title');
}
}
});
}
setTimeout(fixImageAccessibility, 500);
});
// 有連結目的之所有a標籤的無障礙處理
$(function() {
/**
* 全站無障礙 AA 級補強 (多語系偵測版)
*/
function fixAccessibilityAll() {
// --- 0. 網址參數判斷 ---
var urlParams = new URLSearchParams(window.location.search);
var isEditMode = urlParams.get('editmode') === 'on';
var pageLang = $('html').attr('lang') || 'zh-Hant';
var isEn = pageLang.toLowerCase().startsWith('en');
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');
}
// D. 最終清理
$a.removeAttr('aria-label');
if (linkText !== "" && $img.length > 0) { $img.attr('alt', ''); }
});
}
// --- Part 2: 全站連結處理 ---
$('a').each(function() {
var $a = $(this);
var href = ($a.attr('href') || '').toLowerCase();
if (!href || href.startsWith('javascript:')) return;
setTimeout(function() {
fixAccessibilityAll();
}, 600);
});
// 清理 &nbsp; 與 空白
var linkText = $a.text().replace(/\u00a0/g, '').trim();
var $img = $a.find('img');
var currentTitle = ($a.attr('title') || '').trim();
// --- 【新增修正:隱藏空連結】 ---
// 若網址沒有 editmode=on 時,判定 a 裡面文字為空且沒有圖片,則隱藏
if (!isEditMode && linkText === "" && $img.length === 0) {
$a.hide();
return; // 跳過後續處理
}
// 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. 智慧修正與標題補充
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() + '] ' : '';
// 確保具備標題與圖片 alt
$a.attr('title', (fileInfo + imgAlt + " " + 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);
}
}
}
// --- 修正後的 Part D 最終清理 ---
$a.removeAttr('aria-label');
// 只有當「真正可見的文字」存在時,才將圖片設為裝飾性
// 使用 clone() 移除隱藏元件後再計算文字,確保準確度
var visibleText = $a.clone().find(':hidden, style, script').remove().end().text().replace(/\u00a0/g, '').trim();
if (visibleText !== "" && $img.length > 0) {
$img.attr('alt', '');
} else {
// 如果文字是隱藏的 (如你的範例),則必須保留或補強圖片 alt
var rawAlt = ($img.attr('alt') || '').trim();
if (rawAlt === "") {
// 如果連圖片 alt 都沒寫,就從 a 的 title 抓
var cleanTitle = currentTitle.replace(/\(在本視窗開啟\)|\(在新視窗開啟\)/g, '').trim();
$img.attr('alt', cleanTitle || i18n.link);
}
}
});
}
setTimeout(function() {
fixAccessibilityAll();
}, 600);
});
// if (location.href.search('editmode=on') === -1) {
// // 1. 處理圖片 alt 重複問題 (保持原邏輯但優化)
@ -1189,15 +1211,20 @@
setTimeout(fixJPlayerAccessibility, 500);
});
// 移除 .navbar-brand 內部 display:none 元素的補強
function removeHiddenElementsInsideBrand() {
// 選取 .navbar-brand 內部所有隱藏的元素
$('.navbar-brand *').filter(function() {
// 同時判定 inline style 與 CSS class 造成的 display: none
return $(this).css('display') === 'none';
}).remove(); // 徹底從 DOM 中移除該標籤
}).remove(); // 徹底從 DOM 中移除該標籤,避免無障礙檢測工具誤判
}
// 執行 function
removeHiddenElementsInsideBrand();
// 使用 setTimeout 確保內容渲染後執行
// 建議設定 500~800 毫秒,避開大部分動態載入的時間差
setTimeout(function() {
removeHiddenElementsInsideBrand();
}, 600);
//修正 Alt+M 定位點位置
$(function() {
function fixAccessKeyM() {