2575 lines
99 KiB
JavaScript
2575 lines
99 KiB
JavaScript
;(function($, win, undefined) {
|
||
// ECMAScript 5 嚴格模式
|
||
'use strict';
|
||
|
||
//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-bs-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-bs-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 = $('<span class="menu-drop"><i class="dropdown-toggle-icon level-1 fa fa-chevron-down"></i></span>');
|
||
var $caret2 = $('<span class="menu-drop"><i class="dropdown-toggle-icon level-2 fa fa-chevron-down"></i></span>');
|
||
|
||
// 如果有第二層選單,新增對應的類別到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(`<span class="sr-only">${label}</span>`);
|
||
}
|
||
});
|
||
});
|
||
//播放驗證碼語音
|
||
$(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(`<legend>${headingText}</legend>`);
|
||
}
|
||
});
|
||
|
||
// 處理「上一頁」按鈕
|
||
$(".cmdBackward").each(function () {
|
||
$(this)
|
||
.attr("title", "上一頁")
|
||
.attr("aria-label", "上一頁");
|
||
|
||
if ($(this).find(".sr-only").length === 0) {
|
||
$(this).append('<span class="sr-only">上一頁</span>');
|
||
}
|
||
|
||
$(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('<span class="sr-only">下一頁</span>');
|
||
}
|
||
|
||
$(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('<span style="display: none;">下一張</span>');
|
||
$("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);
|
||
// 確保 <a> 內沒有文字節點 (避免重複添加)
|
||
if ($this.text().trim() === "") {
|
||
$this.append('<span class="sr-only">公告圖片</span>');
|
||
}
|
||
});
|
||
$(".widget-link__widget-title").each(function () {
|
||
if ($(this).text().trim() === "") {
|
||
$(this).append('<span class="sr-only">公告標題</span>');
|
||
}
|
||
});
|
||
$(".sitemenu-title").each(function () {
|
||
if ($(this).text().trim() === "") {
|
||
$(this).append('<span class="sr-only">次選單</span>');
|
||
}
|
||
});
|
||
$(".annc-title").each(function () {
|
||
if ($(this).text().trim() === "") {
|
||
$(this).append('<span class="sr-only">內頁公告標題</span>');
|
||
}
|
||
});
|
||
$(".event-annc-title").each(function () {
|
||
if ($(this).text().trim() === "") {
|
||
$(this).append('<span class="sr-only">內頁活動公告標題</span>');
|
||
}
|
||
});
|
||
$(".show-title").each(function () {
|
||
if ($(this).text().trim() === "") {
|
||
$(this).append('<span class="sr-only">內頁活動公告標題</span>');
|
||
}
|
||
});
|
||
$(".w-annc__widget-title").each(function () {
|
||
if ($(this).text().trim() === "") {
|
||
$(this).append('<span class="sr-only">公告標題</span>');
|
||
}
|
||
});
|
||
$(".widget-title").each(function () {
|
||
if ($(this).text().trim() === "") {
|
||
$(this).append('<span class="sr-only">網路資源標題</span>');
|
||
}
|
||
});
|
||
$(".widget-title").each(function () {
|
||
if ($(this).text().trim() === "") {
|
||
$(this).append('<span class="sr-only">網路資源標題</span>');
|
||
}
|
||
});
|
||
$('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 === "裝飾圖片" || 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. 優先嘗試從父層 (<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() {
|
||
/**
|
||
* 全站無障礙 AA 級補強 (多語系偵測版)
|
||
*/
|
||
function fixAccessibilityAll() {
|
||
// --- 0. 網址參數判斷 ---
|
||
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' : '連結'
|
||
};
|
||
|
||
// --- 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);
|
||
var href = ($a.attr('href') || '').toLowerCase();
|
||
if (!href || href.startsWith('javascript:')) return;
|
||
|
||
// 清理 與 空白
|
||
var linkText = $a.text().replace(/\u00a0/g, '').trim();
|
||
var $img = $a.find('img');
|
||
var currentTitle = ($a.attr('title') || '').trim();
|
||
|
||
// --- 【新增修正:隱藏空連結】 ---
|
||
// 若網址沒有 editmode=on 時,判定 a 裡面文字為空且沒有圖片,則隱藏
|
||
if (!isEditMode && linkText === "" && $img.length === 0) {
|
||
$a.hide();
|
||
return; // 跳過後續處理
|
||
}
|
||
|
||
// 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('另開新視窗') ||
|
||
currentTitle.includes('Open in new window');
|
||
|
||
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() + '] ' : '';
|
||
|
||
// 確保具備標題與圖片 alt
|
||
$a.attr('title', (fileInfo + imgAlt + " " + windowTask).trim());
|
||
$img.attr('alt', imgAlt);
|
||
}
|
||
else if (linkText !== "") {
|
||
// 【有文字連結】
|
||
if (fileExt !== "" || hasBadSymbol || currentTitle === "") {
|
||
var isTag = $a.hasClass('label') || $a.hasClass('tag') || $a.find('[class*="tag"]').length > 0;
|
||
|
||
if (fileExt !== "") {
|
||
$a.attr('title', linkText + " ." + fileExt + " " + windowTask);
|
||
} else if (linkText.length <= 6 || isTag) {
|
||
$a.attr('title', linkText + " " + windowTask);
|
||
} else {
|
||
$a.attr('title', windowTask);
|
||
}
|
||
}
|
||
}
|
||
|
||
// --- 修正後的 Part D 最終清理 ---
|
||
$a.removeAttr('aria-label');
|
||
|
||
// 只有當「真正可見的文字」存在時,才將圖片設為裝飾性
|
||
// 使用 clone() 移除隱藏元件後再計算文字,確保準確度
|
||
var visibleText = $a.clone().find(':hidden, style, script').remove().end().text().replace(/\u00a0/g, '').trim();
|
||
|
||
if (visibleText !== "" && $img.length > 0) {
|
||
$img.attr('alt', '');
|
||
} else {
|
||
// 如果文字是隱藏的 (如你的範例),則必須保留或補強圖片 alt
|
||
var rawAlt = ($img.attr('alt') || '').trim();
|
||
if (rawAlt === "") {
|
||
// 如果連圖片 alt 都沒寫,就從 a 的 title 抓
|
||
var cleanTitle = currentTitle.replace(/\(在本視窗開啟\)|\(在新視窗開啟\)/g, '').trim();
|
||
$img.attr('alt', cleanTitle || i18n.link);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
setTimeout(function() {
|
||
fixAccessibilityAll();
|
||
}, 600);
|
||
});
|
||
|
||
// if (location.href.search('editmode=on') === -1) {
|
||
// // 1. 處理圖片 alt 重複問題 (保持原邏輯但優化)
|
||
// $('a').has('img').each(function () {
|
||
// const $link = $(this);
|
||
// const linkText = $link.text().trim();
|
||
|
||
// $link.find('img').each(function () {
|
||
// const $img = $(this);
|
||
// const altText = $img.attr('alt')?.trim();
|
||
|
||
// if (altText && altText === linkText) {
|
||
// $img.attr('alt', '');
|
||
// }
|
||
// });
|
||
// });
|
||
// }
|
||
$(function() {
|
||
function smartFixIcons() {
|
||
$('i').each(function() {
|
||
var $icon = $(this);
|
||
var $parent = $icon.parent();
|
||
|
||
// 1. 基本安全:所有圖示先對螢幕閱讀器隱藏 (避免讀出 Unicode 亂碼)
|
||
$icon.attr('aria-hidden', 'true');
|
||
|
||
// 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 = '日期:';
|
||
else if (cls.includes('user') || cls.includes('male')) labelText = '發布者:';
|
||
else if (cls.includes('tag')) labelText = '標籤:';
|
||
else if (cls.includes('clock') || cls.includes('time')) labelText = '時間:';
|
||
else if (cls.includes('map-marker') || cls.includes('location')) labelText = '地點:';
|
||
else if (cls.includes('phone')) labelText = '電話:';
|
||
else if (cls.includes('envelope') || cls.includes('mail')) labelText = '信箱:';
|
||
else if (cls.includes('folder')) labelText = '分類:';
|
||
else if (cls.includes('eye')) labelText = '瀏覽次數:';
|
||
else if (cls.includes('download')) labelText = '下載檔案:';
|
||
|
||
// --- 策略 B:功能性按鈕 (如果 i 放在 <a> 或 <button> 裡面且容器沒文字) ---
|
||
var $container = $icon.closest('a, button');
|
||
if ($container.length > 0 && $container.text().trim() === "") {
|
||
// 如果容器裡面什麼字都沒有,這是一個「純圖示按鈕」
|
||
// 我們嘗試抓取容器的 title 作為 label
|
||
var btnTitle = $container.attr('title');
|
||
if (btnTitle) {
|
||
labelText = btnTitle;
|
||
} else if (cls.includes('search')) labelText = '搜尋';
|
||
else if (cls.includes('bars') || cls.includes('navicon')) labelText = '選單';
|
||
else if (cls.includes('print')) labelText = '列印此頁';
|
||
else if (cls.includes('share')) labelText = '分享至社群';
|
||
else if (cls.includes('close') || cls.includes('times')) labelText = '關閉視窗';
|
||
}
|
||
|
||
// --- 3. 執行補強 ---
|
||
if (labelText !== '') {
|
||
// 如果是按鈕內部,用 aria-label 補強容器
|
||
if ($container.length > 0 && $container.text().trim() === "") {
|
||
$container.attr('aria-label', labelText);
|
||
} else {
|
||
// 如果是資訊列表,在 i 後面插入 sr-only
|
||
$icon.after('<span class="sr-only">' + labelText + '</span>');
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 延遲執行確保內容渲染完成
|
||
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('<span class="sr-only">' + titleText + '</span>');
|
||
}
|
||
});
|
||
// 刪除空的檔案室
|
||
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')) {
|
||
} else {
|
||
$('.nav-level-1').removeClass('show');
|
||
$(this).parent().find('.nav-level-1').addClass('show');
|
||
}
|
||
});
|
||
$('.nav-level-1>li>a').focus(function(e) {
|
||
e.stopPropagation();
|
||
if ($(this).parent().find('.nav-level-2').hasClass('show')) {
|
||
}else{
|
||
$('.nav-level-2').removeClass('show');
|
||
$(this).parent().find('.nav-level-2').addClass('show');
|
||
}
|
||
});
|
||
$('show').parent('li').focus();
|
||
|
||
$('.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,鍵盤永遠進不去
|
||
$("<style>")
|
||
.prop("type", "text/css")
|
||
.html(`
|
||
.jp-video.hide-ui .jp-gui {
|
||
display: block !important;
|
||
opacity: 0;
|
||
transition: opacity 0.2s;
|
||
}
|
||
/* 當按鈕獲得焦點,或是滑鼠移入,強制顯示介面 */
|
||
.jp-video.hide-ui:focus-within .jp-gui,
|
||
.jp-video.hide-ui:hover .jp-gui {
|
||
opacity: 1;
|
||
}
|
||
/* 增加明顯的焦點框,讓鍵盤使用者知道現在在哪 */
|
||
.jp-video button:focus {
|
||
outline: 3px solid #005aff !important;
|
||
outline-offset: 2px;
|
||
}
|
||
`)
|
||
.appendTo("head");
|
||
}
|
||
|
||
// 執行補強(設定延遲確保 jPlayer 已生成 DOM)
|
||
setTimeout(fixJPlayerAccessibility, 500);
|
||
});
|
||
|
||
// 移除 .navbar-brand 內部 display:none 元素的補強
|
||
function removeHiddenElementsInsideBrand() {
|
||
// 選取 .navbar-brand 內部所有隱藏的元素
|
||
$('.navbar-brand *').filter(function() {
|
||
// 同時判定 inline style 與 CSS class 造成的 display: none
|
||
return $(this).css('display') === 'none';
|
||
}).remove(); // 徹底從 DOM 中移除該標籤,避免無障礙檢測工具誤判
|
||
}
|
||
|
||
// 使用 setTimeout 確保內容渲染後執行
|
||
// 建議設定 500~800 毫秒,避開大部分動態載入的時間差
|
||
setTimeout(function() {
|
||
removeHiddenElementsInsideBrand();
|
||
}, 600);
|
||
//修正 Alt+M 定位點位置
|
||
$(function() {
|
||
function fixAccessKeyM() {
|
||
var $accessKeyM = $('#accesskey_menu');
|
||
var $navbarHeader = $('.navbar-header');
|
||
|
||
if ($accessKeyM.length > 0 && $navbarHeader.length > 0) {
|
||
$accessKeyM.insertBefore($navbarHeader);
|
||
$accessKeyM.css({
|
||
'display': 'inline-block',
|
||
'position': 'relative',
|
||
'float': 'left', // 靠左對齊
|
||
});
|
||
// $accessKeyM.attr('title', '中央內容區塊導覽列 (Alt+M)');
|
||
}
|
||
}
|
||
setTimeout(fixAccessKeyM, 500);
|
||
});
|
||
//公告頁籤無障礙
|
||
$(function() {
|
||
function fixTabLinearOrder() {
|
||
// ✅ 只處理內部含有 .tab_nav 的 .w-annc
|
||
var $targetAnnc = $('.w-annc').filter(function() {
|
||
return $(this).find('.tab_nav').length > 0;
|
||
});
|
||
|
||
// 若頁面上沒有符合條件的 .w-annc,直接離開
|
||
if ($targetAnnc.length === 0) return;
|
||
|
||
var $tabs = $targetAnnc.find('.filter_tab');
|
||
var $anncList = $targetAnnc.find('.w-annc__list');
|
||
|
||
// --- 1. 順向遊走:標籤 -> 對應內容 ---
|
||
$tabs.on('keydown', function(e) {
|
||
if (e.which === 9 && !e.shiftKey) {
|
||
var category = $(this).data('category');
|
||
var $scope = $(this).closest('.w-annc'); // ✅ 限定在同一個 .w-annc
|
||
var $visibleItems = $scope.find('.w-annc__item[data-category="' + category + '"]:visible');
|
||
|
||
if ($visibleItems.length > 0) {
|
||
var $firstLink = $visibleItems.find('a').first();
|
||
if ($firstLink.length > 0) {
|
||
e.preventDefault();
|
||
$firstLink.focus();
|
||
}
|
||
}
|
||
}
|
||
if (e.which === 13 || e.which === 32) {
|
||
e.preventDefault();
|
||
$(this).click();
|
||
}
|
||
});
|
||
|
||
// --- 2. 反向遊走:內容 -> 對應標籤 ---
|
||
$anncList.on('keydown', '.w-annc__item a', function(e) {
|
||
var $currentLink = $(this);
|
||
var $currentItem = $currentLink.closest('.w-annc__item');
|
||
var $scope = $currentLink.closest('.w-annc'); // ✅ 限定在同一個 .w-annc
|
||
var category = $currentItem.data('category');
|
||
var $visibleItems = $scope.find('.w-annc__item[data-category="' + category + '"]:visible');
|
||
|
||
if (e.which === 9 && e.shiftKey) {
|
||
if ($currentLink.is($visibleItems.find('a').first())) {
|
||
e.preventDefault();
|
||
$scope.find('.filter_tab[data-category="' + category + '"]').focus();
|
||
}
|
||
}
|
||
|
||
if (e.which === 9 && !e.shiftKey) {
|
||
if ($currentLink.is($visibleItems.find('a').last())) {
|
||
var $currentTab = $scope.find('.filter_tab[data-category="' + category + '"]');
|
||
var $nextTab = $currentTab.next('.filter_tab');
|
||
if ($nextTab.length > 0) {
|
||
e.preventDefault();
|
||
$nextTab.focus();
|
||
$nextTab.click();
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
// --- 3. 反向遊走:標籤 -> 上一個標籤的內容最後一個連結 ---
|
||
$tabs.on('keydown', function(e) {
|
||
if (e.which === 9 && e.shiftKey) {
|
||
var $scope = $(this).closest('.w-annc'); // ✅ 限定在同一個 .w-annc
|
||
var $prevTab = $(this).prev('.filter_tab');
|
||
if ($prevTab.length > 0) {
|
||
var prevCategory = $prevTab.data('category');
|
||
$prevTab.click();
|
||
|
||
var $prevItems = $scope.find('.w-annc__item[data-category="' + prevCategory + '"]:visible');
|
||
var $lastLink = $prevItems.find('a').last();
|
||
|
||
if ($lastLink.length > 0) {
|
||
e.preventDefault();
|
||
$lastLink.focus();
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
fixTabLinearOrder();
|
||
});
|
||
//導覽選單子選單無障礙狀態修正 (支援多層級)
|
||
function fixNavMenuA11y() {
|
||
const $navItems = $('#main-nav li');
|
||
|
||
$navItems.each(function() {
|
||
const $li = $(this);
|
||
const $toggle = $li.children('a');
|
||
const $subMenu = $li.children('ul');
|
||
|
||
// 判斷是否有子選單
|
||
if ($subMenu.length > 0) {
|
||
// 1. 初始化屬性
|
||
// aria-haspopup="true" 表示有點擊後彈出選單的功能
|
||
// aria-expanded="false" 預設為摺疊
|
||
$toggle.attr({
|
||
'aria-haspopup': 'true',
|
||
'aria-expanded': 'false'
|
||
});
|
||
|
||
// 如果 href 是 javascript:void(0);,建議補上 role="button" 讓語音讀出它是按鈕
|
||
if ($toggle.attr('href').indexOf('javascript') !== -1) {
|
||
$toggle.attr('role', 'button');
|
||
}
|
||
|
||
// 2. 焦點移入事件 (Focus)
|
||
$toggle.on('focus', function() {
|
||
// 這裡假設你的選單是用 CSS 或其他 JS 控制顯示,
|
||
// 當焦點進入時,將狀態改為 true
|
||
$(this).attr('aria-expanded', 'true');
|
||
// 如果需要透過 JS 強制顯示選單可在此加上:$subMenu.addClass('show'); (視你的 CSS 而定)
|
||
});
|
||
|
||
// 3. 處理失焦事件 (Focusout)
|
||
// 使用 focusout 並檢查焦點是否移出了整個 li 區塊
|
||
$li.on('focusout', function(e) {
|
||
// 使用 setTimeout 確保能抓到下一個獲焦元素
|
||
setTimeout(function() {
|
||
if (!$li.is(':focus-within')) {
|
||
$toggle.attr('aria-expanded', 'false');
|
||
// 如果有 class 控制顯示:$subMenu.removeClass('show');
|
||
}
|
||
}, 50);
|
||
});
|
||
}
|
||
});
|
||
}
|
||
// 執行修正
|
||
fixNavMenuA11y();
|
||
}
|
||
forFreeGo();
|
||
|
||
|
||
|
||
//header banner setting
|
||
if ( location.href.search('editmode=on') != -1 ) {
|
||
$('.header-banner').css('z-index','2');
|
||
} else {
|
||
$('.header-banner').css({
|
||
'position': 'relative',
|
||
'top': '0',
|
||
'z-index': '-2',
|
||
});
|
||
};
|
||
|
||
//公告頁籤
|
||
function annc_widget_nav() {
|
||
$('.tab_nav').nextAll().addClass('tab_content');
|
||
$('.tab_content').css("display","none");
|
||
$('.tab_content').eq(0).css('display', 'block');
|
||
|
||
var num = $('.tab_nav li').length;
|
||
$('.tab_content').eq(num).css('display', 'block');
|
||
$('.tab_content').eq(num).nextAll().css('display', 'block');
|
||
|
||
$('.tab_nav li').off('click').on('click',function() {
|
||
$('.tab_nav li').removeClass('active');
|
||
$(this).addClass('active');
|
||
var fa = $(this).index();
|
||
|
||
$('.tab_content').attr('style','');
|
||
$('.tab_content').css("display","none");
|
||
$('.tab_content').eq(fa).css('display','block');
|
||
var num = $('.tab_nav li').length;
|
||
$('.tab_content').eq(num).css('display', 'block');
|
||
$('.tab_content').eq(num).nextAll().css('display', 'block');
|
||
});
|
||
|
||
var url = window.location.search;
|
||
if (url == "?editmode=on") {
|
||
$('.tab_content').css({'position': 'relative','display':'block'});
|
||
}
|
||
}
|
||
annc_widget_nav();
|
||
|
||
//切換語言停留在同一頁
|
||
if(window.location.pathname!="/")
|
||
$("#en").attr("href",window.location.pathname.replace("zh_tw","en"))
|
||
|
||
//檔案室 下載檔案 hover 彈出備註訊息
|
||
$('[data-bs-toggle="tooltip"]').tooltip()
|
||
|
||
//下載檔案格式dot pdf分色
|
||
$(".i-archive .label.label-primary").each(function() {
|
||
var downloadType = $(this).text();
|
||
$(this).addClass(downloadType);
|
||
})
|
||
|
||
//檔案室模組 Widget 手風琴
|
||
function extendPanelWidget() {
|
||
var len = $('.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);
|
||
}
|
||
}
|
||
}
|
||
extendPanelWidget();
|
||
|
||
// member show tab scroll
|
||
$('.nav-pills').scrollingTabs({
|
||
scrollToTabEdge: true,
|
||
enableSwiping: true,
|
||
leftArrowContent: [
|
||
'<div class="scrtabs-tab-scroll-arrow custom-scroll-arrow"><i class="fa fa-caret-left" aria-hidden="true"></i>',
|
||
'</div>'
|
||
].join(''),
|
||
rightArrowContent: [
|
||
'<div class="scrtabs-tab-scroll-arrow custom-scroll-arrow"><i class="fa fa-caret-right" aria-hidden="true"></i>',
|
||
'</div>'
|
||
].join('')
|
||
});
|
||
|
||
|
||
}
|
||
|
||
$(document).ready(function () {
|
||
// 處理所有 .fnav-item 裡的 <a>
|
||
$(".fnav-item a").each(function () {
|
||
const $a = $(this);
|
||
|
||
// 如果內部已經有 .sr-only,就略過
|
||
if ($a.find(".sr-only").length > 0) return;
|
||
|
||
// 嘗試從 title 擷取語意文字
|
||
let label = $a.attr("title") || "";
|
||
|
||
// 如果還是空字串,再嘗試用 i 的 title
|
||
if (!label.trim()) {
|
||
const iconTitle = $a.find("i").attr("title");
|
||
if (iconTitle) label = iconTitle;
|
||
}
|
||
|
||
// 如果真的都沒有語意,預設一個 generic label(也可加入 warning log)
|
||
if (!label.trim()) {
|
||
label = "操作按鈕";
|
||
}
|
||
|
||
// 加上 title 和 aria-label
|
||
$a.attr("title", label).attr("aria-label", label);
|
||
|
||
// 加上 sr-only 輔助文字
|
||
$a.append(`<span class="sr-only">${label}</span>`);
|
||
|
||
// 確保 icon 不被閱讀器讀取
|
||
$a.find("i").attr("aria-hidden", "true");
|
||
$a.find(".icon").attr("aria-hidden", "true");
|
||
});
|
||
});
|
||
|
||
//video js
|
||
$(document).ready(function () {
|
||
if ($(".main-content .video_detail").length > 0) {
|
||
$('.videopagenone').css("display","none");
|
||
$('.videopage').css('display', 'block');
|
||
$('.sitemenu').css("display","none");
|
||
$('span img[alt="HD"]').parent().hide();
|
||
$('span img[alt="觀看人數"]').remove();
|
||
$(".video_detail .view_info span").each(function () {
|
||
var text = $(this).text().trim(); // 取得 <span> 裡的文字,去掉前後空格
|
||
var number = text.replace(/\D/g, ""); // 只保留數字部分
|
||
if (number) {
|
||
$(this).text(`・觀看次數:${number}次`); // 更新內容格式
|
||
}
|
||
});
|
||
$(".movie_desc").before('<div class="movietitle"><h4>影片內容</h4></div>');
|
||
$(".movie_desc").each(function () {
|
||
var decodedHtml = $("<div/>").html($(this).text()).html(); // 轉換轉義的 HTML
|
||
$(this).html(decodedHtml); // 設置為真正的 HTML
|
||
});
|
||
$(".video_group_time").each(function () {
|
||
var $this = $(this);
|
||
// 找到對應的 <q>,並移動到 .video_group_time 內部
|
||
var $q = $this.closest(".imglst_desc").find(".movie_desc q");
|
||
if ($q.length) {
|
||
$this.append($q.clone()); // 將 <q> 複製並添加到 .video_group_time
|
||
$q.remove(); // 移除 .movie_desc 裡的 <q>
|
||
}
|
||
// 移動 .view_info 到 .video_group_time 的內部
|
||
$this.append($this.siblings(".view_info"));
|
||
// 取得內容並移除 "SystemAdmin | " 前綴
|
||
var text = $this.text().trim();
|
||
var newText = text.replace(/^.*\|\s*/, ""); // 移除 "SystemAdmin | "
|
||
$this.text(newText); // 更新內容
|
||
$(this).insertBefore($(this).closest(".imglst_desc").siblings("h3"));
|
||
});
|
||
|
||
$(".main-content").css({
|
||
"max-width": "920px",
|
||
"margin": "auto"
|
||
});
|
||
$(".video_box_wrap").css("padding-bottom", "56%");
|
||
$(".video_detail .video_yt_box").insertBefore(".video_detail .video_group_time");
|
||
|
||
};
|
||
function getYouTubeThumbnail() {
|
||
var $ytThumb = $(".ytp-cued-thumbnail-overlay-image");
|
||
if ($ytThumb.length) {
|
||
var imageUrl = $ytThumb.css("background-image");
|
||
// 檢查背景圖格式:url("https://...")
|
||
var urlMatch = imageUrl.match(/url\(["']?(.*?)["']?\)/);
|
||
var extractedUrl = urlMatch ? urlMatch[1] : null;
|
||
if (extractedUrl) {
|
||
// console.log("成功獲取縮圖:", extractedUrl);
|
||
$(".background").css("background-image", `url("${extractedUrl}")`);
|
||
} else {
|
||
// console.log("背景圖格式不對,改用影片 ID 生成縮圖");
|
||
setThumbnailFromVideoId();
|
||
}
|
||
} else {
|
||
// console.log("找不到 .ytp-cued-thumbnail-overlay-image,改用影片 ID 生成縮圖");
|
||
setThumbnailFromVideoId();
|
||
}
|
||
}
|
||
function setThumbnailFromVideoId() {
|
||
var $iframe = $("iframe[src*='youtube.com/embed']");
|
||
if ($iframe.length) {
|
||
var src = $iframe.attr("src");
|
||
var videoIdMatch = src.match(/youtube\.com\/embed\/([^?]+)/);
|
||
var videoId = videoIdMatch ? videoIdMatch[1] : null;
|
||
|
||
if (videoId) {
|
||
var fallbackImageUrl = `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`;
|
||
// console.log("透過影片 ID 取得縮圖:", fallbackImageUrl);
|
||
$(".background").css("background-image", `url("${fallbackImageUrl}")`);
|
||
}
|
||
}
|
||
}
|
||
// 嘗試多次加載
|
||
var interval = setInterval(function () {
|
||
if ($(".ytp-cued-thumbnail-overlay-image").length || $("iframe[src*='youtube.com/embed']").length) {
|
||
getYouTubeThumbnail();
|
||
clearInterval(interval);
|
||
}
|
||
}, 1000);
|
||
//改變日期格式
|
||
$(".video_group_time").each(function () {
|
||
var $this = $(this);
|
||
var originalText = $this.text().trim();
|
||
// 把 YYYY-MM-DD 轉換成 M月D日
|
||
var formattedText = originalText.replace(/(\d{4})-(\d{2})-(\d{2})/g, function (match, year, month, day) {
|
||
return parseInt(month, 10) + "月" + parseInt(day, 10) + "日";
|
||
});
|
||
// 找到對應的 <q>,並複製
|
||
var $q = $this.closest(".video_data").find(".video_desc q").clone();
|
||
// 更新內容並加上 <q>
|
||
$this.html(formattedText).append($q);
|
||
});
|
||
|
||
});
|
||
//rucaptcha-image
|
||
$(document).ready(function () {
|
||
$('.rucaptcha-image').removeAttr('onload');
|
||
|
||
// 檢查是否已插入過
|
||
if (!$('#captcha_audio').length) {
|
||
const audioButton = $(`
|
||
<button
|
||
title="播放驗證碼語音"
|
||
type="button"
|
||
onclick="document.getElementById('captcha_audio').play();"
|
||
class="fas fa-volume-up"
|
||
aria-label="播放驗證碼語音"
|
||
role="button"
|
||
style="font-size: 1.5em; color: #333; cursor: pointer; border: 2px solid #333; padding: 0.2em;">
|
||
<span class="sr-only">播放驗證碼語音</span>
|
||
</button>
|
||
`);
|
||
|
||
const audio = $('<audio id="captcha_audio" src="/rucaptcha/?format=wav&locale=zh_tw"></audio>');
|
||
|
||
$('.rucaptcha-image').after(audioButton, audio);
|
||
}
|
||
});
|
||
|
||
//萬用表格searchbtn2
|
||
$(document).ready(function () {
|
||
$('.searchbtn2').click(function (event) {
|
||
event.preventDefault(); // 防止預設行為
|
||
$(".searchbox").slideToggle(300, function () {
|
||
updateAriaExpanded();
|
||
});
|
||
$(this).closest('.ken-click').toggleClass('ken-click2');
|
||
});
|
||
|
||
let triggeredByFocus = false;
|
||
|
||
function updateAriaExpanded() {
|
||
const isVisible = $(".searchbox").is(":visible");
|
||
$(".searchbtn2").attr("aria-expanded", isVisible ? "true" : "false");
|
||
}
|
||
|
||
// 預設 aria-expanded 為 false
|
||
$(".searchbtn2").attr("aria-expanded", "false");
|
||
});
|
||
//強制保持全站search展開
|
||
$(document).ready(function () {
|
||
|
||
//search移位
|
||
function moveSearchIfWide() {
|
||
if ($('.input-search').is(':focus')) return;
|
||
|
||
if ($(window).width() > 769) {
|
||
// 如果已經在正確位置就不動
|
||
if (!$('.modules-menu-level-0 .searchclass').length) {
|
||
$('.searchclass').appendTo('.header-nav');
|
||
}
|
||
} else {
|
||
if (!$('.navbar-header .searchclass').length) {
|
||
$('.navbar-brand').after($('.searchclass'));
|
||
}
|
||
}
|
||
}
|
||
|
||
$(document).ready(moveSearchIfWide);
|
||
$(window).on('resize', moveSearchIfWide);
|
||
|
||
const $searchBox = $('.search-box');
|
||
const $input = $searchBox.find('.input-search');
|
||
const $btn = $('.btn-search');
|
||
|
||
// 點擊 btn 時:若未展開則展開,展開後才可送出
|
||
$btn.on('click', function (e) {
|
||
if (!$searchBox.hasClass('searching')) {
|
||
e.preventDefault(); // 第一次點擊不送出
|
||
// 延遲讓 Android 不會立即 blur
|
||
setTimeout(() => {
|
||
$searchBox.addClass('searching');
|
||
$input[0].focus(); // 用 DOM 方式較穩
|
||
}, 100);
|
||
} else if (!$input.val().trim()) {
|
||
// 沒有輸入值 → 不送出,focus 回去
|
||
e.preventDefault();
|
||
$input[0].focus();
|
||
}
|
||
// 有輸入值就正常送出
|
||
});
|
||
|
||
// 點外面收起(無字才收)
|
||
$(document).on('click touchstart', function (e) {
|
||
if (
|
||
!$searchBox.is(e.target) &&
|
||
$searchBox.has(e.target).length === 0 &&
|
||
!$input.val().trim()
|
||
) {
|
||
$searchBox.removeClass('searching');
|
||
}
|
||
});
|
||
|
||
// focus 時延遲加 .searching,避免 Android 被打斷
|
||
$input.on('focus', function () {
|
||
setTimeout(() => {
|
||
$searchBox.addClass('searching');
|
||
}, 50);
|
||
});
|
||
|
||
// blur 時延遲移除 .searching,避免太早發生
|
||
$input.on('blur', function () {
|
||
setTimeout(() => {
|
||
if (!$input.val().trim()) {
|
||
$searchBox.removeClass('searching');
|
||
}
|
||
}, 150);
|
||
});
|
||
});
|
||
// 當文件物件模型(DOM)載入後,執行init函數
|
||
$(document).ready(function() {
|
||
$(window).on('scroll', function () {
|
||
var scrollTop = $(this).scrollTop();
|
||
var windowHeight = $(window).height();
|
||
|
||
var $dotball = $('.background-dotballleft');
|
||
var dotballTop = $dotball.offset().top;
|
||
var dotballHeight = $dotball.outerHeight();
|
||
|
||
// 當滾動到元素頂端開始才觸發
|
||
if (scrollTop + windowHeight > dotballTop) {
|
||
// 計算距離元素頂端滾動了多少
|
||
var progress = scrollTop + windowHeight - dotballTop;
|
||
var move = Math.min(progress * 0.3, 200); // 控制移動速度與最大值
|
||
|
||
$dotball.css({
|
||
transform: `translate(0, -${move}px)`,
|
||
transition: 'transform 0.2s ease-out'
|
||
});
|
||
} else {
|
||
// 還沒滾到,保持原位
|
||
$dotball.css({
|
||
transform: 'translate(0, 0)'
|
||
});
|
||
}
|
||
});
|
||
$(window).on('scroll', function () {
|
||
var scrollTop = $(this).scrollTop();
|
||
var windowHeight = $(window).height();
|
||
|
||
var $dotball = $('.background-dotball');
|
||
var dotballTop = $dotball.offset().top;
|
||
var dotballHeight = $dotball.outerHeight();
|
||
|
||
// 當滾動到元素頂端開始才觸發
|
||
if (scrollTop + windowHeight > dotballTop) {
|
||
// 計算距離元素頂端滾動了多少
|
||
var progress = scrollTop + windowHeight - dotballTop;
|
||
var move = Math.min(progress * 0.3, 200); // 控制移動速度與最大值
|
||
|
||
$dotball.css({
|
||
transform: `translate(0, -${move}px)`,
|
||
transition: 'transform 0.2s ease-out'
|
||
});
|
||
} else {
|
||
// 還沒滾到,保持原位
|
||
$dotball.css({
|
||
transform: 'translate(0, 0)'
|
||
});
|
||
}
|
||
});
|
||
$(window).on('scroll', function () {
|
||
var scrollTop = $(this).scrollTop();
|
||
var windowHeight = $(window).height();
|
||
|
||
var $dotball = $('.background-ball2');
|
||
var dotballTop = $dotball.offset().top;
|
||
var dotballHeight = $dotball.outerHeight();
|
||
|
||
// 當滾動到元素頂端開始才觸發
|
||
if (scrollTop + windowHeight > dotballTop) {
|
||
// 計算距離元素頂端滾動了多少
|
||
var progress = scrollTop + windowHeight - dotballTop;
|
||
var move = Math.min(progress * 0.3, 200); // 控制移動速度與最大值
|
||
|
||
$dotball.css({
|
||
transform: `translate(0, -${move}px)`,
|
||
transition: 'transform 0.2s ease-out'
|
||
});
|
||
} else {
|
||
// 還沒滾到,保持原位
|
||
$dotball.css({
|
||
transform: 'translate(0, 0)'
|
||
});
|
||
}
|
||
});
|
||
//常用到的js
|
||
// $('.').after($('.'));
|
||
// $('.').before($('.'));
|
||
// $('.').append($('.'));
|
||
// if($('.show-announcement').hasClass('show-announcement')) {
|
||
// $('.').css('', '');
|
||
// }
|
||
if ($('.fatfooter').length === 0) {
|
||
$('.btn-fatfooter').hide();
|
||
};
|
||
if($('.s-annc').length){
|
||
$(".carousel_images h4").remove();
|
||
$('.carousel_images').addClass('carousel_images2');
|
||
$(".carousel_images .w-ba-banner").next("div").find(".button-mid").remove();
|
||
$(".s-annc__post-wrap").next("hr").remove();
|
||
// $(".carousel_images").insertAfter(".s-annc__meta-wrap");
|
||
$('.breadcrumb-wrap').css('display', 'block');
|
||
// $(".main-content").css({
|
||
// "max-width": "920px",
|
||
// "margin": "auto"
|
||
// });
|
||
}
|
||
$('.s-annc__tag-wrap ').after($('.s-annc__post-orbithashtags'));
|
||
$('.i-member-pic-wrap a').removeAttr('target');
|
||
function markCheckStatusButton() {
|
||
$('.ask-question').each(function () {
|
||
var $prev = $(this).prev(); // 取得前一個元素
|
||
|
||
// 如果前一個元素是 <a> 且 class 包含 "btn"
|
||
if ($prev.is('a') && $prev.hasClass('btn')) {
|
||
$prev.addClass('CheckStatus'); // 加上 class
|
||
}
|
||
});
|
||
};
|
||
markCheckStatusButton();
|
||
|
||
|
||
// 綁定滑動事件
|
||
$(".cycle-slideshow").swipe({
|
||
swipeLeft: function () {
|
||
$(this).cycle("next");
|
||
},
|
||
swipeRight: function () {
|
||
$(this).cycle("prev");
|
||
},
|
||
threshold: 50, // 滑動靈敏度(數值越小越敏感)
|
||
});
|
||
|
||
$('#check_history_form input[type="submit"][value="Check History"]').addClass('CheckHistory');
|
||
$(".mybooking").append('<i class="fa-solid fa-circle-user"></i>');
|
||
//內頁dattpp移位
|
||
$('.i-annc__page-title').after($('.sitemenu-wrap2'));
|
||
$('.i-archive-title').after($('.sitemenu-wrap2'));
|
||
$('.page-module-title').after($('.sitemenu-wrap2'));
|
||
$('.box-social-share').before($('.sitemenu-wrap3'));
|
||
$('.box-social-share').before($('.sitemenu-wrap3'));
|
||
$('.box-social-share').before($('.sitemenu-wrap3'));
|
||
// $(".member-data2-tr").before($(".show-member .table-striped > tbody > tr:nth-of-type(4)"));
|
||
$(".nav-pills").before($(".show-member .table-striped > tbody > tr:last-child"));
|
||
|
||
//檔案室手風琴
|
||
$('.panel-title>.collapsed').click(function(){
|
||
$(this).find('.fa').toggleClass("fa-chevron-down");
|
||
$(this).find('.fa').toggleClass("fa-chevron-up");
|
||
});
|
||
|
||
//背景widget設定
|
||
if ( location.href.search('editmode=on') != -1 ) {
|
||
$('.background').css('z-index','2');
|
||
$('.background').css('position','relative');
|
||
} else {
|
||
$('.background').css('z-index','-1');
|
||
$('.background').css('position','fixed');
|
||
};
|
||
//公告類別顏色
|
||
// $(".w-annc .w-annc__category-wrap").each(function() {
|
||
// var SaveCategory = $(this).find(".w-annc__category").text();
|
||
// $(this).addClass(SaveCategory);
|
||
// })
|
||
// $(".w-annc__item ").each(function() {
|
||
// var SaveCategory2 = $(this).find(".w-annc__category").text();
|
||
// $(this).addClass(SaveCategory2);
|
||
// })
|
||
$(".i-annc__item .i-annc__category-wrap").each(function() {
|
||
var SaveCategory = $(this).find(".i-annc__category").text();
|
||
$(this).addClass(SaveCategory);
|
||
})
|
||
$(".i-annc__item ").each(function() {
|
||
var SaveCategory2 = $(this).find(".i-annc__category").text();
|
||
$(this).addClass(SaveCategory2);
|
||
})
|
||
|
||
//預約
|
||
if ($(window).width() > 821) {
|
||
$('.form-horizontal').append($('.cancelbooking'));
|
||
$(".hire-ken-click").click(function(){
|
||
// $(".searchbox").slideToggle(300);
|
||
$('.form-horizontal').toggleClass('hire-ken-click2');
|
||
$('.col-lg-5').toggleClass('shadowblock');
|
||
$(".cancelbooking").click(function(){
|
||
$('.form-horizontal').removeClass('hire-ken-click2');
|
||
$('.col-lg-5').removeClass('shadowblock');
|
||
});
|
||
});
|
||
}
|
||
//navrwd移到選單
|
||
if ($(window).width() <769) {
|
||
$('.modules-menu-level-0').after($('.header-nav'));
|
||
}else{
|
||
$('.navbar-header').before($('.header-nav'));
|
||
};
|
||
$('.sitemenu-vertical .sitemenu-dropdown-toggle').click(function(){
|
||
$('.sitemenu-vertical .dropdown-menu').slideToggle();
|
||
$(".sitemenu-vertical .sitemenu-dropdown-toggle").toggleClass("fa-caret-down");
|
||
$(".sitemenu-vertical .sitemenu-dropdown-toggle").toggleClass("fa-caret-up");
|
||
});
|
||
//頁尾選單開合
|
||
$('.btn-fatfooter').click(function(){
|
||
$('.fatfooter').slideToggle();
|
||
$(".btn-fatfooter .fa-chevron-down").toggleClass("rotate");
|
||
});
|
||
|
||
$(".menu-toggle").on('click', function() {
|
||
$(this).toggleClass("on");
|
||
$('.menu-section').toggleClass("on");
|
||
$("nav ul").toggleClass('hidden');
|
||
});
|
||
$('.morebken').click(function(){
|
||
$('.list-unstyled>li:nth-child(n+5)').slideToggle();
|
||
$(".morebken .fa-chevron-down").toggleClass("rotate");
|
||
$(".openmorebken").toggleClass("closemorebken");
|
||
});
|
||
//RWD 自動縮放headerbannner
|
||
function headerH() {
|
||
if ($(window).width() < 769) {
|
||
const navH = $('.layout-header .navbar-header').outerHeight();
|
||
$('.header-banner').css('height', navH );
|
||
}
|
||
}
|
||
headerH();
|
||
//downIcon
|
||
$(".downIcon").click(function () {
|
||
var move_to_target = function (stop) {
|
||
var theTop;
|
||
if (stop) {
|
||
// $(".kenjohn").addClass('navFixed');
|
||
if ($('.layout-content2.topcontent').length != 0 && $('.layout-content2.topcontent').offset().top < 400) {
|
||
$('.layout-content2').css('margin-top', $('.kenjohn').height() - $('#orbit-bar').height());
|
||
}
|
||
if (parseInt($('.layout-content2').css('margin-top') == 0)) {
|
||
theTop = $('.layout-content2.topcontent').offset().top - $(".kenjohn").position().top - 95;
|
||
} else {
|
||
theTop = $('.layout-content2.topcontent').offset().top - $(".kenjohn").position().top - $(".kenjohn").height() - 95;
|
||
}
|
||
} else {
|
||
theTop = 5;
|
||
}
|
||
// console.log(theTop);
|
||
$("html, body").animate({
|
||
scrollTop: theTop
|
||
}, {
|
||
duration: 400, easing: "swing", complete: function () {
|
||
// console.log('finish');
|
||
if (!stop) {
|
||
move_to_target(true);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
move_to_target(false);
|
||
return false;
|
||
});
|
||
$(window).resize(function() {
|
||
if ($(window).width() <769) {
|
||
|
||
$('.modules-menu-level-0').after($('.header-nav'));
|
||
}else{
|
||
$('.navbar-header').before($('.header-nav'));
|
||
};
|
||
|
||
if ($(window).width() > 821) {
|
||
$('.form-horizontal').append($('.cancelbooking'));
|
||
$(".hire-ken-click").click(function(){
|
||
// $(".searchbox").slideToggle(300);
|
||
$('.form-horizontal').toggleClass('hire-ken-click2');
|
||
$('.col-lg-5').toggleClass('shadowblock');
|
||
$(".cancelbooking").click(function(){
|
||
$('.form-horizontal').removeClass('hire-ken-click2');
|
||
$('.col-lg-5').removeClass('shadowblock');
|
||
});
|
||
});
|
||
}
|
||
headerH();
|
||
})
|
||
$(window).scroll(function() {
|
||
initdata1();
|
||
});
|
||
// $(window).scroll(function() {
|
||
// if ($(this).scrollTop() > 100) { /* 要滑動到選單的距離 */
|
||
// $('.outdropdowns').addClass('navFixed'); /* 幫選單加上固定效果 */
|
||
// } else {
|
||
// $('.outdropdowns').removeClass('navFixed'); /* 移除選單固定效果 */
|
||
// }
|
||
// });
|
||
// $('.navbar-brand h2').replaceWith(function() {
|
||
// return $("<h1>", {
|
||
// class: this.className,
|
||
// html: $(this).html()
|
||
// });
|
||
// });
|
||
$('#search'). attr('title', '另開新視窗');
|
||
$(window).scroll(function () {
|
||
var windowTop = $(window).scrollTop();
|
||
var windowBottom = windowTop + $(window).innerHeight();
|
||
|
||
function handleAnimationOnce(selector, animationClass, offsetRatio = 0.5) {
|
||
$(selector).each(function () {
|
||
var elementTop = $(this).offset().top;
|
||
var elementHeight = $(this).height();
|
||
var triggerPoint = elementTop + elementHeight * offsetRatio;
|
||
|
||
if (
|
||
triggerPoint >= windowTop &&
|
||
triggerPoint <= windowBottom &&
|
||
!$(this).hasClass(animationClass)
|
||
) {
|
||
$(this).addClass(animationClass);
|
||
}
|
||
});
|
||
}
|
||
|
||
handleAnimationOnce('.hide0', 'animationvisible', 0.1);
|
||
handleAnimationOnce('.hide1', 'animationvisible1', 0.5);
|
||
handleAnimationOnce('.hide2', 'animationvisible2', 0.5);
|
||
handleAnimationOnce('.hide3', 'animationvisible3', 0.5);
|
||
handleAnimationOnce('.rotate0', 'animationrotate0', 0.5);
|
||
handleAnimationOnce('.zoomin', 'animationvisible5', 0.5);
|
||
});
|
||
|
||
init();
|
||
});
|
||
|
||
|
||
// 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 $desktopBtn = $('#languagebutton');
|
||
if ($desktopBtn.length > 0) {
|
||
$desktopBtn.attr({ 'aria-expanded': 'false', 'role': 'button', 'aria-haspopup': 'true' });
|
||
$desktopBtn.on('focus', function() {
|
||
$(this).closest('#language-li').find('ul').addClass('show');
|
||
$(this).attr('aria-expanded', 'true');
|
||
$('.orbit-bar-search-sign-language').addClass('show');
|
||
});
|
||
}
|
||
|
||
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);
|
||
});
|
||
}
|
||
|
||
// 強制鎖定 Title
|
||
var target = document.getElementById('languagebutton');
|
||
if (target) {
|
||
var isEn = document.documentElement.lang === 'en';
|
||
var correctTitle = isEn ? 'Open language menu' : '在本視窗開啟語言選單';
|
||
var observer = new MutationObserver(function() {
|
||
if (target.getAttribute('title') !== correctTitle) target.setAttribute('title', correctTitle);
|
||
});
|
||
observer.observe(target, { attributes: true });
|
||
}
|
||
}
|
||
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');
|
||
|
||
if (lang === 'en') {
|
||
$('.searchbtn2').each(function () {
|
||
$(this).attr('title', 'Search'); // 修改 tooltip
|
||
$(this).html('<i class="fa-solid fa-magnifying-glass"></i> Search'); // 修改按鈕文字
|
||
});
|
||
} else if (lang === 'zh_tw') {
|
||
$('.searchbtn2').each(function () {
|
||
$(this).attr('title', '查詢');
|
||
$(this).html('<i class="fa-solid fa-magnifying-glass"></i>查詢');
|
||
});
|
||
}
|
||
});
|
||
$(document).ready(function () {
|
||
$('.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 + '(已選取)');
|
||
});
|
||
});
|
||
//member轉換a
|
||
$(document).ready(function () {
|
||
$('.member-data-value-5 a').each(function () {
|
||
$(this).replaceWith($(this).contents()); // 把<a>替換成它裡面的內容
|
||
});
|
||
$('.member-data-value-3 a').each(function () {
|
||
$(this).replaceWith($(this).contents()); // 把<a>替換成它裡面的內容
|
||
});
|
||
$('.member-data-value-3 a').has('i').each(function() {
|
||
$(this).replaceWith($(this).contents());
|
||
});
|
||
$('.member-data-value-2 a').has('i').each(function() {
|
||
$(this).replaceWith($(this).contents());
|
||
});
|
||
});
|
||
// $(document).ready(function () {
|
||
// $(".navbar-brand").append(
|
||
// '<p class="site-description">National Formosa University</p>'
|
||
// );
|
||
// });
|
||
//選單li加上fa-chevron-down
|
||
$(document).ready(function () {
|
||
function addDropdownIcons() {
|
||
if ($(window).width() > 769) {
|
||
$('#main-nav.modules-menu-level-0 > li').each(function () {
|
||
if ($(this).children('ul').length > 0) {
|
||
const $toggle = $(this).children('a.dropdown-toggle');
|
||
if ($toggle.find('i.fa-chevron-down').length === 0) {
|
||
$toggle.append(' <i class="kenmenu-drop fa-solid fa-chevron-down"></i>');
|
||
}
|
||
}
|
||
});
|
||
}else {
|
||
// 螢幕寬度小於等於 768 時,移除所有 chevron-down icon
|
||
$('#main-nav.modules-menu-level-0 .kenmenu-drop').remove();
|
||
}
|
||
}
|
||
|
||
addDropdownIcons();
|
||
|
||
$(window).resize(function () {
|
||
addDropdownIcons();
|
||
});
|
||
});
|
||
// //選單樣式2
|
||
// $(document).ready(function() {
|
||
// "use strict";
|
||
// $(".menu > ul > li").hover(function(e) {
|
||
// if ($(window).width() > 943) {
|
||
// $(this).children("ul").stop(true, false).fadeToggle(150);
|
||
// e.preventDefault();
|
||
// }
|
||
// });
|
||
// $('.modules-menu-level-1').css('left','-'+$('.outdropdowns .dropdowns').offset().left+'px');
|
||
// });
|
||
// $(document).resize(function() {
|
||
// $('.modules-menu-level-1').css('left','-'+$('.outdropdowns .dropdowns').offset().left+'px');
|
||
// if ($(window).width() < 769){
|
||
// $('.modules-menu-level-1').css('left','')
|
||
// }
|
||
// });
|
||
//隱藏Hashtags
|
||
$(document).ready(function () {
|
||
$('.universal-table-show .table-title').each(function () {
|
||
var $titleTd = $(this);
|
||
var titleText = $titleTd.text().trim();
|
||
var $nextTd = $titleTd.next('td');
|
||
|
||
if (titleText === 'Hashtags' && $nextTd.length > 0 && $nextTd.text().trim() === '') {
|
||
$titleTd.closest('tr').hide();
|
||
}
|
||
});
|
||
});
|
||
$(document).ready(function () {
|
||
$('.universal-table-index .theadsearch tr th').each(function (index) {
|
||
const $th = $(this);
|
||
const title = $th.find('.universal-th-text').text().trim();
|
||
|
||
// 找到 Hashtags 欄
|
||
if (title === 'Hashtags') {
|
||
let allEmpty = true;
|
||
|
||
// 走訪 tbody 的每一列檢查對應欄位是否都為空
|
||
$('.universal-table-index tbody tr').each(function () {
|
||
const $td = $(this).find('td').eq(index);
|
||
if ($td.text().trim() !== '') {
|
||
allEmpty = false;
|
||
return false; // 提前跳出 each
|
||
}
|
||
});
|
||
|
||
if (allEmpty) {
|
||
// 隱藏 thead 裡對應的 th
|
||
$th.hide();
|
||
|
||
// 隱藏 tbody 所有對應的 td 欄位
|
||
$('.universal-table-index tbody tr').each(function () {
|
||
$(this).find('td').eq(index).hide();
|
||
});
|
||
}
|
||
}
|
||
});
|
||
});
|
||
$(window).load(function(){
|
||
$("iframe[src*='google']").attr('title','googleOauth');
|
||
});
|
||
//tabtitle位置
|
||
$(document).ready(function() {
|
||
$('.w-annc .w-annc__widget-title').each(function() {
|
||
var $title = $(this);
|
||
var $tabs = $title.find('.nav-tabs, .tab_nav, .nav_tabs_filter');
|
||
|
||
if ($tabs.length) {
|
||
$tabs.insertAfter($title);
|
||
}
|
||
});
|
||
});
|
||
//會員信箱a
|
||
$(document).ready(function() {
|
||
$('.member-data-value-6 a[href^="mailto:"]').each(function() {
|
||
var $link = $(this);
|
||
var html = $link.html();
|
||
|
||
// 檢查是否有信箱且有 <br>
|
||
if (html.indexOf('@') !== -1 && html.indexOf('<br>') !== -1) {
|
||
// 分割內容
|
||
var parts = html.split(/<br\s*\/?>/i);
|
||
var email = parts[0].trim();
|
||
var rest = parts.slice(1).join('<br>').trim();
|
||
|
||
// 更新連結
|
||
$link.html(email)
|
||
.attr('href', 'mailto:' + email)
|
||
.attr('title', email + '(在本視窗開啟)')
|
||
.attr('aria-label', email);
|
||
|
||
// 插入其餘內容
|
||
if (rest) {
|
||
$link.after('<br>' + rest);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
//網站導覽
|
||
$(document).ready(function() {
|
||
// 1. 定位到網站導覽的連結 (使用 href 屬性定位最精確)
|
||
var $sitemapLink = $('.header-nav a[href*="/sitemap"]');
|
||
|
||
// 2. 遍歷該連結之後的所有節點
|
||
$sitemapLink.each(function() {
|
||
// 取得該 <a> 標籤後方的下一個節點 (可以是文字或標籤)
|
||
var nextNode = this.nextSibling;
|
||
|
||
// 3. 檢查下一個節點是否為文字節點 (nodeType === 3)
|
||
// 並且內容包含 "|"
|
||
if (nextNode && nextNode.nodeType === 3) {
|
||
// 使用正則表達式將 | 替換為空字串
|
||
nextNode.nodeValue = nextNode.nodeValue.replace('|', '');
|
||
}
|
||
});
|
||
});
|
||
//影片模組縮圖
|
||
$(document).ready(function() {
|
||
function fixVideoPosterAlt() {
|
||
// 使用 setTimeout 確保動態產生的影片封面已出現在 DOM 中
|
||
setTimeout(function() {
|
||
var $poster = $('#jp_poster_0');
|
||
|
||
// 1. 檢查圖片是否存在
|
||
if ($poster.length > 0) {
|
||
var currentAlt = $poster.attr('alt');
|
||
|
||
// 2. 如果沒有 alt 屬性,或 alt 為空
|
||
if (!currentAlt || $.trim(currentAlt) === "") {
|
||
|
||
// 3. 抓取 .video_detail 底下的 h3 文字內容
|
||
var $videoTitleElement = $('.video_detail h3').first();
|
||
|
||
if ($videoTitleElement.length > 0) {
|
||
var videoTitle = $.trim($videoTitleElement.text());
|
||
|
||
// 4. 設定給圖片的 alt 屬性
|
||
if (videoTitle !== "") {
|
||
$poster.attr('alt', videoTitle);
|
||
} else {
|
||
// 若標題也是空的,給予預設值
|
||
$poster.attr('alt', '影片封面圖片');
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}, 500); // 延遲 500 毫秒執行
|
||
}
|
||
|
||
// 執行修復功能
|
||
fixVideoPosterAlt();
|
||
});
|
||
|
||
//修正無超連結目的之連結
|
||
$(function() {
|
||
/**
|
||
* 針對所有 href="#" 的連結改為 javascript:void(0);
|
||
* 避免使用者點擊後頁面跳回頂端,造成操作困擾
|
||
*/
|
||
function fixEmptyHref() {
|
||
$('a[href="#"]').each(function() {
|
||
// 將 href 修改為不觸發跳轉的 void 腳本
|
||
$(this).attr('href', 'javascript:void(0);');
|
||
$(this).attr('role', 'button');
|
||
});
|
||
}
|
||
|
||
// 延遲執行,確保動態產生的選單也能被補強
|
||
setTimeout(fixEmptyHref, 500);
|
||
});
|
||
//頁籤無障礙
|
||
$(function() {
|
||
/**
|
||
* 頁籤導覽 (Tab Navigation) 無障礙補強
|
||
* 1. 容器加入 role="tablist"
|
||
* 2. 項目加入 role="tab"
|
||
* 3. 動態切換 aria-selected="true/false"
|
||
* 4. 確保 Enter 鍵可以觸發切換 (針對 tabindex="0" 的優化)
|
||
*/
|
||
function fixTabAccessibility() {
|
||
var $tabNav = $('.tab_nav');
|
||
var $tabs = $tabNav.find('.filter_tab');
|
||
|
||
// --- 1. 初始化結構語意 ---
|
||
$tabNav.attr('role', 'tablist');
|
||
|
||
$tabs.each(function() {
|
||
var $this = $(this);
|
||
var isActive = $this.hasClass('active');
|
||
|
||
// 加入頁籤角色與選取狀態
|
||
$this.attr({
|
||
'role': 'tab',
|
||
'aria-selected': isActive ? 'true' : 'false'
|
||
});
|
||
|
||
// 修正 Title:讓使用者知道這是切換頁籤
|
||
var tabName = $this.text().trim();
|
||
$this.attr('title', '切換至 ' + tabName);
|
||
});
|
||
|
||
// --- 2. 監聽切換事件 (點擊或鍵盤) ---
|
||
// 假設原本已有切換邏輯,我們在此「補強」屬性的變更
|
||
$tabs.on('click', function() {
|
||
var $clickedTab = $(this);
|
||
|
||
// 先將所有頁籤設為未選取
|
||
$tabs.attr('aria-selected', 'false');
|
||
|
||
// 將當前點擊的頁籤設為已選取
|
||
$clickedTab.attr('aria-selected', 'true');
|
||
});
|
||
|
||
// --- 3. 鍵盤操作補強 (針對 tabindex="0" 的非按鈕元素) ---
|
||
$tabs.on('keydown', function(e) {
|
||
// 當按下 Enter (13) 或 Space (32) 時觸發點擊
|
||
if (e.which === 13 || e.which === 32) {
|
||
e.preventDefault();
|
||
$(this).trigger('click');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 延遲執行確保頁籤元件已渲染
|
||
setTimeout(fixTabAccessibility, 500);
|
||
});
|
||
//go-back-top
|
||
$(function() {
|
||
function wrapGoBackTop() {
|
||
$('.go-back-top').each(function() {
|
||
var $this = $(this);
|
||
if ($this.find('.go-back-top-inner').length === 0) {
|
||
// 將原本的內容 (例如文字 "top") 用新的 div 包起來
|
||
$this.contents().wrapAll('<div class="go-back-top-inner" style="width:100%; height:100%; display:flex; align-items:center; justify-content:center;"></div>');
|
||
}
|
||
});
|
||
|
||
}
|
||
|
||
// 延遲 600 毫秒執行,確保動態元件已載入
|
||
setTimeout(wrapGoBackTop, 500);
|
||
});
|
||
$(function() {
|
||
/**
|
||
* 修正 Logo 連結與無障礙文字
|
||
* 目標:將登入連結改為官網連結,並更新相關替代文字
|
||
*/
|
||
function fixLogoLinkToOfficial() {
|
||
// 選取目標連結(建議透過 class 鎖定)
|
||
var $logoLink = $('a.orbit-bar-logo');
|
||
|
||
if ($logoLink.length > 0) {
|
||
// 1. 修改超連結位址 (href) 與 標題 (title)
|
||
$logoLink.attr({
|
||
'href': 'https://www.nfu.edu.tw',
|
||
'title': '國立虎尾科技大學(在本視窗開啟)'
|
||
});
|
||
|
||
// 2. 修改內部圖片的替代文字 (alt)
|
||
$logoLink.find('img').attr('alt', '國立虎尾科技大學');
|
||
|
||
// 3. 移除內部的 <p> 標籤 (避免 display:none 的舊文字干擾無障礙檢測)
|
||
$logoLink.find('p').remove();
|
||
}
|
||
}
|
||
|
||
// 建議使用 setTimeout 確保在 DOM 完全加載或動態產生後執行
|
||
setTimeout(function() {
|
||
fixLogoLinkToOfficial();
|
||
}, 500);
|
||
});
|
||
// 執行 member等高計算,目前改用flexbox故mark掉 by ika 20160105
|
||
// $(window).load(function() {
|
||
// if ($('.index-member-3').length && $(window).width() > 992) {
|
||
// ORBITFRONT.member.equalHeight('.i-member-item-inner');
|
||
// }
|
||
// });
|
||
|
||
}(jQuery, window));
|