# JQuery: Problem mit clone beim duplizieren von Tabellenzeilen



## Kryptaesthesie (7. November 2008)

Guten Tag.
Wir haben eine Tabelle und möchten, wenn der Cursor das letzte Textfeld verlässt eine Tabellenzeile anhängen.
Das klappt auch gut, nur wenn wir beim .clone() true mit übergeben, so dass Events auch geklont werden, tritt im IE (im FF nicht) ein Fehler innerhalb des JQuery.js auf (s. Bild im Anhang). Die erste Zeile wird auch im IE noch kopiert, aber bei der dritten Zeile kommt ein Fehler.

Unser Quellcode:

```
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title>
              TabelleClone.htm
        </title>
        <script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
        
        <script language="JavaScript" type="text/javascript">
        <!--
            $(document).ready(function(){
                $("tr:even").css("background-color", "#bbbbff");
                $("input:last").blur(function(){
                    $("tr:last").clone(true).insertAfter("tr:last");
                    var labelNameNeu = $(".labelaufzaehlung:last").html().replace(new RegExp("\\d{1,}"), String(parseInt(new RegExp("\\d{1,}").exec($(".labelaufzaehlung:last").html())[0]) + 1));
                    $(".labelaufzaehlung:last").html(labelNameNeu);                    
                });
            });
        //-->
        </script>    
        <style>
            p { color:blue; margin:8px; }
            b { color:red; }
            table {background:#eeeeee; }
        </style>
                                
      </head>
      <body>
        <table id="testtabelle">
            <thead>
                <tr>
                    <th> </th>
                    <th>Spalte 1</th>
                    <th>Spalte 2</th>                          
                    <th>Spalte 3</th>  
                </tr>
            </thead>
            <tbody>
                <tr id="testtabelle_1">
                    <td>
                        <span id="testtabelle_label_1" class="labelaufzaehlung">1. Zeile</span>
                    </td>    
                    <td>
                        <input type="text" id="testtabelle_spalte1_1" name="testtabelle_spalte1_1" size="10" />
                    </td>
                    <td>
                        <input type="text" id="testtabelle_spalte2_1" name="testtabelle_spalte2_1" size="10" />
                    </td>
                    <td>
                        <input type="text" id="testtabelle_spalte3_1" name="testtabelle_spalte3_1" size="10" />
                    </td> 
                </tr>        
            </tbody>
        </table>
     </body>
 </html>
```

Die IDs der Elemente werden noch nicht aktualisiert. Entferne ich die IDs zum Testen, ändert sich aber nichts daran, dass im FF beliebig viele Zeilen geklont werden können, im IE aber nicht.

Evtl. haben wir lediglich einen Denkfehler gemacht?!
Danke schon mal für eure Hilfe!

Gruß
Gerrit


----------



## Sven Mintel (8. November 2008)

Moin,

die genaue Ursache kann ich dir auch nicht sagen, habe nur einen Lösungsvorschlag 

```
function funktion()
{
  $("tr:last").clone(true).insertAfter("tr:last");
  var labelNameNeu = $(".labelaufzaehlung:last").html().replace(new RegExp("\\d{1,}"), String(parseInt(new RegExp("\\d{1,}").exec($(".labelaufzaehlung:last").html())[0]) + 1));
  $(".labelaufzaehlung:last").html(labelNameNeu);  
          
  $("input:last").one('blur',funktion);
}
        
$(document).ready(
  function()
  {
    $("tr:even").css("background-color", "#bbbbff");
    $("input:last").one('blur',funktion);
  }
);
```





```
$("input:last").one('blur',funktion);
```
 sorgt dafür, dass *funktion* von $('input:last') genau 1x aufgerufen werden kann, ist dies passiert, wird das INPUT von seiner onblur-Aufgabe "entbunden".
Am Ende von *funktion* wird die Eventüberwachung dann wieder hinzugefügt, denn $('input:last') ist ja nun ein anderes Element als eingangs der Funktion.


----------



## Kryptaesthesie (10. November 2008)

Das funktioniert,
vielen Dank soweit


----------



## knusifan (14. November 2008)

Guten Morgen,
ich muss das Thema noch einmal aufgreifen. Leider komme ich doch noch nicht zum Ziel.



Sven Mintel hat gesagt.:


> ```
> $("input:last").one('blur',funktion);
> ```


Kann ich leider nicht verwenden, da an verschiedenen Stellen, aber unterschiedlichen Elementen noch andere onclicks, usw. sein können.


Darum habe ich weiter gesucht und komme immer wieder an dem Punkt an, dass das Name-Attribut beim IE nicht geändert werden kann (im FF schon), wenn das Element, bspw. ein <input>-Feld bereits existiet. Wird es per JS erstellt, klappt das.

Darum dachte ich an den Umweg über ein tmp-Attribut, um es später in "name" zu schreiben - klappt auch nicht.

Ich poste mal meinen Code und evtl. sieht jemand eine Lösung.

```
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
	<head>
    	<title>
      		TabelleClone.htm
    	</title>
		<script type="text/javascript" src="../../api/jquery/jquery-1.2.6.js"></script>
	    
		<script language="JavaScript" type="text/javascript">
    <!--
		
			$(document).ready(function(){    
				$("tr:even").css("background-color", "#bbbbff");    
				$("input:last").blur(zeileDuplizieren);  				
			});	
			
			function zeileDuplizieren(){ 
				// Letzte Tabellenzeile clonen und anhängen
				$("tr:last").clone(true).insertAfter("tr:last");
						
				// Label hochzälen und letztes Label ersetzen
				var labelNameNeu = $(".labelaufzaehlung:last").html().replace(new RegExp("\\d{1,}"), String(parseInt(new RegExp("\\d{1,}").exec($(".labelaufzaehlung:last").html())[0]) + 1));
				$(".labelaufzaehlung:last").html(labelNameNeu); 
				
				//Id hochzählen
				var tabellenSelector = "tbody > tr:last";
				var zeilenId = idWertSetzen($(tabellenSelector), tabellenSelector);
				
				$("#hauptf :input").each(function(i){
					this.name = this.tmp; 
					//this.removeAttr("tmp");
				});

				alert("neue Zeile: \n" + $("tr:last")[0].innerHTML);
			}   
			
			function idWertSetzen(jqueryObjekt, tabellenSelector)
			{
				//debugger;
				var neueZeilenId = "";
				var neueZeilennummer = "";
				for (var i = 0; i < jqueryObjekt.length; i++)
				{
					if (jqueryObjekt[i].id != "" && jqueryObjekt[i].id != undefined)
					{
						neueZeilennummer = parseInt(jqueryObjekt[i].id.match(/\d+$/)[0]) + 1;
						neueZeilenId = jqueryObjekt[i].id.match(/.+_/) + "" + neueZeilennummer;
						//neueZeilenId = jqueryObjekt[i].id.replace(jqueryObjekt[i].id.match(/\d+$/)[0], String(parseInt(jqueryObjekt[i].id.match(/\d+$/)[0]) + 1));
						jqueryObjekt[i].id = neueZeilenId;
					}
					if (jqueryObjekt[i].name != "" && jqueryObjekt[i].name != undefined)
					{
						//debugger;
						neueZeilennummer = parseInt(jqueryObjekt[i].name.match(/\d+$/)[0]) + 1;
						neuerZeilenName = jqueryObjekt[i].name.match(/.+_/) + "" + neueZeilennummer;
						$("#" + neueZeilenId).attr("tmp", neueZeilenId);

						//var neuesNameAttribut = document.createAttribute("name");
						//neuesNameAttribut.nodeValue = neuerZeilenName;
						//document.$("#neuerZeilenName").setAttributeNode(neuesNameAttribut);			
					}
				}		
				tabellenSelector +=  " > *"; 
				if($(tabellenSelector).length > 0)
				{
					idWertSetzen($(tabellenSelector), tabellenSelector);
				}
				return neueZeilenId;
			}
					
	    //-->
	    </script>	
		
	    						
  	</head>
  	<body>
  		<!--  	
  		<table border="1">
		    <tr><td>Row with Index #0</td></tr>
		    <tr><td>Row with Index #1</td></tr>
		    <tr><td>Row with Index #2</td></tr>
		    <tr><td>Row with Index #3</td></tr>
		</table>
  		  	
		<p><b>Test</b> Paragraph.</p>
		<p></p>
  		--> 
	   	<form action="" id='hauptf' name='haupt' method='POST'>  	
	  		<div id="test">
	  			<table id="testtabelle">
	  				<thead>
	  					<tr>
	  						<th> </th>
	  						<th>Spalte 1</th>
	  						<th>Spalte 2</th>  						
	  						<th>Spalte 3</th>  
	  					</tr>
	  				</thead>
	  				<tbody>
	  					<tr id="testtabelle_1">
	  						<td>
	  		    				<span id="testtabelle_label_1" class="labelaufzaehlung">1. Zeile</span>
	  		    			</td>	
	  		    			<td>
	  		    				<input type="text" id="testtabelle_spalte1_1" name="testtabelle_spalte1_1" size="10" />
	  		    			</td>
	  		    			<td>
	  		    				<input type="text" id="testtabelle_spalte2_1" name="testtabelle_spalte2_1" size="10" />
	  		    			</td>
	  		    			<td>
	  		    				<input type="text" id="testtabelle_spalte3_1" name="testtabelle_spalte3_1" size="10" />
	  		    			</td> 
						</tr>		
					</tbody>
				</table>
			</div>	
		</form> 
 	</body>
 </html>
```

Weiß evtl. jemand Rat?
Sinn der ganzen Angelegenheit ist es, eine Zeile zu duplizieren (inkl. aller Attribute, wie auch onclick, onblur, name, etc.) und die Nummerierung im ID und Name-Attribut anzupassen. Die ID kann problemlos gesetzt werden, das funktioniert. Nur "name" geht nicht 

Der HTML-Code kann so in eine HTML-Datei übernommen werden und der JQuery-Pfad muss angepasst werden.


Vielen Dank schon mal für eure Hilfe!
Gruß
Simone


----------



## Sven Mintel (14. November 2008)

knusifan hat gesagt.:


> Kann ich leider nicht verwenden, da an verschiedenen Stellen, aber unterschiedlichen Elementen noch andere onclicks, usw. sein können.




Inwiefern ist das problematisch, mein Workaround hat doch keine Auswirkungen auf onclick....woauchimmer


----------



## Kryptaesthesie (14. November 2008)

Vielen Dank schon mal für deine Mühe Sven! 

Wir bauen unsere Tabelle mal so auf, wie sie später mal aussehen soll, mit den ganzen Funktionalitäten an den Stellen, wo welche sein werden (können) und posten diese später mal.
Vielleicht wird unser Problem dadurch klarer!
Wir hatten erst vor unsere Fragestellung schmaler und übersichtlicher zu halten.

Knusifan und ich arbeiten übrigens in einem Team, darum nicht wundern, wenn von uns beiden zu diesem Problem Fragen kommen 

Gruß
Gerrit


----------

