0;
var canB2 = !!(d.stream_urls && d.stream_urls.length);
var canGd = hasGd;
var canHls = !!d.hls_url;
this._prevServer = this.server;
// Fullscreen bisa native (document.fullscreenElement) ATAU
// mode fallback CSS Plyr (`.plyr--fullscreen-fallback`, dipakai
// WebView / browser tanpa Fullscreen API). Kalau hanya cek
// document.fullscreenElement, di mode fallback ini nilainya
// null -> re-enter tak pernah jalan -> keluar fullscreen.
this._wasFullscreen = !!(document.fullscreenElement
|| document.querySelector('.plyr--fullscreen-fallback'));
const c = document.getElementById('anime-player-container');
if (c) {
var spriteUrl = d.sprite_url ? d.sprite_url : null;
window.b2PlayerOptions = {
sources: d.stream_urls,
gdriveSources: gdSrcs,
episodeId: d.id,
prevUrl: d.prev_url,
nextUrl: d.next_url,
skipIntroAt: null,
posterUrl: d.poster_url,
title: epTitle,
slug: slug,
currentEp: d.episode_number,
episodes: window.b2PlayerOptions?.episodes || [],
epTotal: window.b2PlayerOptions?.epTotal || 0,
epPerPage: window.b2PlayerOptions?.epPerPage || 50,
epCurrentPage: window.b2PlayerOptions?.epCurrentPage || 1,
logoUrl: window.b2PlayerOptions?.logoUrl || null,
spriteUrl: spriteUrl,
};
var _pp = window.b2PlayerOptions.epPerPage || 52;
var _eps = window.b2PlayerOptions.episodes || [];
var _epIdx = _eps.findIndex(function(e) { return e.id === d.id; });
window.b2PlayerOptions.epCurrentPage = _epIdx >= 0 ? Math.floor(_epIdx / _pp) + 1 : 1;
}
this.gdriveSources = gdSrcs;
if (window.b2PlayerOptions) window.b2PlayerOptions.hlsUrl = d.hls_url || null;
// Resolve the target server BEFORE touching any player, otherwise the
// previous episode keeps playing inside a display:none frame (double audio).
var order = (this.server === 'hls') ? ['hls', 'b2', 'gdrive'] : ['b2', 'gdrive', 'hls'];
var picked = null;
for (var oi = 0; oi < order.length; oi++) {
if (order[oi] === 'b2' && canB2) { picked = 'b2'; break; }
if (order[oi] === 'gdrive' && canGd) { picked = 'gdrive'; break; }
if (order[oi] === 'hls' && canHls) { picked = 'hls'; break; }
}
if (!picked) picked = canB2 ? 'b2' : (canGd ? 'gdrive' : (canHls ? 'hls' : this.server));
this.server = picked;
this.pauseInactivePlayers();
// Player langsung mencoba primary GDrive. Kalau kena 403,
// player.js (_handleFailure) yang menampilkan overlay dan
// memicu mirror on-demand — jadi pindah episode tidak lagi
// tertahan menunggu mirror dibuat.
if (picked === 'hls' || (!canB2 && !canGd)) {
this.killDirectPlayer();
} else if (c) {
var gdNow = (picked === 'gdrive');
var srces = gdNow ? gdSrcs : d.stream_urls;
if (gdNow) this.gdriveLoaded = false; else this.b2Loaded = false;
if (c._player && c._player.switchSource) {
c._player.isGdrive = gdNow;
c._player.switchSource(
srces, d.prev_url, d.next_url, d.poster_url, epTitle,
slug, window.b2PlayerOptions.episodes, d.episode_number,
window.b2PlayerOptions.epCurrentPage, window.b2PlayerOptions.epPerPage,
window.b2PlayerOptions.epTotal, d.id, spriteUrl
);
const v = c.querySelector('#anime-video');
if (v) {
let _done = false;
const _ready = () => { if (_done) return; _done = true; if (gdNow) this.gdriveLoaded = true; else this.b2Loaded = true; };
v.addEventListener('playing', _ready, { once: true });
v.addEventListener('canplay', _ready, { once: true });
setTimeout(_ready, 8000);
} else { if (gdNow) this.gdriveLoaded = true; else this.b2Loaded = true; }
} else {
c.querySelectorAll('video').forEach((v) => this._hardStopMedia(v));
c.innerHTML = '';
this.$nextTick(() => {
if (gdNow) window.initAnimePlayer(c, Object.assign({}, window.b2PlayerOptions, { sources: srces, isGdrive: true }));
else window.initAnimePlayer(c, window.b2PlayerOptions);
if (gdNow) this.gdriveLoaded = true; else this.b2Loaded = true;
});
}
}
// HLS player: (re)source it only after the server is resolved.
if (this.server === 'hls') {
this.hlsLoaded = false;
const hc = document.getElementById('hls-player-container');
// A new episode is an explicit play intent -- unless the
// user paused while this switch was still in flight.
if (hc && (hc._hlsPauseEpoch || 0) === hcEp0) hc._hlsUserPaused = false;
if (!canHls) {
this.killHlsPlayer();
} else if (hc && typeof hc.switchHlsSource === 'function') {
hc.switchHlsSource(d.hls_url);
this.hlsLoaded = true;
} else {
this.$nextTick(() => this.loadHls());
}
} else {
this._pauseHls();
}
// 1. Release date
if (this.$refs.epReleaseDate) {
var dt = this.$refs.epReleaseDate;
if (d.formatted_release_date) {
dt.querySelector('span') ? dt.querySelector('span').textContent = d.formatted_release_date : dt.appendChild(document.createTextNode(d.formatted_release_date));
dt.style.display = '';
} else {
dt.style.display = 'none';
}
}
// 3. Duration
if (this.$refs.epDuration) {
if (d.duration) {
this.$refs.epDuration.querySelector('span').textContent = d.duration;
this.$refs.epDuration.style.display = '';
} else {
this.$refs.epDuration.style.display = 'none';
}
}
// 4. Description
if (this.$refs.epDescription) {
var descP = this.$refs.epDescription.querySelector('p');
if (descP) {
if (d.description) {
descP.innerHTML = '
Episode ' + epLabel + ' - ' + d.description;
this.$refs.epDescription.style.display = '';
} else {
this.$refs.epDescription.style.display = 'none';
}
}
}
// 5. Like button
var likeBtn = document.getElementById('like-btn');
if (likeBtn) {
likeBtn.dataset.episodeId = d.id;
likeBtn.dataset.liked = d.is_liked ? '1' : '0';
var lc = document.getElementById('like-count');
if (lc) lc.textContent = d.likes_count || '0';
var icon = likeBtn.querySelector('svg');
if (d.is_liked) {
likeBtn.classList.add('liked');
if (icon) icon.setAttribute('fill', 'currentColor');
} else {
likeBtn.classList.remove('liked');
if (icon) icon.setAttribute('fill', 'none');
}
}
// 7. Update current episode ID for pagination
this.currentEpisodeId = d.id;
// 9. HLS / GDrive / B2 tabs — source + player already resolved above
this.hasHls = canHls;
this.hasGdrive = canGd;
this.hasB2Stream = canB2;
if (this._wasFullscreen && this._prevServer !== this.server) {
const target = this._isDirect()
? document.getElementById('anime-player-container')
: document.getElementById('hls-player-container');
this._reenterFullscreen(target, 0);
}
var posterOverlays = document.querySelectorAll('.watch-player-frame [style*="background-image"]');
if (d.poster_url) {
for (var i = 0; i < posterOverlays.length; i++) {
posterOverlays[i].style.backgroundImage = 'url(\'' + d.poster_url + '\')';
}
}
// 10. Prev/Next buttons
if (this.$refs.prevBtn) {
if (d.prev_url) { this.$refs.prevBtn.href = d.prev_url; this.$refs.prevBtn.classList.remove('hidden'); }
else { this.$refs.prevBtn.classList.add('hidden'); }
}
if (this.$refs.nextBtn) {
if (d.next_url) { this.$refs.nextBtn.href = d.next_url; this.$refs.nextBtn.classList.remove('hidden'); }
else { this.$refs.nextBtn.classList.add('hidden'); }
}
// 11. Browser URL
history.pushState(null, '', '/anime/' + slug + '/episode/' + d.episode_number);
// 12. Breadcrumb episode
var breadcrumbEpisode = document.querySelector('#watch-breadcrumb .crumb-seg:last-child .crumb-label');
if (breadcrumbEpisode) {
breadcrumbEpisode.textContent = false ? 'Movie' : 'Ep ' + epLabel;
}
// 13. Episode chips active state
document.querySelectorAll('.ep-chip').forEach(function(el) {
el.classList.remove('active');
if (parseInt(el.dataset.ep) === d.episode_number) {
el.classList.add('active');
}
});
// 12b. Full grid items active state (showAllEpisodes)
document.querySelectorAll('.ep-btn, .ep-btn-sidebar').forEach(function(el) {
if (parseInt(el.dataset.ep) === d.episode_number) {
el.classList.add('bg-purple-600', 'text-white');
el.classList.remove('bg-gray-800', 'text-gray-400', 'border', 'border-gray-700/50', 'hover:bg-gray-700', 'bg-gray-700/50');
} else {
el.classList.remove('bg-purple-600', 'text-white');
el.classList.add('bg-gray-800', 'text-gray-400', 'border', 'border-gray-700/50', 'hover:bg-gray-700');
}
});
// 13. Sidebar episodes active state
document.querySelectorAll('.sidebar-ep-item').forEach(function(el) {
el.classList.remove('active', 'bg-purple-600/10');
el.classList.add('hover:bg-white/5');
if (parseInt(el.dataset.ep) === d.episode_number) {
el.classList.remove('hover:bg-white/5');
el.classList.add('active', 'bg-purple-600/10');
}
});
// 14. Repost button
var rpBtn = document.getElementById('repost-btn');
if (rpBtn) rpBtn.dataset.episodeId = d.id;
// 15. Download link
var dlLink = document.getElementById('download-link');
if (dlLink) dlLink.href = '/anime/' + slug + '/episode/' + d.episode_number + '/download';
// 16. Report forms
document.querySelectorAll('.report-form').forEach(function(f) {
f.action = '/episode/' + d.id + '/report';
});
// 17. Comments
if (d.comments_html) {
var csEl = document.getElementById('comment-section');
if (csEl) csEl.outerHTML = d.comments_html;
}
// 18. Episode Berikutnya
var nexEl = document.getElementById('next-episode-container');
if (nexEl) {
nexEl.innerHTML = d.next_episode_html || '';
nexEl.hidden = !(d.next_episode_html || '').trim();
}
// Safety net: only the resolved server may keep playing.
this.pauseInactivePlayers();
this._loading = false;
})
.catch(() => { this._loading = false; });
},
// Keluar dari fullscreen (native maupun fallback CSS) pada player
// selain `keep`.
_exitOtherFullscreens(keep) {
const keepPlayer = keep ? (keep._player ? keep._player.player : keep._hlsPlayer) : null;
const keepTarget = keepPlayer && keepPlayer.fullscreen ? keepPlayer.fullscreen.target : null;
['anime-player-container', 'hls-player-container'].forEach((id) => {
const oc = document.getElementById(id);
if (!oc || oc === keep) return;
const op = oc._player ? oc._player.player : oc._hlsPlayer;
try {
if (!op || !op.fullscreen || !op.fullscreen.active) return;
// Target fullscreen sama (`.player-fs-shell` dipakai bersama
// kedua player) -> JANGAN di-exit; itu justru menutup
// fullscreen yang sedang aktif.
if (keepTarget && op.fullscreen.target === keepTarget) return;
op.fullscreen.exit();
} catch (e) {}
});
},
_reenterFullscreen(container, attempts) {
if (!container) return;
attempts = attempts || 0;
if (attempts > 60) return;
const retry = (delay) => setTimeout(() => this._reenterFullscreen(container, attempts + 1), delay || 200);
const pe = container.querySelector('.plyr');
const p = container._player ? (container._player.player || null) : (container._hlsPlayer || null);
if (!p || !p.fullscreen) { retry(); return; }
// Sudah fullscreen di player ini (native atau fallback CSS)?
if (p.fullscreen.active) {
const nf = document.fullscreenElement;
if (!nf || !pe || nf === pe || pe.contains(nf) || nf.contains(pe)) return;
}
// Player yang baru ditinggalkan harus keluar dulu -- baik native
// (document.fullscreenElement) maupun fallback CSS (class), karena
// di mode fallback document.fullscreenElement selalu null.
this._exitOtherFullscreens(container);
// Native: tunggu sampai browser benar-benar melepas fullscreen.
if (document.fullscreenElement) { retry(); return; }
// Frame tujuan harus sudah ter-render (Alpine x-show), kalau tidak
// fullscreen ke elemen yang belum tampil akan kosong.
const frame = container.closest('.watch-player-frame');
if (frame && window.getComputedStyle(frame).display === 'none') { retry(); return; }
if (!pe) { retry(); return; }
// Plyr's fullscreen.enter() TIDAK mengembalikan promise -> jangan pakai
// .catch() (dulu melempar TypeError dan bikin re-enter tak pernah jalan).
// requestFullscreen juga bisa ditolak (butuh user gesture), jadi hasilnya
// dipantau lewat retry, bukan dianggap sukses begitu saja.
try {
if (!p.fullscreen.active) p.fullscreen.enter();
} catch (e) {
retry(300);
return;
}
retry(300);
},
loadPage(page) {
if (this._loadingGrid) return;
this._loadingGrid = true;
const params = new URLSearchParams({
page: page || 1,
ep: this.currentEpisodeId,
sort: this.epSort,
search: this.epSearch
});
fetch('/anime/naruto-shippuuden/episodes/grid?' + params.toString())
.then(r => r.json())
.then(d => {
if (this.$refs.sidebarEpList) this.$refs.sidebarEpList.innerHTML = d.sidebar_episodes;
if (this.$refs.sidebarPag) this.$refs.sidebarPag.innerHTML = d.pagination;
this._loadingGrid = false;
})
.catch(() => { this._loadingGrid = false; });
},
applyEpSearch() {
this.loadPage(1);
}
}"
class="">
EP 5 - The Kazekage Stands Tall
Info
Komentar (0)
Repost
Download
Report
Laporkan Masalah
Pilih alasan untuk melaporkan episode ini.
Batal
Laporkan Masalah
Jelaskan masalah yang kamu temui agar tim kami bisa memperbaikinya.
Share
Badai Naruto Sejarah, Naruto Shippuden
Naruto: Shippuuden - Naruto: Shippuuden is the continuation of the original animated TV series Naruto. The story revolves around an older and slightly more matured Uzumaki Naruto and his quest to save his friend Uchiha Sasuke from the grips of the snake-like Shinobi, Orochimaru. After 2 and a half years Naruto finally returns to his village of Konoha, and sets about putting his ambitions to work, though it will not be easy, as he has amassed a few (more dangerous) enemies, in the likes of the shinobi organization; Akatsuki.
(Source: Anime News Network)
Nonton Naruto: Shippuuden Episode 5 Subtitle Indonesia secara online dengan berbagai pilihan kualitas video, mulai dari 360p, 480p, 720p hingga 1080p. Pilih server dan resolusi yang sesuai untuk menikmati episode Naruto: Shippuuden dengan subtitle Indonesia di perangkat kamu.
Studio Pierrot
Naruto: Shippuuden episode 5 subtitle indonesia, download Naruto: Shippuuden episode 5 subtitle indonesia, unduh Naruto: Shippuuden episode 5 subtitle indonesia, streaming Naruto: Shippuuden episode 5 subtitle indonesia, nonton Naruto: Shippuuden episode 5 subtitle indonesia, anime Naruto: Shippuuden episode 5 subtitle indonesia, download anime Naruto: Shippuuden episode 5 subtitle indonesia, unduh anime Naruto: Shippuuden episode 5 subtitle indonesia, streaming anime Naruto: Shippuuden episode 5 subtitle indonesia, nonton anime Naruto: Shippuuden episode 5 subtitle indonesia, Naruto: Shippuuden episode 5 sub indo, download Naruto: Shippuuden episode 5 sub indo, unduh Naruto: Shippuuden episode 5 sub indo, streaming Naruto: Shippuuden episode 5 sub indo, nonton Naruto: Shippuuden episode 5 sub indo, anime Naruto: Shippuuden episode 5 sub indo, download anime Naruto: Shippuuden episode 5 sub indo, unduh anime Naruto: Shippuuden episode 5 sub indo, streaming anime Naruto: Shippuuden episode 5 sub indo, nonton anime Naruto: Shippuuden episode 5 sub indo, Naruto: Shippuuden episode 5 takarir indonesia, download Naruto: Shippuuden episode 5 takarir indonesia, unduh Naruto: Shippuuden episode 5 takarir indonesia, streaming Naruto: Shippuuden episode 5 takarir indonesia, nonton Naruto: Shippuuden episode 5 takarir indonesia, anime Naruto: Shippuuden episode 5 takarir indonesia, download anime Naruto: Shippuuden episode 5 takarir indonesia, unduh anime Naruto: Shippuuden episode 5 takarir indonesia, streaming anime Naruto: Shippuuden episode 5 takarir indonesia, nonton anime Naruto: Shippuuden episode 5 takarir indonesia, Naruto: Shippuuden episode 5 takarir indo, download Naruto: Shippuuden episode 5 takarir indo, unduh Naruto: Shippuuden episode 5 takarir indo, streaming Naruto: Shippuuden episode 5 takarir indo, nonton Naruto: Shippuuden episode 5 takarir indo, anime Naruto: Shippuuden episode 5 takarir indo, download anime Naruto: Shippuuden episode 5 takarir indo, unduh anime Naruto: Shippuuden episode 5 takarir indo, streaming anime Naruto: Shippuuden episode 5 takarir indo, nonton anime Naruto: Shippuuden episode 5 takarir indo, Naruto: Shippuuden episode 5 subtitle indo, download Naruto: Shippuuden episode 5 subtitle indo, unduh Naruto: Shippuuden episode 5 subtitle indo, streaming Naruto: Shippuuden episode 5 subtitle indo, nonton Naruto: Shippuuden episode 5 subtitle indo, anime Naruto: Shippuuden episode 5 subtitle indo, download anime Naruto: Shippuuden episode 5 subtitle indo, unduh anime Naruto: Shippuuden episode 5 subtitle indo, streaming anime Naruto: Shippuuden episode 5 subtitle indo, nonton anime Naruto: Shippuuden episode 5 subtitle indo
Komentar (0)
atau untuk berkomentar.
Belum ada komentar. Jadilah yang pertama!