# Skript zur Darstellung von Bildern auf einer einfachen Website



## okapipapi (4. Feb 2021)

Hallo zusammen,

ich bin Java/HTML/CSS Anfänger und will für ein privates Projekt eine simple Website bauen. Wie die Website strukturell aussehen soll, habe ich in diesem Bild zusammengefasst (Bild1 im Anhang): 

Zur Erklärung: Oben sind vier Buttons zu sehen, denen ein Wert zugeordnet ist. Darunter ist eine Eingabemaske, in der die geklickten Buttons in der geklickten Reihenfolge eingetragen werden, also eine Art "Button-Click-Logbuch". 

Im Feld darunter bzw. in der freien Fläche soll der eingegebene Code ein Bild ausspucken. Die Bilder in meinem Zielordner "output" haben folgende Namen: 

ABC.png
ABD.png
ACD.png
BCD.png
(usw. in allen Kombinationen) 

Mit dem Skript, das ich bisher zusammengeschrieben habe, funktioniert das auch FAST wie gewünscht, allerdings habe ich folgendes Problem: Wenn ich z.B. das Bild ABC.png haben möchte, würde ich gerne die Buchstaben in einer *beliebigen Reihenfolge *eingeben können. D.h. ich will dass mir das Bild ABC.png angezeigt wird aber das soll sowohl mit der Eingabe von A-B-C als auch mit B-C-A als auch mit C-B-A funktionieren. Der einzige Workaround der mir aktuell einfällt ist das Bild ABC.png in meinem Ordner zu kopieren und nochmals als CBA.png usw. abzuspeichern. Für eine simple Anwendung wäre dies noch möglich aber mein Endziel ist eine Anwendung mit sehr viel mehr Buttons und Bildern, so dass dieser Workaround exponentiell mehr Arbeit machen würde. Zudem ist es auch nicht sonderlich elegant. 

Schaut euch hier das Skript an: 

[CODE lang="java" title="Skript"]  <script>

$(document).ready(function() {
  /**
   * Select the buttons.
   * The $display and $clickedButtons are just to output
   * the values that are stored.
   */
  const $buttons = $('.button');
  const $display = $('#display');
  const $clickedButtons = $('#clicked-buttons');
  const $reset = $('#reset');
  $reset.on('click', function() {
    values = [];
    $clickedButtons.text(values);
  });

  /**
   * Array which tracks your clicked buttons.
   * If a button is clicked, the value of that button
   * should be added to this array. The combination
   * of the values will then later represent the key.
   */
  var values = [];

  /**
   * Listen for the click event on all the buttons.
   * When clicked, get the value of that clicked button
   * and add that to the values array.
   * After that the clicked button values will be combined
   * to form a single key and check if that key matches
   * a combination. If there is a match the content should
   * be anything other than undefined.
   */

  $buttons.on('click', function() {
    // This is the currently clicked button.
    const $button = $(this);

    // Get the value of the button.
    const value = $button.val();

    // If there already are 15 previously clicked buttons,
    // then empty the array, so we can start a new combination.
    if (values.length === 15) {
      values = [];
    }

    // Now add the newly clicked value.
    values.push(value);

    // This will output the current values in the array.
    $clickedButtons.text(values);

    // Transform the array into a single string.
    // This will be the key to select content.
    // ["1", "2", "3"] becomes "123".
    const key = values.join('');   

    // Check if key has a match in the combinations object.
    $display.attr('src', 'output/' + key + '.png');
  });
});
</script>[/CODE]

Gibt es eine Möglichkeit diese Funktionalität zu implementieren, die ich oben beschreibe? 

Vielen Dank für eure Hilfe bereits im Voraus!


----------



## mihe7 (4. Feb 2021)

Sortiere die Zeichenketten, dann kannst Du die sortierten Zeichenketten vergleichen.

EDIT: die Zeichen in den Zeichenketten, versteht sich. Aus HAMBURG wird dann z. B. ABGHMRU und es spielt keine Rolle, in welcher Reihenfolge die Zeichen eingegeben wurden.


----------



## okapipapi (4. Feb 2021)

Ok, das klingt doch schon mal gut. Nur wie mach ich das? Wie gesagt bin ich blutiger Anfänger ...


----------



## M.L. (4. Feb 2021)

Dafür *könnte* man die Sort-Methode (oder ein Eigenimplementierung) von JavaScript verwenden: https://www.geeksforgeeks.org/how-to-sort-strings-in-javascript/

```
var string = ["B", "C", "A"];   //statt der Vorgabe ["Suraj", "Sanjeev", "Rajnish", "Yash", "Ravi"];
```
Output dann: 
	
	
	
	





```
Original String
B,C,A

After sorting
A,B,C
```


----------



## Thallius (4. Feb 2021)

Und du bist sicher das wenn du ganz viele Bilder hast, diese niemals aus den gleichen Buchstaben bestehen werden?

z.B.

LAMPE.png wäre dann das gleiche bild wie AMPEL

Gruß

Claus


----------



## okapipapi (4. Feb 2021)

M.L. hat gesagt.:


> Dafür *könnte* man die Sort-Methode (oder ein Eigenimplementierung) von JavaScript verwenden: https://www.geeksforgeeks.org/how-to-sort-strings-in-javascript/
> 
> ```
> var string = ["B", "C", "A"];   //statt der Vorgabe ["Suraj", "Sanjeev", "Rajnish", "Yash", "Ravi"];
> ...



Hey,

über sorting hatte ich mir bereits Gedanken gemacht und das wurde mir auch von einem Freund vorhin vorgeschlagen. Allerdings bestünde das Problem dann darin, dass es alphabetisch sortieren würde und es auch nur für alphabetische Strings geht. In der eigentlichen Anwendung sind die Bildernamen komplexer und bestehen sowohl aus Zahlen als auch Buchstaben, so dass diese Methode wahrscheinlich den Zweck verfehlt . Mir war das nicht bewusst als ich den Post erstellt habe, sonst hätte ich das Problem noch präziser beschreiben können! 



Thallius hat gesagt.:


> Und du bist sicher das wenn du ganz viele Bilder hast, diese niemals aus den gleichen Buchstaben bestehen werden?
> 
> z.B.
> 
> ...



Hey Claus! Alle Bilder haben eine einzigartige Bezeichnung, insofern wäre das kein Problem. Stellt es euch folgendermaßen vor:

Jedes Bild in meiner DB hat die Attribute: Künstler, Farbe, Jahr und die Bilder heißen KünstlerFarbeJahr.png, also z.B. PicassoGrün1986.png

Ich will sowohl mit der Eingabefolge Picasso-Grün-1986 das Bild erscheinen lassen als auch Grün-1986-Picasso.

In Wirklichkeit ist die Anwendung noch etwas komplexer aber dazu müsste ich den Fachbereich erläutern und dieses Beispiel illustriert ganz gut wie die Anwendung funktionieren soll.


----------



## okapipapi (4. Feb 2021)

Dieses Bild stellt die gewünschte Anwendung nun etwas besser dar!

Ich habe an anderer Stelle den Hinweis bekommen, dass ich ggf. mit dem "Map" Object arbeiten solle - was denkt ihr dazu?


----------



## Thallius (4. Feb 2021)

Warum sollte das sortieren mit Sonderzeichen und zahlen nicht funktionieren?


----------



## okapipapi (4. Feb 2021)

Thallius hat gesagt.:


> Warum sollte das sortieren mit Sonderzeichen und zahlen nicht funktionieren?



Also doch, die Sortierung würde grundsätzlich nach dem Prinzip funktionieren, allerdings würde die Eingabe 1986-Grün-Picasso das ja in Grün-Picasso-1986 sortieren, das Bild hieße aber nach wie vor PicassoGrün1986.png weil die Bildbenennung in der Datenbank nicht alphabetisch, sondern nach dem Muster KünstlerFarbeJahr.png erfolgen würde. Oder verstehe ich da etwas falsch?


----------



## mihe7 (5. Feb 2021)

okapipapi hat gesagt.:


> Oder verstehe ich da etwas falsch?


Ja.

Ganz allgemein transformierst Du einen Dateinamen in einen Matchcode. Das machst Du sowohl für die Dateinamen, die in der DB gespeichert sind, als auch für den gesuchten Dateinamen. Gefunden werden dann die Dateien, deren Matchcode mit dem gesuchten Matchcode übereinstimmen.

Die Frage ist also nur, wie Du einen Dateinamen in einen für Deine Anforderungen geeigneten Matchcode transformieren kannst. Für das, was man bisher von Dir erfahren konnte, bietet sich die Sortierung der Zeichen des Dateinamens in z. B. Großbuchstaben an (ggf. willst Du auch nur Zeichen und Zahlen berücksichtigen und alle anderen Zeichen rausfiltern, das spielt fürs Prinzip aber keine Rolle; EDIT: auch die Dateiendung kann man natürlich dabei abschneiden).

Aus "PicassoGrün1986.png" wird so der Matchcode ".1689GPACGINNOPRSSÜ", der auch in der DB abgespeichert werden kann. Wenn jetzt nach "Grün6891Picasso.png" gesucht wird, wird der Suchbegriff zuerst in einen Matchcode transformiert. Dabei entsteht ebenfalls ".1689GPACGINNOPRSSÜ", so dass die Datei "PicassoGrün1968.png" in der DB gefunden werden könnte, da die Matchcodes übereinstimmen. Mit der Sortierung der Datensätze hat das gar nichts zu tun.

EDIT: ohne Dateiendung wäre der Matchcode z. B. "1689GPACINORSSÜ".


----------



## okapipapi (5. Feb 2021)

Ok, das habe ich verstanden. Hab das jetzt mal für die tatsächliche Anwendung durchgedacht und ich glaube es würde dennoch zu Problem führen. Das hängt damit zusammen, dass es auch Buttons gäbe die Ab, Bc, De (und viele weitere Kombinationen) hießen, so dass eines der Bilder aus der Datenbank so benannt wäre:

456AbBcDe.png

es gäbe aber auch:

456AcBeDb.png

Nach der Sortierlogik würden aber beide nach 456ABbcDe.png sortiert ...

Sorry dass mir das so Stück für Stück bewusst wird, mir fehlt einfach das Grundverständnis für das Ausmaß der Aufgabe, so dass ich mit jedem Bruchstück neues Wissens auf neue Probleme stoße. Für die beschriebene Anwendung für das Sorting wie du es beschreibst aber definitiv funktionieren.


----------



## Thallius (5. Feb 2021)

Das war ja genau meine Frage aus Post #5


----------



## okapipapi (5. Feb 2021)

Thallius hat gesagt.:


> Das war ja genau meine Frage aus Post #5



Hast Recht ... Mea Culpa

Vielleicht eine "dumme" Frage aber gäbe es die Möglichkeit, dass der Sorting-Algorithmus bestimmte Button-Values nicht splittet, sondern immer zusammen sortiert? D.h. wenn ein Button den Value "Ab" hat, ließe sich dieser Value gemeinsam sortieren, so dass 413AbAcAd zu 134AbAcAd wird?


----------



## mihe7 (5. Feb 2021)

okapipapi hat gesagt.:


> Vielleicht eine "dumme" Frage aber gäbe es die Möglichkeit, dass der Sorting-Algorithmus bestimmte Button-Values nicht splittet, sondern immer zusammen sortiert? D.h. wenn ein Button den Value "Ab" hat, ließe sich dieser Value gemeinsam sortieren, so dass 413AbAcAd zu 134AbAcAd wird?



Dann ist die Frage doch einfach, ob im Dateinamen "Ab" enthalten ist


----------



## okapipapi (5. Feb 2021)

Im Dateinamen kämen solche Benennungen vor, ja.

Ich bin nun so weit gekommen, dass die Funktionalität z.T. gegeben ist. Allerdings bin ich mir nicht sicher, wie ich die Ausgabe des Bildes und das "Logbuch" einfüge wie im Beispiel oben ... Könntet ihr mir da aushelfen?  


```
var imgs = ["ABC123.png", "1A2B4C.png", "ABC132.png", "123ABC.png"];

function case_insensitive_comp(strA, strB) {
  return strA.toLowerCase().localeCompare(strB.toLowerCase());
}

function reSortFiles() {
  var all = {};
  imgs.forEach(function(a) {
    d = a.split(".");
    img = d[0].split("");
    img = sortStr(img);
    img = img.join("");

    all[img] ? all[img].push(a) : all[img] = [a];
  });

  return all;
}

function sortStr(str) {
  return str.sort(case_insensitive_comp)
}

allImages = reSortFiles()
console.log(allImages)


buttons = document.querySelectorAll("button")

clicked = "";

buttons.forEach(function(btn) {
  btn.addEventListener("click", function(e) {
    clicked += e.target.dataset.value;
    clicked_s = sortStr(clicked.split("")).join("")
    console.log(clicked, clicked_s)
    img = allImages[clicked_s]
    if (img) {
      console.log("Found: ", img.join(","))
      clicked="";
    }
  });
});
```


----------



## mihe7 (5. Feb 2021)

okapipapi hat gesagt.:


> Allerdings bin ich mir nicht sicher, wie ich die Ausgabe des Bildes und das "Logbuch" einfüge wie im Beispiel oben


Per DOM-Manipulation. 


```
<img id="foundImage" ........ >
```


```
const foundImage = document.querySelector("#foundImage");
foundImage.src = "abc.png"; // hier halt den entsprechenden Pfad zum gefundenen Bild verwenden
```

Und HTML selbst kannst Du z. B. über das Attribut innerHTML (oder innerText, wenn es nur Text ist) z. B. eines div-Elements einstellen.


----------



## okapipapi (8. Feb 2021)

Also, hab das mal so getestet aber irgendwo muss ich noch einen Fehler drin haben. Ein Bild wird leider nicht angezeigt ...


```
<!DOCTYPE html>
<html>
<head>
    <title>random game</title>
    <body>
        <button type="button" data-value="A">A</button>
<button type="button" data-value="B">B</button>
<button type="button" data-value="C">C</button>
<button type="button" data-value="1">1</button>
<button type="button" data-value="2">2</button>
<button type="button" data-value="3">3</button>
<button type="button" data-value="4">4</button>
       
<img id="foundImage">
    </body>
    <script type="text/javascript">
       
const foundImage = document.querySelector("#foundImage");
foundImage.src = img.join(","));
       

var imgs = ["ABC123.png", "1A2B4C.png", "ABC132.png", "123ABC.png"];

function case_insensitive_comp(strA, strB) {
  return strA.toLowerCase().localeCompare(strB.toLowerCase());
}

function reSortFiles() {
  var all = {};
  imgs.forEach(function(a) {
    d = a.split(".");
    img = d[0].split("");
    img = sortStr(img);
    img = img.join("");

    all[img] ? all[img].push(a) : all[img] = [a];
  });

  return all;
}

function sortStr(str) {
  return str.sort(case_insensitive_comp)
}

allImages = reSortFiles()
console.log(allImages)


buttons = document.querySelectorAll("button")

clicked = "";

buttons.forEach(function(btn) {
  btn.addEventListener("click", function(e) {
    clicked += e.target.dataset.value;
    clicked_s = sortStr(clicked.split("")).join("")
    console.log(clicked, clicked_s)
    img = allImages[clicked_s]
    if (img) {
      console.log("Found: ", img.join(","))
      clicked="";
    }
  });
});
    </script>
```


----------



## Thallius (8. Feb 2021)

wie soll das auch funktionieren? Du setzt den Inhalt des Bildes before du img überhaupt definiert hast. und was soll das join dahinter? Eigentlich müßtest du in der Browser console auch nen ordentlichen error bekommen


----------

