Biografi
Kapittel 16 · Vikingen
John-Olav Einemo
Født 1975 · Oslo, Norge
ADCC World Champion 2003
Oslo, Norge
Frontline-linjen
MMA-veteran
Maeda→
Carlos Jr.→
Yogui Santiago→
John-Olav Einemo
MesterenMarcelo "Yogui" Santiago
ADCC VM2003, 88–98 kg — slo Roger Gracie i semifinalen
IBJJF VMBlåbelte, 2001
GrunnlaFrontline Academy (2004, med Trond Saksenvik og Thomas Hytten)
Før Tommy Langaker, før Tarik Hopstock, før Frontline Academy var et navn verden kjente — var det John-Olav Einemo. «The Viking» fra Oslo er mannen som satte norsk BJJ på kartet med en prestasjon som fremdeles er blant de mest bemerkelsesverdige i norsk kampsporthistorie.
Einemo begynte under Marcelo "Yogui" Santiago, den brasilianske svartbelten som ankom Skandinavia i 1997 og grunnla Scandinavian Brazilian Jiu-Jitsu Academy. Yogui var katalysatoren for tidlig norsk BJJ, og Einemo var blant hans fremste elever.
ADCC 2003 — den umulige seieren
I 2003 deltok Einemo i ADCC World Submission Wrestling Championship i Lisboa — verdens prestisjestreste grappling-turnering. I 88–98 kg-klassen møtte han i semifinalen en 21 år gammel brasilianer som allerede ble betraktet som en fremtidig legende: Roger Gracie.
Einemo slo Roger Gracie. Og vant turneringen. Det er den eneste gangen Roger Gracie noensinne har tapt ved ADCC. Einemo ble dermed den første europeeren som vant ADCC verdensmesterskap — en tittel han beholder den dag i dag som historisk milepæl.
"Jeg visste ikke at ingen europeere hadde vunnet ADCC før. Jeg visste bare at jeg ville vinne."
Frontline og arven
Etter ADCC-triumfen var Einemo med på å grunnlegge Frontline Academy i Oslo i 2004 — sammen med Trond Saksenvik, Thomas Hytten og Joachim Hansen. Saksenvik ble Norges første BJJ-svartbelte året etter. Frontline vokste til å bli Norges viktigste BJJ-institusjon, og Einemos tidlige innsats la grunnlaget for alt som fulgte.
Viktige resultater og milepæler
• ADCC World Champion 2003 — slo Roger Gracie i semifinalen
• Første europeeren som vant ADCC verdensmesterskap
• IBJJF World Champion blåbelte, 2001
• Medgrunnlegger av Frontline Academy, Oslo (2004)
• MMA-karriere: Affliction, UFC, StrikeForce
// ── Supabase ──
const SUPA_URL = 'https://lqiddsqelkdsjvgjfxtt.supabase.co';
const SUPA_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImxxaWRkc3FlbGtkc2p2Z2pmeHR0Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzU0NzE1MTIsImV4cCI6MjA5MTA0NzUxMn0.QzWlQRSjiR0-FPBm-S9fL5xYIdKD8CeZd1Yme6aSwAU';
const supa = supabase.createClient(SUPA_URL, SUPA_KEY);
// Rydd opp access_token-hash fra URL etter OAuth-redirect
if (window.location.hash.includes('access_token')) {
history.replaceState(null, '', window.location.pathname);
}
let bruker = null;
let mineFavoritter = new Set();
// Auth-tilstand
supa.auth.onAuthStateChange(async (event, session) => {
try {
bruker = session?.user || null;
oppdaterAuthWidget();
if (bruker) {
await lastFavoritter();
await oppdaterProfil();
} else {
mineFavoritter.clear();
}
} catch (e) {
// Korrupt sesjon — rydd opp og start på nytt
Object.keys(localStorage)
.filter(k => k.startsWith('sb-'))
.forEach(k => localStorage.removeItem(k));
bruker = null;
oppdaterAuthWidget();
}
});
function oppdaterAuthWidget() {
const widget = document.getElementById('auth-widget');
if (!bruker) {
widget.innerHTML = `Logg inn med Google`;
document.getElementById('login-btn').addEventListener('click', loggInn);
} else {
const navn = bruker.user_metadata?.full_name?.split(' ')[0] || 'Deg';
const bilde = bruker.user_metadata?.avatar_url || '';
widget.innerHTML = `
${bilde ? `` : ''}
${navn}
Logg ut`;
document.getElementById('logout-btn').addEventListener('click', loggUt);
}
}
async function loggInn() {
const { data } = await supa.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: window.location.origin + '/auth-callback.html',
skipBrowserRedirect: true
}
});
if (!data?.url) return;
const popup = window.open(data.url, 'google-oauth', 'width=480,height=600,scrollbars=yes');
if (!popup) {
// Popup blokkert — fallback til vanlig redirect
window.location.href = data.url;
return;
}
const poll = setInterval(async () => {
if (popup.closed) {
clearInterval(poll);
const { data: sd } = await supa.auth.getSession();
if (sd?.session) {
bruker = sd.session.user;
oppdaterAuthWidget();
await lastFavoritter();
await oppdaterProfil();
}
}
}, 500);
}
async function loggUt() {
await supa.auth.signOut();
Object.keys(localStorage)
.filter(k => k.startsWith('sb-'))
.forEach(k => localStorage.removeItem(k));
window.location.reload();
}
async function lastFavoritter() {
if (!bruker) return;
const { data } = await supa
.from('user_favorites')
.select('person_id')
.eq('user_id', bruker.id);
mineFavoritter = new Set((data || []).map(r => r.person_id));
}
async function oppdaterProfil() {
if (!bruker) return;
await supa.from('user_profiles').upsert({
id: bruker.id,
navn: bruker.user_metadata?.full_name || null,
avatar_url: bruker.user_metadata?.avatar_url || null,
email: bruker.email || null,
sist_logget_inn: new Date().toISOString(),
}, { onConflict: 'id' });
}
async function toggleFavoritt(personId, knapp) {
if (!bruker) { loggInn(); return; }
if (mineFavoritter.has(personId)) {
const { error } = await supa.from('user_favorites')
.delete()
.eq('user_id', bruker.id)
.eq('person_id', personId);
if (error) { console.error('Slett favoritt feil:', error.message); return; }
mineFavoritter.delete(personId);
knapp.classList.remove('aktiv');
knapp.innerHTML = '♡ Lagre';
} else {
const { error } = await supa.from('user_favorites')
.insert({ user_id: bruker.id, person_id: personId });
if (error) { console.error('Lagre favoritt feil:', error.message); return; }
mineFavoritter.add(personId);
knapp.classList.add('aktiv');
knapp.innerHTML = '♥ Lagret';
}
// Oppdater favoritt-visning hvis den er åpen
if (document.getElementById('fav-view').style.display !== 'none') {
visFavoritter();
}
}
// ── Alle data hentes fra data.json ──
let cardData = [];
const modal = document.getElementById('modal');
const modalBody = document.getElementById('modal-body');
const modalSheet = document.getElementById('modal-sheet');
let currentIndex = -1;
function buildCard(d, i) {
const tagsHTML = (d.display_tags || []).map(t =>
`${t.tekst}`
).join('');
const card = document.createElement('div');
card.className = 'p-card';
card.dataset.filter = d.filter_kategori || 'alle';
card.dataset.index = i;
card.innerHTML = `
${d.kapittel_label || ''}
${d.navn || d.navn}
${d.datoer_tekst || ''}
${tagsHTML}
${d.kort_bio || ''}
Les mer →
`;
card.addEventListener('click', () => openModal(i));
return card;
}
function renderCards() {
const grid = document.getElementById('cards-grid');
grid.innerHTML = '';
cardData.forEach((d, i) => grid.appendChild(buildCard(d, i)));
bindFilter();
bindTreeNodes();
}
function bindFilter() {
document.querySelectorAll('.f-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.f-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const f = btn.dataset.filter;
if (f === 'favoritter') {
visFavoritter();
return;
}
// Tilbake til kortvisning hvis vi var i favoritt-modus
skjulFavoritter();
visningsModus('kort');
document.querySelectorAll('.p-card').forEach(card => {
card.classList.toggle('hidden', f !== 'alle' && card.dataset.filter !== f);
});
});
});
}
function bindTreeNodes() {
document.querySelectorAll('.t-node[data-id]').forEach(node => {
node.addEventListener('click', () => {
const i = cardData.findIndex(d => d.html_id === node.dataset.id);
if (i >= 0) openModal(i);
});
});
}
function openModal(i) {
currentIndex = i;
renderModal();
modal.classList.add('open');
document.body.style.overflow = 'hidden';
// Registrer besøk for "mest besøkt"-fanen
const d = cardData[i];
if (d && d.id) registrerBesøk(d.id);
}
function lagFavKnapp(personId) {
// Fjern evt. eksisterende favorittknapp først
document.querySelectorAll('.fav-btn').forEach(el => el.remove());
const knapp = document.createElement('button');
knapp.className = 'fav-btn' + (mineFavoritter.has(personId) ? ' aktiv' : '');
knapp.innerHTML = mineFavoritter.has(personId) ? '♥ Lagret' : '♡ Lagre';
knapp.addEventListener('click', () => toggleFavoritt(personId, knapp));
return knapp;
}
function esc(str) {
if (!str) return '';
return String(str).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"');
}
function renderModal() {
const d = cardData[currentIndex];
const chapter = d.html_id ? document.getElementById(d.html_id) : null;
if (chapter) {
modalBody.innerHTML = chapter.outerHTML;
// Legg til favorittknapp
const topbar = document.querySelector('.modal-topbar .modal-nav');
if (topbar) topbar.appendChild(lagFavKnapp(d.id));
} else {
// Fallback for nye personer uten HTML-kapittel ennå
const tagsHTML = (d.display_tags || []).map(t =>
`${t.tekst}`
).join('');
const metaHTML = [
d.nasjonalitet ? `${esc(d.nasjonalitet)}` : '',
d.grad ? `${esc(d.grad)}` : '',
].filter(Boolean).join(' · ');
const wikiURL = d.kilder?.wikipedia;
const safeWikiURL = wikiURL?.startsWith('https://') ? wikiURL : null;
modalBody.innerHTML = `