diff --git a/assets/javascripts/app.js b/assets/javascripts/app.js index 32ac9e6..c23873c 100644 --- a/assets/javascripts/app.js +++ b/assets/javascripts/app.js @@ -2552,6 +2552,276 @@ $(function() { }); }); + // 1. OrbitBar 基礎與搜尋選單邏輯 +$(document).ready(function() { + const isEn = document.documentElement.lang === 'en'; + const $orbitLabel = $('label[for="open-orbit-nav"]'); + const $searchArea = $('.orbit-bar-search-sign-language'); + const $firstInput = $('#q'); // 搜尋框通常是選單內第一個獲焦元素 + + // 初始化屬性 + if (isEn) { + $orbitLabel.attr({ title: 'Site search and language menu', 'aria-label': 'Site search and language menu' }); + } else { + $orbitLabel.attr({ title: '全站搜尋及語言切換選單', 'aria-label': '全站搜尋及語言切換選單' }); + } + $orbitLabel.attr({ 'role': 'button', 'aria-haspopup': 'true', 'aria-expanded': 'false', 'tabindex': '0' }); + + // --- 【修正重點 1】處理 Label 的焦點與按鍵行為 --- + $orbitLabel.on('focusin', function(e) { + var relatedTarget = e.relatedTarget; + // 如果是從選單內部退回來的 (Shift+Tab) + if (relatedTarget && ($searchArea.find(relatedTarget).length > 0)) { + $searchArea.removeClass('show'); + $(this).attr('aria-expanded', 'false'); + } else { + // 正向進入 + $searchArea.addClass('show'); + $(this).attr('aria-expanded', 'true'); + } + }); + + // 強制偵測:在 Label 上按下 Shift+Tab 代表要離開這整塊,立即收合 + $orbitLabel.on('keydown', function(e) { + if (e.shiftKey && e.keyCode === 9) { // Shift + Tab + $searchArea.removeClass('show'); + $searchArea.find('ul').removeClass('show'); + $(this).attr('aria-expanded', 'false'); + } + }); + + // --- 【修正重點 2】處理選單內第一個元素的 Shift+Tab --- + $firstInput.on('keydown', function(e) { + if (e.shiftKey && e.keyCode === 9) { // 在第一個輸入框按 Shift + Tab + // 讓它自然回到 Label,Label 的 focusin 會接手處理收合 + // 這裡不做額外動作,交給上面的 focusin 邏輯 + } + }); + + // --- 【修正重點 3】處理離開大區塊(往後 Tab)的狀態清除 --- + $searchArea.on('focusout', function() { + var $thisArea = $(this); + setTimeout(function() { + if (!$thisArea.is(':focus-within') && !$(document.activeElement).is($orbitLabel)) { + $thisArea.removeClass('show'); + $thisArea.find('ul').removeClass('show'); + $orbitLabel.attr('aria-expanded', 'false'); + $('#languagebutton').attr('aria-expanded', 'false'); + } + }, 150); + }); + + // 點擊行為 + $orbitLabel.on('click', function() { + var isOpen = $searchArea.hasClass('show'); + $searchArea.toggleClass('show', !isOpen); + $(this).attr('aria-expanded', !isOpen); + }); + + // RWD 位置搬移 + function moveSearch() { + if ($(window).width() < 767) { + $searchArea.insertAfter('label[for="open-orbit-nav"]'); + } else { + $searchArea.appendTo('.orbit-bar-inner'); + } + } + moveSearch(); + $(window).resize(moveSearch); +}); + +// 2. 語言按鈕與手機版選單補強 +$(function() { + function fixLanguageA11y() { + var isEn = document.documentElement.lang === 'en'; + var correctTitle = isEn ? 'Open language menu' : '在本視窗開啟語言選單'; + var $desktopBtn = $('#languagebutton'); + var $langLi = $('#language-li'); + var $langUl = $('#language-li ul'); + + // ============================================= + // ✅ 新增 GN1210101E:繁體中文 li 補上可聚焦 + // 桌面版 + 手機版都處理 + // ============================================= + var $activeLis = $langUl.find('li.active') + .add($('#language-li-ul').find('li.active')); + + $activeLis.each(function() { + var $li = $(this); + if ($li.find('a, button').length === 0) { + var activeText = $li.text().trim(); + $li.html( + '' + + activeText + + '' + ); + } + }); + + // ============================================= + // Desktop 語言按鈕 + // ============================================= + if ($desktopBtn.length > 0) { + $desktopBtn.attr({ + 'aria-expanded': 'false', + 'role': 'button', + 'aria-haspopup': 'true', + 'title': correctTitle + }); + $desktopBtn.removeAttr('aria-label'); + + function openLangMenu() { + $langUl.addClass('show'); + $desktopBtn.attr('aria-expanded', 'true'); + $('.orbit-bar-search-sign-language').addClass('show'); + } + function closeLangMenu() { + $langUl.removeClass('show'); + $desktopBtn.attr('aria-expanded', 'false'); + } + + // 原有:focus 展開 + $desktopBtn.on('focus', function() { + openLangMenu(); + }); + + // ✅ 新增 GN1210100E:Enter / Space 切換、Escape 收合 + $desktopBtn.on('keydown', function(e) { + if (e.which === 13 || e.which === 32) { + e.preventDefault(); + $langUl.hasClass('show') ? closeLangMenu() : openLangMenu(); + } + if (e.which === 27) { + closeLangMenu(); + $desktopBtn.focus(); + } + }); + + // 原有:click 切換 + $desktopBtn.on('click', function(e) { + e.preventDefault(); + $langUl.hasClass('show') ? closeLangMenu() : openLangMenu(); + }); + + // ✅ 新增:選單內 Escape 跳回按鈕 + $langUl.find('a').on('keydown', function(e) { + if (e.which === 27) { + e.preventDefault(); + closeLangMenu(); + $desktopBtn.focus(); + } + }); + + // 原有:焦點離開整個 language-li 時收合 + $langLi.on('focusout', function() { + var $container = $(this); + setTimeout(function() { + if (!$container.is(':focus-within')) { + closeLangMenu(); + } + }, 150); + }); + } + + // ============================================= + // 手機版選單補強(原有邏輯完整保留) + // ============================================= + var $mobileBtn = $('.mobile-button'); + if ($mobileBtn.length > 0) { + $mobileBtn.attr({ 'role': 'button', 'tabindex': '0', 'aria-haspopup': 'true', 'aria-expanded': 'false' }); + $mobileBtn.on('focus', function() { + $(this).closest('li').find('ul').addClass('show'); + $(this).attr('aria-expanded', 'true'); + }); + $mobileBtn.on('keydown', function(e) { + if (e.which === 13 || e.which === 32) { + e.preventDefault(); + var $ul = $(this).closest('li').find('ul'); + $ul.toggleClass('show'); + $(this).attr('aria-expanded', $ul.hasClass('show') ? 'true' : 'false'); + } + }); + $('#language-li-ul').on('focusout', function() { + var $container = $(this); + setTimeout(function() { + if (!$container.is(':focus-within')) { + $container.find('ul').removeClass('show'); + $mobileBtn.attr('aria-expanded', 'false'); + } + }, 150); + }); + } + + // ============================================= + // 原有:MutationObserver 強制鎖定 title + // ============================================= + var target = document.getElementById('languagebutton'); + if (target) { + var observer = new MutationObserver(function() { + if (target.getAttribute('title') !== correctTitle) { + target.setAttribute('title', correctTitle); + } + }); + observer.observe(target, { attributes: true, attributeFilter: ['title'] }); + } + } + + setTimeout(fixLanguageA11y, 600); +}); +// rwd左上選單無障礙 +$(function() { + /** + * 修正:當焦點離開整個區塊(含語言選單最後一項)時,關閉大選單 + */ + function fixSearchMenuFocusOut() { + var $searchArea = $('.orbit-bar-search-sign-language'); + var $orbitLabel = $('label[for="open-orbit-nav"]'); + var $langBtn = $('#languagebutton'); + + // 使用 focusout 監聽整個搜尋/語言區域 + $searchArea.on('focusout', function(e) { + // 關鍵:使用 setTimeout 讓 document.activeElement 抓到下一個獲焦元素 + setTimeout(function() { + // 如果目前的焦點不在 $searchArea 裡面,也不是回到觸發的 $orbitLabel 上 + if (!$searchArea.is(':focus-within') && !$(document.activeElement).is($orbitLabel)) { + + // 1. 移除大區塊顯示 + $searchArea.removeClass('show'); + + // 2. 移除子層語言選單顯示 + $searchArea.find('ul').removeClass('show'); + + // 3. 狀態重置為「折疊」供語音報讀 + $orbitLabel.attr('aria-expanded', 'false'); + $langBtn.attr('aria-expanded', 'false'); + } + }, 50); + }); + + // 桌面版 Language 按鈕特殊處理:焦點移入時 + $langBtn.on('focus', function() { + // 確保父層搜尋區塊是顯示的 (針對從別處直接 tab 過來的情況) + $searchArea.addClass('show'); + $(this).attr('aria-expanded', 'true'); + }); + + // 針對手機版 mobile-button (span) 同理處理 + $('.mobile-button').on('focusout', function() { + var $mobileParent = $('#language-li-ul'); + setTimeout(function() { + if (!$mobileParent.is(':focus-within')) { + $mobileParent.find('ul').removeClass('show'); + $('.mobile-button').attr('aria-expanded', 'false'); + } + }, 50); + }); + } + + setTimeout(fixSearchMenuFocusOut, 600); +}); //萬用表格查詢按鈕翻中英 $(document).ready(function () { const lang = $('html').attr('lang'); diff --git a/assets/stylesheets/template/modules/ad_banner.scss b/assets/stylesheets/template/modules/ad_banner.scss index 1ae264a..e06c691 100644 --- a/assets/stylesheets/template/modules/ad_banner.scss +++ b/assets/stylesheets/template/modules/ad_banner.scss @@ -31,7 +31,7 @@ ul.button-mid{ } } .button-mid { - z-index: 100; + z-index: 199; position: absolute; width: 100%; height: 0; diff --git a/assets/stylesheets/template/modules/announcement.scss b/assets/stylesheets/template/modules/announcement.scss index b3a86ca..3cdef12 100644 --- a/assets/stylesheets/template/modules/announcement.scss +++ b/assets/stylesheets/template/modules/announcement.scss @@ -1764,7 +1764,7 @@ a.w-annc__a { // Widget-6 .widget-announcement-6 { .w-annc__postdate{ - border: 2px solid #4d85b5; + border: 2px solid #2978bc; border-radius: 0.5em; display: block; text-align: center; @@ -1774,14 +1774,14 @@ a.w-annc__a { } .w-annc__postdate-year{ display: block; - background: #4d85b5; + background: #2978bc; padding: 0.2em; color: #fff; } .w-annc__postdate-md{ display: block; padding: 0.2em; - color: #4d85b5; + color: #2978bc; } .w-annc__category{ margin: 0px 0px 0px 0px; @@ -1847,7 +1847,7 @@ a.w-annc__a { // Widget-7 .widget-announcement-7 { .w-annc__postdate{ - border: 2px solid #4d85b5; + border: 2px solid #2978bc; border-radius: 0.5em; display: block; text-align: center; @@ -1857,14 +1857,14 @@ a.w-annc__a { } .w-annc__postdate-year{ display: block; - background: #4d85b5; + background: #2978bc; padding: 0.2em; color: #fff; } .w-annc__postdate-md{ display: block; padding: 0.2em; - color: #4d85b5; + color: #2978bc; } .w-annc__category{ margin: 0px 0px 0px 0px; @@ -2004,7 +2004,7 @@ a.w-annc__a { // Widget-10 .widget-announcement-10 { .w-annc__postdate{ - border: 2px solid #4d85b5; + border: 2px solid #2978bc; border-radius: 0.5em; display: block; text-align: center; @@ -2014,14 +2014,14 @@ a.w-annc__a { } .w-annc__postdate-year{ display: block; - background: #4d85b5; + background: #2978bc; padding: 0.2em; color: #fff; } .w-annc__postdate-md{ display: block; padding: 0.2em; - color: #4d85b5; + color: #2978bc; } .w-annc__item { &:hover{ @@ -2782,7 +2782,7 @@ table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td:first-child:before, tabl } } .i-annc__postdate{ - border: 2px solid #4d85b5; + border: 2px solid #2978bc; border-radius: 0.5em; display: block; text-align: center; @@ -2792,14 +2792,14 @@ table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td:first-child:before, tabl } .i-annc__postdate-year{ display: block; - background: #4d85b5; + background: #2978bc; padding: 0.2em; color: #fff; } .i-annc__postdate-md{ display: block; padding: 0.2em; - color: #4d85b5; + color: #2978bc; } .i-annc__item { margin-bottom: 0; @@ -2834,7 +2834,7 @@ table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td:first-child:before, tabl .index-announcement-3, .index-announcement-4 { .i-annc__postdate{ - border: 2px solid #4d85b5; + border: 2px solid #2978bc; border-radius: 0.5em; display: block; text-align: center; @@ -2844,14 +2844,14 @@ table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td:first-child:before, tabl } .i-annc__postdate-year{ display: block; - background: #4d85b5; + background: #2978bc; padding: 0.2em; color: #fff; } .i-annc__postdate-md{ display: block; padding: 0.2em; - color: #4d85b5; + color: #2978bc; } .i-annc__item { diff --git a/modules/ad_banner/_ad_banner_widget2.html.erb b/modules/ad_banner/_ad_banner_widget2.html.erb index dd8b863..e7c9f79 100644 --- a/modules/ad_banner/_ad_banner_widget2.html.erb +++ b/modules/ad_banner/_ad_banner_widget2.html.erb @@ -21,7 +21,7 @@ data-cycle-title="{{title}}" data-cycle-desc="{{context}}" data-overlay-template="

{{title}}

{{desc}}" - data-target="{{target}}" + data-bs-target="{{target}}" > @@ -29,10 +29,7 @@ - - + - + -