diff --git a/assets/javascripts/app.js b/assets/javascripts/app.js index 66ddca9..dd79f9a 100644 --- a/assets/javascripts/app.js +++ b/assets/javascripts/app.js @@ -1107,56 +1107,59 @@ $(function() { } } - // 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); - } + // 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(); + // ✅ 符合 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); - } + // ✅ title 去掉開窗字串後,若與連結文字或圖片原始 alt 相同,則只保留開窗提示 + // ✅ 新增:若 linkText 包含副檔名且 title 也是同樣檔名,也只保留開窗提示 + if ( + (titleWithoutWindow === linkText && linkText !== i18n.link) || + (imgAltOriginal !== '' && titleWithoutWindow === imgAltOriginal) || + (fileExt !== '' && linkText.toLowerCase().endsWith('.' + fileExt) && titleWithoutWindow === linkText) + ) { + $a.attr('title', windowTask); + return; // ✅ 加上 return,避免繼續執行後面的清理邏輯造成二次污染 } + // ✅ 最終清理:若 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'); }); @@ -1190,6 +1193,47 @@ $(function() { fixAccessibilityAll(); }, 800); }); +// 修正漢堡選單按鈕無障礙 +$(function() { + function fixNavbarToggleA11y() { + var isEn = $('html').attr('lang') === 'en'; + var label = isEn ? '開啟或關閉導覽選單' : '開啟或關閉導覽選單'; + + $('.navbar-toggle').each(function() { + var $btn = $(this); + + // 修正 title + $btn.attr('title', label); + + // 修正 sr-only 文字(原本是 "Toggle navigation") + var $sr = $btn.find('.sr-only'); + if ($sr.length) { + $sr.text(label); + } else { + $btn.prepend('' + label + ''); + } + + // 補上 aria-label + $btn.attr('aria-label', label); + + // 補上 aria-expanded(依據目前是否展開) + if (!$btn.attr('aria-expanded')) { + var isExpanded = !$btn.hasClass('collapsed'); + $btn.attr('aria-expanded', isExpanded ? 'true' : 'false'); + } + + // 點擊時同步更新 aria-expanded + $btn.off('click.navA11y').on('click.navA11y', function() { + setTimeout(function() { + var isExpanded = !$('.navbar-toggle').hasClass('collapsed'); + $('.navbar-toggle').attr('aria-expanded', isExpanded ? 'true' : 'false'); + }, 50); + }); + }); + } + + setTimeout(fixNavbarToggleA11y, 500); +}); $(function() { @@ -3066,6 +3110,208 @@ $(document).ready(function () { fixSortLinkA11y(); fixSearchInputA11y(); }, 500); +}); +//會員tab邏輯 +$(document).ready(function () { + setTimeout(function () { + $('.dtr-control').removeAttr('tabindex'); + }, 500); +}); +function fixTabKeyboardNav() { + setTimeout(function () { + var $tablist = $('.member-plugins[role="tablist"]'); + var $tabs = $tablist.find('a[role="tab"]'); + + // 初始化 roving tabindex 和 aria-selected + $tabs.each(function (i) { + var $tab = $(this); + var isActive = $tab.closest('li').hasClass('active'); + $tab.attr({ + 'tabindex': isActive ? '0' : '-1', + 'aria-selected': isActive ? 'true' : 'false' + }); + }); + + // 方向鍵切換頁籤 + $tabs.on('keydown', function (e) { + var $current = $(this); + var currentIndex = $tabs.index($current); + var $target; + + if (e.keyCode === 39 || e.keyCode === 40) { + // 右鍵或下鍵:下一個 + e.preventDefault(); + $target = $tabs.eq((currentIndex + 1) % $tabs.length); + } else if (e.keyCode === 37 || e.keyCode === 38) { + // 左鍵或上鍵:上一個 + e.preventDefault(); + $target = $tabs.eq((currentIndex - 1 + $tabs.length) % $tabs.length); + } else if (e.keyCode === 36) { + // Home:第一個 + e.preventDefault(); + $target = $tabs.first(); + } else if (e.keyCode === 35) { + // End:最後一個 + e.preventDefault(); + $target = $tabs.last(); + } else { + return; + } + + // 更新 roving tabindex 和 aria-selected + $tabs.attr({ 'tabindex': '-1', 'aria-selected': 'false' }); + $target.attr({ 'tabindex': '0', 'aria-selected': 'true' }); + $target.focus().trigger('click'); + }); + + // 點擊頁籤時同步更新狀態 + $tabs.on('click', function () { + $tabs.attr({ 'tabindex': '-1', 'aria-selected': 'false' }); + $(this).attr({ 'tabindex': '0', 'aria-selected': 'true' }); + }); + + }, 500); +} +$(document).ready(function () { + fixTabKeyboardNav(); +}); +function removeBareUrlLinks() { + setTimeout(function() { + $('.dataTables_wrapper a').each(function() { + var $a = $(this); + var text = $a.text().trim(); + + if (/^https?:\/\//i.test(text)) { + $a.replaceWith(text); + } + }); + }, 500); +} +$(document).ready(function() { + removeBareUrlLinks(); +}); +//麵包屑無障礙 +$(document).ready(function () { + $('.widget-breadcrumb .breadcrumb li:last-child a').attr('aria-current', 'page'); + + // 若尚未有 nav 包住,自動加上 + $('.widget-breadcrumb .breadcrumb').each(function () { + if (!$(this).closest('nav').length) { + $(this).wrap(''); + } + }); +}); +//gallery view +function fixGalleryViewLinkA11y() { + $('a.btn.view').each(function () { + var $a = $(this); + + $a.find('span').each(function () { + var $span = $(this); + + // 避免重複處理 + if ($span.hasClass('sr-only')) return; + + var style = $span.attr('style') || ''; + if (style.indexOf('display: none') !== -1 || style.indexOf('display:none') !== -1) { + $span.removeAttr('style').addClass('sr-only'); + } + }); + + $a.find('i, svg').attr('aria-hidden', 'true'); + }); +} +$(document).ready(function () { + // 比 fixAccessibilityAll 的 800ms 晚,確保最後執行 + setTimeout(fixGalleryViewLinkA11y, 2000); +}); + +$(function() { + function fixMemberAcademicLinkA11y() { + setTimeout(function() { + $('.i-member-item').each(function() { + var $item = $(this); + + // ✅ 取得該成員的姓名 + var memberName = $item.find('.member-data-value-name a').text().trim(); + if (!memberName) return; + + // ✅ 找到學術歷程連結,補上包含姓名的 title + $item.find('.member-data-value-11 a').each(function() { + var $a = $(this); + var currentTitle = $a.attr('title') || ''; + + // ✅ 移除舊的開窗字串,組合新 title + var titleWithoutWindow = currentTitle + .replace('另開新視窗前往', '') + .replace('在新視窗開啟', '') + .replace('在本視窗開啟', '') + .trim(); + + var isNewWindow = $a.attr('target') === '_blank'; + var windowText = isNewWindow ? ' 在新視窗開啟' : ' 在本視窗開啟'; + + $a.attr('title', memberName + ' ' + titleWithoutWindow + windowText); + }); + }); + }, 500); + } + + fixMemberAcademicLinkA11y(); +}); +//搜尋 +$(document).ready(function() { + + // 開啟 + $('.btn-search-trigger').on('click', function() { + $('#searchOverlay').css('display', 'flex'); + $('body').css('overflow', 'hidden'); + setTimeout(function() { + $('#searchOverlayClose').focus(); // 先 focus 叉叉 + }, 50); + }); + + // 關閉叉叉 + $('#searchOverlayClose').on('click', function() { + closeOverlay(); + }); + + // ESC 關閉 + $(document).on('keydown', function(e) { + if (e.key === 'Escape' && $('#searchOverlay').is(':visible')) { + closeOverlay(); + } + }); + + // focus trap:Tab 鍵只在 overlay 內游走 + $('#searchOverlay').on('keydown', function(e) { + if (e.key !== 'Tab') return; + + var $focusable = $('#searchOverlay').find('button, input, [tabindex]').filter(':visible'); + var $first = $focusable.first(); + var $last = $focusable.last(); + + if (e.shiftKey) { + // Shift + Tab:到第一個就跳回最後一個 + if ($(document.activeElement).is($first)) { + e.preventDefault(); + $last.focus(); + } + } else { + // Tab:到最後一個就跳回第一個 + if ($(document.activeElement).is($last)) { + e.preventDefault(); + $first.focus(); + } + } + }); + + function closeOverlay() { + $('#searchOverlay').css('display', 'none'); + $('body').css('overflow', ''); + $('.btn-search-trigger').focus(); + } + }); // 執行 member等高計算,目前改用flexbox故mark掉 by ika 20160105 // $(window).load(function() { diff --git a/assets/stylesheets/template/base/_accesskey.scss b/assets/stylesheets/template/base/_accesskey.scss index 3fdd8d7..8ac1fb5 100644 --- a/assets/stylesheets/template/base/_accesskey.scss +++ b/assets/stylesheets/template/base/_accesskey.scss @@ -2,7 +2,6 @@ a[accesskey] { position: absolute; - margin-left: -0.9375em; color: transparent ; } diff --git a/assets/stylesheets/template/base/_global.scss b/assets/stylesheets/template/base/_global.scss index f62b7ae..ac0bfdf 100644 --- a/assets/stylesheets/template/base/_global.scss +++ b/assets/stylesheets/template/base/_global.scss @@ -26,16 +26,16 @@ } } } -label[for="open-orbit-login"] { - @media(max-width:768px){ - display: none!important; - } -} -[accesskey="U"],[accesskey="W"]{ - @media(max-width:768px){ - color: #666!important; - } -} +// label[for="open-orbit-login"] { +// @media(max-width:768px){ +// display: none!important; +// } +// } +// [accesskey="U"],[accesskey="W"]{ +// @media(max-width:768px){ +// color: #666!important; +// } +// } .orbit-bar-inner{ [accesskey="U"]{ height: 40px; diff --git a/assets/stylesheets/template/modules/ad_banner.scss b/assets/stylesheets/template/modules/ad_banner.scss index 71cdd1c..6ca5154 100644 --- a/assets/stylesheets/template/modules/ad_banner.scss +++ b/assets/stylesheets/template/modules/ad_banner.scss @@ -8,6 +8,9 @@ // Widget // ## gerenral styles +.w-ba-banner { + position: relative; +} ul.button-mid{ margin:0; z-index: 101; diff --git a/assets/stylesheets/template/modules/archives.scss b/assets/stylesheets/template/modules/archives.scss index db6307c..e39d57c 100644 --- a/assets/stylesheets/template/modules/archives.scss +++ b/assets/stylesheets/template/modules/archives.scss @@ -152,7 +152,7 @@ @extend .unity-title; } .link { background-color: #1368d4 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ -.txt { background-color: #3a8a40 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ +.txt { background-color: #2a7e31 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ .xlsx { background-color: #9e3050 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ .pdf { background-color: #2a7d36 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ .docx { background-color: #5e46a0 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ @@ -161,7 +161,7 @@ .jpg { background-color: #8f3333 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ .zip { background-color: #8a6400 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ .rar { background-color: #9e5000 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ -.xls { background-color: #3a8a40 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ +.xls { background-color: #2a7e31 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ .odt { background-color: #767676 !important; margin-left: 0.5em; } /* 對比 4.6:1 */ .table>caption+thead>tr:first-child>td, .table>caption+thead>tr:first-child>th, .table>colgroup+thead>tr:first-child>td, .table>colgroup+thead>tr:first-child>th, .table>thead:first-child>tr:first-child>td, .table>thead:first-child>tr:first-child>th{ // border-top: 0.0625em solid #ddd; diff --git a/modules/ad_banner/_ad_banner_widget1.html.erb b/modules/ad_banner/_ad_banner_widget1.html.erb index 72699e2..e91a1a5 100644 --- a/modules/ad_banner/_ad_banner_widget1.html.erb +++ b/modules/ad_banner/_ad_banner_widget1.html.erb @@ -65,7 +65,22 @@ }) $('[data-subpart-id="{{subpart-id}}"] .prev-button').click(function(){ $(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle("prev"); - }) + }); + /* 修正點:處理 Pager 無障礙朗讀文字 */ + $('.cycle-slideshow').on('cycle-post-initialize', function(event, optionHash) { + var $container = $(this).closest('.w-ba-banner'); + var $slides = $(this).find('.w-ba-banner__slide'); + var $pagerButtons = $container.find(".banner-pager button"); + + $pagerButtons.each(function(index) { + var slideTitle = $slides.eq(index).data('cycle-title') || ""; + var ariaLabel = "第 " + (index + 1) + " 張投影片 " + slideTitle; + $(this).attr({ + "aria-label": ariaLabel, + "title": ariaLabel + }); + }); + }); \ No newline at end of file diff --git a/modules/archive/archive_index14.html.erb b/modules/archive/archive_index14.html.erb index 1e993a7..f06620a 100644 --- a/modules/archive/archive_index14.html.erb +++ b/modules/archive/archive_index14.html.erb @@ -17,8 +17,7 @@