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) {
var isMovieAnime = false;
breadcrumbEpisode.textContent = isMovieAnime ? '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/hunter-x-hunter-2011/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 69 - A × Heated × Showdown
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
Pemburu x Pemburu (2011)
Hunter x Hunter (2011) - A new adaption of the manga of the same name by Togashi Yoshihiro.
A Hunter is one who travels the world doing all sorts of dangerous tasks. From capturing criminals to searching deep within uncharted lands for any lost treasures. Gon is a young boy whose father disappeared long ago, being a Hunter. He believes if he could also follow his father's path, he could one day reunite with him.
After becoming 12, Gon leaves his home and takes on the task of entering the Hunter exam, notorious for its low success rate and high probability of death to become an official Hunter. He befriends the revenge-driven Kurapika, the doctor-to-be Leorio and the rebellious ex-assassin Killua in the exam, with their friendship prevailing throughout the many trials and threats they come upon taking on the dangerous career of a Hunter.
Nonton Hunter x Hunter (2011) Episode 69 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 Hunter x Hunter (2011) dengan subtitle Indonesia di perangkat kamu.
Madhouse
Hunter x Hunter (2011) episode 69 subtitle indonesia, download Hunter x Hunter (2011) episode 69 subtitle indonesia, unduh Hunter x Hunter (2011) episode 69 subtitle indonesia, streaming Hunter x Hunter (2011) episode 69 subtitle indonesia, nonton Hunter x Hunter (2011) episode 69 subtitle indonesia, anime Hunter x Hunter (2011) episode 69 subtitle indonesia, download anime Hunter x Hunter (2011) episode 69 subtitle indonesia, unduh anime Hunter x Hunter (2011) episode 69 subtitle indonesia, streaming anime Hunter x Hunter (2011) episode 69 subtitle indonesia, nonton anime Hunter x Hunter (2011) episode 69 subtitle indonesia, Hunter x Hunter (2011) episode 69 sub indo, download Hunter x Hunter (2011) episode 69 sub indo, unduh Hunter x Hunter (2011) episode 69 sub indo, streaming Hunter x Hunter (2011) episode 69 sub indo, nonton Hunter x Hunter (2011) episode 69 sub indo, anime Hunter x Hunter (2011) episode 69 sub indo, download anime Hunter x Hunter (2011) episode 69 sub indo, unduh anime Hunter x Hunter (2011) episode 69 sub indo, streaming anime Hunter x Hunter (2011) episode 69 sub indo, nonton anime Hunter x Hunter (2011) episode 69 sub indo, Hunter x Hunter (2011) episode 69 takarir indonesia, download Hunter x Hunter (2011) episode 69 takarir indonesia, unduh Hunter x Hunter (2011) episode 69 takarir indonesia, streaming Hunter x Hunter (2011) episode 69 takarir indonesia, nonton Hunter x Hunter (2011) episode 69 takarir indonesia, anime Hunter x Hunter (2011) episode 69 takarir indonesia, download anime Hunter x Hunter (2011) episode 69 takarir indonesia, unduh anime Hunter x Hunter (2011) episode 69 takarir indonesia, streaming anime Hunter x Hunter (2011) episode 69 takarir indonesia, nonton anime Hunter x Hunter (2011) episode 69 takarir indonesia, Hunter x Hunter (2011) episode 69 takarir indo, download Hunter x Hunter (2011) episode 69 takarir indo, unduh Hunter x Hunter (2011) episode 69 takarir indo, streaming Hunter x Hunter (2011) episode 69 takarir indo, nonton Hunter x Hunter (2011) episode 69 takarir indo, anime Hunter x Hunter (2011) episode 69 takarir indo, download anime Hunter x Hunter (2011) episode 69 takarir indo, unduh anime Hunter x Hunter (2011) episode 69 takarir indo, streaming anime Hunter x Hunter (2011) episode 69 takarir indo, nonton anime Hunter x Hunter (2011) episode 69 takarir indo, Hunter x Hunter (2011) episode 69 subtitle indo, download Hunter x Hunter (2011) episode 69 subtitle indo, unduh Hunter x Hunter (2011) episode 69 subtitle indo, streaming Hunter x Hunter (2011) episode 69 subtitle indo, nonton Hunter x Hunter (2011) episode 69 subtitle indo, anime Hunter x Hunter (2011) episode 69 subtitle indo, download anime Hunter x Hunter (2011) episode 69 subtitle indo, unduh anime Hunter x Hunter (2011) episode 69 subtitle indo, streaming anime Hunter x Hunter (2011) episode 69 subtitle indo, nonton anime Hunter x Hunter (2011) episode 69 subtitle indo
Komentar (0)
atau untuk berkomentar.
Belum ada komentar. Jadilah yang pertama!