2026-07-13 14:18:28 +02:00
<!DOCTYPE html>
< html lang = "da" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > Kodegenerator</ title >
< style >
* { box-sizing : border-box ; margin : 0 ; }
body { font-family : - apple-system , sans-serif ; background : #f5f5f5 ; padding : 2 rem ; }
. container { max-width : 800 px ; margin : 0 auto ; }
h1 { margin-bottom : 1.5 rem ; }
. grid { display : grid ; grid-template-columns : 1 fr 1 fr ; gap : 1.5 rem ; }
. card { background : #fff ; border-radius : 8 px ; padding : 1.5 rem ; box-shadow : 0 1 px 3 px rgba ( 0 , 0 , 0 , .1 ); }
. card h2 { font-size : 1 rem ; margin-bottom : .75 rem ; }
textarea { width : 100 % ; height : 200 px ; font-family : monospace ; font-size : .9 rem ; padding : .5 rem ; border : 1 px solid #ccc ; border-radius : 4 px ; resize : vertical ; }
label { display : flex ; align-items : center ; gap : .5 rem ; margin-bottom : .5 rem ; font-size : .9 rem ; }
input [ type = "number" ] { width : 70 px ; padding : .3 rem ; border : 1 px solid #ccc ; border-radius : 4 px ; }
. controls { display : flex ; gap : .75 rem ; flex-wrap : wrap ; align-items : center ; margin : 1 rem 0 ; }
button { padding : .6 rem 1.2 rem ; border : none ; border-radius : 6 px ; cursor : pointer ; font-size : .9 rem ; }
. btn-primary { background : #2563eb ; color : #fff ; }
. btn-primary : hover { background : #1d4ed8 ; }
. btn-secondary { background : #6b7280 ; color : #fff ; }
. btn-secondary : hover { background : #4b5563 ; }
# output { width : 100 % ; height : 300 px ; font-family : monospace ; font-size : .9 rem ; padding : .5 rem ; border : 1 px solid #ccc ; border-radius : 4 px ; resize : vertical ; background : #fafafa ; }
. info { font-size : .8 rem ; color : #666 ; margin-top : .5 rem ; }
</ style >
</ head >
< body >
< div class = "container" >
< h1 > Kodegenerator</ h1 >
< div class = "grid" >
< div class = "card" >
< h2 > Ordbog (kun navneord)</ h2 >
2026-07-15 13:09:52 +02:00
< textarea id = "words" placeholder = "Vent på indlæsning..." readonly ></ textarea >
2026-07-13 14:18:28 +02:00
</ div >
< div class = "card" >
< h2 > Opsætning</ h2 >
2026-07-15 13:09:52 +02:00
< p style = "font-size:.85rem;color:#666;margin-bottom:.75rem" > Format: Ord1 + Ord2 + suffix</ p >
2026-07-13 14:18:28 +02:00
< label > Separator mellem ord: < input type = "text" id = "separator" value = "" style = "width:30px;padding:.3rem;border:1px solid #ccc;border-radius:4px" ></ label >
< label > Suffix længde: < input type = "number" id = "suffixLen" value = "5" min = "1" max = "10" ></ label >
2026-07-15 13:09:52 +02:00
< label >< input type = "checkbox" id = "useSymbols" checked > Specialtegn (!@#$%& *+-=?)</ label >
< label >< input type = "checkbox" id = "useDigits" checked > Tal (0-9)</ label >
2026-07-13 14:18:28 +02:00
< label > Antal koder: < input type = "number" id = "count" value = "3" min = "1" max = "20" ></ label >
< div class = "controls" >
< button class = "btn-primary" onclick = "generate()" > Generer</ button >
< button class = "btn-secondary" onclick = "copy()" > Kopiér</ button >
< button class = "btn-secondary" onclick = "clearOutput()" > Ryd</ button >
</ div >
< div class = "info" id = "status" ></ div >
</ div >
</ div >
< textarea id = "output" placeholder = "Genererede koder vises her..." readonly ></ textarea >
</ div >
< script >
2026-07-15 13:09:52 +02:00
async function loadWords () {
const el = document . getElementById ( 'words' );
try {
const res = await fetch ( 'ordliste.txt' );
if ( ! res . ok ) throw new Error ( 'HTTP ' + res . status );
const text = await res . text ();
el . value = text . trim ();
el . readOnly = false ;
el . placeholder = 'Et ord pr. linje' ;
document . getElementById ( 'status' ). textContent = 'Indlæst ' + text . trim (). split ( '\n' ). length + ' ord' ;
} catch ( e ) {
el . placeholder = 'Kunne ikke indlæse ordliste.txt (' + e . message + ')' ;
}
}
loadWords ();
const SYMBOLS = '!@#$%&*+-=?' ;
const DIGITS = '0123456789' ;
2026-07-13 14:18:28 +02:00
function rand ( n ) { return Math . floor ( Math . random () * n ); }
2026-07-15 13:09:52 +02:00
function getSuffixCharset () {
const useSym = document . getElementById ( 'useSymbols' ). checked ;
const useDig = document . getElementById ( 'useDigits' ). checked ;
let s = '' ;
if ( useSym ) s += SYMBOLS ;
if ( useDig ) s += DIGITS ;
return s ;
}
2026-07-13 14:18:28 +02:00
2026-07-15 13:09:52 +02:00
function randomSuffix ( len , charset ) {
2026-07-13 14:18:28 +02:00
let r = '' ;
2026-07-15 13:09:52 +02:00
for ( let i = 0 ; i < len ; i ++ ) r += charset [ rand ( charset . length )];
2026-07-13 14:18:28 +02:00
return r ;
}
function generate () {
const words = document . getElementById ( 'words' ). value . split ( '\n' ). map ( w => w . trim ()). filter ( w => w );
2026-07-15 13:09:52 +02:00
let suffixLen = parseInt ( document . getElementById ( 'suffixLen' ). value , 10 );
if ( isNaN ( suffixLen ) || suffixLen < 1 ) suffixLen = 5 ;
const countEl = document . getElementById ( 'count' );
let count = parseInt ( countEl . value , 10 );
if ( isNaN ( count ) || count < 1 ) count = 3 ;
2026-07-13 14:18:28 +02:00
const sep = document . getElementById ( 'separator' ). value ;
const output = document . getElementById ( 'output' );
2026-07-15 13:09:52 +02:00
const charset = getSuffixCharset ();
const status = document . getElementById ( 'status' );
2026-07-13 14:18:28 +02:00
2026-07-15 13:09:52 +02:00
if ( ! words . length ) { output . value = 'Tilføj mindst ét ord i ordbogen.' ; status . textContent = '' ; return ; }
if ( words . length < 2 ) { output . value = 'Brug mindst 2 ord i ordbogen.' ; status . textContent = '' ; return ; }
if ( ! charset . length ) { output . value = 'Vælg mindst én suffix-type (specialtegn eller tal).' ; status . textContent = '' ; return ; }
if ( suffixLen === 1 && charset . length > 1 ) { output . value = 'Ved suffix længde 1 skal du vælge enten specialtegn eller tal (ikke begge).' ; status . textContent = '' ; return ; }
2026-07-13 14:18:28 +02:00
const codes = [];
for ( let i = 0 ; i < count ; i ++ ) {
let w1 , w2 ;
do { w1 = words [ rand ( words . length )]; w2 = words [ rand ( words . length )]; } while ( w1 === w2 );
2026-07-15 13:09:52 +02:00
codes . push ( w1 + sep + w2 + randomSuffix ( suffixLen , charset ));
2026-07-13 14:18:28 +02:00
}
output . value = codes . join ( '\n' );
2026-07-15 13:09:52 +02:00
status . textContent = `Genereret ${ count } koder` ;
2026-07-13 14:18:28 +02:00
}
function copy () {
const el = document . getElementById ( 'output' );
if ( ! el . value ) return ;
navigator . clipboard . writeText ( el . value ). then (() => {
document . getElementById ( 'status' ). textContent = 'Kopieret til udklipsholder' ;
}). catch (() => {
el . select ();
document . execCommand ( 'copy' );
document . getElementById ( 'status' ). textContent = 'Kopieret' ;
});
}
function clearOutput () {
document . getElementById ( 'output' ). value = '' ;
document . getElementById ( 'status' ). textContent = '' ;
}
</ script >
</ body >
</ html >