maebinger: bei cloneNode eine ID hochzählen lassen

Hallo,

ich bin nicht wirklich bewandert in Javascript, aber hin und wieder benötige ich es dann doch. Ich möchte eine Tabellenzeile kopieren und einfügen per Buttonklick. Das hab ich soweit auch hinbekommen mit CloneNode.

Da ich in meinem PHP-Skript aber auch noch eine id (benutzer) im Formluar habe, die ich wiederum abfrage für ein ComboDropdown Feld bräuchte ich noch eine Funktion/Möglichkeit das diese genannte ID pro Klick um eins hochgezählt wird.

Ich stell mir das so vor: zuerst id='benutzer', 1. Klick id='benutzer1', 2. Klick id='benutzer2' Hoffe ihr versteht was ich meine/suche.

Bin für jede Unterstützung dankbar.

Vielen Dank

maebinger

function clone_this(button, objid){
    // Tabelle innerhalb des DIVs mit ID "new_passage" clonen
    // Achtung: Es dürfen keine Zeichen zwischen dem DIV- und dem TABLE-Tag stehen!
    var clone_me = document.getElementById(objid).firstChild.cloneNode(true);
    // Im Parent-DIV vor dem Kindknoten "button" einhängen
    button.parentNode.insertBefore(clone_me, button);
}
<form method='post' id='request' name='request'>
	<div id='new_passage'><table name='cloneTable' width='1500px' align='center' border='0'>
		<tr>
			<td height='30px' width='150px' align='center'><select name='typ[]' style='width:150px;'>
				<option value='Filesystem'>Dateisystem</option>
				<option value='PublicFolder'>öffentliche Ordner</option>
			</select></td>
			<td height='30px' width='410px' align='center'><input type='text' name='foldername[]' placeholder='Ordnername' style='width:400px' autocomplete='off'></td>
			<td width='310px' align='center'><input type='text' name='username[]' id='benutzer' placeholder='Name des Mitarbeiters' autocomplete='off'></td>
			<td width='310px' align='center'><select name='amt[]'>
			   <option value=''>...bitte Abteilung wählen...</option>
			</select>
			</td>
		</tr>
</table>
<table width='1500px' align='center' border='0'>
		<tr>
			<td><div><input value='weitere Zeile hinzufügen' onclick=\"javascript:clone_this(this, 'new_passage');\" type='button' style='margin-left:1190px;background:#900;color:white;'></input></div></td>
		</tr>
</table>
</form>
  1. Hallo maebinger,

    Wozu brauchst du die id? Die wird ohnehin nicht gepostet. Hast du anderweitige Skripte auf der Seite, die die id brauchen?

    Wirklich gebraucht werden IDs für die Zuordnung von Eingabefeldern und <label> Elementen, das ist etwas, was dir noch ganz fehlt. Placeholder sind kein Ersatz.

    Ich sitze an Handy und kann jetzt keinen Code schreiben. Kommt später, es sei denn, jemand drängelt sich vor.

    Dass deine clone Funktion Chaos im DOM (die HTML Elementstruktur) stiftet, ist dir vielleicht nicht klar? Du fügst den Klon direkt vor dem Button ein, innerhalb der Row. Bestimmt ist das nicht der Plan.

    Vielleicht könntest du mal skizzieren (nur das nötigste), wie du dir das DOM nach der Klon Operation vorstellst. Dass es dann noch Dinge zu tunen gibt, ist eine weitere Baustelle.

    Ich empfehle dir aber dringend, die Grundlagen neu zu erarbeiten. Guck in unser Wiki, da gibt's HTML Grundkurse. Einiges wirst du überlesen können, vieles aber nicht. Vor allem solltest du Gestalten mit CSS lernen. Im Moment sieht dein Code aus wie von 1999.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      vielen Dank schon mal für die Infos...

      Die ID's benötige ich weil ein weiteres "Skript" eine eindeutige ID benötigt um hier ne Ausgabe zu starten. Das ist an sich der ganze komm her :)

      Nein, haste Recht das die Clone Funktion Chaos stiftet ist mir nicht bewusst :) Hab ich noch nix davon mitbekommen :) Inwiefern soll ich das skizzieren?

      Was ich möchte:

      • ich brauche eine Möglichkeit das in meinem PHP Skript eine Tabellenzeile hinzufügt. Ich hab da auch selects drin mit DB Abfrage. ne möglichkeit hier
      • das hochzählen der ID's wäre "nett". Ich hab halt an der ID noch ein Skript das quasi ne DB Suchfunktion ist (Dropdown).

      Wenn das von 1999 ist... bin halt anscheinend doch ein Nostalgiker ;)

      Vielen Dank nochmals

      1. Hallo maebinger,

        ich brauche eine Möglichkeit das in meinem PHP Skript eine Tabellenzeile hinzufügt.

        Was denn jetzt? Im PHP oder mit JavaScript? Wenn Du das mit PHP machen willst, musst Du den Einfüge-Auftrag per POST an den Server schicken, der speichert dann eventuelle Änderungen in den bestehenden Zeilen, baut das HTML mit einer weiteren Zeile auf und gibt es wieder aus.

        Die ID's benötige ich weil ein weiteres "Skript" eine eindeutige ID benötigt um hier ne Ausgabe zu starten. Ich hab halt an der ID noch ein Skript das quasi ne DB Suchfunktion ist (Dropdown).

        In dem Fall muss die ID aber in der DB existieren, und das heißt: Dein Server muss die ID kennen. Damit ist eine Suche erst dann sinnvoll, wenn der Inhalt einer neuen Zeile einmal gespeichert worden ist, und die ID muss, denke ich, die ID der Person in deiner DB sein. Eine ID-Vergabe aus JavaScript heraus scheint mir nicht zielführend. Du könntest die Personen-ID im PHP als data-Attribut an das tr-Element der jeweiligen Zeile setzen.

          <tr data-id="4711">
          </tr>
        

        In dem Script, das die Suche durchführt (wenn es denn JavaScript ist), kannst Du das tr-Element aufsuchen und mit trElement.dataset.id auf das data-id Attribut zugreifen.

        das die Clone Funktion Chaos stiftet ist mir nicht bewusst :) Inwiefern soll ich das skizzieren?

        Na, ich skizziere mal für Dich. Deine HTML Struktur ist: (das </input>-Tag habe ich weggelassen, das gibt es nicht, <input> ist ein Element ohne Ende-Tag)

        <form>
          <div id="new_passage">
            <table name="cloneTable">
              <tbody>
                <tr>...</tr>
              </tbody>
            </table>
        ********************* hier fehlt ein </div>, würde ich vermuten
            <table>
              <tbody>
                <tr>
                  <td>
                    <div>
                      <input value="weitere Zeile" onclick="...">
                    </div>
                  </td>
                </tr>
        ********************* hier fehlt ein </tbody>
            </table>
        </form>
        

        Dein Clone-Button nimmt das erste Kind von new_passage, also die cloneTable, und fügt es vor dem "weitere Zeile" Button ein. Das Ergebnis ist (die neuen Zeilen habe ich vorn mit # markiert):

        <form>
          <div id="new_passage">
            <table name="cloneTable">
              <tbody>
                <tr>...</tr>
              </tbody>
            </table>
            <table>
              <tbody>
                <tr>
                  <td>
                    <div>
        #             <table name="cloneTable">
        #               <tbody>
        #                 <tr>...</tr>
        #               </tbody>
        #             </table>
                      <input value="weitere Zeile">
                    </div>
                  </td>
                </tr>
            </table>
        </form>
        

        Und das willst Du wohl ganz bestimmt nicht. Eine bessere Struktur wäre:

        <form>
          <div id="new_passage">
            <table>
              <tbody>
                <tr id="clone_source">...</tr>
              </tbody>
              <tfoot>
                <tr>
                  <td colspan="3"></td>
                  <td><button type="button" id="clone_button">Weitere Zeile"</button></td>
                </tr>
              </tfoot>
            </table>
        </form>
        
        <script>
           const cloneSource = document.getElementById("clone_source");
           document.getElementById("clone_button")
                   .addEventListener("click", function(event) {
              const clone_me = cloneSource.cloneNode(true);
              cloneSource.parentElement.append(clone_me);
           });
        </script>
        

        Damit hast Du

        • kein onclick mehr im HTML, sondern ''unobtrusive JavaScript''
        • eine bessere HTML Struktur, weil Du nur eine Table hast und nicht die Spaltenbreiten zweier Tables synchron halten musst
        • kein Gefummel mit Margins, damit der Button halbwegs unter der letzten Spalte steht
        • lediglich den Klon einer Zeile, und nicht einer ganzen Table

        Was es mit deiner divitis auf sich hat, kann ich nicht beurteilen, aber jedes "Hüll-div" ist erstmal eins zu viel und muss seine Existenz rechtfertigen. Ich kenne deine Seite nicht und muss diese Beurteilung deshalb Dir überlassen. Grundsätzlich kannst Du aber auch einer table eine id geben, du kannst Tables und td-Elemente mit Farben und Rändern versehen - dafür brauchst Du keine divs. Bei jedem div, das Du einbaust, musst Du aufpassen, wo Du es wieder schließt. In deinem HTML hast Du das new_passage-div jedenfalls nicht geschlossen.

        Ein weiterer Hinweis: In deinem Code steht:

           onclick=\"javascript:clone_this(this, 'new_passage');\" 
        

        und das riecht danach, dass Du im PHP dein HTML mit echo ausgibst. Tu das nicht, du siehst ja genau an dieser Stelle das Problem: Du escapest Dich irgendwann zu Tode. Die korrekte Lösung ist: Schließe den PHP-Modus mit ?>, schreib das benötigte HTML hin und beginne danach mit <?php den PHP Modus neu. Wenn Du innerhalb des HTML Blocks eine PHP Variable brauchst, verwende <?= ... ?>. Wenn Du einen brauchbaren Editor hast, erkennt der das und besorgt Dir sowohl für PHP wie auch für HTML ein ordentliches Syntax-Highlighting und ggf. auch Code-Folding (ausblenden von Unterstrukturen).

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Hallo Rolf,

          ich glaube da hab ich mich dann ein wenig falsch ausgedrückt. Javascript war mein Ziel (das in meinem PHP eingebettet wird). In dem Fall soll es direkt funktionieren, nicht noch umständlich mit POST oder GET. Sorry.

          Zu der Geschichte mit der ID. <input type='text' name='username[]' id='benutzer' placeholder='Name des Mitarbeiters' autocomplete='off'> diese ID (benutzer) soll pro weiterer Zeile um eins erhöht werden.

          Ich habe wie gesagt ein weiteres JavaSkript das dann zum tragen kommt.

          $(function(){
          	// ############################# Softwareliste ######################################
          	// Software Ansprechpartner1
              $('#benutzer').autocomplete('autocomplete/mysql_suche.php?mode=benutzer', {
                  width: 300,
                  max: 20
              });
          

          die weiterleitung:

          <?php
          @$mode		=	  $_GET['mode'];
          require_once('CMySQL.php');
          $sParam = $GLOBALS['MySQL']->escape($_GET['q']); // escaping external data
          if (! $sParam) exit;
          switch ($mode) {
              case 'benutzer': // Usersuche
          		$sRequest = "SELECT name,vname,user FROM userlist WHERE user LIKE '%{$sParam}%' OR name LIKE '%{$sParam}%' OR vname LIKE '%{$sParam}%' ORDER BY name";
          		$aItemInfo = $GLOBALS['MySQL']->getAll($sRequest);
          		foreach ($aItemInfo as $aValues) {
          			echo $aValues['name']." ".$aValues['vname']." (".$aValues['user'].")\n";
          		}
          	break;
          }	
          ?>
          

          so bekomme ich den dropdown und darum benötige ich den Zähler bei der ID. Wenn du noch ne andere Idee oder Lösung hast... Ich find das mit dem Dropdown halt angenehm, weil ich das noch "lesen" kann und zumindest halbwegs verstehe nicht so wie diverse andere Skripte in Javascript oder JQuery.

          Zu dem skizzieren, jetzt hab ich ungefähr verstanden wie du es gemeint hast :) Ja deine Skizze sieht natürlich besser aus. Aber wenn man nicht vom Fach ist... baut man sich seine eigene Welt und sitzt auch gerne mal aufm Schlauch :) Unter anderem auch in dem Bezug zu deiner Anmerkung mit onclick... aber sicherheitsrelevant ist das nicht? Oder doch?

          1. Hallo maebinger,

            Okay, verstehe. Du installierst ein jQuery-Plugin auf dem Benutzer-Feld.

            Solche Plugins agieren genau auf dem Feld, auf dem sie installiert werden.

            Das dürfte derzeit bei Dir bereits ein Problem sein, wenn Du die Seite lädst und zwei Zeilen enthalten sind. Denn Du musst beim Laden der Seite das Plugin auf allen Benutzer-Eingabefeldern installieren, und $('#benutzer') liefert nur das erste Element mit dieser ID. Dein autocomplete wirkt dann nur auf der ersten Zeile.

            Besser ist es, wenn Du eine Klasse statt einer ID verwendest, also class="benutzer" und nicht nicht id="benutzer". Verwende dann $(".benutzer") statt $("#benutzer"), dann bekommst Du alle Elemente mit der Klasse Benutzer, und jQuery sollte autocomplete für jedes Element aufrufen.

            Jetzt musst Du autocomplete nur noch für geklonte Zeilen nachinstallieren. Wenn Du den Knoten geklont und ins DOM gehängt hast, dann hast Du die Tabellenzeile, die Du hinzugefügt hast, noch im Zugriff, die steckt in clone_me. Du kannst jQuery sagen, dass es eine Suche nur in einem bestimmten Kontext ausführen soll, dazu verwendest Du einen zweiten Parameter:

            $(".benutzer", clone_me).autocomplete...

            Guckst Du Dokumentation

            Das liefert Dir nur die Elemente mit Klasse benutzer, die im Bereich des Elements in clone_me stehen, und hängt autocomplete da dran.

            Fertig.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Vielen Dank für die Unterstützung... das werde ich mir mal anschauen und versuchen umzusetzen. Ich melde mich wieder wies geklappt hat. Nochmals vielen Dank!