OCR review: no-team rows still show who/page/change
YouTube click-to-play and watch-next
Line 381: Line 381:
$slot.prepend($iframe);
$slot.prepend($iframe);
}
}
});
}());
(function buildYouTubeWatchlist() {
var YT_ID = /^[A-Za-z0-9_-]{11}$/;
function splitSoldiers(raw) {
return String(raw || '').split(';').map(function (s) {
return $.trim(s);
}).filter(Boolean);
}
function overlap(a, b) {
var i, j;
for (i = 0; i < a.length; i++) {
for (j = 0; j < b.length; j++) {
if (a[i] === b[j]) {
return true;
}
}
}
return false;
}
function playEmbed($slot, id, title) {
var src = 'https://www.youtube-nocookie.com/embed/' +
encodeURIComponent(id) + '?autoplay=1&rel=0';
var $iframe = $('<iframe class="yt-embed-frame" allowfullscreen allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"></iframe>')
.attr({
src: src,
title: title || 'YouTube video',
loading: 'lazy'
});
$slot.empty().append($iframe).addClass('yt-embed-playing');
}
$('.mw-parser-output .yt-embed[data-youtube-id]').each(function () {
var $slot = $(this);
if ($slot.data('rbYtEmbed')) {
return;
}
var id = String($slot.attr('data-youtube-id') || '');
if (!YT_ID.test(id)) {
return;
}
$slot.data('rbYtEmbed', 1);
var title = String($slot.attr('data-title') || 'YouTube video');
var $fallback = $slot.find('.yt-embed-fallback').first();
var $btn = $('<button type="button" class="yt-embed-play"></button>')
.attr('aria-label', 'Play ' + title)
.append($('<span class="yt-embed-play-icon" aria-hidden="true"></span>'))
.append($('<span class="yt-embed-play-text"></span>').text('Play video'));
var $thumb = $('<img class="yt-embed-thumb" alt="">')
.attr({
src: 'https://i.ytimg.com/vi/' + encodeURIComponent(id) + '/hqdefault.jpg',
alt: title
});
var $poster = $('<div class="yt-embed-poster"></div>').append($thumb).append($btn);
if ($fallback.length) {
$fallback.before($poster);
$fallback.hide();
} else {
$slot.prepend($poster);
}
$poster.on('click', function (ev) {
ev.preventDefault();
playEmbed($slot, id, title);
});
});
var $cards = $('.mw-parser-output .yt-interview[data-youtube-id]');
$cards.each(function (idx) {
var $card = $(this);
if ($card.data('rbYtNext')) {
return;
}
$card.data('rbYtNext', 1);
var $slot = $card.find('.yt-interview-next').first();
if (!$slot.length) {
return;
}
var mine = splitSoldiers($card.attr('data-soldiers'));
var picks = [];
var seen = {};
function addCard($other, why) {
var oid = String($other.attr('data-youtube-id') || '');
if (!oid || seen[oid] || oid === $card.attr('data-youtube-id')) {
return;
}
seen[oid] = 1;
picks.push({
id: oid,
heading: String($other.attr('data-heading') || $other.find('h3, h2').first().text() || 'Interview'),
short: String($other.attr('data-short') || ''),
why: why
});
}
$cards.each(function (j) {
if (j === idx || picks.length >= 3) {
return;
}
var $other = $($cards.get(j));
if (overlap(mine, splitSoldiers($other.attr('data-soldiers')))) {
addCard($other, 'same soldier');
}
});
if (idx + 1 < $cards.length) {
addCard($($cards.get(idx + 1)), 'next');
}
if (!picks.length) {
return;
}
var $list = $('<ul class="yt-interview-next-list"></ul>');
picks.slice(0, 3).forEach(function (item) {
var label = item.short ? (item.heading + ' — ' + item.short) : item.heading;
var $a = $('<a></a>').attr('href', '#yt-' + item.id).text(label);
var $li = $('<li></li>').append($a);
if (item.why === 'same soldier') {
$li.append($('<span class="yt-interview-next-why"></span>').text(' (same person)'));
}
$list.append($li);
});
$slot.empty()
.append($('<div class="yt-interview-next-label"></div>').text('Watch next'))
.append($list);
});
});
}());
}());
Line 447: Line 574:
if ($leadCue.length) {
if ($leadCue.length) {
$leadCue.after($storyCue);
$leadCue.after($storyCue);
}
}
// Interview / film cue sits with the story cue under the lead.
var $mediaCue = $out.find('.soldier-media-cue').first();
if ($mediaCue.length && !$mediaCue.data('rbMediaCuePlaced')) {
$mediaCue.data('rbMediaCuePlaced', 1);
var $afterStory = $out.find('.soldier-story-cue').first();
if ($afterStory.length) {
$afterStory.after($mediaCue);
} else {
var $leadMedia = $out.find('.soldier-lead, .page-lead').first();
if ($leadMedia.length) {
$leadMedia.after($mediaCue);
}
}
}
}
}