1/** 2 * Taniga Tranan â Konami code easter egg. 3 * 4 * Lyssnar efter den klassiska Konami-sekvensen: 5 * ArrowUp, ArrowUp, ArrowDown, ArrowDown, 6 * ArrowLeft, ArrowRight, ArrowLeft, ArrowRight, 7 * B, A 8 * 9 * Regler: 10 * - Tangenter fÃ¥r ligga max 3 sekunder isär; vid längre paus nollställs 11 * progressen och nästa tangent jämförs mot sekvensens första. 12 * - Tangenttryck i textinmatningsfält (input/textarea/contenteditable) 13 * ignoreras helt â Konami-koden ska inte trigga medan man skriver i 14 * kontaktformulärets fält. 15 * - När sekvensen är komplett klickar vi pÃ¥ den dolda launcher-knappen 16 * inuti `.taniga-tranan-konami` sÃ¥ spelet öppnas i helskärm via det 17 * vanliga flödet (`taniga-tranan.js` sköter overlay + game-instans). 18 */ 19(function () { 20 'use strict'; 21 22 var KONAMI = [ 23 'ArrowUp', 'ArrowUp', 24 'ArrowDown', 'ArrowDown', 25 'ArrowLeft', 'ArrowRight', 26 'ArrowLeft', 'ArrowRight', 27 'b', 'a' 28 ]; 29 var STEP_TIMEOUT_MS = 3000; 30 31 var pos = 0; 32 var lastTime = 0; 33 var coolingDown = false; 34 35 function normalizeKey(key) { 36 if (typeof key !== 'string') return ''; 37 // Bokstavstangenter normaliseras till lower-case sÃ¥ Shift+B funkar. 38 return key.length === 1 ? key.toLowerCase() : key; 39 } 40 41 function isInTextInput() { 42 var el = document.activeElement; 43 if (!el) return false; 44 var tag = (el.tagName || '').toUpperCase(); 45 if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') { 46 return true; 47 } 48 return el.isContentEditable === true; 49 } 50 51 function triggerGame() { 52 if (coolingDown) return; 53 var btn = document.querySelector('.taniga-tranan-konami [data-action="open-taniga"]'); 54 if (!btn) return; 55 coolingDown = true; 56 // Mjuk debounce sÃ¥ att en upprepad sekvens inte spammar open() 57 setTimeout(function () { coolingDown = false; }, 1500); 58 btn.click(); 59 } 60 61 function resetSequence() { 62 pos = 0; 63 lastTime = 0; 64 } 65 66 document.addEventListener('keydown', function (ev) { 67 if (isInTextInput()) { 68 return; 69 } 70 71 var key = normalizeKey(ev.key); 72 if (!key) return; 73 74 var now = Date.now(); 75 76 // För lÃ¥ng paus sedan förra träffen â starta om. 77 if (lastTime && now - lastTime > STEP_TIMEOUT_MS) { 78 resetSequence(); 79 } 80 81 var matched = false; 82 83 if (key === KONAMI[pos]) { 84 pos++; 85 lastTime = now; 86 matched = true; 87 } else if (key === KONAMI[0]) { 88 // Tangenten matchar inte nästa förväntade men matchar sekvensens 89 // första â tolka det som att användaren startar om. Räkna det 90 // trycket som det första steget. 91 pos = 1; 92 lastTime = now; 93 matched = true; 94 } else { 95 resetSequence(); 96 } 97 98 // Förhindra att piltangenter scrollar sidan medan sekvensen matas in, 99 // annars riskerar man att tappa fokus eller bli förvirrad mitt i. 100 if (matched && key.indexOf('Arrow') === 0) { 101 ev.preventDefault(); 102 } 103 104 if (pos === KONAMI.length) { 105 resetSequence(); 106 triggerGame(); 107 } 108 }); 109})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.