Archiv der Kategorie: jquery/Javascript

Das kann ich einfacher: Kontrastfarbe berechnen

Heute war in The Whip (Ausgabe 759) ein Artikel darüber, dass Lyft ihren ColorBox-Algorithmus zur Berechnung der optimalen Kontrastfarbe Open Source zur Verfügung gestellt hat, hier mal der Link zum Artikel:

Lyft Open Sources ColorBox Algorithm for Building Accessible Color Systems

Ziel der Sache ist, schwarze oder weiße Schrift auf farbigem Grund mit einem Farbkontrast darzustellen, der möglichst gut lesbar und damit barrierefrei ist.

Ich hab mir den Source auf Github natürlich gleich mal angesehen, schließlich habe ich vor nicht allzulanger Zeit hier ein kleines Javascript vorgestellt (Kontrastfarbe automatisch berechnen) das genau diesen Zweck erfüllt. Was soll ich sagen, das Skript von Lyft ist recht eindrucksvoll und etliche Seiten lang. Ich mach das selbe, mit weniger als 80 Zeilen Sourcecode, und davon ist noch die Hälfte für die HTML-Ausgabe. Warum umständlich, wenns auch einfach geht 🙂

Ein kleiner Chat in PHP – wieder mal was für Minimalisten

Da ich mich derzeit viel im Chat in meinem Lieblings-Handarbeitsforum herumtreibe, dachte ich mir: so einen kleinen, eher spartanischen Chatroom solltest du eigentlich auch selber programmieren können, das kann so schwierig nicht sein. Bei Google gibt es -zig Beispiele, wie man so etwas angehen könnte, ich hab mich auf die Suche nach etwas Einfachem gemacht und bin hier bei php-einfach.de fündig geworden.

Ich hab allerdings ein paar Fehler bereinigt, auf PHP 7 umgeschrieben, die Ajax-Funktionalität eliminiert (warum kompliziert wenns auch einfach geht?), die MySQL-Tabelle komplett anders strukturiert, eine Teilnehmerliste hinzugefügt und sämtliche Formatierungen umgekrempelt, so dass letztendlich eine komplett umgeschmissene Logik dabei herausgekommen ist. Wie gesagt, die Grundidee stammt von php-einfach.de, und ich bedanke mich auch artig für den Denkanstoß. Aber ich denke, es ist genug kreative Eigenleistung dazugekommen, dass ich den Source hier als auf meinem Mist gewachsen einstellen kann.

Die Voraussetzungen

Viel ist nicht dran: man soll seinen Nick und seine Nachricht eingeben können, auf den Senden!-Button klicken, und dann soll im Chatfenster die Nachricht für alle sichtbar am unteren Ende des Fensters auftauchen. Ich hab noch die Uhrzeit wann die Nachricht geschrieben wurde mit dazugenommen, und protokolliere im Hintergrund auch das Datum mit, da ich in meinem Chat immer nur die Beiträge des heutigen Tages anzeigen möchte.

Aussehen tut das Ganze so:

screenshot_chat

screenshot_chat

Man kann seinen Nick eingeben (der bleibt auch nach dem Abschicken stehen), man kann seine Nachricht eingeben, und man kann auf den Senden!-Button klicken. Im Chatfenster scrollen die älteren Einträge nach oben weg, der neueste Eintrag landet immer ganz unten, und es wird noch die Uhrzeit zu jedem Beitrag angezeigt. Es werden nur die Einträge des heutigen Tages angezeigt, den Rest habe ich natürlich auch gebunkert, daraus könnte man noch ein Chat-Archiv erstellen. Rechts kriegt man noch eine Liste angezeigt, wer heute schon aller im Chat war, und das wars.

Im Hintergrund: natürlich eine MySQL-Tabelle

Die ist recht einfach strukturiert und heißt bei mir chat_daten:

chat_daten

chat_daten

Eine AutoIncrement-id als Primärschlüssel, und vier Textfelder für nick, eintrag, uhrzeit und datum, das war schon alles.

Der Sourcecode

Wir packen die Connect-Daten in eine externe Datei:

<?php 
$server    = 'localhost'; 
$user    = 'root'; 
$pass    = ''; 
$db    = 'chat'; 
$table    = 'chat_daten'; 
$conn=mysqli_connect($server, $user,$pass); 
mysqli_select_db($conn,$db); 
?>

Die Felder für Nick und Eintrag und den Senden-Button packen wir in ein Formular:

<?php  
//Config auslesen 
require_once('inc/config.php'); 
  
$heute = date("d.m.Y",time());
echo '<img src="el_logo.jpg">';
echo '<h1>Evis Chat live am '.$heute.'</h1>';

echo ' 
 <form action="index.php" method="post"> 
    <table border="0"> 
        <tr> ';
//Falls ein Nick eingegeben wurde, diesen als default in die Textbox setzen
if(!empty($_POST['nick'])){
    $akt_nick = $_POST['nick'];
}
else{
    $akt_nick='';
};
    
echo '<th>Nickname:</th><td><input type="text" name="nick" value="'.$akt_nick.'" id="textbox1"></td></tr>                 
        <tr> 
            <th>Nachricht:</th><td><input type="text" name="eintrag" value="" id="textbox">&nbsp;<input type="submit" name="eintragen" value="Senden!" id="button">&nbsp;</td> 
        </tr> 
    </table> ';

Damit man den Nick nicht immer neu eingeben muss, frage ich ab ob das Feld schon gesetzt wurde und schreibe dann den Wert als Default rein.

Dann starte ich, wenn auf den Button Senden geklickt wurde, und schreibe mir Nick, Eintrag, Datum und Uhrzeit in die Datenbank:

if(isset($_POST['eintragen'])){ 

if(empty($_POST['nick']) or empty($_POST['eintrag'])){ 
    echo '<script>alert("Bitte Nick UND Message eingeben")</script>'; 
}else{ 
    //Variablen definieren und mit "POST" Daten füllen (Mit htmlspecialchars filtern, Apostrophe maskieren..) 
    $nick = addslashes(htmlspecialchars($_POST['nick'])); 
    $eintrag = addslashes(htmlspecialchars($_POST['eintrag'])); 
    $uhrzeit = date("H:i",time());
    $datum = date("d.m.Y",time());

    
//Nick + Eintrag + datum+uhrzeit in die Datenbank schreiben 
    mysqli_query($conn,"INSERT INTO $table  
                      (nick,eintrag,uhrzeit, datum) VALUES 
                      ('$nick', '$eintrag', '$uhrzeit', '$datum')"); 
    } 

}

Falls kein Nick oder keine Nachricht eingegeben wurden, gibts einen Alert, andernfalls mache ich den Insert mit den aktuellen Daten.

Für die Ausgabe des Chats baue ich mir eine Div mit zwei darin enthaltenen Divs, weil ich Nick und Nachricht linksbündig, die Uhrzeit aber rechtsbündig ausgeben möchte. Das CSS dazu gibt es weiter unten, hier erstmal die Divs für das Chatfenster:

//alle Einträge von heute ausgeben
echo '<div id="chat_fenster" >';
        
        //Nur die Einträge von heute auslesen
          $abfrage = mysqli_query($conn,"SELECT * FROM $table WHERE datum LIKE '$datum'"); 
          while($row = mysqli_fetch_array($abfrage,MYSQLI_ASSOC)) 
          { 
            echo '<div id ="nick_und_message"><span style="color:red">'.$row['nick'].':</span><span style ="color:black">'.$row['eintrag'].'</span></div>
            <div id = "uhrzeit"><span style ="color:green">'.$row['uhrzeit'].'</span></div><br>'; 
          }
echo '</div>';

Als kleines Extra gebe ich rechts neben dem Chatfenster noch eine Liste aller Teilnehmer von heute aus:

//alle Teilnehmer von heute ausgeben
echo '<div id="teilnehmer_fenster" >';
        echo '<h2>Heute im Chat:</h2>';
        //Nur die Teilnehmer von heute auslesen
          $abfrage = mysqli_query($conn,"SELECT DISTINCT nick FROM $table WHERE datum LIKE '$datum'"); 
          while($row = mysqli_fetch_array($abfrage,MYSQLI_ASSOC)) 
          { 
            echo $row['nick'].'<br>'; 
          }
echo '</div>';

Jetzt noch ein wenig CSS-Kosmetik:

<style type="text/css"> 
    
    #textbox{ 
        width:600px; 
        border:1px solid blue; 
    } 
     
    #textbox1{ 
        width:80px; 
        border:1px solid blue; 
    }
    
    #button{ 

        border:1px solid #FF1493; 
        cursor:pointer; 
    } 
     
    #button:hover{ 
        border:1px solid #3399FF; 
    } 
    
    #nick_und_message{
        width:80%;
        float:left;
    }
    #uhrzeit {
        width:20%;
        float:right;
        text-align: right;
    }
    #chat_fenster{
        border:2px solid blue;
        width:750px; 
        height:350px; 
        padding:3px; 
        overflow: auto;
        float:left;
    }
    
    #teilnehmer_fenster{
        float:right;
        width:200px;
    }
</style>

Wichtig ist hier der Eintrag overflow:auto für das Chatfenster, der sorgt für den Scrollbalken. Damit jetzt die bereits vorhandenen Einträge nach oben wegscrollen und der letzte Eintrag immer im Chatfenster ganz unten auftaucht, noch ein kleiner Javascript-Trick:

<script>
window.onload = function()
{
//Chatfenster nach oben wegscrollen, damit immer die neuesten Einträge sichtbar sind
document.getElementById('chat_fenster').scrollTop = 9999999;
}
</script>

Man setzt einfach einen sehr hohen Wert für das Scrollen nach oben, damit ist die Liste immer nach oben weggescrollt und das Ende mit den neuesten Beiträgen bleibt im sichtbaren Bereich.

Das wars – viel Spaß beim Nachbauen! Das liesse sich natürlich noch beliebig erweitern, in einem CMS könnte man z.B. den Chat nur für eingeloggte User freischalten, dann entfällt das Abfragen des Nicks. Man könnte auch noch ein Chat-Archiv anlegen, in dem man die Beiträge der letzten Tage einsehen kann, und man könnte sonst noch allerhand Spielereien veranstalten, da kann sich jeder selber austoben. Ich lass es mal so stehen, als wirklich simple Lösung.

Nummerische Pagination mit Werten aus Array (pure PHP)

Das hat jetzt mit WordPress nur noch insofern etwas zu tun, als es einem auch hier mal unterkommen kann, dass die Daten für eine seitenweise nummerierte Ausgabe in Form eines Arrays ankommen und nicht direkt mit SQL aus der Datenbank abgefragt werden. Typischerweise passiert sowas, wenn man über eine API auf die Datenbank zugreift und die Ergebnisse der Abfrage als JSON zurückgegeben werden. Das kann man mit Hilfe von json_decode() flugs in ein Array umwandeln und mit einem foreach() wie gehabt seitenweise ausgeben. Wenn allerdings die Datensätze pro Seite einen Rest ergeben, fliegt PHP bei der letzten Seite auf die Nase und spuckt so etwas aus:

Notice: Undefined offset: 334 in C:\xampp\htdocs\kleine_api\err_num_page.php on line 74

Die kleine Tücke: der Rest

Wir haben, sagen wir mal, 334 Datensätze. Und wir legen die Anzahl der Datensätze pro Seite auf 10 fest. Das gibt 33 ganze Seiten a 10 Datensätze, und auf der letzten Seite haben wir nur noch vier Datensätze. Da muss man jetzt eine Sonderbehandlung für den Rest einbauen, weil unser Array ja nur einen Index bis 333 zuläßt – Offset by one, den 334. Array-Entrag gibt es nicht mehr. Dieses Dilemma hat man nicht, wenn man direkt auf die Datenbank zugreift und mit einem SQL-Limit arbeiten kann, da ist es egal wenn am Ende die Seite nicht ganz voll wird, es gibt keine Fehlermeldung.

Aber, wir arbeiten ja mit einem Array, und da muss man die ganze Logik ein bisschen umstricken. Also, frisch ans Werk!

Das Array

… enthält 334 Kochrezepte und sieht nach einem json_decode in etwa so aus:

array(1) 
{ ["rezepte"]=> array(334) {
 [0]=> array(3) { ["ID"]=> string(4) "1828" ["post_title"]=> string(31) "Pudding nach Art des Hauses Leu" ["post_content"]=> string(37) "Vanille oder Schoko oder Johannisbeer" }
 [1]=> array(3) { ["ID"]=> string(4) "1827" ["post_title"]=> string(5) "Milch" ["post_content"]=> string(23) "reicht nicht bis morgen" } 
 [2]=> array(3) { ["ID"]=> string(4) "1825" ["post_title"]=> string(14) "Petersilwurzel" ["post_content"]=> string(29) "hab ich abgeerntet, ist nicht" }

Das heißt, um beispielsweise an die ID und den Titel eines Datensatzes heranzukommen, muss ich folgende Syntax verwenden:

$akt_id = $dataObject['rezepte'][$i]['ID'];
$akt_titel = $dataObject['rezepte'][$i]['post_title'];

Das ist jetzt noch nicht weiter tragisch, ich muss nur daran denken dass mein Array bei 0 anfängt, das heißt bei einer Anzahl Datensätze pro Seite von X darf ich nur von 0 bis X-1 ausgeben. Praktisch sieht das z.B.bei 10 Datensätzen pro Seite so aus:

Seite 1: Datensätze 0…9
Seite 2: Datensätze 10…19
Seite 3: Datensätze 20…29

letzte Seite: der Rest

Das heisst aber, ich muss für meine ganzen Seiten eine andere Logik anwenden als für die letzte Seite, auf der auch weniger als 10 Datensätze stehen können.

Aber fangen wir erstmal vorne an:

Ermitteln der Seitenzahl und des Restes

Mein Array mit den 334 Datensätzen heißt $dataObject und wurde aus einem JSON in ein Array umgewandelt. Jetzt rechne ich erstmal aus, wieviele ganze Seiten das ergibt, wenn ich hier beispielsweise 10 Datensätze pro Seite ausgebe, und welcher Rest bleibt.

<?php

//JSON alle Rezepte abholen und in Array umwandeln
$json = file_get_contents('http://localhost/kleine_api/rezepte/rezeptelesen.php');
$dataObject = json_decode($json,true);

//Rezepte pro Seite ausrechnen
$pro_seite = 10; //Wert kann beliebig geändert werden
$anzahl = count($dataObject['rezepte']);
echo "Datens&auml;tze gesamt = ".$anzahl."<br>";
echo "Das macht ".floor($anzahl/$pro_seite)." ganze Seiten
 bei ".$pro_seite." Rezepten pro Seite, Rest: ".$anzahl%$pro_seite."<br>";

Ich habe mit Absicht eine sehr geschwätzige echo-Ausgabe eingebaut, zur besseren Kontrolle. Der Output sieht jetzt mal so aus:

echo_kennzahlen

echo_kennzahlen

Damit kann ich mir jetzt schon mal die Buttons für die einzelnen Seiten zusammenbauen. Das mache ich wieder mit einem Formular. Ich zähle mein i von Seite 1 bis zur letzten Seite inklusive hoch, als Value kriegt jeder Button den aktuellen Wert von i. Ausserdem kriegt jeder Button noch eine ID, die brauchen wir später noch.

//Formular mit Buttons für die Seitenzahlen, Start 1, Ende: nächsthöhere Ganzzahl
for ($i=1; $i <=ceil($anzahl/$pro_seite); $i++){
    echo "<form action = 'array_num_page.php' method = 'get'>";
    echo "<input type='submit' id='el_num_button_".$i."' name=akt_i value='".$i."'>";
}
echo "</form>";

Das sieht jetzt schonmal so aus:

buttons

buttons

Jetzt gehts daran zu ermitteln, welche Seite gerade aktuell ist. Ich starte als Default mit der 1, und je nachdem welchen Button der Anwender angeklickt hat hole ich mir den Wert aus dem Formular.

//Checken ob eine Seite geklickt wurde
$seitenstart=1;
if (isset($_GET['akt_i'])){
    $seitenstart = $_GET['akt_i'];
    }else{
    $seitenstart=1;
    }
//versteckte Ausgabe für farbige Markierung der aktuellen Seite mit Script    
echo "<div id ='seitenstart' style='display:none;'>".$seitenstart."</div>";

Meinen Seitenstart schreibe ich mir noch in eine versteckte Div, die brauche ich nachher für die farbige Markierung der aktuellen Seite.

Jetzt gehts erst mal an die Ausgabe.

Die ganzen Seiten

Hier darf ich nur bis zur letzten ganzen Seite hochzählen, die letzte Seite mit den weniger Datensätzen kommt später dran:

//Ausgabe aller ganzen Seiten von 1 bis zum letzten ganzzahligen Vielfachen
if (($seitenstart > 0) and ($seitenstart < floor($anzahl/$pro_seite))){

//Tabelle für Ausgabe aller Rezepte zusammenbauen
echo "<table border : 1px>";
echo "<th>ID</th><th>Titel</th><th>Content</th> 
/*Ausgabe als Tabelle*/

Jetzt wird es ein bisschen knifflig. Ich bleibe mal bei einem Wert pro Seite von 10 Datensätzen, es klappt aber auch mit jedem anderen Wert.

Auf Seite eins muss ich bei 0 anfangen und bis eins weniger als die Anzahl der Datensätze pro Seite hochzählen, also bis 9. Auf Seite zwei muss ich bei 10 anfangen und bis 19 hochzählen, usw.:

//Bei 0 anfangen, bis max. eins weniger als die Anzahl der ganzen Seiten hochzählen (0..9, 10..19 usw...)
for ($i=($seitenstart-1)*$pro_seite; $i <= $pro_seite*$seitenstart-1; $i++){

Die ganze for-Schleife mit der Ausgabe der einzelnen Werte aus dem Array in Tabellenzeilen sieht so aus:

//Bei 0 anfangen, bis max. eins weniger als die Anzahl der ganzen Seiten hochzählen (0..9, 10..19 usw...)
for ($i=($seitenstart-1)*$pro_seite; $i <= $pro_seite*$seitenstart-1; $i++){

echo "<tr>";
//Werte aus dem Array auf Var. legen
$akt_id = $dataObject['rezepte'][$i]['ID'];
$akt_titel = $dataObject['rezepte'][$i]['post_title'];
//Content tags raus und auf 100 Zeichen kürzen
$akt_content = substr(strip_tags($dataObject['rezepte'][$i]['post_content']),0,200);

echo "<td>".$akt_id."</td><td>".$akt_titel."</td><td>".$akt_content."</td>";
echo "</tr>";
}

Damit haben wir die Ausgabe aller ganzen Seiten erledigt. Jetzt kümmern wir uns um den Rest. Da nehmen wir nur noch die Indizes aus dem Array, die grösser als der letzte Wert vor dem letzten ganzzahligen Vielfachen der Seitenzahl sind, und marschieren nach oben durch bis 1 vor der Gesamtzahl der Datensätze.

//****Ausgabe Rest wenn Seitenzahl grösser als das letzte ganzzahlige Vielfache ist
if($seitenstart > floor($anzahl/$pro_seite)){
...

//starten beim letzten ganzzahligen Vielfachen der Gesamt-Seitenzahl, 
//stoppen eins unter Gesamtzahl
for ($i=floor($anzahl/$pro_seite)*$pro_seite; $i < $anzahl; $i++){

Voila, das wars! Der ganze Code mit Ausgabe der Tabelle sieht so aus:

//**************************Ausgabe Rest wenn Seitenzahl grösser als das letzte ganzzahlige Vielfache ist
if($seitenstart > floor($anzahl/$pro_seite)){
    

//Tabelle für Ausgabe des Rests zusammenbauen
echo "<table border : 1px>";
echo "<th>ID</th><th>Titel</th><th>Content</th>";

//starten beim letzten ganzzahligen Vielfachen der Gesamt-Seitenzahl, stoppen eins unter Gesamtzahl
for ($i=floor($anzahl/$pro_seite)*$pro_seite; $i < $anzahl; $i++){

echo "<tr>";
//Werte aus dem Array auf Var. legen
$akt_id = $dataObject['rezepte'][$i]['ID'];
$akt_titel = $dataObject['rezepte'][$i]['post_title'];
//Content tags raus und auf 100 Zeichen kürzen
$akt_content = substr(strip_tags($dataObject['rezepte'][$i]['post_content']),0,200);

echo "<td>".$akt_id."</td><td>".$akt_titel."</td><td>".$akt_content."</td>";
echo "</tr>";
}
echo "</table>";
    
}

Noch ein Javascript-Zuckerl: aktuelle Seite farbig markieren

Ich hab mir ja zu jedem Seitenzahl-Button eine ID generiert, das sah so aus:

echo "<input type='submit' id='el_num_button_".$i."' name=akt_i value='".$i."'>";

Und ich habe mir den Wert der aktuellen Seite (default 1) in eine versteckte div geschrieben:

//versteckte Ausgabe für farbige Markierung der aktuellen Seite mit Script    
echo "<div id ='seitenstart' style='display:none;'>".$seitenstart."</div>";

Damit habe ich mir ein kleines Javascripterl gebastelt, das die aktuelle Seite farbig markiert:

<script>

    $(document).ready(function() {
    var dieid = document.getElementById('seitenstart').innerHTML;
    //alert(dieid);
    document.getElementById('el_num_button_'+dieid).style.backgroundColor = "lightgreen";
    }); 


</script>

Ich klaube mir die aktuelle Seitenzahl aus der verstecken Div und spreche damit die zugehörige Button-ID an, die style ich mir nach Belieben, das war auch schon alles. Hübscher kleiner Effekt!

seite_farbig

seite_farbig

 

Kontrastfarbe automatisch berechnen mit jquery/Javascript

Das hat jetzt mit WordPress nur insoweit was zu tun, als ich eine Anforderung vom Kunden hatte, ein Info-Widget mit in zufälligen Intervallen wechselnden Farben zu hinterlegen, der wollte das halt gern so haben. Dabei stellte sich aber gleich die Herausforderung, dass der Text (default schwarz) bei dunklen Hintergrundfarben natürlich schlecht bis gar nicht zu lesen war. Will heissen, die Textfarbe sollte dann auch dynamisch angepasst werden, und das mach ich mit jquery/Javascript. Dafür hab ich mir eine Lösungsstrategie zusammengegooglet, die man vielleicht mal irgendwo anders brauchen kann, deswegen kommt sie hier rein.

Zufällige Farbe für den Hintergrund bestimmen

Dafür habe ich mir dieses recht überschaubare Snippet ergooglet, das sehr zuverlässig funktioniert:

//******Zufällige Hex-Farbe erzeugen*********************/
    function randomColor(){
    
    var x=Math.round(0xffffff * Math.random()).toString(16);
    var y=(6-x.length);
    var z="000000";
    var z1 = z.substring(0,y);
    var color= "#" + z1 + x;
    
    return color;
    }

Relative (wahrgenommene) Helligkeit einer Farbe bestimmen

Dafür gibt es vom w3c eine Faustformel, die ich für den Kontrast bei barrierefreien Seiten immer wieder mal brauche, die geht so:

//***********relative Helligkeit von r,g,b bestimmen
    function Brightness(r, g, b)
    {
       return Math.sqrt(
          r * r * .241 + 
          g * g * .691 + 
          b * b * .068);
    }

Man füttert sie mit den RGB-Werten einer Farbe und kriegt einen Wert zwischen 0 und 255 heraus, der die relative Helligkeit einer Farbe bezeichnet. Man nimmt dann als Kontrastfarbe für die untere Hälfte des Farbspektrums weiß, für die obere Hälfte schwarz. Den Schwellwert von 130 kann man nach Geschmack noch ein bisschen nach oben oder unten anpassen.

//****************Textfarbe je nach Schwellwert zurückgeben
    function textfarbe(helligkeit){
    if (helligkeit > 130){return 'black'}
    if (helligkeit <= 130){return 'white'}

    }

Wir haben Hex und brauchen RGB

Deswegen gibts noch eine Umwandlungsfunktion, die uns den Hex-String zerlegt und die RGB_Werte liefert:

//************rgb-Werte aus hex holen
    function hexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)}
    function hexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)}
    function hexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)}
    function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}

var R = hexToR(aktfarbe);
var G = hexToG(aktfarbe);
var B = hexToB(aktfarbe);

Mit den drei Variablen kann man dann die Funktion Brightness() aufrufen, und mit der wiederum die Funktion textfarbe(), die uns dann schlussendlich die passende Kontrastfarbe für unsere zufällige Hintergrundfarbe liefert. Ich gebe zu es ist ein bisschen von hinten durch die Brust ins Auge, aber es funktioniert. Hier mal das ganze Script zum Nachvollziehen:

Das Script

<script>
    $(document).ready(function(){
    setInterval(farbwechsler, 5000)
    farbwechsler();
    
    //******Zufällige Hex-Farbe erzeugen*********************/
    function randomColor(){
    
    var x=Math.round(0xffffff * Math.random()).toString(16);
    var y=(6-x.length);
    var z="000000";
    var z1 = z.substring(0,y);
    var color= "#" + z1 + x;
    
    return color;
    }

    //************rgb-Werte aus hex holen
    function hexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)}
    function hexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)}
    function hexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)}
    function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}
    
    //***********relative Helligkeit von r,g,b bestimmen
    function Brightness(r, g, b)
    {
       return Math.sqrt(
          r * r * .241 + 
          g * g * .691 + 
          b * b * .068);
    }
    
    //****************Textfarbe je nach Schwellwert zurückgeben
    function textfarbe(helligkeit){
    if (helligkeit > 130){return 'black'}
    if (helligkeit < 130){return 'white'}

    }
        
function farbwechsler(){

var aktfarbe = randomColor();

var R = hexToR(aktfarbe);
var G = hexToG(aktfarbe);
var B = hexToB(aktfarbe);


           document.getElementById("zufall").style.backgroundColor = aktfarbe;
           document.getElementById("inhalt").innerHTML ="Hex: "+ aktfarbe;
           document.getElementById("rgb").innerHTML = "rgb: "+R+", "+G+", "+B;
           document.getElementById("brightness").innerHTML ="Helligkeit: "+ Brightness(R,G,B);
           document.getElementById("schrift").style.backgroundColor = aktfarbe;
           document.getElementById("schrift").style.color = textfarbe(Brightness(R,G,B));
           }

    
  })
</script>

Ich hab mal die Funktion farbwechsler() auf alle 5 Sekunden gesetzt, für den Demo-Effekt.

Und hier noch das passende HTML zum Ausprobieren:

<body>

<h1>Beispiel Contrast Colors mit Javascript</h1>
<div id = "zufall">Schriftfarbe statisch</div>
<div id="inhalt">...</div>
<div id="rgb">...</div>
<div id="brightness">...</div>
<div id="schrift"><h1>Schriftfarbe dynamisch</h1></div>

</body>

Das wars! So gibt es immer lesbare Schrift auch auf zufällig generierten Hintergrundfarben.