• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[GELÖST] EventListener click, mouseover ..., aber ohne HTML und CSS ???

Lotti

New member
Ich möchte 20 Bilder nebeneinander und 12 Bilder untereinander (zusammen 240 Bilder) darstellen. Die Bilder heißen "1.jpg" bis "50.jpg". Das Array Bild[] wird zuvor mit 240 Einträgen befüllt, die wild durcheinander Werte zwischen 1 und 50 haben (und den Bildnamen ohne ".jpg" entsprechen). Die Arrays xPos[] und yPos[] enthalten konstant die (240) Koordinaten, an denen die Bilder ausgegeben werden sollen.

Die Lösung von kkapsner und die Empfehlungen im Threat "HTML-Link mit Zufallsbild zum anklicken" habe ich umgesetzt (die Bilder sind anklickbar), aber irgendwie bin ich nun in einer anderen Sackgasse und kämpfe mit den drei Zuständen
- Mouseover-Effekt (hover), z.B. "opacity(0.7)"
- Markieren eines angeklickten Bildes, z.B. "opacity(0.5)"
- Demarkieren eines markierten Bildes, z.B. "opacity(1)"

Im WWW und hier im Forum habe ich keine Lösung gefunden, wie das ohne HTML/CSS und <a href ...> klappt. Mein neues "Konstrukt" funktioniert nur zum Teil. Auf "mouseover" wird das letzte Bild (i = 239, rechts unten) an seiner Position ausgeblendet und überblendet das Mouseover-Bild. Bei Verlassen des Mouseover-Bildes verschwindet das Bild Nr. 239 an seiner richtigen Position endgültig, wird aber beim nächsten Mouseover-Bild immer wieder kurz ein- und ausgeblendet.

Es dürfte wohl an appendChild liegen. Aber was wäre die Alternative?

Code:
function PLAY (Level) {

    ...

    var Raster   = document.getElementById('RasterID'); 
    // RasterID ist nur im HTML-Script definiert (<div ID="RasterID"></div>) und nicht im CSS-Script
 
    function KLICK (Pos,PIC) {
        ...
        Stein.style.filter   = "opacity(0.5)";
        Raster.appendChild(PIC);
    }

    function M_OVER (Pos,PIC) {
        ...
        Stein.style.filter   = "opacity(0.7)";
        Raster.appendChild(PIC);
    }

    function M_OUT (Pos,PIC) {
        ...
        Stein.style.filter   = "opacity(1)";
        Raster.appendChild(PIC);
    }

    function STEIN2SCREEN (Pos,PIC) {
        Stein.style.position = "absolute";
        Stein.style.left     = xPos[Pos]+"px";
        Stein.style.top      = yPos[Pos]+"px";
        Stein.style.width    = "40px";
        Stein.style.height   = "50px";
        Stein.style.filter   = "opacity(1)";
        Raster.appendChild(PIC);
    }

    for (var i = 0; i < 240; i += 1) {
        var Stein = document.createElement("img");
        Stein.src = Bild[i] + ".jpg";
        Stein.alt = Bild[i];
        Stein.addEventListener("click", function(i) { return function() { KLICK (i,Stein); }; } (i), false);
        Stein.addEventListener("mouseover", function(i) { return function() { M_OVER (i,Stein); }; } (i), false);
        Stein.addEventListener("mouseout", function(i) { return function() { M_OUT (i,Stein); }; } (i), false);
        STEIN2SCREEN (i,Stein);
    }
}
 
Zuletzt bearbeitet von einem Moderator:
Danke für die schnelle Reaktion ...
... und keine Sorge, was den IE<=8-Müll angeht. Es wird wohl darauf hinauslaufen, dass ich den Bildern einfach nur einen schwarzen Rahmen verpasse, und den nach click nur gelb einfärbe (border: 1px solid yellow;).

Den Threat habe ich zuvor auch schon gelesen, passt eber m.E. irgendwie nicht?
Das Klicken ohne "Schnörkel" funktioniert in meinem Script bestens und fehlerfrei. Nur der zusätzlich gewünschte mouseover-event klappt nicht.
Oder meinst Du die Verwendung von console.log (PIC) anstelle von appendChild (PIC)?
 
Also ich würde das mit CSS-Klassen machen:
HTML:
<!DOCTYPE html>
<html>
<head>
    <title>Images</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        .stones {
            width: 40px;
            height: 50px;
            margin: 0;
            padding: 0;
            border: 0;
            opacity: 1.0;
            position: absolute;
        }

        .stones:hover {
            opacity: 0.6;
        }

        .stoneClicked {
            opacity: 0.3;
        }
    </style>
    <script>
        function stoneClicked(positionIndex, stone) {
            if (stone.classList.contains('stoneClicked')) {
                stone.classList.remove('stoneClicked');
            } else {
                stone.classList.add('stoneClicked');
            }
        }

        function play(level) {
            var i,
                Stein,
                imagePath = 'Mahjong_images',
                imageType = 'jpg',
                Raster = document.getElementById('RasterID'),
                Bild = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
                xPos = [0, 50, 100, 150, 200, 250, 0, 50, 100, 150, 200, 250],
                yPos = [0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 60, 60];

            for (i = 0; i < 12; i = i + 1) {
                Stein = document.createElement('img');
                Stein.alt = Bild[i];
                Stein.src = imagePath + '/' + Bild[i] + '.' + imageType;
                Stein.classList.add('stones');
                Stein.style.left = xPos[i] + 'px';
                Stein.style.top = yPos[i] + 'px';
                Stein.addEventListener('click', function(positionIndex, stone) {
                    return function() {
                        stoneClicked(positionIndex, stone);
                    };
                }(i, Stein), false);
                Raster.appendChild(Stein);
            }
        }
    </script>
</head>

<body>
    <div id="RasterID"></div>
    <script>play(1);</script>
</body>
</html>
 
Vielen Dank, es funzt ... :)
Natürlich würde ich es lieber mit CSS machen (und versuche das auch). Ich habe den Titel des Threats bewusst so formuliert, damit ich nicht noch eine weitere Lösung bekomme, wie man das mit HTML macht.
 
Nun habe ich doch noch eine "Jokerfrage" für mein Verständnis:
Das Markieren, Demarkieren und hover aus o.a. Vorschlag von miniA4kuser funktioniert - zunächst - einwandfrei, hat aber einen Effekt, den ich mit meinem getrübten Blick aus der Froschperspektive einfach nicht nachvollziehen kann.

Im Vorschlag befindet sich das Array Bild[] innerhalb der function play(level). Abweichend befülle ich das Array in meinem Script vor Aufruf der function play(level) in einer separaten function mit zufälligen Werten. Auch habe ich die Styles in die separate CSS-Datei ausgelagert.

Über die for-Schleife werden alle Bilder an den entsprechenden Postionen angezeigt (Bild [1] an xPos[1] und yPos[1] ...). Nun gibt es auch eine Option "neu mischen". Die macht nichts anderes, als die vorhandenen Werte im Array Bild[] in eine andere Reihenfolge zu bringen. Danach wird die function play(level) erneut aufgerufen und Bingo! Die Bilder werden tatsächlich in veränderter Reihenfolge "ordnungsgemäß" angezeigt und können auch alle (wie zuvor) "gehovert", markiert und demarkiert werden, ABER:

Beim ersten Aufruf hat z.B. das Bild an Position 10 (Bild[10]) den Wert 5 und auch mouseover und click haben Bild "5.jpg".
Beim 2. Aufruf (nach neu mischen) befindet sich an Position 10 nun z.B. das Bild "23.jpg". Beim Mouseover wird aber Bild "23.jpg" durch Bild "5.jpg" überlagert, das sich vor dem Mischen dort befand, und bei Klick wird ebenfalls Bild "5.jpg" über Bild "23.jpg" gelegt. Beim Demarkieren wird Bild "5.jpg" wieder entfernt und das richtige Bild "23.jpg" wird wieder an Position 10 sichtbar.
Nach erneutem Mischen (3. Aufruf) wird nun an Position 10 z.B. Bild "40.jpg" dargestellt. Jetzt wird bei Hover und Click aber das Bild "40.jpg" durch Bild "23.jpg" (aus dem 2. Aufruf) überlagert.

Hover und 1. click hängen also irgendwie immer einen Schritt hinterher und überlagern das aktuelle Bild mit einem "veralteten" Bild, das beim 2. click wieder entfernt wird.

Ich habe bereits alle Kombinationen von "Stein" und "stone" ausprobiert, um ID- bzw. Element- und Style-Konflikte auszuschließen. Dadurch ändert sich aber nichts.

Irgendwie habe ich den Eindruck, dass es sich bei JS um eine "labyrithorientierte, problembasierte Fremdsprache" handelt, bei der man alle Erfahrungen mit anderen Sprachen ignorieren muss? :mad:
 
Mit ein wenig Beispielcode wie du das jetzt genau umgesetzt hast, oder einem Link zu einer Beispielseite, würde das Nachvollziehen deines Problems leichter werden. Leider kann ich so nicht nachvollziehen wo dein roblem ist. Hast du vorher die alten "Steine" aus deinem "Raster" gelöscht, oder einfach nur appendet?

Habe mal ein "Mischen" eingebaut, kann aber keinen Fehler erkennen:
HTML:
<!DOCTYPE html>
<html>
<head>
    <title>Images</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        #RasterID{
            position: relative;
        }

        .stones {
            width: 40px;
            height: 50px;
            margin: 0;
            padding: 0;
            border: 0;
            opacity: 1.0;
            position: absolute;
        }

        .stones:hover {
            opacity: 0.6;
            cursor: pointer;
        }

        .stoneClicked {
            opacity: 0.3;
        }
    </style>
    <script>
        var Bild = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
            xPos = [0, 50, 100, 150, 200, 250, 0, 50, 100, 150, 200, 250],
            yPos = [0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 60, 60];

        function shuffleArray(arr) {
            for (var i = arr.length; i--; ){
                var sIndex = Math.floor(Math.random() * (i + 1));
                var h = arr[i];
                arr[i] = arr[sIndex];
                arr[sIndex] = h;
            }
            return arr;
        }

        function stoneClicked(positionIndex, stone) {
            console.log('positionIndex: ', positionIndex);
            console.log('stone.alt: ', stone.alt);
            console.log('stone: ', stone);
            if (stone.classList.contains('stoneClicked')) {
                stone.classList.remove('stoneClicked');
            } else {
                stone.classList.add('stoneClicked');
            }
        }

        function play(level) {
            var i,
                Stein,
                imagePath = 'Mahjong_images',
                imageType = 'jpg',
                Raster = document.getElementById('RasterID');

            Raster.innerHTML = '';
            for (i = 0; i < 12; i = i + 1) {
                Stein = document.createElement('img');
                Stein.alt = Bild[i];
                Stein.src = imagePath + '/' + Bild[i] + '.' + imageType;
                Stein.classList.add('stones');
                Stein.style.left = xPos[i] + 'px';
                Stein.style.top = yPos[i] + 'px';
                Stein.addEventListener('click', function(positionIndex, stone) {
                    return function() {
                        stoneClicked(positionIndex, stone);
                    };
                }(i, Stein), false);
                Raster.appendChild(Stein);
            }
        }

        function stonesShuffle(arr) {
            Bild = shuffleArray(Bild);
            play(1);
        }
    </script>
</head>

<body>
    <button onclick="stonesShuffle()">Neu mischen</button>
    <br /><br />
    <div id="RasterID"></div>
    <script>play(1);</script>
</body>
</html>
 
Vielen Dank und einen ganz dicken Daumen hoch für Deine Arbeit und Antworten !!!

In meinem Code mische ich das Array "Bild" auch nur durch, daher habe ich den Code weggelassen. Ansonsten: richtig erkannt, die alten Steine habe ich nicht ausdrücklich gelöscht, sondern einfach nur appended.

Da die neuen Steine richtig angezeigt werden, ging ich (gewohnheitsmäßig von PHP ...) davon aus, dass beim Durchlauf einer Schleife nur die "gewollten" Daten und Werte zum Zeitpunkt des Durchlaufs aktuell "geladen" und verarbeitet werden und diese nicht mit alten Daten aus vorherigen Durchläufen vermischt werden und kollidieren könnten.
Aber nun ist mir klar: "append" hat Schuld - und es fehlte nur die Zeile Raster.innerHTML = '';

Für "Wechsler" (wie mich) ist es extrem schwierig, zu lernen, wissen und anzuerkennen, wie JS tickt und dass im Hintergrund selbst bei einfachsten Routinen Effekte entstehen, auf die man erst einmal kommen muss.
 
Zuletzt bearbeitet:
Zurück
Oben