This commit is contained in:
parent
18e760e796
commit
9ee863debb
|
|
@ -3574,137 +3574,252 @@ $(function() {
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
//banner英文
|
//banner英文
|
||||||
$(function() {
|
$(function() {
|
||||||
function fixBannerA11yByLang() {
|
function fixBannerA11yByLang() {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase();
|
var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase();
|
||||||
var isEn = pageLang.startsWith('en');
|
var isEn = pageLang.startsWith('en');
|
||||||
|
|
||||||
var i18n = {
|
var i18n = {
|
||||||
playControls: isEn ? 'Playback Controls' : '播放控制選項',
|
playControls: isEn ? 'Playback Controls' : '播放控制選項',
|
||||||
resume: isEn ? 'Play' : '繼續播放',
|
resume: isEn ? 'Play' : '繼續播放',
|
||||||
pause: isEn ? 'Pause' : '暫停播放',
|
pause: isEn ? 'Pause' : '暫停播放',
|
||||||
prev: isEn ? 'Previous' : '上一張',
|
prev: isEn ? 'Previous' : '上一張',
|
||||||
next: isEn ? 'Next' : '下一張',
|
next: isEn ? 'Next' : '下一張',
|
||||||
slide: isEn ? 'Slide' : '第',
|
slide: isEn ? 'Slide' : '第',
|
||||||
slideUnit: isEn ? '' : ' 張投影片'
|
slideUnit: isEn ? '' : ' 張投影片'
|
||||||
};
|
};
|
||||||
|
|
||||||
$('.w-ba-banner').each(function() {
|
$('.w-ba-banner').each(function() {
|
||||||
var $banner = $(this);
|
var $banner = $(this);
|
||||||
|
|
||||||
// ✅ 播放控制選項 radiogroup label
|
$banner.find('.controlplay').attr('aria-label', i18n.playControls);
|
||||||
$banner.find('.controlplay').attr('aria-label', i18n.playControls);
|
|
||||||
|
|
||||||
// ✅ 繼續播放按鈕
|
$banner.find('.resume-slide').attr({
|
||||||
$banner.find('.resume-slide').attr({
|
'aria-label': i18n.resume,
|
||||||
'aria-label': i18n.resume,
|
'title': i18n.resume
|
||||||
'title': i18n.resume
|
});
|
||||||
});
|
$banner.find('.resume-slide p').text(i18n.resume);
|
||||||
$banner.find('.resume-slide p').text(i18n.resume);
|
|
||||||
|
|
||||||
// ✅ 暫停播放按鈕
|
$banner.find('.pause-slide').attr({
|
||||||
$banner.find('.pause-slide').attr({
|
'aria-label': i18n.pause,
|
||||||
'aria-label': i18n.pause,
|
'title': i18n.pause
|
||||||
'title': i18n.pause
|
});
|
||||||
});
|
$banner.find('.pause-slide p').text(i18n.pause);
|
||||||
$banner.find('.pause-slide p').text(i18n.pause);
|
|
||||||
|
|
||||||
// ✅ 上一張按鈕
|
$banner.find('.prev-button').attr('aria-label', i18n.prev);
|
||||||
$banner.find('.prev-button').attr('aria-label', i18n.prev);
|
$banner.find('.next-button').attr('aria-label', i18n.next);
|
||||||
|
|
||||||
// ✅ 下一張按鈕
|
var $slides = $banner.find('.w-ba-banner__slide');
|
||||||
$banner.find('.next-button').attr('aria-label', i18n.next);
|
$banner.find('.banner-pager button').each(function(index) {
|
||||||
|
var slideTitle = $slides.eq(index).data('cycle-title') || '';
|
||||||
|
var ariaLabel = isEn
|
||||||
|
? i18n.slide + ' ' + (index + 1) + (slideTitle ? ' ' + slideTitle : '')
|
||||||
|
: i18n.slide + (index + 1) + i18n.slideUnit + (slideTitle ? ' ' + slideTitle : '');
|
||||||
|
$(this).attr({ 'aria-label': ariaLabel, 'title': ariaLabel });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// ✅ Pager 按鈕
|
// ✅ Cycle2 初始化後重新處理 Pager + 切換後播報當前圖片資訊
|
||||||
var $slides = $banner.find('.w-ba-banner__slide');
|
$('.w-ba-banner .cycle-slideshow').on('cycle-post-initialize cycle-after', function(event) {
|
||||||
$banner.find('.banner-pager button').each(function(index) {
|
var $slideshow = $(this);
|
||||||
var slideTitle = $slides.eq(index).data('cycle-title') || '';
|
var $banner = $slideshow.closest('.w-ba-banner');
|
||||||
var ariaLabel = isEn
|
var $slides = $banner.find('.w-ba-banner__slide');
|
||||||
? i18n.slide + ' ' + (index + 1) + (slideTitle ? ' ' + slideTitle : '')
|
|
||||||
: i18n.slide + (index + 1) + i18n.slideUnit + (slideTitle ? ' ' + slideTitle : '');
|
|
||||||
$(this).attr({
|
|
||||||
'aria-label': ariaLabel,
|
|
||||||
'title': ariaLabel
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ✅ Cycle2 初始化後也重新處理 Pager(因為 pager 是動態產生的)
|
// 更新 Pager aria-label
|
||||||
$('.w-ba-banner .cycle-slideshow').on('cycle-post-initialize cycle-after', function() {
|
$banner.find('.banner-pager button').each(function(index) {
|
||||||
var $banner = $(this).closest('.w-ba-banner');
|
var slideTitle = $slides.eq(index).data('cycle-title') || '';
|
||||||
var $slides = $banner.find('.w-ba-banner__slide');
|
var ariaLabel = isEn
|
||||||
$banner.find('.banner-pager button').each(function(index) {
|
? i18n.slide + ' ' + (index + 1) + (slideTitle ? ' ' + slideTitle : '')
|
||||||
var slideTitle = $slides.eq(index).data('cycle-title') || '';
|
: i18n.slide + (index + 1) + i18n.slideUnit + (slideTitle ? ' ' + slideTitle : '');
|
||||||
var ariaLabel = isEn
|
$(this).attr({ 'aria-label': ariaLabel, 'title': ariaLabel });
|
||||||
? i18n.slide + ' ' + (index + 1) + (slideTitle ? ' ' + slideTitle : '')
|
});
|
||||||
: i18n.slide + (index + 1) + i18n.slideUnit + (slideTitle ? ' ' + slideTitle : '');
|
|
||||||
$(this).attr({
|
|
||||||
'aria-label': ariaLabel,
|
|
||||||
'title': ariaLabel
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}, 800);
|
// ✅ 問題1:cycle-after 時用 live region 播報當前圖片資訊
|
||||||
}
|
if (event.type === 'cycle-after') {
|
||||||
|
var opts = $slideshow.data('cycle.opts');
|
||||||
|
if (opts) {
|
||||||
|
var currentIndex = opts.currSlide;
|
||||||
|
var $currentSlide = $slides.eq(currentIndex);
|
||||||
|
var currentTitle = $currentSlide.data('cycle-title') || '';
|
||||||
|
var currentAlt = $currentSlide.find('img').attr('alt') || '';
|
||||||
|
var announceText = isEn
|
||||||
|
? 'Slide ' + (currentIndex + 1) + ' of ' + $slides.length + (currentTitle ? ': ' + currentTitle : (currentAlt ? ': ' + currentAlt : ''))
|
||||||
|
: '第 ' + (currentIndex + 1) + ' 張,共 ' + $slides.length + ' 張' + (currentTitle ? ':' + currentTitle : (currentAlt ? ':' + currentAlt : ''));
|
||||||
|
|
||||||
|
var $announcer = $banner.find('.banner-announcer');
|
||||||
|
if ($announcer.length === 0) {
|
||||||
|
$announcer = $('<div class="banner-announcer" aria-live="polite" aria-atomic="true" style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;"></div>');
|
||||||
|
$banner.append($announcer);
|
||||||
|
}
|
||||||
|
$announcer.text('');
|
||||||
|
setTimeout(function() {
|
||||||
|
$announcer.text(announceText);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 800);
|
||||||
|
}
|
||||||
|
|
||||||
|
fixBannerA11yByLang();
|
||||||
|
});
|
||||||
|
|
||||||
fixBannerA11yByLang();
|
|
||||||
});
|
|
||||||
//bannercontrolplay
|
//bannercontrolplay
|
||||||
$(function() {
|
$(function() {
|
||||||
function fixBannerPlayPauseA11y() {
|
function fixBannerPlayPauseA11y() {
|
||||||
|
setTimeout(function() {
|
||||||
|
var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase();
|
||||||
|
var isEn = pageLang.startsWith('en');
|
||||||
|
|
||||||
|
var i18n = {
|
||||||
|
resume: isEn ? 'Play' : '繼續播放',
|
||||||
|
pause: isEn ? 'Pause' : '暫停播放'
|
||||||
|
};
|
||||||
|
|
||||||
|
$('.w-ba-banner').each(function() {
|
||||||
|
var $banner = $(this);
|
||||||
|
var $controlplay = $banner.find('.controlplay');
|
||||||
|
var $slideshow = $banner.find('.cycle-slideshow');
|
||||||
|
|
||||||
|
$controlplay.removeAttr('role aria-label');
|
||||||
|
|
||||||
|
var $resume = $banner.find('.resume-slide');
|
||||||
|
$resume
|
||||||
|
.attr('role', 'button')
|
||||||
|
.attr('aria-pressed', $resume.hasClass('active') ? 'true' : 'false')
|
||||||
|
.attr('aria-label', i18n.resume)
|
||||||
|
.attr('title', i18n.resume)
|
||||||
|
.removeAttr('aria-checked aria-live');
|
||||||
|
|
||||||
|
var $pause = $banner.find('.pause-slide');
|
||||||
|
$pause
|
||||||
|
.attr('role', 'button')
|
||||||
|
.attr('aria-pressed', $pause.hasClass('active') ? 'true' : 'false')
|
||||||
|
.attr('aria-label', i18n.pause)
|
||||||
|
.attr('title', i18n.pause)
|
||||||
|
.removeAttr('aria-checked aria-live');
|
||||||
|
|
||||||
|
$resume.off('click.bannerA11y').on('click.bannerA11y', function() {
|
||||||
|
$resume.attr('aria-pressed', 'true');
|
||||||
|
$pause.attr('aria-pressed', 'false');
|
||||||
|
});
|
||||||
|
|
||||||
|
$pause.off('click.bannerA11y').on('click.bannerA11y', function() {
|
||||||
|
$pause.attr('aria-pressed', 'true');
|
||||||
|
$resume.attr('aria-pressed', 'false');
|
||||||
|
});
|
||||||
|
|
||||||
|
// ✅ 問題2:focus 時動態讀出當前播放狀態
|
||||||
|
$resume.off('focus.bannerStatus').on('focus.bannerStatus', function() {
|
||||||
|
var isPlaying = !$slideshow.hasClass('cycle-paused');
|
||||||
|
var statusText = isEn
|
||||||
|
? 'Play button. Current status: ' + (isPlaying ? 'Playing' : 'Paused')
|
||||||
|
: '繼續播放按鈕。目前狀態:' + (isPlaying ? '播放中' : '已暫停');
|
||||||
|
$(this).attr('aria-label', statusText);
|
||||||
|
});
|
||||||
|
$resume.off('blur.bannerStatus').on('blur.bannerStatus', function() {
|
||||||
|
$(this).attr('aria-label', i18n.resume);
|
||||||
|
});
|
||||||
|
|
||||||
|
$pause.off('focus.bannerStatus').on('focus.bannerStatus', function() {
|
||||||
|
var isPlaying = !$slideshow.hasClass('cycle-paused');
|
||||||
|
var statusText = isEn
|
||||||
|
? 'Pause button. Current status: ' + (isPlaying ? 'Playing' : 'Paused')
|
||||||
|
: '暫停播放按鈕。目前狀態:' + (isPlaying ? '播放中' : '已暫停');
|
||||||
|
$(this).attr('aria-label', statusText);
|
||||||
|
});
|
||||||
|
$pause.off('blur.bannerStatus').on('blur.bannerStatus', function() {
|
||||||
|
$(this).attr('aria-label', i18n.pause);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 800);
|
||||||
|
}
|
||||||
|
|
||||||
|
fixBannerPlayPauseA11y();
|
||||||
|
});
|
||||||
|
//banner進入自動暫停
|
||||||
|
$(function() {
|
||||||
|
function fixBannerFocusPauseA11y() {
|
||||||
|
setTimeout(function() {
|
||||||
|
$('.w-ba-banner').each(function() {
|
||||||
|
var $banner = $(this);
|
||||||
|
var $slideshow = $banner.find('.cycle-slideshow');
|
||||||
|
var $pauseBtn = $banner.find('.pause-slide');
|
||||||
|
var $resumeBtn = $banner.find('.resume-slide');
|
||||||
|
|
||||||
|
var manuallyPaused = false;
|
||||||
|
|
||||||
|
// ✅ 焦點進入輪播區域時自動暫停
|
||||||
|
$banner.on('focusin', function() {
|
||||||
|
$slideshow.cycle('pause');
|
||||||
|
$pauseBtn.addClass('active').attr('aria-checked', 'true');
|
||||||
|
$resumeBtn.removeClass('active').attr('aria-checked', 'false');
|
||||||
|
});
|
||||||
|
|
||||||
|
// ✅ 若使用者手動按下暫停,焦點離開後不自動恢復
|
||||||
|
$pauseBtn.on('click', function() {
|
||||||
|
manuallyPaused = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
$resumeBtn.on('click', function() {
|
||||||
|
manuallyPaused = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ✅ 覆寫 focusout 加入 manuallyPaused 判斷
|
||||||
|
$banner.off('focusout').on('focusout', function() {
|
||||||
|
setTimeout(function() {
|
||||||
|
if (!$banner.find(':focus').length && !manuallyPaused) {
|
||||||
|
$slideshow.cycle('resume');
|
||||||
|
$resumeBtn.addClass('active').attr('aria-checked', 'true');
|
||||||
|
$pauseBtn.removeClass('active').attr('aria-checked', 'false');
|
||||||
|
}
|
||||||
|
}, 150);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}, 800);
|
||||||
|
}
|
||||||
|
|
||||||
|
fixBannerFocusPauseA11y();
|
||||||
|
});
|
||||||
|
//banner pager 按下狀態
|
||||||
|
$(function() {
|
||||||
|
function fixBannerPagerPressedA11y() {
|
||||||
|
setTimeout(function() {
|
||||||
|
function syncPagerPressed($banner) {
|
||||||
|
$banner.find('.banner-pager button').each(function() {
|
||||||
|
var $btn = $(this);
|
||||||
|
$btn.attr('aria-pressed', $btn.hasClass('active-slide') ? 'true' : 'false');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始狀態(頁面載入當下預設顯示的那張圖)
|
||||||
|
$('.w-ba-banner').each(function() {
|
||||||
|
syncPagerPressed($(this));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cycle2 初始化完成、以及每次切換投影片後,同步 aria-pressed
|
||||||
|
$('.w-ba-banner .cycle-slideshow').on('cycle-post-initialize cycle-after', function() {
|
||||||
|
syncPagerPressed($(this).closest('.w-ba-banner'));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 直接點擊 pager 按鈕時,class 切換與 cycle-after 觸發之間可能有極短延遲,
|
||||||
|
// 這裡多補一次同步,確保狀態不會滯後
|
||||||
|
$(document).on('click', '.banner-pager button', function() {
|
||||||
|
var $banner = $(this).closest('.w-ba-banner');
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
var pageLang = ($('html').attr('lang') || 'zh-Hant').toLowerCase();
|
syncPagerPressed($banner);
|
||||||
var isEn = pageLang.startsWith('en');
|
}, 50);
|
||||||
|
});
|
||||||
|
}, 800);
|
||||||
|
}
|
||||||
|
|
||||||
var i18n = {
|
fixBannerPagerPressedA11y();
|
||||||
resume: isEn ? 'Play' : '繼續播放',
|
|
||||||
pause: isEn ? 'Pause' : '暫停播放'
|
|
||||||
};
|
|
||||||
|
|
||||||
$('.w-ba-banner').each(function() {
|
|
||||||
var $banner = $(this);
|
|
||||||
var $controlplay = $banner.find('.controlplay');
|
|
||||||
|
|
||||||
// ✅ 把 radiogroup 改為一般容器
|
|
||||||
$controlplay.removeAttr('role aria-label');
|
|
||||||
|
|
||||||
// ✅ 繼續播放按鈕
|
|
||||||
var $resume = $banner.find('.resume-slide');
|
|
||||||
$resume
|
|
||||||
.attr('role', 'button')
|
|
||||||
.attr('aria-pressed', $resume.hasClass('active') ? 'true' : 'false')
|
|
||||||
.attr('aria-label', i18n.resume)
|
|
||||||
.attr('title', i18n.resume)
|
|
||||||
.removeAttr('aria-checked aria-live');
|
|
||||||
|
|
||||||
// ✅ 暫停播放按鈕
|
|
||||||
var $pause = $banner.find('.pause-slide');
|
|
||||||
$pause
|
|
||||||
.attr('role', 'button')
|
|
||||||
.attr('aria-pressed', $pause.hasClass('active') ? 'true' : 'false')
|
|
||||||
.attr('aria-label', i18n.pause)
|
|
||||||
.attr('title', i18n.pause)
|
|
||||||
.removeAttr('aria-checked aria-live');
|
|
||||||
|
|
||||||
// ✅ 點擊後同步 aria-pressed
|
|
||||||
$resume.off('click.bannerA11y').on('click.bannerA11y', function() {
|
|
||||||
$resume.attr('aria-pressed', 'true');
|
|
||||||
$pause.attr('aria-pressed', 'false');
|
|
||||||
});
|
|
||||||
|
|
||||||
$pause.off('click.bannerA11y').on('click.bannerA11y', function() {
|
|
||||||
$pause.attr('aria-pressed', 'true');
|
|
||||||
$resume.attr('aria-pressed', 'false');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}, 800);
|
|
||||||
}
|
|
||||||
|
|
||||||
fixBannerPlayPauseA11y();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}(jQuery, window));
|
}(jQuery, window));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
@charset "utf-8";
|
@charset "utf-8";
|
||||||
|
|
||||||
@import "../initial";
|
@import "../initial";
|
||||||
|
.accessibility_mode a:focus{
|
||||||
|
outline: 0.3125em auto $theme-color-second !important;
|
||||||
|
}
|
||||||
.line-it-button{
|
.line-it-button{
|
||||||
.label{
|
.label{
|
||||||
color: #333!important;
|
color: #333!important;
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,22 @@
|
||||||
})
|
})
|
||||||
$('[data-subpart-id="{{subpart-id}}"] .prev-button').click(function(){
|
$('[data-subpart-id="{{subpart-id}}"] .prev-button').click(function(){
|
||||||
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle("prev");
|
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle("prev");
|
||||||
})
|
});
|
||||||
|
/* 修正點:處理 Pager 無障礙朗讀文字 */
|
||||||
|
$('.cycle-slideshow').on('cycle-post-initialize', function(event, optionHash) {
|
||||||
|
var $container = $(this).closest('.w-ba-banner');
|
||||||
|
var $slides = $(this).find('.w-ba-banner__slide');
|
||||||
|
var $pagerButtons = $container.find(".banner-pager button");
|
||||||
|
|
||||||
|
$pagerButtons.each(function(index) {
|
||||||
|
var slideTitle = $slides.eq(index).data('cycle-title') || "";
|
||||||
|
var ariaLabel = "第 " + (index + 1) + " 張投影片 " + slideTitle;
|
||||||
|
$(this).attr({
|
||||||
|
"aria-label": ariaLabel,
|
||||||
|
"title": ariaLabel
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.w-ba-banner .controlplay .resume-slide.active i{
|
.w-ba-banner .controlplay .resume-slide.active i{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue