From d9a416d9c8c0e9df5dbb7b63b9d69de73268c42a Mon Sep 17 00:00:00 2001 From: ken Date: Tue, 8 Sep 2026 12:33:18 +0800 Subject: [PATCH] update --- assets/javascripts/app.js | 375 ++++++++++++++++-- assets/stylesheets/template/base/_global.scss | 11 +- modules/announcement/annc_index18.html.erb | 2 +- modules/announcement/annc_index19.html.erb | 4 +- modules/announcement/annc_index5.html.erb | 4 +- modules/announcement/annc_index6.html.erb | 4 +- .../event_news_mod/event_news_index5.html.erb | 2 +- .../event_news_mod/event_news_index6.html.erb | 2 +- .../event_news_mod/event_news_index7.html.erb | 2 +- modules/member/member_index2.html.erb | 2 +- modules/universal_table/index3.html.erb | 5 +- modules/universal_table/index7.html.erb | 5 +- .../web_resource/_web_res_widget8.html.erb | 3 +- modules/web_resource/web_res_index1.html.erb | 2 +- modules/web_resource/web_res_index2.html.erb | 2 +- 15 files changed, 364 insertions(+), 61 deletions(-) diff --git a/assets/javascripts/app.js b/assets/javascripts/app.js index b08e93a..ec23187 100644 --- a/assets/javascripts/app.js +++ b/assets/javascripts/app.js @@ -532,20 +532,28 @@ $(function () { }); //播放驗證碼語音 $(function () { - $('.ask-question') - .find('.controls button.fas.fa-volume-up') - .each(function () { - const $btn = $(this); + var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase(); + var isEn = pageLang.startsWith('en'); + var label = isEn ? 'Play Captcha Voice' : '播放驗證碼語音'; - // 已經補過就不重複處理 - if ($btn.attr('aria-label')) return; + $('.ask-question') + .find('.controls button.fas.fa-volume-up') + .each(function () { + var $btn = $(this); - $btn.attr({ - 'aria-label': '播放驗證碼語音', - 'aria-controls': 'captcha_audio', - 'role': 'button' - }); - }); + $btn.attr({ + 'aria-label': label, + 'title': label, + 'aria-controls': 'captcha_audio', + 'role': 'button' + }); + + // ✅ 同步更新 sr-only 文字(若有) + var $sr = $btn.find('.sr-only'); + if ($sr.length > 0) { + $sr.text(label); + } + }); }); //刪除td的id @@ -916,7 +924,7 @@ $(function () { var isLinkImage = $parentA.length > 0 && $parentA.text().replace(/\u00a0/g, '').trim() === ""; // --- 1. 處理「裝飾性圖片」標註 --- - if (currentAlt === "announcement image" || currentAlt === "裝飾圖片" || currentTitle === "裝飾圖片" || currentAlt === "這是一張圖片" || currentTitle === "這是一張圖片") { + if (currentAlt === "announcement image" || currentAlt === "裝飾圖片" || currentTitle === "裝飾圖片" || currentAlt === "這是一張圖片" || currentTitle === "這是一張圖片"||currentAlt === "This is a image" ||currentTitle === "This is a image"){ $img.attr('alt', ''); $img.removeAttr('title'); return; @@ -3103,11 +3111,15 @@ $(document).ready(function () { }); //post $(document).ready(function () { - setTimeout(function () { - $('iframe.twitter-share-button, iframe.twitter-tweet-button').each(function () { - $(this).attr('title', '分享至 X 在新視窗開啟'); - }); - }, 1500); + setTimeout(function () { + var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase(); + var isEn = pageLang.startsWith('en'); + var title = isEn ? 'Share to X Open in new window' : '分享至 X 在新視窗開啟'; + + $('iframe.twitter-share-button, iframe.twitter-tweet-button').each(function () { + $(this).attr('title', title); + }); + }, 1500); }); $(function() { function bindIframeFocus() { @@ -3334,13 +3346,141 @@ function fixSearchInputA11y() { $input.attr('title', label); }); } - $(document).ready(function () { setTimeout(function () { fixSortLinkA11y(); fixSearchInputA11y(); }, 500); }); +//萬用表格input +$(function() { + function fixUniversalSearchLabelA11y() { + setTimeout(function() { + var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase(); + var isEn = pageLang.startsWith('en'); + + $('.universal-dropdown').each(function(index) { + var $dropdown = $(this); + var $input = $dropdown.find('input[type="text"], input[type="search"]').first(); + if ($input.length === 0) return; + + // ✅ 優先從 .universal-th-text 取欄位名稱 + var labelText = $dropdown.closest('[class*="col-"]').find('.universal-th-text').first().text().trim(); + + // ✅ 備援 + if (!labelText) { + labelText = ($input.attr('placeholder') || '').trim(); + } + if (!labelText) { + labelText = isEn ? 'Search' : '搜尋'; + } + + // ✅ 補上唯一 id(若已有就沿用) + var inputId = $input.attr('id') || ('universal-search-input-' + index); + $input.attr('id', inputId); + + // ✅ 更新 label 文字(移除舊的再插入新的) + $('label[for="' + inputId + '"]').remove(); + $input.before(''); + + // ✅ 同步 aria-label 和 title + $input.attr({ + 'aria-label': labelText, + 'title': labelText + }); + }); + + // ✅ 修正 submit 按鈕的無意義 title + $('.theadsearch2 button[type="submit"]').each(function() { + var $btn = $(this); + var btnText = $btn.text().trim() || $btn.attr('aria-label') || ''; + if (btnText) { + $btn.attr('title', isEn ? btnText + ' Open in this window' : btnText + ' 在本視窗開啟'); + } + }); + + }, 500); + } + + fixUniversalSearchLabelA11y(); +}); +//萬用表格顯示狀態訊息 +$(function() { + function fixSearchResultStatusA11y() { + setTimeout(function() { + var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase(); + var isEn = pageLang.startsWith('en'); + + // ✅ 加上 role="status" live region(若還沒有的話) + if ($('#search-result-status').length === 0) { + $('body').append( + '
' + ); + } + + // ✅ 計算目前搜尋結果數量並通知 + function announceResultCount() { + var $rows = $('.universal-table-show tbody tr:visible'); + var count = $rows.length; + + // ✅ 只取有值的欄位,且去除重複 + var keywords = []; + $('input[name^="q["]').each(function() { + var val = $(this).val().trim(); + if (val && keywords.indexOf(val) === -1) { + keywords.push(val); + } + }); + var keyword = keywords.join(' ').trim(); + + var message = ''; + if (isEn) { + message = keyword + ? 'Search results for "' + keyword + '": ' + count + ' items found.' + : count + ' items found.'; + } else { + message = keyword + ? '搜尋「' + keyword + '」的結果:共找到 ' + count + ' 筆資料。' + : '共找到 ' + count + ' 筆資料。'; + } + + // ✅ 清空再設定,確保 aria-live 每次都觸發 + $('#search-result-status').text(''); + setTimeout(function() { + $('#search-result-status').text(message); + }, 100); + } + + // ✅ 頁面載入時播報目前結果數 + announceResultCount(); + + // ✅ 搜尋按鈕點擊後播報 + $(document).on('click', '.theadsearch2 button[type="submit"], #search-submit', function() { + setTimeout(function() { + announceResultCount(); + }, 1000); + }); + + // ✅ AJAX 結果更新時用 MutationObserver 監聽 + var $tableBody = $('.universal-table-show tbody'); + if ($tableBody.length > 0) { + var observer = new MutationObserver(function() { + setTimeout(function() { + announceResultCount(); + }, 300); + }); + + observer.observe($tableBody[0], { + childList: true, + subtree: true + }); + } + + }, 800); + } + + fixSearchResultStatusA11y(); +}); setTimeout(function() { $('.tdken').each(function() { var $tr = $(this); @@ -3463,31 +3603,58 @@ $(document).ready(function () { }); $(function() { - function fixSearchBtnNewWindowA11y() { - setTimeout(function() { - // ✅ 找所有 target="_blank" 的搜尋 form 裡的送出按鈕 - $('form[target="_blank"] .btn-search').each(function() { - var $btn = $(this); +function fixVoicePlayerA11y() { + setTimeout(function() { + $('a.voice-player').each(function() { + var $a = $(this); - $btn.attr('aria-label', '全站搜尋 在新視窗開啟'); - $btn.attr('title', '全站搜尋 在新視窗開啟'); + // ✅ 移除「在本視窗開啟」的 title,因為這是播放按鈕不是連結 + var currentTitle = ($a.attr('title') || '').trim(); + if (currentTitle === '在本視窗開啟' || currentTitle === 'Open in this window') { + $a.removeAttr('title'); + } - // ✅ 更新 sr-only 文字 - var $sr = $btn.find('.sr-only'); - if ($sr.length > 0) { - $sr.text('全站搜尋 在新視窗開啟'); - } else { - $btn.append('全站搜尋 在新視窗開啟'); + // ✅ 補上 role="button" + $a.attr('role', 'button'); + + // ✅ 補上 tabindex 確保可被 Tab 聚焦 + if (!$a.attr('tabindex')) { + $a.attr('tabindex', '0'); + } + + // ✅ 補上 aria-pressed 初始狀態(未播放) + $a.attr('aria-pressed', 'false'); + + // ✅ Enter / Space 觸發點擊 + $a.off('keydown.voiceA11y').on('keydown.voiceA11y', function(e) { + if (e.which === 13 || e.which === 32) { + e.preventDefault(); + $(this).trigger('click'); } }); - // ✅ 同步修正搜尋 input 的 title - $('form[target="_blank"] .input-search').each(function() { - $(this).attr('title', '全站搜尋'); - }); + // ✅ 點擊時切換 aria-pressed 和圖示狀態 + $a.off('click.voiceA11y').on('click.voiceA11y', function() { + var $btn = $(this); + var $icon = $btn.find('i.fa'); + var isPlaying = $icon.hasClass('fa-pause'); - }, 500); - } + if (isPlaying) { + $icon.removeClass('fa-pause').addClass('fa-play'); + $btn.attr('aria-pressed', 'false'); + } else { + $('a.voice-player').not($btn).each(function() { + $(this).find('i.fa').removeClass('fa-pause').addClass('fa-play'); + $(this).attr('aria-pressed', 'false'); + }); + $icon.removeClass('fa-play').addClass('fa-pause'); + $btn.attr('aria-pressed', 'true'); + } + }); + }); + + }, 500); +} fixSearchBtnNewWindowA11y(); }); @@ -3543,4 +3710,136 @@ $(function() { fixVoicePlayerA11y(); }); +//bannercontrolplay +$(function() { + function fixBannerPlayPauseA11y() { + setTimeout(function() { + var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase(); + var isEn = pageLang.startsWith('en'); + + var i18n = { + resume: isEn ? 'Play' : '繼續播放', + pause: isEn ? 'Pause' : '暫停播放' + }; + + $('.w-ba-banner').each(function() { + var $banner = $(this); + var $controlplay = $banner.find('.controlplay'); + + // ✅ 把 radiogroup 改為一般容器 + $controlplay.removeAttr('role aria-label'); + + // ✅ 繼續播放按鈕 + var $resume = $banner.find('.resume-slide'); + $resume + .attr('role', 'button') + .attr('aria-pressed', $resume.hasClass('active') ? 'true' : 'false') + .attr('aria-label', i18n.resume) + .attr('title', i18n.resume) + .removeAttr('aria-checked aria-live'); + + // ✅ 暫停播放按鈕 + var $pause = $banner.find('.pause-slide'); + $pause + .attr('role', 'button') + .attr('aria-pressed', $pause.hasClass('active') ? 'true' : 'false') + .attr('aria-label', i18n.pause) + .attr('title', i18n.pause) + .removeAttr('aria-checked aria-live'); + + // ✅ 點擊後同步 aria-pressed + $resume.off('click.bannerA11y').on('click.bannerA11y', function() { + $resume.attr('aria-pressed', 'true'); + $pause.attr('aria-pressed', 'false'); + }); + + $pause.off('click.bannerA11y').on('click.bannerA11y', function() { + $pause.attr('aria-pressed', 'true'); + $resume.attr('aria-pressed', 'false'); + }); + }); + + }, 800); + } + + fixBannerPlayPauseA11y(); +}); + //banner英文 + $(function() { + function fixBannerA11yByLang() { + setTimeout(function() { + var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase(); + var isEn = pageLang.startsWith('en'); + + var i18n = { + playControls: isEn ? 'Playback Controls' : '播放控制選項', + resume: isEn ? 'Play' : '繼續播放', + pause: isEn ? 'Pause' : '暫停播放', + prev: isEn ? 'Previous' : '上一張', + next: isEn ? 'Next' : '下一張', + slide: isEn ? 'Slide' : '第', + slideUnit: isEn ? '' : ' 張投影片' + }; + + $('.w-ba-banner').each(function() { + var $banner = $(this); + + // ✅ 播放控制選項 radiogroup label + $banner.find('.controlplay').attr('aria-label', i18n.playControls); + + // ✅ 繼續播放按鈕 + $banner.find('.resume-slide').attr({ + 'aria-label': i18n.resume, + 'title': i18n.resume + }); + $banner.find('.resume-slide p').text(i18n.resume); + + // ✅ 暫停播放按鈕 + $banner.find('.pause-slide').attr({ + 'aria-label': i18n.pause, + 'title': i18n.pause + }); + $banner.find('.pause-slide p').text(i18n.pause); + + // ✅ 上一張按鈕 + $banner.find('.prev-button').attr('aria-label', i18n.prev); + + // ✅ 下一張按鈕 + $banner.find('.next-button').attr('aria-label', i18n.next); + + // ✅ Pager 按鈕 + var $slides = $banner.find('.w-ba-banner__slide'); + $banner.find('.banner-pager button').each(function(index) { + var slideTitle = $slides.eq(index).data('cycle-title') || ''; + var ariaLabel = isEn + ? i18n.slide + ' ' + (index + 1) + (slideTitle ? ' ' + slideTitle : '') + : i18n.slide + (index + 1) + i18n.slideUnit + (slideTitle ? ' ' + slideTitle : ''); + $(this).attr({ + 'aria-label': ariaLabel, + 'title': ariaLabel + }); + }); + }); + + // ✅ Cycle2 初始化後也重新處理 Pager(因為 pager 是動態產生的) + $('.w-ba-banner .cycle-slideshow').on('cycle-post-initialize cycle-after', function() { + var $banner = $(this).closest('.w-ba-banner'); + var $slides = $banner.find('.w-ba-banner__slide'); + $banner.find('.banner-pager button').each(function(index) { + var slideTitle = $slides.eq(index).data('cycle-title') || ''; + var ariaLabel = isEn + ? i18n.slide + ' ' + (index + 1) + (slideTitle ? ' ' + slideTitle : '') + : i18n.slide + (index + 1) + i18n.slideUnit + (slideTitle ? ' ' + slideTitle : ''); + $(this).attr({ + 'aria-label': ariaLabel, + 'title': ariaLabel + }); + }); + }); + + }, 800); + } + + fixBannerA11yByLang(); + }); }(jQuery, window)); diff --git a/assets/stylesheets/template/base/_global.scss b/assets/stylesheets/template/base/_global.scss index 05a6e24..8c69c1e 100644 --- a/assets/stylesheets/template/base/_global.scss +++ b/assets/stylesheets/template/base/_global.scss @@ -6,6 +6,11 @@ .fa-classic, .fa-regular, .fa-solid, .far, .fas ,.fa{ font-family: "FontAwesome"; } +li#language-li { + @media(max-width:767px){ + display: none !important; + } +} #orbit-bar .orbit-bar-inner > label:focus, #orbit-bar .orbit-bar-inner > label.focus{ .orbit-bar-search-sign-language{ display: block @@ -209,6 +214,6 @@ img{ // overflow-x: auto; // } // } -*[data-pp]>.editmode-ps>a, .admin-subpart-area .content>.editmode-ps>a{ - position: !important; -} \ No newline at end of file +input[type=checkbox]:focus { + outline: 0.3125em auto -webkit-focus-ring-color; +} diff --git a/modules/announcement/annc_index18.html.erb b/modules/announcement/annc_index18.html.erb index 778bb74..6ecfb02 100644 --- a/modules/announcement/annc_index18.html.erb +++ b/modules/announcement/annc_index18.html.erb @@ -3,7 +3,7 @@