This commit is contained in:
ken 2026-08-06 14:05:18 +08:00
parent 0db139d6d3
commit 0ec89e42ab
6 changed files with 88 additions and 57 deletions

View File

@ -1101,56 +1101,59 @@ $(function() {
}
}
// E. 重新計算標題 (關鍵邏輯:若 hasOriginalTitle 為真,則不進入此區塊)
if (!hasOriginalTitle) {
if (linkText === "" && $img.length > 0) {
var rawAlt = ($img.attr('alt') || '').trim();
var forbidden = ['這是一張圖片', '圖片', 'image', 'photo', '圖', ''];
var imgAlt = forbidden.some(function(txt) { return rawAlt.toLowerCase() === txt; })
? ($a.attr('aria-label') || i18n.link) : rawAlt;
var fileInfo = fileExt ? '[' + fileExt.toUpperCase() + '] ' : '';
$a.attr('title', (fileInfo + imgAlt + " " + windowTask).trim());
$img.attr('alt', imgAlt);
}
else if (linkText !== "") {
if (fileExt !== "" || hasBadSymbol || currentTitle === "" || currentTitle.includes('/uploads/')) {
if (fileExt !== "") {
$a.attr('title', linkText + " ." + fileExt + " " + windowTask);
} else {
$a.attr('title', windowTask);
}
// E. 重新計算標題 (關鍵邏輯:若 hasOriginalTitle 為真,則不進入此區塊)
if (!hasOriginalTitle) {
if (linkText === "" && $img.length > 0) {
var rawAlt = ($img.attr('alt') || '').trim();
var forbidden = ['這是一張圖片', '圖片', 'image', 'photo', '圖', ''];
var imgAlt = forbidden.some(function(txt) { return rawAlt.toLowerCase() === txt; })
? ($a.attr('aria-label') || i18n.link) : rawAlt;
var fileInfo = fileExt ? '[' + fileExt.toUpperCase() + '] ' : '';
$a.attr('title', (fileInfo + imgAlt + " " + windowTask).trim());
$img.attr('alt', imgAlt);
}
else if (linkText !== "") {
if (fileExt !== "" || hasBadSymbol || currentTitle === "" || currentTitle.includes('/uploads/')) {
if (fileExt !== "") {
$a.attr('title', linkText + " ." + fileExt + " " + windowTask);
} else {
$a.attr('title', windowTask);
}
}
}
}
// ✅ 符合 HM1240404Etitle 不應與連結文字或圖片 alt 重複
if (hasOriginalTitle && currentTitle !== "") {
var titleWithoutWindow = currentTitle
.replace('(在本視窗開啟)', '')
.replace('(在新視窗開啟)', '')
.replace('Open in this window', '')
.replace('Open in new window', '')
.replace('另開新視窗前往', '')
.replace('另開新視窗', '')
.trim();
// ✅ 符合 HM1240404Etitle 不應與連結文字或圖片 alt 重複
if (hasOriginalTitle && currentTitle !== "") {
var titleWithoutWindow = currentTitle
.replace('(在本視窗開啟)', '')
.replace('(在新視窗開啟)', '')
.replace('Open in this window', '')
.replace('Open in new window', '')
.replace('另開新視窗前往', '')
.replace('另開新視窗', '')
.trim();
// ✅ title 去掉開窗字串後,若與連結文字或圖片原始 alt 相同,則只保留開窗提示
if (
(titleWithoutWindow === linkText && linkText !== i18n.link) ||
(imgAltOriginal !== '' && titleWithoutWindow === imgAltOriginal)
) {
$a.attr('title', windowTask);
}
// ✅ 最終清理:若 title 出現空括號 () 則移除並補上正確開窗提示
var finalTitle = ($a.attr('title') || '').trim();
if (finalTitle.includes('()')) {
finalTitle = finalTitle.replace(/\(\)/g, '').trim();
$a.attr('title', finalTitle + ' ' + windowTask);
}
// ✅ title 去掉開窗字串後,若與連結文字或圖片原始 alt 相同,則只保留開窗提示
// ✅ 新增:若 linkText 包含副檔名且 title 也是同樣檔名,也只保留開窗提示
if (
(titleWithoutWindow === linkText && linkText !== i18n.link) ||
(imgAltOriginal !== '' && titleWithoutWindow === imgAltOriginal) ||
(fileExt !== '' && linkText.toLowerCase().endsWith('.' + fileExt) && titleWithoutWindow === linkText)
) {
$a.attr('title', windowTask);
return; // ✅ 加上 return避免繼續執行後面的清理邏輯造成二次污染
}
// ✅ 最終清理:若 title 出現空括號 () 則移除並補上正確開窗提示
var finalTitle = ($a.attr('title') || '').trim();
if (finalTitle.includes('()')) {
finalTitle = finalTitle.replace(/\(\)/g, '').trim();
$a.attr('title', finalTitle + ' ' + windowTask);
}
}
// F. 最終清理:移除冗餘 label避免螢幕閱讀器唸兩次
$a.removeAttr('aria-label');
});

View File

@ -9,6 +9,7 @@
// Widget
// ## gerenral styles
ul.button-mid{
z-index: 200;
.prev-button{
height: 2em !important;
width: 2em !important;

View File

@ -10,7 +10,7 @@
// ## Gerneral styles for widgets
.i-annc__category{
white-space: nowrap;
color: #fff;
color:#000;
border-radius: 1em;
padding: 1px 5px;
}

View File

@ -29,7 +29,7 @@
</div>
</div>
<div class="w-ad-banner__pager-2 w-ba-banner__caption banner-pager banner_caption_{{subpart-id}}" data-list="images" data-level="0">
<div class="w-ad-banner__pager-2 w-ba-banner__caption banner-pager banner_caption_{{subpart-id}}" data-list="images" data-level="0">
<li><button title="Slide {{slide_number}}" aria-label="Pager"><span style="display: none;">Slide {{slide_number}}</span></button></li>
</div>
<ul class="controlplay" role="radiogroup" aria-label="播放控制選項">

View File

@ -11,7 +11,7 @@
data-cycle-timeout="{{timeout}}"
data-cycle-fx="{{ad_fx}}"
data-pager=".banner_caption_{{subpart-id}}"
data-cycle-pager-template="<li><img src='{{src}}' alt='thumbnail'></li>"
data-cycle-pager-template="<li role='tab' tabindex='0' aria-selected='false' aria-label='{{title}}'><img src='{{src}}' alt='' aria-hidden='true'></li>"
data-pager-active-class="active-slide"
data-cycle-youtube="true"
data-cycle-youtube-autostart="false"
@ -457,7 +457,8 @@
if (match && pagerItems[i]) {
const videoId = match[1];
pagerItems[i].src = `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`;
pagerItems[i].alt = "YouTube thumbnail";
// alt 已在 pager template 由 {{title}} 提供,此處清空避免輔具重複唸
pagerItems[i].alt = "";
}
});
});
@ -556,18 +557,27 @@ function fixBannerPagerA11y($pager) {
if (!$pager || $pager.length === 0) return;
// 外層補 tablist role
$pager.attr('role', 'tablist').attr('aria-label', '輪播片選擇');
$pager.attr('role', 'tablist').attr('aria-label', '輪播片選擇');
// 每個 li 補 role/tabindex/aria-label/aria-selected
$pager.find('li').each(function(i) {
var $li = $(this);
// 避免重複初始化
if ($li.attr('role') === 'tab') return;
// 取得影片標題:優先用 template 已帶入的 aria-label其次用 img alt最後 fallback 第N張
var existingLabel = ($li.attr('aria-label') || '').trim();
var imgAlt = ($li.find('img').attr('alt') || '').trim();
var label = (existingLabel && existingLabel !== '第' + (i + 1) + '張')
? existingLabel
: (imgAlt ? imgAlt : '第' + (i + 1) + '張影片');
$li
.attr('role', 'tab')
.attr('tabindex', '0')
.attr('aria-selected', $li.hasClass('active-slide') ? 'true' : 'false')
.attr('aria-label', '第' + (i + 1) + '張');
.attr('aria-label', label);
// 縮圖圖片本身為裝飾性alt 清空並加 aria-hidden
$li.find('img').attr('alt', '').attr('aria-hidden', 'true');
});
// 鍵盤 Enter/Space 觸發點擊(用 on 綁定避免重複)

View File

@ -26,7 +26,9 @@
</a>
</div>
</div>
<ul class="w-ba-banner__pager-3 banner-pager banner_caption_{{subpart-id}}"></ul>
<div class="w-ad-banner__pager-2 w-ba-banner__caption banner-pager banner_caption_{{subpart-id}}" data-list="images" data-level="0">
<li><button title="Slide {{slide_number}}" aria-label="Pager"><span style="display: none;">Slide {{slide_number}}</span></button></li>
</div>
<ul class="controlplay" role="radiogroup" aria-label="播放控制選項">
<a role="radio" aria-checked="true" href="javascript:;" class="resume-slide active" title="繼續播放" aria-label="繼續播放" aria-live="assertive">
<i aria-hidden="true"></i>
@ -38,10 +40,10 @@
<p style="display: none;"><%= I18n.t("ad_banner.pause") %></p>
</a>
</ul>
<ul class="button-mid">
<button class="prev-button" title = "<%= (I18n.locale.to_s =="zh_tw") ? "上一張" : "prev" %>" aria-label="Pager"></button>
<button class="next-button" title = "<%= (I18n.locale.to_s =="zh_tw") ? "下一張" : "next" %>" aria-label="Pager"></button>
</ul>
<ul class="button-mid">
<i class="fa fa-angle-left prev-button" aria-label="<%= I18n.t("ad_banner.prev") %>"></i>
<i class="fa fa-angle-right next-button" aria-label="<%= I18n.t("ad_banner.next") %>"></i>
</ul>
</div>
<script>
var flag = 1;
@ -67,5 +69,20 @@
})
$('.prev-button').off('click').on('click',function(){
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle("prev");
})
});
/* 修正點:處理 Pager 無障礙朗讀文字 */
$('.cycle-slideshow').on('cycle-post-initialize', function(event, optionHash) {
var $container = $(this).closest('.w-ba-banner');
var $slides = $(this).find('.w-ba-banner__slide');
var $pagerButtons = $container.find(".banner-pager button");
$pagerButtons.each(function(index) {
var slideTitle = $slides.eq(index).data('cycle-title') || "";
var ariaLabel = "第 " + (index + 1) + " 張投影片 " + slideTitle;
$(this).attr({
"aria-label": ariaLabel,
"title": ariaLabel
});
});
});
</script>