From 50bef511c20b09f08e7df417d9c0a62dda88e33e Mon Sep 17 00:00:00 2001 From: ken Date: Tue, 7 Apr 2026 21:52:39 +0800 Subject: [PATCH] 'orbitbar' --- assets/javascripts/app.js | 59 ++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/assets/javascripts/app.js b/assets/javascripts/app.js index 5dfbb49..ad029fc 100644 --- a/assets/javascripts/app.js +++ b/assets/javascripts/app.js @@ -2164,37 +2164,56 @@ $(document).ready(function() { //導覽選單與語言按鈕無障礙補強 (人工檢測完全合格版) $(function() { /** - * 1. 修正 Language 按鈕:統一 Title 為「在本視窗開啟語言選單」。 - * 2. 轉換次選單語意:針對有下拉選單的連結,增加 role="button"。 - * 3. 狀態即時回饋:動態切換 aria-expanded (true/false)。 - * 4. 移除 Title 冗餘:避免連結文字與 Title 重複讀取。 + * 語言按鈕無障礙補強 (MutationObserver 鎖定版) + * 目的:防止導覽套件在 Focus/Click 時將 Title 抽換為「按下關閉語言選單」 */ - function forceFixLanguageButton() { + function forceFixLanguageButton() { var $langBtn = $('#languagebutton'); + var target = document.getElementById('languagebutton'); // 原生 DOM 用於 Observer - if ($langBtn.length > 0) { - // 1. 初始強制修正 - $langBtn.attr('title', '在本視窗開啟語言選單'); + 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. 針對 WAI-ARIA 屬性同步修正 - $langBtn.attr({ - 'role': 'button', - 'aria-expanded': 'false', - '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); + } + }); }); - // 3. 重要:防止被其他套件改回去 (監聽屬性變動) - // 或是簡單透過點擊事件再次確保 title 正確 + // 開始監聽屬性變動 + observer.observe(target, { attributes: true }); + + // 4. 事件補強:針對點擊與聚焦再次確保 (雙重保險) $langBtn.on('click focusin', function() { - // 當按鈕被點擊或獲取焦點時,再次確保 title 是我們要的 - // 有些套件會在點擊後把 title 改成 "關閉" - $(this).attr('title', '在本視窗開啟語言選單'); + enforceA11y(this); }); } } - // 延遲執行確保 DOM 渲染與套件初始化完成 - setTimeout(forceFixLanguageButton, 500); + // 延遲 600ms 執行,確保避開大部份套件的初始載入時間 + setTimeout(forceFixLanguageButton, 600); }); //修正無超連結目的之連結 $(function() {