210 lines
7.1 KiB
Plaintext
210 lines
7.1 KiB
Plaintext
<div class="w-video_data video_data-widget-6">
|
||
<h3 class="widget-title"><span>{{widget-title}}</span></h3>
|
||
<div class="btnwrapper" style="">
|
||
<button id="prev-{{subpart-id}}" class="btn-left" title = "<%= (I18n.locale.to_s =="zh_tw") ? "上一張" : "prev" %>" style="transition: 0.4s;
|
||
float: left;
|
||
left: 0.5rem;
|
||
transition: 0.4s;
|
||
right: 0.5rem;
|
||
color: rgb(255, 255, 255);
|
||
background: rgba(0, 0, 0, 0.4);
|
||
text-align: center;
|
||
top: 50%;
|
||
position: absolute;
|
||
transform: translateY(-50%);
|
||
z-index: 999;
|
||
height: 2em !important;
|
||
width: 2em !important;
|
||
font-size: 1em !important;
|
||
line-height: 2rem !important;
|
||
border-radius: 1em;
|
||
border: 0;"><i class="fa fa-angle-left prev-button" aria-hidden="true" style="font-size: 1rem;"></i><span style="display: none;"><%= (I18n.locale.to_s =="zh_tw") ? "上一張" : "prev" %></span></button>
|
||
<button id="next-{{subpart-id}}" class="btn-right" title = "<%= (I18n.locale.to_s =="zh_tw") ? "下一張" : "next" %>" style="
|
||
float: right;
|
||
transition: 0.4s;
|
||
right: 1.5rem;
|
||
color: rgb(255, 255, 255);
|
||
background: rgba(0, 0, 0, 0.4);
|
||
text-align: center;
|
||
top: 50%;
|
||
position: absolute;
|
||
transform: translateY(-50%);
|
||
z-index: 999;
|
||
height: 2em !important;
|
||
width: 2em !important;
|
||
font-size: 1em !important;
|
||
line-height: 2rem !important;
|
||
border-radius: 1em;
|
||
border: 0;"><i class="fa fa-angle-right next-button" aria-hidden="true" style="font-size: 1rem;"></i><span style="display: none;"><%= (I18n.locale.to_s =="zh_tw") ? "下一張" : "next" %></span></button>
|
||
</div>
|
||
<ul class="video_data_wrap col-sm-12 cycle-slideshow" data-list="videos" data-level="0" data-cycle-fx="carousel"
|
||
data-cycle-timeout="0"
|
||
data-cycle-carousel-visible="1"
|
||
data-cycle-carousel-fluid="true"
|
||
data-cycle-next="#next-{{subpart-id}}"
|
||
data-cycle-prev="#prev-{{subpart-id}}"
|
||
data-cycle-slides=".video_data"
|
||
>
|
||
<li class="video_data col-xs-12 col-sm-4" data-video-url="{{video_url}}" data-video-webm-url="{{video_webm_url}}" data-type="{{video_type}}" >
|
||
<a href="{{video_show_url}}" title="{{video_title_escape}}">
|
||
<div class="video_linkwrapper6">
|
||
<div class="videohover">
|
||
<div class="view_info">
|
||
<span>{{view_count}}</span>
|
||
</div>
|
||
<div class="Video__Player"><button class="Video__PlayerButton" title="前往{{video_title_escape}}" role="button"></button></div>
|
||
<div class="videoduration"></div>
|
||
</div>
|
||
<img class="video_snapshot" src="{{snapshot_url}}"/>
|
||
</div>
|
||
</a>
|
||
|
||
<div class="video_info">
|
||
<div class="video_length">{{video_duration}}</div>
|
||
<div data-list="video_tags" data-level="1" class="video_tag"><div class="video_tags2">{{video_tag}}</div></div>
|
||
<div class="video_keyword">{{video_keyword}}</div>
|
||
<div class="video_group_time">{{video_postdate}}</div>
|
||
<div class="video_title"><a class="video_link" href="{{video_show_url}}" title="{{video_title_escape}}"><h5>{{video_title}}</h5></a></div>
|
||
<div class="video_desc"><a class="video_link" href="{{video_show_url}}" title="{{video_title_escape}}">{{video_desc}}</a></div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<div class="clearfix"></div>
|
||
<style>
|
||
|
||
.video_title h5{
|
||
@extend .i-title;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.view_info{
|
||
float: right;
|
||
}
|
||
.view_info img{
|
||
margin-right: 5px;
|
||
}
|
||
.view_info{
|
||
max-height: 100%;
|
||
border-radius: 2px;
|
||
font-size: 0.875rem;
|
||
font-weight: normal;
|
||
letter-spacing: 0.3px;
|
||
text-align: center;
|
||
display: flex;
|
||
-webkit-box-align: center;
|
||
align-items: center;
|
||
position: absolute;
|
||
padding: 0px 8px;
|
||
background-color: #000000cc;
|
||
color: rgb(255, 255, 255);
|
||
z-index: 10;
|
||
top: 10px;
|
||
left: 10px;
|
||
border: 1px solid transparent;
|
||
line-height: 1.45;
|
||
span{
|
||
color:#fff;
|
||
}
|
||
&:before{
|
||
content: "";
|
||
display: inline-block;
|
||
margin-right: 5px;
|
||
width: 14px;
|
||
height: 10px;
|
||
background: url(/assets/icon-view@2x.png) no-repeat;
|
||
position: relative;
|
||
background-size: contain;
|
||
}
|
||
}
|
||
</style>
|
||
</div>
|
||
<script>
|
||
$(document).ready(function () {
|
||
|
||
// =============================================
|
||
// video_data-widget-6 專用無障礙修正
|
||
// 問題:鍵盤焦點游走至輪播項目時,輪播不跟著切換
|
||
// =============================================
|
||
|
||
function initVideoCarouselA11y($widget) {
|
||
var $slideshow = $widget.find('.cycle-slideshow');
|
||
var $prevBtn = $widget.find('.btn-left');
|
||
var $nextBtn = $widget.find('.btn-right');
|
||
|
||
if (!$slideshow.length) return;
|
||
|
||
// --- Step 1: 初始化每個 slide 的 tabindex 狀態 ---
|
||
function refreshVideoA11y() {
|
||
$slideshow.find('.video_data').each(function (idx) {
|
||
var $slide = $(this);
|
||
var isActive = $slide.hasClass('cycle-slide-active');
|
||
|
||
$slide.attr('aria-hidden', isActive ? 'false' : 'true');
|
||
|
||
// 非當前 slide 的所有可聚焦元素一律 tabindex="-1"
|
||
$slide.find('a, button, input, select, textarea, [tabindex]').attr(
|
||
'tabindex', isActive ? '0' : '-1'
|
||
);
|
||
});
|
||
}
|
||
|
||
// --- Step 2: 焦點進入某 slide 時,強制輪播切換至該 slide ---
|
||
$slideshow.on('focusin', '.video_data', function () {
|
||
var $focusedSlide = $(this);
|
||
|
||
// 已是 active 就不需要切換
|
||
if ($focusedSlide.hasClass('cycle-slide-active')) return;
|
||
|
||
// 取得該 slide 的索引
|
||
var slideIndex = $slideshow.find('.video_data').index($focusedSlide);
|
||
if (slideIndex < 0) return;
|
||
|
||
// 用 Cycle2 API 跳到對應 slide
|
||
$slideshow.cycle(slideIndex);
|
||
|
||
// 切換後刷新 a11y 狀態,並讓焦點保持在觸發元素上
|
||
$slideshow.one('cycle-after', function () {
|
||
setTimeout(function () {
|
||
refreshVideoA11y();
|
||
// 將焦點移到剛切換到的 slide 的第一個可聚焦元素
|
||
$focusedSlide.find('a, button').first().focus();
|
||
}, 50);
|
||
});
|
||
});
|
||
|
||
// --- Step 3: 按鈕點擊 / Enter 後刷新 a11y ---
|
||
$prevBtn.add($nextBtn).on('click keydown', function (e) {
|
||
if (e.type === 'keydown' && e.keyCode !== 13 && e.keyCode !== 32) return;
|
||
|
||
var $btn = $(this);
|
||
$slideshow.one('cycle-after', function () {
|
||
setTimeout(function () {
|
||
refreshVideoA11y();
|
||
$btn.focus(); // 焦點留在按鈕上
|
||
}, 100);
|
||
});
|
||
});
|
||
|
||
// --- Step 4: 按鈕補強 aria-label(title 屬性輔具不保證讀到)---
|
||
$prevBtn.attr('aria-label', $prevBtn.attr('title') || '上一張');
|
||
$nextBtn.attr('aria-label', $nextBtn.attr('title') || '下一張');
|
||
|
||
// --- Step 5: 綁定 Cycle2 初始化完成事件 ---
|
||
$slideshow.on('cycle-initialized cycle-after', function () {
|
||
setTimeout(refreshVideoA11y, 100);
|
||
});
|
||
|
||
// 立即執行一次初始化
|
||
setTimeout(refreshVideoA11y, 500);
|
||
}
|
||
|
||
// 套用到頁面上所有 video_data-widget-6
|
||
$('.w-video_data').each(function () {
|
||
initVideoCarouselA11y($(this));
|
||
});
|
||
|
||
});
|
||
</script> |