diff --git a/assets/javascripts/app.js b/assets/javascripts/app.js
index 1345cd3..c0731f6 100644
--- a/assets/javascripts/app.js
+++ b/assets/javascripts/app.js
@@ -1,7 +1,36 @@
;(function($, win, undefined) {
// ECMAScript 5 嚴格模式
'use strict';
+ $(function() {
+ var $signLanguageBox = $('.orbit-bar-search-sign-language');
+ var $headerNav = $('.header-nav');
+ var $target = $('.header-nav [accesskey="U"], .header-nav [accesskey="W"]');
+ // 移除 color: inherit !important
+ $target.each(function() {
+ $(this)[0].style.removeProperty('color');
+ });
+
+ function handleNavMove() {
+ var windowWidth = window.innerWidth;
+
+ if (windowWidth > 768) {
+ if ($signLanguageBox.length && $signLanguageBox.find('[accesskey="U"], [accesskey="W"]').length === 0) {
+ $signLanguageBox.prepend($target);
+ }
+ } else {
+ if ($headerNav.length && $headerNav.find('[accesskey="U"], [accesskey="W"]').length === 0) {
+ $headerNav.append($target);
+ }
+ }
+ }
+
+ handleNavMove();
+
+ $(window).on('resize', function() {
+ handleNavMove();
+ });
+ });
//header fixed在上方
function initdata1() {
if ( $('.homebanner').length != 0) {
@@ -337,7 +366,7 @@
break;
case 'member':
orbit.member.removeEmptyRow();
- $('.index-member-3 .member-data-title-email').empty();
+
break;
case 'archive':
orbit.archives.removeEmptyTitle('.i-archive__category-item');
@@ -399,6 +428,89 @@
// $('.header-buttom').appendTo($('.dropdowns'));
// }
function forFreeGo() {
+ setTimeout(function() {
+ $('h1, h2, h3, h4, h5, h6').each(function() {
+ var $heading = $(this);
+
+ // 檢查是否為空 (去除空白後)
+ if ($.trim($heading.text()) === '' && $heading.children().length === 0) {
+ $heading.remove();
+ }
+ });
+ }, 500);
+ //zoom
+ $(function () {
+ $('.fnav a').each(function () {
+ const $a = $(this);
+
+ // 若已經有可見文字(非 icon),直接通過
+ const visibleText = $a.clone()
+ .children('.icon, i, svg, .caret')
+ .remove()
+ .end()
+ .text()
+ .trim();
+
+ if (visibleText.length > 0) return;
+
+ // 取得可用標籤文字(優先順序)
+ let label =
+ $a.attr('aria-label') ||
+ $a.attr('title') ||
+ $a.find('i[title]').attr('title') ||
+ '';
+
+ label = $.trim(label);
+
+ // 若真的完全沒有,就給一個保底(避免空字串違規)
+ if (!label) {
+ label = '功能按鈕';
+ }
+
+ // aria-label 一定要有
+ $a.attr('aria-label', label);
+
+ // icon 對螢幕閱讀器隱藏
+ $a.find('i, svg').attr('aria-hidden', 'true');
+
+ // 若沒有隱藏文字才補
+ if ($a.find('.sr-only, .visually-hidden').length === 0) {
+ $a.append(`${label}`);
+ }
+ });
+ });
+ //播放驗證碼語音
+ $(function () {
+ $('.ask-question')
+ .find('.controls button.fas.fa-volume-up')
+ .each(function () {
+ const $btn = $(this);
+
+ // 已經補過就不重複處理
+ if ($btn.attr('aria-label')) return;
+
+ $btn.attr({
+ 'aria-label': '播放驗證碼語音',
+ 'aria-controls': 'captcha_audio',
+ 'role': 'button'
+ });
+ });
+ });
+
+ //刪除td的id
+ $('td[id]').removeAttr('id');
+
+ //刪除空的title
+ $('[class*="title"]').each(function () {
+ const $el = $(this);
+
+ // 取純文字(忽略 HTML tag、空白、換行)
+ const text = $.trim($el.text());
+
+ if (text === '') {
+ $el.remove();
+ }
+ });
//表單legend
$("fieldset").each(function () {
const $fieldset = $(this);
@@ -516,28 +628,40 @@
}
});
- //li被hover
function handleHover() {
- if ($(window).width() > 769) {
- $('li').off('mouseenter mouseleave').hover(
- function() {
- $(this).children('ul').addClass('show');
- },
- function() {
- $(this).children('ul').removeClass('show');
- }
- );
- } else {
- $('li').off('mouseenter mouseleave'); // 移除 hover 事件
- }
+ // 先統一移除舊事件,避免重複綁定
+ $('li').off('mouseenter mouseleave focusin focusout');
+
+ if ($(window).width() > 769) {
+ // 1. 處理滑鼠 Hover
+ $('li').hover(
+ function() { $(this).children('ul').addClass('show'); },
+ function() { $(this).children('ul').removeClass('show'); }
+ );
+
+ // 2. 處理鍵盤 Tab 聚焦 (關鍵修正)
+ $('li').on('focusin', function() {
+ // 當焦點進入 li 或其子元素時,顯示選單
+ $(this).children('ul').addClass('show');
+ });
+
+ $('li').on('focusout', function() {
+ var $this = $(this);
+ // 延遲偵測焦點是否真的「離開」了這個 li 區塊
+ setTimeout(function() {
+ // 如果新的焦點不在當前這個 li 裡面,才移除 show
+ if ($this.find(':focus').length === 0) {
+ $this.children('ul').removeClass('show');
+ }
+ }, 10);
+ });
+ }
}
- // 先執行一次
+ // 初始化與 Resize 監聽保持不變
handleHover();
-
- // 監聽視窗大小變化
$(window).on('resize', function() {
- handleHover();
+ handleHover();
});
//刪除空的h1
$('h1').each(function() {
@@ -571,6 +695,16 @@
}
});
//無障礙單位轉換
+ $(function() {
+ $('style:contains("font-size")').each(function() {
+ let css = $(this).html();
+ css = css.replace(/font-size\s*:\s*([\d.]+)px\s*;?/gi, (_, px) =>
+ `font-size: ${(parseFloat(px) / 16).toFixed(3)}em;`
+ );
+ $(this).html(css);
+ });
+ });
+
$("[style*='font-size']").each(function() {
var fontSize = $(this).css("font-size");
if (fontSize.includes("px")) {
@@ -623,38 +757,46 @@
if (!$this.attr('title') || $this.attr('title').trim() === '') {
$this.attr('title', '按鈕');
}
- });
- $('img').each(function() {
- var $this = $(this);
- if (!$this.attr('alt') || $this.attr('alt').trim() === '') {
- $this.attr('alt', '這是一張圖片');
- }
- });
- $('img').each(function() {
- var $this = $(this);
- if (!$this.attr('title') || $this.attr('title').trim() === '') {
- $this.attr('title', '這是一張圖片');
- }
});
- $('img').each(function() {
- var $this = $(this);
-
- // 檢查 img 的 alt 屬性是否為 "裝飾圖片"
- if ($this.attr('alt') === "裝飾圖片" || $this.attr('title') === "裝飾圖片") {
- // 設定 alt 為空字串
- $this.attr('alt', '');
-
- // 移除 title 屬性
- $this.removeAttr('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(', ');
+
+ $(selector).each(function() {
+ // 使用 $.trim 移除空格、換行符號
+ // 然後檢查裡面是否完全沒有文字
+ const textContent = $.trim($(this).text());
+
+ if (textContent === "") {
+ // 如果沒有文字,則將整個元素刪除
+ $(this).remove();
+ }
});
- $(".w-annc__img-wrap a").each(function () {
- var $this = $(this);
- // 確保 內沒有文字節點 (避免重複添加)
- if ($this.text().trim() === "") {
- $this.append('公告圖片');
- }
+ }
+ // 執行 function
+ $(document).ready(function() {
+ removeEmptyTitles();
});
+
+ // $(".w-annc__img-wrap a").each(function () {
+ // var $this = $(this);
+ // // 確保 內沒有文字節點 (避免重複添加)
+ // if ($this.text().trim() === "") {
+ // $this.append('公告圖片');
+ // }
+ // });
$(".widget-link__widget-title").each(function () {
if ($(this).text().trim() === "") {
$(this).append('公告標題');
@@ -707,94 +849,435 @@
$button.attr('aria-label', '播放驗證碼語音');
}
});
- //有連結目的之所有a標籤加上aria-label和title
- $('a').each(function () {
- var $a = $(this);
- var href = $a.attr('href');
- if (!href) return;
+ // 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 isLinkImage = $parentA.length > 0 && $parentA.text().replace(/\u00a0/g, '').trim() === "";
- var hasSrOnly = $a.find('.sr-only').length > 0;
+ // --- 1. 處理「裝飾性圖片」標註 ---
+ if (currentAlt === "announcement image" || currentAlt === "裝飾圖片" || currentTitle === "裝飾圖片" || currentAlt === "這是一張圖片" || currentTitle === "這是一張圖片") {
+ $img.attr('alt', '');
+ $img.removeAttr('title');
+ return;
+ }
- // 若有 .sr-only,移除 aria-label 和 title 避免重複朗讀
- if (hasSrOnly) {
- $a.removeAttr('aria-label');
- $a.removeAttr('title');
- return; // 有 .sr-only 就不做其他處理
- }
+ // --- 2. 解決【alt 與 title 相同】的問題 ---
+ if (currentAlt !== '' && currentAlt === currentTitle) {
+ $img.removeAttr('title');
+ currentTitle = '';
+ }
- // ----- aria-label 邏輯 -----
- if (!$a.attr('aria-label')) {
- let ariaLabel = '';
+ // --- 3. 處理「缺失 alt」或「空的 alt」補強邏輯 ---
+ // 修改點:若是具有連結用途的圖片,alt 不可為空
+ if (currentAlt === '') {
+ let finalAlt = "";
- // 加入開啟方式
- if ($a.attr('target') === '_blank') {
- ariaLabel += '在新視窗開啟 ';
- } else if ($a.attr('target') === '_self') {
- ariaLabel += '在本視窗開啟 ';
- }
+ // A. 優先嘗試從父層 () 的 title 抓取
+ var parentATitle = $parentA.attr('title');
+
+ // B. 嘗試抓取同區域內的標題文字
+ var nearbyTitle = $parentA.find('h1, h2, h3, h4, h5, h6').first().text().trim();
- // 如果包含圖片且有圖片 title
- if ($a.find('img').length) {
- const imgTitle = $a.find('img').attr('title');
- if (imgTitle) ariaLabel = imgTitle;
- } else {
- const text = $a.text().trim();
- if (text) {
- ariaLabel += text;
- } else if ($a.children('span').length === 1) {
- ariaLabel += $a.children('span').text().trim();
- }
- }
+ if (parentATitle && parentATitle.trim() !== '') {
+ // 移除 title 內的視窗提示字眼,只取純文字作為 alt
+ finalAlt = parentATitle.replace(/\(在本視窗開啟\)|\(在新視窗開啟\)/g, '').trim();
+ } else if (nearbyTitle !== '') {
+ finalAlt = nearbyTitle;
+ } else if (isLinkImage) {
+ // 如果是連結圖片且都抓不到文字,給予預設值「連結」避免檢測失敗
+ finalAlt = "連結";
+ }
- if (ariaLabel) {
- $a.attr('aria-label', ariaLabel);
- }
- }
+ $img.attr('alt', finalAlt);
- // ----- title 邏輯 -----
- if (!$a.attr('title')) {
- let titleStr = '';
-
- if ($a.attr('target') === '_blank') {
- titleStr += '在新視窗開啟 ';
- } else if ($a.attr('target') === '_self') {
- titleStr += '在本視窗開啟 ';
- }
-
- if ($a.find('img').length) {
- titleStr = '這是一張照片';
- } else {
- const text = $a.text().trim();
- if (text) {
- titleStr += text;
- } else if ($a.children('span').length === 1) {
- titleStr += $a.children('span').text().trim();
- }
- }
-
- if (titleStr) {
- $a.attr('title', titleStr);
- }
- }
- });
- $('a').each(function () {
- const $link = $(this);
- const linkText = $link.text().trim();
-
- $link.find('img').each(function () {
- const $img = $(this);
- const altText = $img.attr('alt')?.trim();
-
- // 如果圖片 alt 是空的,就略過(已符合)
- if (altText === '') return;
-
- // 如果圖片 alt 等於文字內容,就將 alt 清空,避免重複
- if (altText === linkText) {
- $img.attr('alt', '');
- }
+ // --- 4. 二次清理 ---
+ if (currentTitle !== '' && currentTitle === finalAlt) {
+ $img.removeAttr('title');
+ }
+ }
});
- });
+ }
+ setTimeout(fixImageAccessibility, 500);
+ });
+
+// 有連結目的之所有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 規範)
+ */
+ function fixAccessibilityAll() {
+ // --- 0. 環境與語言偵測 ---
+ //1200ms 後執行(確保所有其他 function 執行完畢後才處理)
+ //Part 1:修正語言選單按鈕
+ //Part 2:掃描所有
+ //├─ 排除 navbar-brand、javascript: 連結
+ //├─ 空連結 → 隱藏
+ //├─ 文字是路徑/空 → 補隱藏 span
+ //├─ 圖片+文字共存 → 圖片 alt 清空
+ //├─ 無 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';
+ 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' : '連結',
+ openImg: isEn ? 'Open image' : '開啟圖片內容',
+ sort: isEn ? 'Sort' : '排序'
+ };
+
+ // --- 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);
+
+ // 【條件 1:排除特定 class】
+ if ($a.hasClass('navbar-brand')) {
+ return;
+ }
+
+ var href = ($a.attr('href') || '').toLowerCase();
+ if (!href || href.startsWith('javascript:')) return;
+
+ // --- 關鍵修正:先偵測是否有原始 title ---
+ var rawTitleAttr = $a.attr('title');
+ var hasOriginalTitle = (typeof rawTitleAttr !== 'undefined' && rawTitleAttr !== false && rawTitleAttr.trim() !== "");
+
+ // 清理 與 空白
+ var linkText = $a.text().replace(/\u00a0/g, '').trim();
+ 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) {
+ $a.hide();
+ return;
+ }
+
+ // --- 【修正 2:文字語意防禦】 ---
+ if ((linkText === "" || linkText.startsWith('/') || linkText.includes('?')) && $img.length === 0 && $icons.length === 0) {
+ var accessibleText = i18n.link;
+ if (href.includes('sort')) {
+ accessibleText = i18n.sort;
+ }
+
+ var $span = $a.find('span');
+ if ($span.length > 0) {
+ $span.text(accessibleText);
+ } else {
+ $a.append('' + accessibleText + '');
+ $span = $a.find('span').last();
+ }
+
+ $span.css({
+ 'display': 'inline-block', 'position': 'absolute', 'width': '1px', 'height': '1px',
+ 'padding': '0', 'margin': '-1px', 'overflow': 'hidden', 'clip': 'rect(0, 0, 0, 0)',
+ 'white-space': 'nowrap', 'border': '0'
+ });
+ linkText = accessibleText;
+ }
+
+ // 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('Open in new window') ||
+ currentTitle.includes('/uploads/');
+
+ if (currentTitle.startsWith('/') || currentTitle.includes('?')) {
+ currentTitle = "";
+ }
+
+ // D. 處理【HM1240400C】:圖片與文字毗鄰時,替代文字只能有一份
+ if (($img.length > 0 || $icons.length > 0) && linkText !== "") {
+ if ($img.length > 0) {
+ $img.attr('alt', '');
+ }
+
+ var $hiddenSpans = $a.find('span').filter(function() {
+ return $(this).css('display') === 'none' || $(this).attr('style')?.includes('display: none');
+ });
+
+ if ($hiddenSpans.length > 0) {
+ $hiddenSpans.each(function() {
+ var $span = $(this);
+ if ($span.text().includes('/uploads/')) {
+ $span.text(i18n.openImg);
+ }
+
+ $span.css({
+ 'display': 'inline-block',
+ 'position': 'absolute',
+ 'width': '1px',
+ 'height': '1px',
+ 'padding': '0',
+ 'margin': '-1px',
+ 'overflow': 'hidden',
+ 'clip': 'rect(0, 0, 0, 0)',
+ 'white-space': 'nowrap',
+ 'border': '0'
+ });
+ });
+ }
+ }
+
+ // E. 重新計算標題 (關鍵邏輯:若 hasOriginalTitle 為真,則不進入此區塊)
+ if (!hasOriginalTitle) {
+ 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 + imgAlt + " " + windowTask).trim());
+ $img.attr('alt', imgAlt);
+ }
+ else if (linkText !== "") {
+ if (fileExt !== "" || hasBadSymbol || currentTitle === "" || currentTitle.includes('/uploads/')) {
+ if (fileExt !== "") {
+ $a.attr('title', linkText + " ." + fileExt + " " + windowTask);
+ } else {
+ $a.attr('title', windowTask);
+ }
+ }
+ }
+ }
+
+ // ✅ 符合 HM1240404E:title 不應與連結文字或圖片 alt 重複
+ if (hasOriginalTitle && currentTitle !== "") {
+ var titleWithoutWindow = currentTitle
+ .replace('(在本視窗開啟)', '')
+ .replace('(在新視窗開啟)', '')
+ .replace('Open in this window', '')
+ .replace('Open in new window', '')
+ .replace('另開新視窗前往', '')
+ .replace('另開新視窗', '')
+ .trim();
+
+ // ✅ title 去掉開窗字串後,若與連結文字或圖片原始 alt 相同,則只保留開窗提示
+ if (
+ (titleWithoutWindow === linkText && linkText !== i18n.link) ||
+ (imgAltOriginal !== '' && titleWithoutWindow === imgAltOriginal)
+ ) {
+ $a.attr('title', windowTask);
+ }
+
+ // ✅ 最終清理:若 title 出現空括號 () 則移除並補上正確開窗提示
+ var finalTitle = ($a.attr('title') || '').trim();
+ if (finalTitle.includes('()')) {
+ finalTitle = finalTitle.replace(/\(\)/g, '').trim();
+ $a.attr('title', finalTitle + ' ' + windowTask);
+ }
+ }
+
+ // 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 執行完畢後才處理
+ setTimeout(function() {
+ fixAccessibilityAll();
+ }, 800);
+});
+
+
+$(function() {
+ function smartFixIcons() {
+ var isEn = $('html').attr('lang') === 'en';
+
+ 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' : '顯示原始圖片'
+ };
+
+ $('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', labels.closePopup);
+ if ($icon.next('.sr-only').length === 0) {
+ $icon.after('' + labels.closePopup + '');
+ }
+ 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;
+ }
+
+ // 特判:.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');
+ }
+ if ($icon.next('.sr-only').length === 0) {
+ $icon.after('' + labels.toggleDesc + '');
+ }
+ return;
+ }
+
+ // 特判:.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')=="")
@@ -836,27 +1319,503 @@
for(var i = 0;i < $('*[data-list] tr td a').length ; i++)
if($('*[data-list] tr td a').eq(i).html().trim()=="")
$('*[data-list] tr td a').eq(i).parent('td').parent('tr').remove();
- // tab按鍵選到menu,會顯示下層的menu(為了符合無障礙)
+ // tab按鍵選到menu,會顯示下層的menu(為了符合無障礙)
$('.nav-level-0>li>a').focus(function(e) {
- e.stopPropagation();
- $(this).parent().focus();
+ e.stopPropagation();
+ $(this).parent().focus();
if ($(this).parent().find('.nav-level-1').hasClass('show')) {
+ // 已有 show,不處理
} else {
- $('.nav-level-1').removeClass('show');
- $(this).parent().find('.nav-level-1').addClass('show');
+ $('.nav-level-1').removeClass('show');
+ $('.nav-level-0>li>.menu-drop').removeClass('opened'); // 先清除其他的 opened
+ $(this).parent().find('.nav-level-1').addClass('show');
+ $(this).parent().find('.menu-drop').addClass('opened'); // 加上 opened
}
});
- $('.nav-level-1>li>a').focus(function(e) {
- e.stopPropagation();
- if ($(this).parent().find('.nav-level-2').hasClass('show')) {
- }else{
- $('.nav-level-2').removeClass('show');
- $(this).parent().find('.nav-level-2').addClass('show');
- }
+
+ $('.nav-level-0>li').on('focusout', function(e) {
+ var $li = $(this);
+ setTimeout(function() {
+ if ($li.find(':focus').length === 0) {
+ $li.find('.nav-level-1').removeClass('show');
+ $li.find('.menu-drop').removeClass('opened'); // 移除 opened
+ }
+ }, 50);
});
- $('show').parent('li').focus();
+
+ $('.nav-level-1>li>a').focus(function(e) {
+ e.stopPropagation();
+ if ($(this).parent().find('.nav-level-2').hasClass('show')) {
+ // 已有 show,不處理
+ } else {
+ $('.nav-level-2').removeClass('show');
+ $('.nav-level-1>li>.menu-drop').removeClass('opened'); // 先清除其他的 opened
+ $(this).parent().find('.nav-level-2').addClass('show');
+ $(this).parent().find('.menu-drop').addClass('opened'); // 加上 opened
+ }
+ });
+
+ $('.nav-level-1>li').on('focusout', function(e) {
+ var $li = $(this);
+ setTimeout(function() {
+ if ($li.find(':focus').length === 0) {
+ $li.find('.nav-level-2').removeClass('show');
+ $li.find('.menu-drop').removeClass('opened'); // 移除 opened
+ }
+ }, 50);
+ });
+
+
+ $('.controlplay a[role="radio"]').on('click', function () {
+ // 取消所有的 aria-checked 並還原文字
+ $('.controlplay a[role="radio"]').attr('aria-checked', 'false');
+ $('.controlplay a[role="radio"] span').each(function () {
+ var text = $(this).text().replace('(已選取)', '');
+ $(this).text(text);
+ });
+
+ // 設定目前被點擊的按鈕為已選取
+ $(this).attr('aria-checked', 'true');
+ var selectedText = $(this).text().trim();
+ $(this).find('span').text(selectedText + '(已選取)');
+ });
+ $(function() {
+ /**
+ * jPlayer 控制項無障礙標籤補強
+ * 1. 修正重複且無意義的 title="按鈕"
+ * 2. 解決鍵盤焦點無法進入隱藏介面的問題
+ */
+ function fixJPlayerAccessibility() {
+ var $playerContainer = $('#jp_container_video_file');
+
+ // --- A. 修正按鈕標題 (解決語義問題) ---
+ $playerContainer.find('button').each(function() {
+ var $btn = $(this);
+ var cls = $btn.attr('class') || '';
+ var newTitle = '';
+
+ // 根據 class 判斷功能
+ if (cls.includes('jp-video-play-icon')) newTitle = '播放影片';
+ else if (cls.includes('jp-play')) newTitle = '播放';
+ else if (cls.includes('jp-stop')) newTitle = '停止';
+ else if (cls.includes('jp-mute')) newTitle = '靜音';
+ else if (cls.includes('jp-volume-max')) newTitle = '最大音量';
+ else if (cls.includes('jp-repeat')) newTitle = '重複播放';
+ else if (cls.includes('jp-full-screen')) newTitle = '全螢幕';
+
+ if (newTitle !== '') {
+ // 修正 title 為具體語義
+ $btn.attr('title', newTitle);
+ // 同時補上 aria-label 確保螢幕閱讀器讀取
+ $btn.attr('aria-label', newTitle);
+ }
+ });
+
+ // --- B. 鍵盤焦點互動修正 (解決 GN1210101E) ---
+ // 當鍵盤 Tab 進入按鈕時,強制讓 UI 介面顯現,否則使用者看不到焦點在哪
+ $playerContainer.on('focusin', 'button', function() {
+ $playerContainer.removeClass('hide-ui');
+ });
+
+ // --- C. CSS 強制補強 (解決 display:none 無法獲取焦點問題) ---
+ // 這是必要的,因為 CSS 若設 display:none,鍵盤永遠進不去
+ $("