This commit is contained in:
ken 2026-06-26 15:37:51 +08:00
parent 63a8fd3354
commit 725758a324
2 changed files with 307 additions and 162 deletions

View File

@ -902,7 +902,7 @@
var isLinkImage = $parentA.length > 0 && $parentA.text().replace(/\u00a0/g, '').trim() === "";
// --- 1. 處理「裝飾性圖片」標註 ---
if (currentAlt === "announcement image" || currentAlt === "裝飾圖片" || currentTitle === "裝飾圖片") {
if (currentAlt === "announcement image" || currentAlt === "裝飾圖片" || currentTitle === "裝飾圖片" || currentAlt === "這是一張圖片" || currentTitle === "這是一張圖片") {
$img.attr('alt', '');
$img.removeAttr('title');
return;
@ -1188,108 +1188,132 @@
}, 800);
});
$(function() {
function smartFixIcons() {
$('i').each(function() {
var $icon = $(this);
var $parent = $icon.parent();
$(function() {
function smartFixIcons() {
var isEn = $('html').attr('lang') === 'en';
// 1. 所有圖示先對螢幕閱讀器隱藏
$icon.attr('aria-hidden', 'true');
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' : '顯示原始圖片'
};
// 特判:.close-screen-btn 內的圖示,移除無關的 sr-only 並設正確 aria-label
if ($parent.hasClass('close-screen-btn')) {
$parent.find('.sr-only').remove();
$parent.attr('aria-label', '關閉公告視窗');
if ($icon.next('.sr-only').length === 0) {
$icon.after('<span class="sr-only">關閉公告視窗</span>');
$('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('<span class="sr-only">' + labels.closePopup + '</span>');
}
return;
}
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', '關閉相簿');
$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">關閉相簿</span>');
// 特判:.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;
}
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', '顯示或隱藏圖片說明');
$toggleBtn.attr('role', 'button');
$toggleBtn.attr('tabindex', '0');
// 特判:.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('<span class="sr-only">' + labels.toggleDesc + '</span>');
}
return;
}
if ($icon.next('.sr-only').length === 0) {
$icon.after('<span class="sr-only">顯示或隱藏圖片說明</span>');
// 特判:.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;
}
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', '切換相簿主題');
$themeBtn.attr('role', 'button');
$themeBtn.attr('tabindex', '0');
// 2. 已有 aria-label 或 sr-only 就不重複處理
if ($icon.attr('aria-label') || $icon.next('.sr-only').length > 0 || $parent.find('.sr-only').length > 0) {
return;
}
if ($icon.next('.sr-only').length === 0) {
$icon.after('<span class="sr-only">切換相簿主題</span>');
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;
}
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 = '日期:';
else if (cls.includes('user') || cls.includes('male')) labelText = '發布者:';
else if (cls.includes('tag')) labelText = '標籤:';
else if (cls.includes('clock') || cls.includes('time')) labelText = '時間:';
else if (cls.includes('map-marker') || cls.includes('location')) labelText = '地點:';
else if (cls.includes('phone')) labelText = '電話:';
else if (cls.includes('envelope') || cls.includes('mail')) labelText = '信箱:';
else if (cls.includes('folder')) labelText = '分類:';
else if (cls.includes('eye')) labelText = '瀏覽次數:';
else if (cls.includes('download')) labelText = '下載檔案:';
// --- 策略 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 = '搜尋';
else if (cls.includes('bars') || cls.includes('navicon')) labelText = '選單';
else if (cls.includes('print')) labelText = '列印此頁';
else if (cls.includes('share')) labelText = '分享至社群';
else if (cls.includes('close') || cls.includes('times')) labelText = '關閉視窗';
else if (cls.includes('image') || cls.includes('photo')) labelText = '顯示原始圖片';
}
// --- 3. 執行補強 ---
if (labelText !== '') {
$icon.after('<span class="sr-only">' + labelText + '</span>');
}
});
}
// 延遲執行確保內容渲染完成
setTimeout(smartFixIcons, 500);
// --- 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')=="")
@ -1514,6 +1538,72 @@ function smartFixIcons() {
resizeTimer = setTimeout(fixAccessKeyM, 150);
});
});
//導覽選單子選單無障礙狀態修正 (支援多層級)
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();
//修正無超連結目的之連結
$(function() {
/**
* 針對所有 href="#" 的連結改為 javascript:void(0);
* 避免使用者點擊後頁面跳回頂端造成操作困擾
*/
function fixEmptyHref() {
$('a[href="#"]').each(function() {
// 將 href 修改為不觸發跳轉的 void 腳本
$(this).attr('href', 'javascript:void(0);');
$(this).attr('role', 'button');
});
}
// 延遲執行,確保動態產生的選單也能被補強
setTimeout(fixEmptyHref, 500);
});
//公告頁籤無障礙
$(function() {
function fixTabLinearOrder() {
@ -1600,71 +1690,6 @@ function smartFixIcons() {
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();
//修正無超連結目的之連結
$(function() {
/**
* 針對所有 href="#" 的連結改為 javascript:void(0);
* 避免使用者點擊後頁面跳回頂端造成操作困擾
*/
function fixEmptyHref() {
$('a[href="#"]').each(function() {
// 將 href 修改為不觸發跳轉的 void 腳本
$(this).attr('href', 'javascript:void(0);');
$(this).attr('role', 'button');
});
}
// 延遲執行,確保動態產生的選單也能被補強
setTimeout(fixEmptyHref, 500);
});
//頁籤無障礙
$(function () {
function fixTabAccessibility() {
@ -3011,11 +3036,130 @@ $(function() {
attributeFilter: ['style']
});
});
// 執行 member等高計算目前改用flexbox故mark掉 by ika 20160105
// $(window).load(function() {
// if ($('.index-member-3').length && $(window).width() > 992) {
// ORBITFRONT.member.equalHeight('.i-member-item-inner');
// }
// });
//萬用表格無障礙
function fixSearchInputA11y() {
$('input[type="search"], input[type="text"]').each(function () {
var $input = $(this);
// 已有對應 label 就跳過
var inputId = $input.attr('id');
if (inputId && $('label[for="' + inputId + '"]').length) return;
// 已有 aria-label / aria-labelledby / title 就跳過
if ($input.attr('aria-label') || $input.attr('aria-labelledby') || $input.attr('title')) return;
// 從 placeholder 取得說明文字
var placeholder = $input.attr('placeholder') || '';
// 從最近的 th 或欄位標題取得欄位名稱
var colName = '';
var $th = $input.closest('th, div[class*="col-"]');
if ($th.length) {
colName = $th.find('.universal-th-text').text().trim();
}
// 組合標籤文字
var label = '';
if (colName && placeholder) {
label = colName + '搜尋';
} else if (colName) {
label = colName + '搜尋';
} else if (placeholder) {
label = placeholder;
} else {
label = '搜尋關鍵字';
}
$input.attr('aria-label', label);
$input.attr('title', label);
});
}
$(document).ready(function () {
setTimeout(fixSearchInputA11y, 500);
});
//萬用表格無障礙
function fixSortLinkA11y() {
$('a').filter(function () {
return $(this).find('.universal-th-icon').length > 0;
}).each(function () {
var $link = $(this);
// === Step 1: 移除 display:none 的 span ===
$link.find('span').each(function () {
if ($(this).css('display') === 'none' || $(this).attr('style') && $(this).attr('style').indexOf('display: none') !== -1) {
$(this).remove();
}
});
// === Step 2: 取得 aria-label ===
var ariaLabel = $link.attr('aria-label') || '';
// 若 aria-label 空白或含未替換模板變數,從旁邊 .universal-th-text 補
if (!ariaLabel || ariaLabel.indexOf('{{') !== -1) {
var $th = $link.closest('th, div[class*="col-"]');
var colName = $th.find('.universal-th-text').text().trim();
ariaLabel = colName ? '重新排序' + colName : '排序';
$link.attr('aria-label', ariaLabel);
}
// === Step 3: 補上 title 屬性 ===
if (!$link.attr('title')) {
$link.attr('title', ariaLabel + '(在本視窗開啟)');
}
// === Step 4: 確保圖示有 aria-hidden ===
$link.find('.universal-th-icon').attr('aria-hidden', 'true');
// === Step 5: 補上 visually-hidden 連結文字 ===
if ($link.find('.visually-hidden').length === 0) {
$link.append('<span class="visually-hidden">' + ariaLabel + '</span>');
}
});
}
function fixSearchInputA11y() {
$('input[type="search"], input[type="text"]').each(function () {
var $input = $(this);
// 已有對應 label 就跳過
var inputId = $input.attr('id');
if (inputId && $('label[for="' + inputId + '"]').length) return;
// 已有 aria-label / aria-labelledby / title 就跳過
if ($input.attr('aria-label') || $input.attr('aria-labelledby') || $input.attr('title')) return;
// 從 placeholder 取得說明文字
var placeholder = $input.attr('placeholder') || '';
// 從最近的 th 或欄位標題取得欄位名稱
var colName = '';
var $th = $input.closest('th, div[class*="col-"]');
if ($th.length) {
colName = $th.find('.universal-th-text').text().trim();
}
// 組合標籤文字
var label = '';
if (colName && placeholder) {
label = colName + '搜尋';
} else if (colName) {
label = colName + '搜尋';
} else if (placeholder) {
label = placeholder;
} else {
label = '搜尋關鍵字';
}
$input.attr('aria-label', label);
$input.attr('title', label);
});
}
$(document).ready(function () {
setTimeout(function () {
fixSortLinkA11y();
fixSearchInputA11y();
}, 500);
});
}(jQuery, window));

View File

@ -2516,8 +2516,9 @@ table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td:first-child:before, tabl
border:0;
&:hover{
.i-annc__content-wrap{
background: radial-gradient(circle at 70% 80%, #66a9e2b3, transparent 60%), radial-gradient(circle at 1% 1%, #fb8f72, transparent 30%), radial-gradient(circle at 50% 50%, #3c78ff4d, transparent 70%), linear-gradient(135deg, #2b7bbe 0%, #00437c 80%, #fb8f72 100%);
background: radial-gradient(circle at 70% 80%, #176bb2b3, transparent 60%), radial-gradient(circle at 1% 1%, #b54c30, transparent 30%), radial-gradient(circle at 50% 50%, rgba(60, 120, 255, 0.301961), transparent 70%), linear-gradient(135deg, #045ea9 0%, #00437c 80%, #cb3f19 100%);
color: #fff!important;
text-shadow: 0px 0px 8px #000000;
i,a,.i-annc__postdate-wrap,.i-annc__category-wrap,.i-annc__title{
color: #fff!important;
}