PHP im Javascript ergänzen, ich brauche Variablen

wireless-dj

Mitglied
Moin,

Ich habe mal wieder eine spezielle Frage, bin nicht sicher, ob das nun hierhin, oder eher
ins Javascript-Forum gehört.... Bitte verschieben, falls es hier falsch ist.

Auf der Suche nach einem Drag & Drop Schnipsel bin ich bei diesem Beispiel gelandet:
Kendo UI® Dojo by Progress

Das finde ich total gut, ist schmal geschrieben, und macht genau das, was ich suche,
nämlich "Items" von einer Liste in die Andere zu ziehen, besser gesagt zu "kopieren",
so, dass das Item aber in der ersten Liste verbleibt, und nicht komplett die Liste wechselt.
Finde ich richtig klasse, und ist genau das, was ich gesucht habe.

Mein Problem ist:
Die Items müssen PHP-Variablen enthalten, und ich brauche einen Button, der die
Variablen der Items aus der rechten Liste in der sortierten Reihenfolge (!) an ein weiteres
PHP-Script sendet, damit ich diese sortierte Liste dann auch weiter verarbeiten kann.
Die Items links sollen sich aus dem Resultat einer foreach Schleife mit den Daten und
Variablen aus einer Datenbank generieren, und rechts sollen diese ausgewählten Items dann
weiter verarbeitet werden, und in einer anderen Tabelle der selben Datenbank gespeichert werden.

Ich hoffe, das war halbwegs verständlich.
Kann mir da Jemand helfen? @Sempervivum vielleicht?

Danke & Gruß,

Volker
 
Hallo Volker, willkommen zurück!
Natürlich werde ich gern versuchen, dir bei dieser Sache zu helfen.
Die Items müssen PHP-Variablen enthalten
...

Die Items links sollen sich aus dem Resultat einer foreach Schleife mit den Daten und
Variablen aus einer Datenbank generieren
Wenn ich einen Blick auf die Website von Kendo werfe, finde ich einen Abschnitt über Remote Datasource:
Binding to Remote Data in jQuery DataSource Widget Demo | Kendo UI for jQuery
Das Beispiel ist wahrscheinlich auch auf die Listbox anwendbar. Du müsstest ein PHP-Skript bereitstellen, das die Daten ausliefert und dessen URL übergeben, wie in dem Beispiel beschrieben.

Ich habe auch einen Blick auf das Pricing geworfen und da trifft die Eigenschaft "schmal" eher nicht zu. Willst Du wirklich so viel Geld ausgeben?
 
Moin Ulrich,
Da hab ich ehrlich gesagt gar nicht hingeschaut.
Ich dachte, man dürfte das Beispiel so nehmen, und ggfs. für sich anpassen.

Nein, soviel Geld möchte ich nicht ausgeben.
Dann muss ich weiter suchen.
Oder hast Du zufällig ein Beispiel, welches dem genannten Prinzip entspricht?
 
Ich habe in meinen Beispielen ein wenig gesucht und dies gefunden, was das Drag&Drop mit Klonen macht:
Code:
<!DOCTYPE html>
<html lang="nl">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>Dropzone Dynamic Content</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <style>
        .gallery {
            cursor: pointer !important;
        }

        img {
            width: 200px;
        }
    </style>
</head>

<body>
    <div id="gallery_1" class="gallery" style="padding:25px;">gallery 1</div>
    <div id="gallery_2" class="gallery" style="padding:25px;">gallery 2</div>
    <div id="gallery_3" class="gallery" style="padding:25px;">gallery 3</div>

    <ul id="photos">
        <li class="photo" draggable="true">
            <img id="photo_1" src="../images/dia0.jpg">
        </li>
        <li class="photo" draggable="true">
            <img id="photo_2" src="../images/dia1.jpg">
        </li>
        <li class="photo" draggable="true">
            <img id="photo_3" src="../images/dia2.jpg">
        </li>
    </ul>
    <script>
        const dragImg = new Image();
        document.body.append(dragImg)
        dragImg.width = 60;
        dragImg.height = 40;
        dragImg.style.position = 'absolute';
        dragImg.style.left = -9999;
        document.querySelectorAll('.photo').forEach(item => {
            item.addEventListener('dragstart', event => {
                event.dataTransfer.setData('text/plain', event.target.id);
                dragImg.src = event.target.src;
                event.dataTransfer.setDragImage(dragImg, 0, 0);
            });
        });
        document.querySelectorAll('.gallery').forEach(item => {
            item.addEventListener('dragover', (event) => {
                event.preventDefault();
                event.target.style.border = '2px solid lightblue';
            });
            item.addEventListener('dragleave', (event) => {
                event.preventDefault();
                event.target.style.border = '';
            });
            item.addEventListener('drop', event => {
                event.preventDefault();
                const
                    idGallery = event.target.id,
                    idPhoto = event.dataTransfer.getData('text/plain');
                console.log('ID des Fotos=' + idPhoto + ', ID der Gallerie=' + idGallery);
                event.target.insertAdjacentElement(
                    'beforeend', document.getElementById(idPhoto).cloneNode());
                event.target.style.border = '';
            });
        });
    </script>
</body>

</html>

Auch für das Sortieren bzw. Verschieben in der rechten Liste habe ich ein Beispiel gefunden, dann braucht es keine Buttons:
Code:
<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Test</title>

    <style>
        body {
            margin: 0;
            overflow: hidden;
        }

        ul {
            margin: 0;
            padding: 0;
            position: relative;
        }

        li {
            display: flex;
            justify-content: space-between;
            padding: 20px 10px;
            background: white;
            border-bottom: solid 1px gray;
            border: 1px solid red;
        }

        span {
            width: 1em;
            cursor: move;
        }
    </style>

</head>

<body>
    <ul>
        <li class="sort">List Item 1<span draggable="true">&#x2195;</span></li>
        <li class="sort">List Item 2<span draggable="true">&#x2195;</span></li>
        <li class="sort">List Item 3<span draggable="true">&#x2195;</span></li>
        <li class="sort">List Item 4<span draggable="true">&#x2195;</span></li>
        <li class="sort">List Item 5<span draggable="true">&#x2195;</span></li>
        <li class="sort">List Item 6<span draggable="true">&#x2195;</span></li>
        <li class="sort">List Item 7<span draggable="true">&#x2195;</span></li>
        <li class="sort">List Item 8<span draggable="true">&#x2195;</span></li>
        <li class="sort">List Item 9<span draggable="true">&#x2195;</span></li>
        <li class="sort">List Item 10<span draggable="true">&#x2195;</span></li>
    </ul>
    <script>
        let dragging = null;

        document.addEventListener('dragstart', function (event) {
            // as the draggable element is the span
            // the data to be dragged is the parent element li:
            dragging = event.target.parentNode;
            event.dataTransfer.setData('text/html', dragging);
            // create a copy of the dragging element as drag image:
            dragImg = dragging.cloneNode(true);
            dragImg.style.left = '-9999px';
            document.querySelector('ul').appendChild(dragImg);
            event.dataTransfer.setDragImage(dragImg,
                dragging.offsetWidth, dragging.offsetHeight / 2);
        });

        document.addEventListener('dragover', function (event) {
            event.preventDefault();
        });

        document.addEventListener('dragenter', function (event) {
            // if the element being entered is the span
            // the element the border has to be applied to
            // is the parent element li:
            let ele = event.target;
            if (ele.matches('span')) {
                ele = ele.parentNode;
            }
            ele.style['border-bottom'] = 'solid 4px blue';
        });

        document.addEventListener('dragleave', function (event) {
            // if the element being entered is the span
            // the element where the border has to be removed
            // is the parent element li:
            let ele = event.target;
            if (ele.matches('span')) {
                ele = ele.parentNode;
            }
            ele.style['border-bottom'] = '';
        });

        document.addEventListener('drop', function (event) {
            event.preventDefault();
            // if the target is the span
            // the element where the dragged element
            // has to be inserted
            // is the parent element li:
            let ele = event.target;
            if (ele.matches('span')) {
                ele = ele.parentNode;
            }
            ele.style['border-bottom'] = '';
            ele.parentNode.insertBefore(dragging, ele.nextSibling);
        });
    </script>

</body>


</html>
Das Styling dann hübsch zu machen wie bei Kendo dürfte das kleinere Problem sein.
 
Moin Ulrich,
ich hab das mal überflogen, und kurz damit herum gespielt.
Zumindest mal mit dem ersten Teil.
Das funktioniert leider nur mit Fotos. Texte, Tabellen, usw. funktionieren nicht,
und genau die ( mit enthaltenen Variablen ) brauche ich ja...
 
Guten Morgen Volker,
das Beispiel ist schon mit Fotos aber mit kleinen Anpassungen wird es sicher auch für andere HTML-Elemente funktionieren. Ich werde mir das demnächst ansehen.
Du schreibst von Tabellen, bisher bin ich von dem Beispiel mit Kendo aus gegangen, da sind es ja reine Texte. Wird sich daran noch etwas ändern?
 
Huch, schon so früh wach? :-D

Nein, da ändert sich nichts.
Die "Items", die ich per Drag & Drop verschieben ( klonen ) möchte, sind letztendlich
kleine, optisch ansprechende Tabellen. Jedes Item ist eine Tabelle. Diese Tabellen werden mit einer foreach-Schleife erzeugt, da es - je nach Umfang der Datenbank - auch mal ein paar mehr sein können.
Innerhalb dieser Tabellen sind Texte, evtl. noch eine kleine Grafik als Icon, und
die erwähnten Variablen. Ziel ist es, im Drop Bereich eine Auswahl der einzelnen Tabellen-Items
in einer sortierbaren Reihenfolge zu haben. So, dass man auch ein Item wieder entfernen kann,
falls es versehentlich dort hingezogen wurde, oder diese Drop-Liste im Nachgang verändert werden muss.

Ich erkläre Dir gern den Hintergrund, vielleicht ist es dann verständlicher:
Bestimmt kennst Du "Funk-Steckdosen". Also die, die man mit einer Fernbedienung ein- und
aus schalten kann. Ich habe viele solcher Steckdosen, die im WLAN sind, und per http-Request
an ihre IP-Adresse geschaltet werden können. Diese Steckdosen stehen nun alle mit ihren IP-Adressen
in einer Tabelle der Datenbank. Jede Steckdose wird ein "Item", mit den enthaltenen Variablen für IP-Adresse, schalt-Kommando, usw.

Mit der foreach-Schleife habe ich nun also alle Steckdosen in der Liste.

Jetzt möchte ich aus dieser Liste heraus die Steckdosen-Items in eine Drop-Liste ziehen können, in einer veränderbaren Reihenfolge. Diese Drop-Liste wird eine "Szene", bekommt einen eigenen Namen, und wird in einer weiteren Tabelle der Datenbank gespeicht. In dieser Szene können also beliebig viele Items stehen, die natürlich in der Auswahl-Liste verbleiben sollen - des wegen Klonen, und nicht verschieben.
Dadurch bekomme ich also eine Szene - eine Liste von Items, deren Schaltbefehle nacheinander abgearbeitet werden. Das muss sortierbar, veränderbar sein, die Reihenfolge der Schaltbefehle ist wichtig, die Schaltbefehle selbst natürlich auch - also die Variablen der Steckdosen-Items. Und letztendlich braucht es einen Button, der auf Klick die Reihenfolge der Schaltbefehle korrekt sendet. Diese Szene wird in einer Tabelle der Datenbank gespeichert, muss aber auch genau so wieder editierbar, und auch löschbar sein.

In weiteren Gedanken werden Szenen durch Cronjobs automatisch aufgerufen, durch Sensoren ausgelöst, Szenen erhalten Pausen, Wenn-Dann-Bedingungen, usw. Aber erstmal brauch ich die grundsätzliche Funktionalität, und suche eine Drag & Drop Liste für Texte und Variablen.
 
Coole Sache, zufällig habe ich mich selbst vor kurzer Zeit mit solch einer Funksteckdose beschäftigt. Es ging darum, das Laden eines Smartphones zu steuern, abhängig von seinem Ladezustand.

Immer hilfreich, wenn man über den Hintergrund informiert ist, wo sich das abspielt. Wenn ich das richtig verstehe, ist ein Item, das verschoben werden soll, solch eine kleine Tabelle. Und es gibt eine ganze Anzahl dieser Tabellen.

Ich habe in der Zwischenzeit die Demo für das Drag&Drop auf eine etwas allgemeinere Version umgestellt, wo man Listenelemente verschieben und klonen kann:
Code:
<!DOCTYPE html>
<html lang="nl">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>Draggable List Elements</title>
    <style>
        .dest-ul {
            cursor: pointer;
            min-height: 1.5em;
            border: 2px solid lightblue;
        }
    </style>
</head>

<body>
    <ul class="dest-ul" style="padding:25px;"></ul>
    <ul class="dest-ul" style="padding:25px;"></ul>
    <ul class="dest-ul" style="padding:25px;"></ul>

    <ul id="photos">
        <li id="li-item-1" class="li-item" draggable="true">
            Item 1
        </li>
        <li id="li-item-2" class="li-item" draggable="true">
            Item 2
        </li>
        <li id="li-item-3" class="li-item" draggable="true">
            Item 3
        </li>
    </ul>
    <script>
        document.querySelectorAll('.li-item').forEach(item => {
            item.addEventListener('dragstart', event => {
                event.dataTransfer.setData('text/plain', event.target.id);
            });
        });
        document.querySelectorAll('.dest-ul').forEach(item => {
            item.addEventListener('dragover', (event) => {
                event.preventDefault();
                event.target.style.border = '2px solid lightblue';
            });
            item.addEventListener('dragleave', (event) => {
                event.preventDefault();
                event.target.style.border = '';
            });
            item.addEventListener('drop', event => {
                event.preventDefault();
                const
                    idDestElem = event.target.id,
                    idItem = event.dataTransfer.getData('text/plain');
                console.log('ID des Elementes=' + idItem + ', ID des Zielelementes=' + idDestElem);
                event.target.insertAdjacentElement(
                    'beforeend', document.getElementById(idItem).cloneNode(true));
                event.target.style.border = '';
            });
        });
    </script>
</body>

</html>
 
Hallo Ulrich,

Ich kann immer nur zwischen Tür und Angel mal schauen, hab viel zu tun.
Hab da jetzt mal ein wenig mit herum gespielt, es funktioniert - aber nur zum Teil.
Ich muss wieder ausholen... Huiuiui. Ne Menge Probleme
Also, das Item - also die Tabelle - sieht erweitert in Deinem Script so aus:
Code:
<form action="index.php?page=drag_send" method="post">
    <ul class="dest-ul" style="padding:25px;"></ul>
    <ul class="dest-ul" style="padding:25px;"></ul>
    <ul class="dest-ul" style="padding:25px;"></ul>

    <ul id="photos">
        <li id="li_item_1" class="li_item" draggable="true">
            Item 1
        </li>
        <li id="li_item_2" class="li_item" draggable="true">
            Item 2
        </li>
        <li id="li_item_3" class="li_item" draggable="true">
            Item 3
        </li>
        <?
            foreach ($db_akt_benutzer as $aktor) {
            $li_item = 'li_item_$aktor["id"]';
            ?>
                <table id="$li_item" class="li_item" border="1" draggable="true" bgcolor="#CECECE">
                 <tr>
                  <td colspan="3">Name: <?="$aktor[name]";?> - ID: <?="$aktor[id]";?></td>
                 <tr>
                 <tr>
                  <td><input type=radio name=action value=on>AN </td>
                  <td><input type=radio name=action value=off>AUS </td>
                  <td><input type=radio name=action value=toggle>TOGGLE </td>
                  <input type="hidden" name="aktor_id" value="<?="$aktor[id]";?>">
            <input type="hidden" name="name" value="<?="$aktor[name]";?>">
            <input type="hidden" name="action" value="">
            <input type="hidden" name="bright" value="">
                 </tr>
                 <?
                     if("$aktor[typ]" == "dimmer") {
                    ?>
                        <tr>
                         <td colspan="3">
                            <input type="radio" name="action" value="dim">DIMM &nbsp;&nbsp;<input type="range" min="0" max="98" step="1" value="50" id="foo" name="bright" onchange='document.getElementById("bar").value = "Slider Value = " + document.getElementById("foo").value;'/>
                         </td>
                        </tr>
                    <?
                    }
                 ?>
                </table><br>
            <?
            }
        ?>
       
    </ul>
<input value="speichern" class="button" type="submit" tabindex="3">
</form>

Ist nicht schön, mir geht's erstmal um Funktionalität.
Jetzt werden also alle Items untereinander angezeigt, so weit, so gut.

1. Problem:
Die Radio-Buttons in den Items arbeiten jetzt Item-übergreifend über alle Items.
Schalte ich in irgendeinem Item einen Radio Button, wird ein anderer Button in einem
anderen Item entfernt. So ein Mist. :-(

2. Problem:
Jedes Item hat eigentlich eine eigene ID. Ich kann die Items zwar in die 3 Felder ziehen,
dort angekommen ändern sie aber alle ihre ID auf 1. ???!!!???

3. Problem:
Wenn ich die Form absende, kommt bei [action] und bei [bright] natürlich keine Variable an.
Nur [name] und [id] - wohl wegen der Radio-Buttons, aber das ist ja auch wieder blöd.
Wenn mehrere Items in der Liste vorhanden sind, kommt am Ende nur ein Item an.
Wie kriege ich denn da alle rein? Man weiß ja vorher nicht, wieviele es sind....
Da muss ich dann eine Schleife nehmen, oder?
Oder ist das alles doof, und man speichert die Szene dann gleich in der Datenbank?
Dann muss ich ja aber auch alle Aktoren speichern, die ich in die Liste gezogen habe.....

Puuuuuuh... das artet schon wieder aus.
Ich glaube, ich brauche einen neuen Ansatz.
 
Zuletzt bearbeitet:
Zurück