;(function($, win, undefined) { // ECMAScript 5 嚴格模式 'use strict'; $(function() { var $signLanguageBox = $('.orbit-bar-search-sign-language'); var $headerNav = $('.header-nav'); var $target = $('.header-nav [accesskey="U"], .header-nav [accesskey="W"]'); // 移除 color: inherit !important $target.each(function() { $(this)[0].style.removeProperty('color'); }); function handleNavMove() { var windowWidth = window.innerWidth; if (windowWidth > 768) { if ($signLanguageBox.length && $signLanguageBox.find('[accesskey="U"], [accesskey="W"]').length === 0) { $signLanguageBox.prepend($target); } } else { if ($headerNav.length && $headerNav.find('[accesskey="U"], [accesskey="W"]').length === 0) { $headerNav.append($target); } } } handleNavMove(); $(window).on('resize', function() { handleNavMove(); }); }); //header fixed在上方 function initdata1() { if ( $('.homebanner').length != 0) { $('.layout-header').css('height', ''); var scrollTop = $(window).scrollTop(); var scrollBottom = $('html').height() - $(window).height() - $('.layout-header').height(); if (scrollTop>5 && scrollBottom>0) { /* 要滑動到選單的距離 */ if (parseInt($('.index-layout-content').css('margin-top'))==0){ } $('.outdropdowns').addClass('navFixed'); /* 幫選單加上固定效果 */ } else { if ($('.homebanner').html().trim() == "") { $('.outdropdowns').removeClass('navFixed'); }else{ $('.outdropdowns').removeClass('navFixed'); /* 移除選單固定效果 */ } } } } // 初始函數: 把所有的程式碼都包在init裡面,方便在之後的jQuery ready 函數裡一次呼叫 function init() { // 快取一些常用的變數 var doc = document; var lang = doc.documentElement.lang; var pageModule = doc.body.getAttribute('data-module'); var resizeTimer = -1; // 把所有的函數都包在orbit這個物件裡並按模組做簡單的分類 var orbit = { // 工具函數,裡面包含可以重覆使用的函數 utils: { // 字數限制函數, 因為系統預設沒有,所以使用JS來做 // els = 元素, maxLen = 限制長度 truncateText: function(els, maxLen) { var els = doc.querySelectorAll(els); var newTitle = ''; var i = -1; var elsLen = els.length; for (i = 0; i < elsLen; i++) { if (els[i].firstChild !== null) { if (els[i].firstChild.length > maxLen) { newTitle = els[i].firstChild.textContent; els[i].textContent = newTitle.substring(0, maxLen) + '...'; } } } } }, // 外掛,所有的外掛都可以放到這個物件裡 // plugins: { // // 自適應圖片裁切,Ray的外掛 // bullEye: function() { // $('.bullseye').bullseye({ // fadeEffect: false // }); // } // }, member: { // 欄位相同高度,小心這個函數沒有計算到圖片高度,所以可能要搭配 jQuery load函數使用,或是之後使用更好的方式例如 CSS3 flexbox equalHeight: function(el) { var bigbrother = -1; var $el = $(el); $el.each(function(i) { bigbrother = bigbrother > $el.eq(i).height() ? bigbrother : $el.eq(i).height(); }); $el.height(bigbrother); }, // 把沒有完成資料的表格列藏起來, 因為後台不管有沒有資料都會輸出項目,所以需要在前台藏起來… removeEmptyRow: function() { // index 頁面項目 $('.i-member-profile-item .i-member-value').each(function() { if ($(this).text().trim() === '' || $(this).text().trim() === ':') { $(this).parent().addClass('hide'); } }); // show 頁面項目 $('.show-member .member-data th, .show-member .member-data td').each(function() { if ($(this).text().trim() === '') { $(this).parent('tr').addClass('hide'); } }); }, }, archives: { // 把沒有文字內容的標題藏起來,因為就算是標題裡沒有文字系統仍然會輸出,這樣會造成一些多餘的CSS margins, paddings,或許之後也可以使用 CSS3 :empty selector 處理 // el = 要移除的元素 removeEmptyTitle: function(el) { var $el = $(el); var $els = $el.children(); $.each($els, function(i, val) { if ($els.eq(i).text().trim() === '') { $els.eq(i).addClass('hide'); } }); $.each($el, function(i, val) { if ($el.eq(i).children('.hide').length >= 2) { $el.eq(i).addClass('hide'); } }); }, // bootstarp panel 功能擴充,因為原本的功能不支援多個panel extendPanel: function() { var len = $('.i-archive .panel-title').length; var i = -1; if (len > 0) { // 新增數字到要對應的panel按鈕id及href上面 for (i = 0; i < len; i++) { $('.panel-title:eq(' + i + ') .collapsed').attr('href', '#collapse' + i); $('.panel-collapse:eq(' + i + ')').attr('id', 'collapse' + i); } } } }, adBanner: { // 讓AD banner 的圖片可以點選,因為系統預設輸出的圖片是沒有連結的 // els = 要可以點選的元素(需要配合有data-link這個參數及data-targe才能使用) addLinkOnADBanner: function(els) { $.each(els, function() { if ($(this).data('link') !== '' && !$(this).hasClass('youtube')) { $(this).on('click', function() { var target = $(this).data('target'); var link = $(this).data('link'); // 設定頁面打開的方式,記得要加上data-target在HTML裡面 if (target === '_blank') { window.open(link, target); } else { window.location.href = link; } }).addClass('cursor'); // cursor類別樣式定義在CSS裡面 } }); }, }, // 移除行動版下拉選單 removeDropdown: function() { var $nav = $('#main-nav'); $nav .find('.menu-drop') .remove(); $nav .find('.opened') .removeClass('opened'); }, // 網站次選單設定,如果次選單有第三層就新增下拉選單的圖示及加上bootstrap class // els = 選單元素 sitemenuDropdown: function(els) { var els = doc.querySelectorAll('.sitemenu-list.level-2'); var len = els.length; var i = -1; var caret = null; for (i = 0; i < len; i++) { if (els[i].children.length) { caret = doc.createElement('span'); caret.className = 'sitemenu-dropdown-toggle fa fa-caret-down'; caret.setAttribute('data-toggle', 'dropdown'); els[i].parentNode.insertBefore(caret, els[i]); els[i].className += ' dropdown-menu'; } } }, // 回到頁面最頂端,動態產生DOM // txt = 按鈕的文字, speed = 捲動時的速度 goBackTop: function(txt, speed) { var top = document.createElement('div'); top.className = 'go-back-top no-print'; top.textContent = txt || 'top'; doc.body.appendChild(top); // 判斷是否顯示按鈕 $(window).scroll(function() { if ($(this).scrollTop() !== 0) { $('.go-back-top').fadeIn(); } else { $('.go-back-top').fadeOut(); } }); // 捲動效果 $('.go-back-top').on('click', function() { $('body, html').animate({ scrollTop: 0 }, speed || 300); return false; }); }, // Multi-column layout, passing ID or class string as parameters and a // Bootstrap col class for full width, eg: col-md-12 setColumn: function(leftCol, rightCol, columnCls) { var $leftCol = $(leftCol); var $rightCol = $(rightCol); var columnCls = columnCls || 'col-sm-12'; if ($leftCol.length && $rightCol.length) { $.each([$leftCol, $rightCol], function() { if ($(this).is(':empty')) { $(this) .addClass('empty-column') .siblings() .removeClass(function(index, css) { return (css.match(/(^|\s)col-\S+/g) || []).join(' '); }) .addClass(columnCls); } }); } }, MobileMenu: function() { var $menu = $('[data-menu-level="0"]'); $menu.find('ul[data-menu-level="1"]').parent().addClass('mobile-menu1'); $menu.find('ul[data-menu-level="2"]').parent().addClass('mobile-menu2'); var $caret1 = $(''); var $caret2 = $(''); // 如果有第二層選單,新增對應的類別到parent元素上 $('.nav-level-1') .parent('li') .addClass('has-dropdown level-1'); // 檢查是否已經有dropdown-toggle-icon這個元素,才不會在resize事件中重覆新增 if ($('.has-dropdown.level-1 .menu-drop').length < 1) { $('.mobile-menu1').append($caret1); // 如果有第三層選單,新增對應的類別到parent元素上 $('.nav-level-2') .parent('li') .addClass('has-dropdown level-2'); $caret2.appendTo('.has-dropdown.level-2'); } }, ClickMenuHandler: function() { // 處理主選單切換(漢堡 icon) $(document).on('click', '.navbar-toggle', function (e) { e.preventDefault(); // 確保 .navbar-toggle 放到 .modules-menu 後面 $('.mobile-menu').each(function () { var $menu = $(this); if ($menu.find('.modules-menu').length && !$menu.find('.modules-menu + .navbar-toggle').length) { $menu.find('.modules-menu').after($menu.find('.navbar-toggle')); } }); $('.mobile-menu').toggleClass('active'); $('body').toggleClass('noscroll'); $('.mobile-menu .navbar-toggle').removeClass('collapsed'); // 關閉所有下拉選單 $('.mobile-menu1 > ul, .mobile-menu2 > ul').slideUp(500); $('.mobile-menu1 > .menu-drop, .mobile-menu2 > .menu-drop').removeClass('opened'); // 無障礙:聚焦第一個互動元素 if ($('.mobile-menu').hasClass('active')) { setTimeout(function () { $('.modules-menu').find('input, button, select, textarea, a').first().focus(); }, 100); } }); $('.mobile-menu1 > .menu-drop').click(function(){ var $that = $(this); var opencheck1 = $that.hasClass('opened'); if ( opencheck1 == 0 ) { $('.mobile-menu1 > ul').not($that.siblings('ul')).slideUp(500); $('.mobile-menu1 > .menu-drop').not($that).removeClass('opened'); $('.mobile-menu2 > ul').slideUp(500); $('.mobile-menu2 > .menu-drop').removeClass('opened'); $that.siblings('ul').slideDown(500); $that.addClass('opened'); } else if (opencheck1 == 1) { $that.siblings('ul').slideUp(500); $('.mobile-menu2 > ul').slideUp(500); $('.mobile-menu2 > .menu-drop').removeClass('opened'); $that.removeClass('opened'); } }) $('.mobile-menu2 > .menu-drop').click(function(){ var $that = $(this); var opencheck2 = $that.hasClass('opened'); if ( opencheck2 == 0 ) { $('.mobile-menu2 > ul').not($that.siblings('ul')).slideUp(500); $('.mobile-menu2 > .menu-drop').not($that).removeClass('opened'); $that.siblings('ul').slideDown(500); $that.addClass('opened'); } else if (opencheck2 == 1) { $that.siblings('ul').slideUp(500); $that.removeClass('opened'); } }) } }; // 把orbit物件加到window物件裡面並改名為ORBITFRONT來減少名稱衝突的機會 win.ORBITFRONT = orbit; // 在switch裡測試頁面模組後執行對應的函數 switch (pageModule) { case 'home': break; case 'member': orbit.member.removeEmptyRow(); break; case 'archive': orbit.archives.removeEmptyTitle('.i-archive__category-item'); orbit.archives.extendPanel(); break; case 'gallery': orbit.utils.truncateText('.show-description', 15); break; default: break; } // 在所有的頁面(包含首頁)執行下面這幾個函數 initdata1(); orbit.sitemenuDropdown(); orbit.goBackTop('top', 800); // orbit.plugins.bullEye(); orbit.setColumn('.left-column', '.right-column'); // 自適應網頁使用,當網頁載入時,如果視窗寬度小於769,就執行orbit.nav.setDropdown函數 if ($(window).width() < 769) { // orbit.nav.setDropdown(); orbit.MobileMenu(); $('.mobile-menu').append($('.modules-menu')); $('.header-buttom').appendTo($('.modules-menu')); orbit.ClickMenuHandler(); } // 自適應網頁使用,當使用者改變瀏覽器寬度時呼叫orbit.nav.setDropdown函數 $(window).resize(function() { if ($(window).width() < 769) { if (resizeTimer) clearTimeout(resizeTimer); resizeTimer = setTimeout(function() { // if ( $('.modules-menu i').length == 0 ) { // orbit.MobileMenu(); // } if( $('.mobile-menu .modules-menu').length == 0 ) { $('.mobile-menu').append($('.modules-menu')); $('.header-buttom').appendTo($('.modules-menu')); orbit.MobileMenu(); orbit.ClickMenuHandler(); // $('.navbar-toggle').bind('click', orbit.ClickMenuHandler); // $('.navbar-toggle').bind(orbit.ClickMenuHandler()); } },500 )} else { resizeTimer = setTimeout(function(){ if( $('.mobile-menu .modules-menu').length > 0 ) { $('.layout-header .outdropdowns .dropdowns').append($('.modules-menu')); $('.dropdowns').append($('.header-buttom')); } orbit.removeDropdown(); }, 500); } }); // if($(window).width()<769){ // $('.header-buttom').appendTo($('.modules-menu')); // }else{ // $('.header-buttom').appendTo($('.dropdowns')); // } function forFreeGo() { setTimeout(function() { $('h1, h2, h3, h4, h5, h6').each(function() { var $heading = $(this); // 檢查是否為空 (去除空白後) if ($.trim($heading.text()) === '' && $heading.children().length === 0) { $heading.remove(); } }); }, 500); //zoom $(function () { $('.fnav a').each(function () { const $a = $(this); // 若已經有可見文字(非 icon),直接通過 const visibleText = $a.clone() .children('.icon, i, svg, .caret') .remove() .end() .text() .trim(); if (visibleText.length > 0) return; // 取得可用標籤文字(優先順序) let label = $a.attr('aria-label') || $a.attr('title') || $a.find('i[title]').attr('title') || ''; label = $.trim(label); // 若真的完全沒有,就給一個保底(避免空字串違規) if (!label) { label = '功能按鈕'; } // aria-label 一定要有 $a.attr('aria-label', label); // icon 對螢幕閱讀器隱藏 $a.find('i, svg').attr('aria-hidden', 'true'); // 若沒有隱藏文字才補 if ($a.find('.sr-only, .visually-hidden').length === 0) { $a.append(`${label}`); } }); }); //播放驗證碼語音 $(function () { $('.ask-question') .find('.controls button.fas.fa-volume-up') .each(function () { const $btn = $(this); // 已經補過就不重複處理 if ($btn.attr('aria-label')) return; $btn.attr({ 'aria-label': '播放驗證碼語音', 'aria-controls': 'captcha_audio', 'role': 'button' }); }); }); //刪除td的id $('td[id]').removeAttr('id'); //刪除空的title $('[class*="title"]').each(function () { const $el = $(this); // 取純文字(忽略 HTML tag、空白、換行) const text = $.trim($el.text()); if (text === '') { $el.remove(); } }); //表單legend $("fieldset").each(function () { const $fieldset = $(this); const hasLegend = $fieldset.children("legend").length > 0; if (!hasLegend) { // 嘗試抓最上層的群組標題,例如 "Apply" const headingText = $fieldset.find(".form-group:first").text().trim() || "表單填寫"; // 插入 legend 為第一個元素 $fieldset.prepend(`${headingText}`); } }); // 處理「上一頁」按鈕 $(".cmdBackward").each(function () { $(this) .attr("title", "上一頁") .attr("aria-label", "上一頁"); if ($(this).find(".sr-only").length === 0) { $(this).append('上一頁'); } $(this).find("i").attr("aria-hidden", "true"); $(this).find(".icon").attr("aria-hidden", "true"); }); // 處理「下一頁」按鈕 $(".cmdForward").each(function () { $(this) .attr("title", "下一頁") .attr("aria-label", "下一頁"); if ($(this).find(".sr-only").length === 0) { $(this).append('下一頁'); } $(this).find("i").attr("aria-hidden", "true"); $(this).find(".icon").attr("aria-hidden", "true"); }); $('.pagination li.active a').attr('aria-current', 'page'); $('path').each(function () { $(this) .attr('aria-hidden', 'true') .attr('focusable', 'false') .attr('tabindex', '-1'); }); $('.controlplay a[role="radio"]').on('click', function () { // 取消所有的 aria-checked 並還原文字 $('.controlplay a[role="radio"]').attr('aria-checked', 'false'); $('.controlplay a[role="radio"] span').each(function () { var text = $(this).text().replace('(已選取)', ''); $(this).text(text); }); // 設定目前被點擊的按鈕為已選取 $(this).attr('aria-checked', 'true'); var selectedText = $(this).text().trim(); $(this).find('span').text(selectedText + '(已選取)'); }); // 遍历所有的 .s-annc__tag-wrap 元素 $('.s-annc__tag-wrap').each(function() { // 遍历 .s-annc__tag-wrap 下的每个 a 元素 $(this).find('a').each(function() { // 如果 .s-annc__tag 元素为空或没有内容 if ($(this).find('.s-annc__tag').is(':empty')) { // 移除该 a 元素 $(this).remove(); } }); }); $('.w-ba-banner__caption li button').each(function (index) { const $slide = $('.w-ba-banner__slide').eq(index); const title = $slide.attr('data-cycle-title')?.trim(); if (title) { const fullText = title + '的pager'; $(this).attr('aria-label', fullText); $(this).attr('title', fullText); } }); // 當 focus 到 menu link 時,顯示對應 ul $('.sitemenu-item > a').on('focus', function () { $(this).siblings('ul').addClass('show'); }); // 當 focus 離開最後一個子選單 link 時,移除 .show $('.sitemenu-item').each(function () { const $submenuLinks = $(this).find('ul a'); if ($submenuLinks.length > 0) { $submenuLinks.last().on('blur', function () { // 當最後一個子項 blur 時關閉 ul $(this).closest('ul').removeClass('show'); }); } else { // 若沒有子項,當主選單項 blur 也隱藏 $(this).find('> a').on('blur', function () { $(this).siblings('ul').removeClass('show'); }); } }); if (document.documentElement.lang === 'zh_tw') { document.documentElement.lang = 'zh-Hant'; } //tab鍵按下 $(document).on('keydown', function(e) { if (e.key === "Tab" || e.keyCode === 9) { $('.header-nav, .dropdowns').css('display', 'block'); } }); function handleHover() { // 先統一移除舊事件,避免重複綁定 $('li').off('mouseenter mouseleave focusin focusout'); if ($(window).width() > 769) { // 1. 處理滑鼠 Hover $('li').hover( function() { $(this).children('ul').addClass('show'); }, function() { $(this).children('ul').removeClass('show'); } ); // 2. 處理鍵盤 Tab 聚焦 (關鍵修正) $('li').on('focusin', function() { // 當焦點進入 li 或其子元素時,顯示選單 $(this).children('ul').addClass('show'); }); $('li').on('focusout', function() { var $this = $(this); // 延遲偵測焦點是否真的「離開」了這個 li 區塊 setTimeout(function() { // 如果新的焦點不在當前這個 li 裡面,才移除 show if ($this.find(':focus').length === 0) { $this.children('ul').removeClass('show'); } }, 10); }); } } // 初始化與 Resize 監聽保持不變 handleHover(); $(window).on('resize', function() { handleHover(); }); //刪除空的h1 $('h1').each(function() { if ($(this).text().trim() === '') { $(this).remove(); } }); //refresh_btn加上aria-label $('#refresh_btn').each(function() { var $this = $(this); // 如果 button 尚未有 aria-label,則新增 if (!$this.attr('aria-label')) { $this.attr('aria-label', '重新整理'); } }); //無障礙會員表格刪除沒有顯示的th $('.i-member-tr-head').each(function() { if ($(this).css('display') === 'none') { $(this).remove(); } }); //無障礙公告a是空的 $('.w-annc__subtitle').each(function () { var $this = $(this); var $link = $this.find('a'); // 檢查 a 是否存在,且去除空白後是否為空字串 if ($link.length && $link.text().trim() === '') { $this.remove(); // 移除外層 .w-annc__subtitle } }); //無障礙單位轉換 $(function() { $('style:contains("font-size")').each(function() { let css = $(this).html(); css = css.replace(/font-size\s*:\s*([\d.]+)px\s*;?/gi, (_, px) => `font-size: ${(parseFloat(px) / 16).toFixed(3)}em;` ); $(this).html(css); }); }); $("[style*='font-size']").each(function() { var fontSize = $(this).css("font-size"); if (fontSize.includes("px")) { var pxValue = parseFloat(fontSize); // 取得數值 var emValue = pxValue / 16; // 假設 1em = 16px $(this).css("font-size", emValue + "em"); } }); $("[style*='font-size']").each(function() { var fontSize = $(this).css("font-size"); if (fontSize.includes("pt")) { var ptValue = parseFloat(fontSize); // 取得數值 var emValue = ptValue / 12; // 1em = 12pt(一般轉換標準) $(this).css("font-size", emValue + "em"); } }); $("[style*='font-size']").each(function() { var styleAttr = $(this).attr("style"); // 取得原始 style 屬性字串 var match = styleAttr.match(/font-size\s*:\s*(\d+(?:\.\d+)?)pt/i); if (match) { var ptValue = parseFloat(match[1]); var emValue = ptValue / 12; // 替換 style 屬性字串中的 pt 為 em var newStyle = styleAttr.replace(/font-size\s*:\s*\d+(?:\.\d+)?pt/i, `font-size: ${emValue}em`); $(this).attr("style", newStyle); } }); //表格scope $("table").each(function() { $(this).find("tr").each(function(rowIndex) { $(this).find("th").each(function(colIndex) { if (rowIndex === 0) { // 第一列的 th,適用於該欄 $(this).attr("scope", "col"); } else if (colIndex === 0) { // 其他列的第一個 th,適用於該行 $(this).attr("scope", "row"); } }); }); }); $(".banner-pager button").addClass('banner-pagerbtn'); $(".banner-pager button").attr("type","button"); $(".banner-pager button").append('下一張'); $("button").attr("role", "button"); $("select").attr("title","選擇類別"); $(".jarallax-video-audio").attr("role", "button"); $('button').each(function() { var $this = $(this); if (!$this.attr('title') || $this.attr('title').trim() === '') { $this.attr('title', '按鈕'); } }); function removeEmptyTitles() { // 定義所有需要檢查的 class const targetClasses = [ '.w-annc__widget-title', '.widget-title', '.show-title', '.event-annc-title', '.annc-title', '.sitemenu-title', '.widget-link__widget-title' ]; // 將陣列轉換為 jQuery 選擇器字串 const selector = targetClasses.join(', '); $(selector).each(function() { // 使用 $.trim 移除空格、換行符號 // 然後檢查裡面是否完全沒有文字 const textContent = $.trim($(this).text()); if (textContent === "") { // 如果沒有文字,則將整個元素刪除 $(this).remove(); } }); } // 執行 function $(document).ready(function() { removeEmptyTitles(); }); // $(".w-annc__img-wrap a").each(function () { // var $this = $(this); // // 確保 內沒有文字節點 (避免重複添加) // if ($this.text().trim() === "") { // $this.append('公告圖片'); // } // }); $(".widget-link__widget-title").each(function () { if ($(this).text().trim() === "") { $(this).append('公告標題'); } }); $(".sitemenu-title").each(function () { if ($(this).text().trim() === "") { $(this).append('次選單'); } }); $(".annc-title").each(function () { if ($(this).text().trim() === "") { $(this).append('內頁公告標題'); } }); $(".event-annc-title").each(function () { if ($(this).text().trim() === "") { $(this).append('內頁活動公告標題'); } }); $(".show-title").each(function () { if ($(this).text().trim() === "") { $(this).append('內頁活動公告標題'); } }); $(".w-annc__widget-title").each(function () { if ($(this).text().trim() === "") { $(this).append('公告標題'); } }); $(".widget-title").each(function () { if ($(this).text().trim() === "") { $(this).append('網路資源標題'); } }); $(".widget-title").each(function () { if ($(this).text().trim() === "") { $(this).append('網路資源標題'); } }); $('input').each(function() { var $this = $(this); if (!$this.attr('title') || $this.attr('title').trim() === '') { $this.attr('title', '網內搜尋'); } }); $('.rucaptcha-image').each(function() { var $button = $(this).next('button'); // 取得緊接在 .rucaptcha-image 之後的 button if ($button.length && !$button.attr('aria-label')) { $button.attr('aria-label', '播放驗證碼語音'); } }); // img無障礙 $(function() { /** * 圖片無障礙 AA 級補強 (人工檢測優化版) */ function fixImageAccessibility() { $('img').each(function() { var $img = $(this); var $parentA = $img.closest('a'); // 取得父層連結 var currentAlt = ($img.attr('alt') || '').trim(); var currentTitle = ($img.attr('title') || '').trim(); // 判定該連結是否「僅靠圖片傳達目的」(連結內無文字) var isLinkImage = $parentA.length > 0 && $parentA.text().replace(/\u00a0/g, '').trim() === ""; // --- 1. 處理「裝飾性圖片」標註 --- if (currentAlt === "announcement image" || currentAlt === "裝飾圖片" || currentTitle === "裝飾圖片" || currentAlt === "這是一張圖片" || currentTitle === "這是一張圖片") { $img.attr('alt', ''); $img.removeAttr('title'); return; } // --- 2. 解決【alt 與 title 相同】的問題 --- if (currentAlt !== '' && currentAlt === currentTitle) { $img.removeAttr('title'); currentTitle = ''; } // --- 3. 處理「缺失 alt」或「空的 alt」補強邏輯 --- // 修改點:若是具有連結用途的圖片,alt 不可為空 if (currentAlt === '') { let finalAlt = ""; // A. 優先嘗試從父層 () 的 title 抓取 var parentATitle = $parentA.attr('title'); // B. 嘗試抓取同區域內的標題文字 var nearbyTitle = $parentA.find('h1, h2, h3, h4, h5, h6').first().text().trim(); if (parentATitle && parentATitle.trim() !== '') { // 移除 title 內的視窗提示字眼,只取純文字作為 alt finalAlt = parentATitle.replace(/\(在本視窗開啟\)|\(在新視窗開啟\)/g, '').trim(); } else if (nearbyTitle !== '') { finalAlt = nearbyTitle; } else if (isLinkImage) { // 如果是連結圖片且都抓不到文字,給予預設值「連結」避免檢測失敗 finalAlt = "連結"; } $img.attr('alt', finalAlt); // --- 4. 二次清理 --- if (currentTitle !== '' && currentTitle === finalAlt) { $img.removeAttr('title'); } } }); } setTimeout(fixImageAccessibility, 500); }); // 有連結目的之所有a標籤的無障礙處理 $(function() { // Bootstrap 會把原始 title 搬到 data-bs-original-title,先還原回來 $('a[data-bs-original-title]').each(function() { var $a = $(this); var originalTitle = $a.attr('data-bs-original-title'); if (originalTitle && originalTitle.trim() !== '') { $a.attr('title', originalTitle); } }); /** * 全站無障礙 AA 級補強 (整合 HM1240400C 與 HM1240401C 規範) */ function fixAccessibilityAll() { // --- 0. 環境與語言偵測 --- //1200ms 後執行(確保所有其他 function 執行完畢後才處理) //Part 1:修正語言選單按鈕 //Part 2:掃描所有 //├─ 排除 navbar-brand、javascript: 連結 //├─ 空連結 → 隱藏 //├─ 文字是路徑/空 → 補隱藏 span //├─ 圖片+文字共存 → 圖片 alt 清空 //├─ 無 title → 自動產出 title //├─ 有 title 但與連結文字或圖片 alt 重複 → 只保留開窗提示 //├─ 有 title 出現空括號 () → 清除並補上正確開窗提示 //└─ 移除 aria-label var urlParams = new URLSearchParams(window.location.search); var isEditMode = urlParams.get('editmode') === 'on'; var pageLang = $('html').attr('lang') || 'zh-Hant'; var isEn = pageLang.toLowerCase().startsWith('en'); var i18n = { langBtn: isEn ? 'Open language menu in this window' : '在本視窗開啟語言選單', newWin: isEn ? 'Open in new window' : '在新視窗開啟', selfWin: isEn ? 'Open in this window' : '在本視窗開啟', link: isEn ? 'Link' : '連結', openImg: isEn ? 'Open image' : '開啟圖片內容', sort: isEn ? 'Sort' : '排序' }; // --- Part 1: 語言選單修正 --- var $langBtn = $('#languagebutton'); if ($langBtn.length > 0) { $langBtn.attr('title', i18n.langBtn); $langBtn.removeAttr('aria-label'); } // --- Part 2: 全站連結與圖片邏輯處理 --- $('a').each(function() { var $a = $(this); // 【條件 1:排除特定 class】 if ($a.hasClass('navbar-brand')) { return; } var href = ($a.attr('href') || '').toLowerCase(); if (!href || href.startsWith('javascript:')) return; // --- 關鍵修正:先偵測是否有原始 title --- var rawTitleAttr = $a.attr('title'); var hasOriginalTitle = (typeof rawTitleAttr !== 'undefined' && rawTitleAttr !== false && rawTitleAttr.trim() !== ""); // 清理   與 空白 var linkText = $a.text().replace(/\u00a0/g, '').trim(); var $img = $a.find('img'); var $icons = $a.find('i, svg'); var currentTitle = ($a.attr('title') || '').trim(); // ✅ 在 D 區塊清空 alt 之前,先記錄圖片原始 alt var imgAltOriginal = $img.length > 0 ? ($img.attr('alt') || '').trim() : ''; // --- 【修正 1:隱藏空連結】 --- if (!isEditMode && linkText === "" && $img.length === 0 && $icons.length === 0) { $a.hide(); return; } // --- 【修正 2:文字語意防禦】 --- if ((linkText === "" || linkText.startsWith('/') || linkText.includes('?')) && $img.length === 0 && $icons.length === 0) { var accessibleText = i18n.link; if (href.includes('sort')) { accessibleText = i18n.sort; } var $span = $a.find('span'); if ($span.length > 0) { $span.text(accessibleText); } else { $a.append('' + accessibleText + ''); $span = $a.find('span').last(); } $span.css({ 'display': 'inline-block', 'position': 'absolute', 'width': '1px', 'height': '1px', 'padding': '0', 'margin': '-1px', 'overflow': 'hidden', 'clip': 'rect(0, 0, 0, 0)', 'white-space': 'nowrap', 'border': '0' }); linkText = accessibleText; } // A. 視窗動作規範 var isNewWindow = ($a.attr('target') === '_blank'); var windowTask = isNewWindow ? i18n.newWin : i18n.selfWin; // B. 偵測檔案類型 var fileExt = ""; var fileMatches = href.match(/\.(pdf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odp|zip|rar|jpg|png|csv)$/); if (fileMatches) { fileExt = fileMatches[1].toLowerCase(); } // C. 智慧修正標題判斷 var hasBadSymbol = currentTitle.includes('()') || currentTitle.includes('Open in new window') || currentTitle.includes('/uploads/'); if (currentTitle.startsWith('/') || currentTitle.includes('?')) { currentTitle = ""; } // D. 處理【HM1240400C】:圖片與文字毗鄰時,替代文字只能有一份 if (($img.length > 0 || $icons.length > 0) && linkText !== "") { if ($img.length > 0) { $img.attr('alt', ''); } var $hiddenSpans = $a.find('span').filter(function() { return $(this).css('display') === 'none' || $(this).attr('style')?.includes('display: none'); }); if ($hiddenSpans.length > 0) { $hiddenSpans.each(function() { var $span = $(this); if ($span.text().includes('/uploads/')) { $span.text(i18n.openImg); } $span.css({ 'display': 'inline-block', 'position': 'absolute', 'width': '1px', 'height': '1px', 'padding': '0', 'margin': '-1px', 'overflow': 'hidden', 'clip': 'rect(0, 0, 0, 0)', 'white-space': 'nowrap', 'border': '0' }); }); } } // 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(); // ✅ 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); } } // F. 最終清理:移除冗餘 label,避免螢幕閱讀器唸兩次 $a.removeAttr('aria-label'); }); // ✅ G. 補強特定連結(須在迴圈外,因為 javascript: 連結被迴圈跳過) $('.btn-o a').each(function() { var $a = $(this); if (!$a.attr('target')) { $a.attr('target', '_blank'); $a.attr('rel', 'noopener noreferrer'); } $a.attr('title', isEn ? 'Share to X Open in new window' : '分享至 X 在新視窗開啟'); }); $('.print-button a').each(function() { var $a = $(this); if (!$a.attr('title') || $a.attr('title').trim().toLowerCase() === 'print') { $a.attr('title', isEn ? 'Print this page' : '列印此頁'); } }); $('a.i-archive__file-name').each(function () { var $a = $(this); var isNewWindow = ($a.attr('target') === '_blank'); $a.attr('title', isNewWindow ? i18n.newWin : i18n.selfWin); }); } // ✅ 延遲 800ms 確保所有其他 function 執行完畢後才處理 setTimeout(function() { fixAccessibilityAll(); }, 800); }); $(function() { function smartFixIcons() { var isEn = $('html').attr('lang') === 'en'; 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' : '顯示原始圖片' }; $('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('' + labels.closePopup + ''); } 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', 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('' + labels.closeGallery + ''); } 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', labels.toggleDesc); $toggleBtn.attr('role', 'button'); $toggleBtn.attr('tabindex', '0'); } if ($icon.next('.sr-only').length === 0) { $icon.after('' + labels.toggleDesc + ''); } 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', labels.themeSwitch); $themeBtn.attr('role', 'button'); $themeBtn.attr('tabindex', '0'); } if ($icon.next('.sr-only').length === 0) { $icon.after('' + labels.themeSwitch + ''); } 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 = 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; } // --- 3. 執行補強 --- if (labelText !== '') { $icon.after('' + labelText + ''); } }); } 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')=="") $('.w-ba-banner__slide a').eq(i).removeAttr('href'); if($('.w-ba-banner__slide a').eq(i).attr('target') == "") $('.w-ba-banner__slide a').eq(i).removeAttr('target'); }; // 幫無標題之iframe加上title for(var i=0;i<$('iframe').length;i++) if($('iframe').eq(i).attr('title')=="" || $('iframe').eq(i).attr('title')== undefined ){ if($('iframe').eq(i).attr('src').search('facebook') != -1 ) $('iframe').eq(i).attr('title','facebook'); else if($('iframe').eq(i).attr('src').search('google') != -1 ) $('iframe').eq(i).attr('title','google'); else if($('iframe').eq(i).attr('src').search('youtube') != -1 ) $('iframe').eq(i).attr('title','youtube'); else if($('iframe').eq(i).attr('src').search('twitframe') != -1 ) $('iframe').eq(i).attr('title','twitter'); else $('iframe').eq(i).attr('title','unknown'); }; //button是空的就加上內容 $('button').each(function() { var $this = $(this); var titleText = $this.attr('title') || ''; // 檢查 button 是否是空的(沒有可見文字或子元素) if ($this.text().trim() === '' && !$this.children().length && titleText) { // 新增隱藏的 span,內容為 title $this.append('' + titleText + ''); } }); // 刪除空的檔案室 var archievelen = $('dd a.i-archive-files-item').length; for(i=archievelen-1;i>=0;i--) if($('dd a.i-archive-files-item').eq(i).html().trim()=="") $('dd a.i-archive-files-item').eq(i).parent('dd').remove(); // 刪除具有空連結欄位的橫列 for(var i = 0;i < $('*[data-list] tr td a').length ; i++) if($('*[data-list] tr td a').eq(i).html().trim()=="") $('*[data-list] tr td a').eq(i).parent('td').parent('tr').remove(); // tab按鍵選到menu,會顯示下層的menu(為了符合無障礙) $('.nav-level-0>li>a').focus(function(e) { e.stopPropagation(); $(this).parent().focus(); if ($(this).parent().find('.nav-level-1').hasClass('show')) { // 已有 show,不處理 } else { $('.nav-level-1').removeClass('show'); $('.nav-level-0>li>.menu-drop').removeClass('opened'); // 先清除其他的 opened $(this).parent().find('.nav-level-1').addClass('show'); $(this).parent().find('.menu-drop').addClass('opened'); // 加上 opened } }); $('.nav-level-0>li').on('focusout', function(e) { var $li = $(this); setTimeout(function() { if ($li.find(':focus').length === 0) { $li.find('.nav-level-1').removeClass('show'); $li.find('.menu-drop').removeClass('opened'); // 移除 opened } }, 50); }); $('.nav-level-1>li>a').focus(function(e) { e.stopPropagation(); if ($(this).parent().find('.nav-level-2').hasClass('show')) { // 已有 show,不處理 } else { $('.nav-level-2').removeClass('show'); $('.nav-level-1>li>.menu-drop').removeClass('opened'); // 先清除其他的 opened $(this).parent().find('.nav-level-2').addClass('show'); $(this).parent().find('.menu-drop').addClass('opened'); // 加上 opened } }); $('.nav-level-1>li').on('focusout', function(e) { var $li = $(this); setTimeout(function() { if ($li.find(':focus').length === 0) { $li.find('.nav-level-2').removeClass('show'); $li.find('.menu-drop').removeClass('opened'); // 移除 opened } }, 50); }); $('.controlplay a[role="radio"]').on('click', function () { // 取消所有的 aria-checked 並還原文字 $('.controlplay a[role="radio"]').attr('aria-checked', 'false'); $('.controlplay a[role="radio"] span').each(function () { var text = $(this).text().replace('(已選取)', ''); $(this).text(text); }); // 設定目前被點擊的按鈕為已選取 $(this).attr('aria-checked', 'true'); var selectedText = $(this).text().trim(); $(this).find('span').text(selectedText + '(已選取)'); }); $(function() { /** * jPlayer 控制項無障礙標籤補強 * 1. 修正重複且無意義的 title="按鈕" * 2. 解決鍵盤焦點無法進入隱藏介面的問題 */ function fixJPlayerAccessibility() { var $playerContainer = $('#jp_container_video_file'); // --- A. 修正按鈕標題 (解決語義問題) --- $playerContainer.find('button').each(function() { var $btn = $(this); var cls = $btn.attr('class') || ''; var newTitle = ''; // 根據 class 判斷功能 if (cls.includes('jp-video-play-icon')) newTitle = '播放影片'; else if (cls.includes('jp-play')) newTitle = '播放'; else if (cls.includes('jp-stop')) newTitle = '停止'; else if (cls.includes('jp-mute')) newTitle = '靜音'; else if (cls.includes('jp-volume-max')) newTitle = '最大音量'; else if (cls.includes('jp-repeat')) newTitle = '重複播放'; else if (cls.includes('jp-full-screen')) newTitle = '全螢幕'; if (newTitle !== '') { // 修正 title 為具體語義 $btn.attr('title', newTitle); // 同時補上 aria-label 確保螢幕閱讀器讀取 $btn.attr('aria-label', newTitle); } }); // --- B. 鍵盤焦點互動修正 (解決 GN1210101E) --- // 當鍵盤 Tab 進入按鈕時,強制讓 UI 介面顯現,否則使用者看不到焦點在哪 $playerContainer.on('focusin', 'button', function() { $playerContainer.removeClass('hide-ui'); }); // --- C. CSS 強制補強 (解決 display:none 無法獲取焦點問題) --- // 這是必要的,因為 CSS 若設 display:none,鍵盤永遠進不去 $("