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

View File

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

View File

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

View File

@ -29,7 +29,7 @@
</div> </div>
</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> <li><button title="Slide {{slide_number}}" aria-label="Pager"><span style="display: none;">Slide {{slide_number}}</span></button></li>
</div> </div>
<ul class="controlplay" role="radiogroup" aria-label="播放控制選項"> <ul class="controlplay" role="radiogroup" aria-label="播放控制選項">

View File

@ -11,7 +11,7 @@
data-cycle-timeout="{{timeout}}" data-cycle-timeout="{{timeout}}"
data-cycle-fx="{{ad_fx}}" data-cycle-fx="{{ad_fx}}"
data-pager=".banner_caption_{{subpart-id}}" 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-pager-active-class="active-slide"
data-cycle-youtube="true" data-cycle-youtube="true"
data-cycle-youtube-autostart="false" data-cycle-youtube-autostart="false"
@ -457,7 +457,8 @@
if (match && pagerItems[i]) { if (match && pagerItems[i]) {
const videoId = match[1]; const videoId = match[1];
pagerItems[i].src = `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`; 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; if (!$pager || $pager.length === 0) return;
// 外層補 tablist role // 外層補 tablist role
$pager.attr('role', 'tablist').attr('aria-label', '輪播片選擇'); $pager.attr('role', 'tablist').attr('aria-label', '輪播片選擇');
// 每個 li 補 role/tabindex/aria-label/aria-selected // 每個 li 補 role/tabindex/aria-label/aria-selected
$pager.find('li').each(function(i) { $pager.find('li').each(function(i) {
var $li = $(this); 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 $li
.attr('role', 'tab') .attr('role', 'tab')
.attr('tabindex', '0') .attr('tabindex', '0')
.attr('aria-selected', $li.hasClass('active-slide') ? 'true' : 'false') .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 綁定避免重複) // 鍵盤 Enter/Space 觸發點擊(用 on 綁定避免重複)

View File

@ -26,7 +26,9 @@
</a> </a>
</div> </div>
</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="播放控制選項"> <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"> <a role="radio" aria-checked="true" href="javascript:;" class="resume-slide active" title="繼續播放" aria-label="繼續播放" aria-live="assertive">
<i aria-hidden="true"></i> <i aria-hidden="true"></i>
@ -38,10 +40,10 @@
<p style="display: none;"><%= I18n.t("ad_banner.pause") %></p> <p style="display: none;"><%= I18n.t("ad_banner.pause") %></p>
</a> </a>
</ul> </ul>
<ul class="button-mid"> <ul class="button-mid">
<button class="prev-button" title = "<%= (I18n.locale.to_s =="zh_tw") ? "上一張" : "prev" %>" aria-label="Pager"></button> <i class="fa fa-angle-left prev-button" aria-label="<%= I18n.t("ad_banner.prev") %>"></i>
<button class="next-button" title = "<%= (I18n.locale.to_s =="zh_tw") ? "下一張" : "next" %>" aria-label="Pager"></button> <i class="fa fa-angle-right next-button" aria-label="<%= I18n.t("ad_banner.next") %>"></i>
</ul> </ul>
</div> </div>
<script> <script>
var flag = 1; var flag = 1;
@ -67,5 +69,20 @@
}) })
$('.prev-button').off('click').on('click',function(){ $('.prev-button').off('click').on('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>