<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script language="javascript" type="text/javascript"> var elemIdCollection = new Array(); let clonecount = 1; function eicConstructor(aOriginalId, aUpdatedId) { this.eOriginalId = aOriginalId; this.eUpdatedId = aUpdatedId; } function cloneCollection(cloneCollection) { elemIdCollection.length = 0; let processRequest = 1; let lastUsedRowCount = 0; if (cloneCollection.indexOf("_") > 0) { cloneCollection = cloneCollection.split("_")[0]; } let cloneContainerTable = new String(cloneCollection); cloneContainerTable = cloneContainerTable.concat("_cloneContainer"); lastUsedRowCount = clonecount; if (processRequest == 1) { if (lastUsedRowCount) { /* Update clone count information */ lastUsedRowCount += 1; clonecount = lastUsedRowCount; /* Clone collection */ let collectionId = new String(cloneCollection); let cloneTDId = new String(cloneCollection); let cloneCollectionId = new String(cloneCollection); collectionId = collectionId.concat("_Instance_1"); cloneTDId = cloneTDId.concat("_CloneTD_1"); cloneCollectionId = cloneCollectionId.concat("_CloneCollection_1"); if (document.getElementById(cloneCollectionId)) { let referenceCollection = document.getElementById(cloneCollectionId); let cloneToClone = referenceCollection.cloneNode(true); let rdos = referenceCollection.querySelectorAll("input[type=radio]:checked"); let nextCollectionId = new String(generateRootId(collectionId, lastUsedRowCount)); let nextcloneTDId = new String(generateRootId(cloneTDId, lastUsedRowCount)); let nextcloneCollectionId = new String(generateRootId(cloneCollectionId, lastUsedRowCount)); let cloneInsertRow = document.getElementById(cloneContainerTable).insertRow(-1); cloneInsertRow.id = nextCollectionId; let cloneContentTD = cloneInsertRow.insertCell(); cloneContentTD.setAttribute("id", nextcloneTDId); cloneContentTD.appendChild(cloneToClone); /* Update Cloned Nodes */ let cloneToUpdate = document.getElementById(nextcloneTDId); let cloneToUpdateElements = cloneToUpdate.querySelectorAll("*"); rdos.forEach(rdoElement => { rdoElement.setAttribute("checked", true); if (rdoElement.hasAttribute("id")) { document.getElementById(rdoElement.getAttribute("id")).checked = true; } }); cloneToUpdateElements.forEach(cloneElem => { let originalId = new String(); let currentId = new String(); if (cloneElem.hasAttribute("id")) { if (cloneElem.getAttribute("id") == cloneCollectionId) { cloneElem.setAttribute("id", nextcloneCollectionId); } else { originalId = cloneElem.getAttribute("id"); currentId = generateIdMarker(cloneElem.getAttribute("id"), lastUsedRowCount); eicAddIds(originalId, currentId); cloneElem.setAttribute("id", currentId); } } if (cloneElem.hasAttribute("for")) { cloneElem.setAttribute("for", generateIdMarker(cloneElem.getAttribute("for"), lastUsedRowCount)); } if (cloneElem.hasAttribute("name")) { let originalName = cloneElem.getAttribute("name"); /* The first clone collection that is cloned starts at 1 */ if (originalName.indexOf("_cln01_") > -1) { let rcf = new String(); let rcc = new String(); let rcSegmentsPre = originalName.split("_cln01_")[0]; let rcSegmentsPost = originalName.split("_cln01_")[1]; if (lastUsedRowCount < 10) { rcc = rcc.concat("_cln0", lastUsedRowCount, "_"); } else { rcc = rcc.concat("_ctl", lastUsedRowCount, "_"); } rcf = rcf.concat(rcSegmentsPre, rcc, rcSegmentsPost); cloneElem.setAttribute("name", rcf); } else if (originalName == originalId) { /* The ID and the NAME may be the same for a form field */ if (currenId.length > 0) { cloneElem.setAttribute("name", currentId); } } else { /* Leave the name unchanged */ } } /* Value Chain */ if (currentId.length > 0) { if (cloneElem.tagName && cloneElem.tagName.length > 0 && currentId.length > 0) { let tn = cloneElem.tagName.toLowerCase(); if (tn == "input") { if ('getAttribute' in cloneElem) { if (cloneElem.getAttribute("type") !== null) { let tt = cloneElem.getAttribute("type").toLowerCase(); if (tt == "text") { if (cloneElem.hasAttribute("value")) { cloneElem.setAttribute("value", ""); } document.getElementById(currentId).value = ""; } else if (tt == "radio" || tt == "checkbox") { if (document.getElementById(currentId).checked == true) { document.getElementById(currentId).checked = false; } } } } } else if (tn == "textarea") { if (cloneElem.hasAttribute("value")) { cloneElem.setAttribute("value", ""); } document.getElementById(currentId).value = ""; } else if (tn == "select") { document.getElementById(currentId).selectedIndex = 0; } } } }); if (Object.keys(elemIdCollection).length) { elemIdCollection.sort((a, b) => b.eUpdatedId.length - a.eUpdatedId.length); } /* Update Node Events */ cloneToUpdateElements.forEach(cloneElem => { let dataSetment = new String(); let dataFinal = new String(); if (cloneElem.tagName && cloneElem.tagName.length > 0) { let rso = cloneElem.tagName.toLowerCase(); if (rso == "select") { let opts = cloneElem.options.length; for (let so = 0; so < opts; so++) { if (cloneElem.options[so].hasAttribute("data-id")) { dataSegment = cloneElem.options[so].getAttribute("data-id"); dataFinal = updateIdMarker(dataSegment); cloneElem.options[so].setAttribute("data-id", dataFinal); } } } } if (cloneElem.hasAttribute("onclick")) { dataSegment = cloneElem.getAttribute("onclick"); dataFinal = updateIdMarker(dataSegment); cloneElem.setAttribute("onclick", dataFinal); } if (cloneElem.hasAttribute("onchange")) { dataSegment = cloneElem.getAttribute("onchange"); dataFinal = updateIdMarker(dataSegment); cloneElem.setAttribute("onchange", dataFinal); } if (cloneElem.hasAttribute("onfocus")) { dataSegment = cloneElem.getAttribute("onfocus"); dataFinal = updateIdMarker(dataSegment); cloneElem.setAttribute("onfocus", dataFinal); } if (cloneElem.hasAttribute("onblur")) { dataSegment = cloneElem.getAttribute("onblur"); dataFinal = updateIdMarker(dataSegment); cloneElem.setAttribute("onblur", dataFinal); } if (cloneElem.hasAttribute("onkeypress")) { dataSegment = cloneElem.getAttribute("onkeypress"); dataFinal = updateIdMarker(dataSegment); cloneElem.setAttribute("onkeypress", dataFinal); } if (cloneElem.hasAttribute("onkeyup")) { dataSegment = cloneElem.getAttribute("onkeyup"); dataFinal = updateIdMarker(dataSegment); cloneElem.setAttribute("onkeyup", dataFinal); } }); } else { alert("ERROR 1 Found."); } } } else { alert("ERROR 2 Found."); } } function eicAddIds(aOriginalId, aUpdatedId) { if (Object.keys(elemIdCollection).length) { /* Do not capture duplicate Ids */ let dupState = 0; for (d = 0; d < elemIdCollection.length; d++) { if (aOriginalId == elemIdCollection[d]) { dupState = 1; break; } } if (dupState == 0) { elemIdCollection[elemIdCollection.length] = new eicConstructor(aOriginalId, aUpdatedId); } } else { elemIdCollection[0] = new eicConstructor(aOriginalId, aUpdatedId); } } function generateRootId(id, lastCount) { let nextCollectionId = new String(); var segments = id.split("_"); for (var s = 0; s < (segments.length - 1); s++) { if (nextCollectionId.length > 0) { nextCollectionId = new String().concat(nextCollectionId, "_", segments[s].toString()); } else { nextCollectionId = new String().concat(nextCollectionId, segments[s].toString()); } } nextCollectionId = new String().concat(nextCollectionId, "_", lastCount); return nextCollectionId; } function generateIdMarker(id, lastCount) { let nextCollectionId = new String(); nextCollectionId = new String().concat(id, "_", lastCount); return nextCollectionId; } function updateIdMarker(dataMarker) { let revisedMarker = new String(dataMarker); if (Object.keys(elemIdCollection).length) { let cStep = 0; let revisedSequence = new String(); let foundOccurrances = []; for (let i = 0; i < elemIdCollection.length; i++) { let originalId = new String(elemIdCollection[i].eOriginalId); let posBeginSearch = 0; while(dataMarker.indexOf(originalId, posBeginSearch) != -1) { let nrec = true; let oFound = dataMarker.indexOf(originalId, posBeginSearch); if (foundOccurrances.length > 0) { for (let e = 0; e < foundOccurrances.length; e++) { let p = foundOccurrances[e].matchLocation; if (p == oFound) { nrec = false; } } } if (nrec == true) { foundOccurrances.push({"originalId": i, "matchLocation": oFound}); } posBeginSearch = oFound + 1; } } if (foundOccurrances.length > 0) { foundOccurrances.sort((a, b) => a.matchLocation - b.matchLocation); for (let f = 0; f < foundOccurrances.length; f++) { let fId = foundOccurrances[f].originalId; let fOriginalId = elemIdCollection[fId].eOriginalId; let fUpdateId = elemIdCollection[fId].eUpdatedId; let fPos = foundOccurrances[f].matchLocation; for (let c = cStep; c < dataMarker.length; c++) { if (c < fPos) { revisedSequence = revisedSequence.concat(dataMarker[c]); } else if (c == fPos) { cStep = c + fOriginalId.length; revisedSequence = revisedSequence.concat(fUpdateId); break; } } } if (cStep < dataMarker.length) { for (let e = cStep; e < dataMarker.length; e++) { revisedSequence = revisedSequence.concat(dataMarker[e]); } } revisedMarker = revisedSequence; } } return revisedMarker; } </script> </head> <body> <strong>Block To Clone:</strong><br /> HTML elements in the block are cloned. If any values or choices are made, those are not kept in the clone because it is a new block that, it is assumed, may need to have different values/choices. Unique element names and ids are created for the cloned block and if the original block had events associated to it (like onclick), the parameter values of those events are automatically updated for the new names and ids of form elements in the cloned block they would relate to. <hr /> <table id="cloneBase_cloneContainer" width="100%"> <tbody> <tr id="cloneBase_Instance_1"> <td width="100%" valign="top" id="cloneBase_CloneTD_1"> <!-- The data that gets cloned starts here --> <table id="cloneBase_CloneCollection_1"> <tbody> <tr id="cloneTr1"> <td id="td1" name="tdone"> <hr /> <label id="Label" name="anything_cln01_Label" style="color:#FF0000;">Some label text.</label> </td> <td></td> </tr> <tr id="cloneTr2"> <td id="td2" name="tdtwo"> <span>Enter some text:</span> <input type="text" id="ExistResName" name="anInputbox_cln01_Input" onblur="javascript:alert('ExistResName');"> <br /> <input type="hidden" id="hid1" name="hidone" value="abcd"> <input type="radio" id="rdo1" name="radiobtn_cln01_circle"> Radio button 1<br /> <input type="radio" id="rdo2" name="radiobtn_cln01_circle"> Radio button 2<br /> <input type="checkbox" id="chk1" name="checkboxbtn"> Some checkbox<br /> <span>Some text area to add text:</span><br /> <textarea id="txtarea1" name="txtareaone" cols="10" rows="3">textarea something</textarea><br /> </td> <td></td> </tr> <tr id="cloneTr3"> <td> <label for="someInputBox" name="anythingSecond_cln01_Label">Provide new name</label> </td> <td> <input type="text" id="someInputBox" name="anotherInputbox_cln01_InputFresh"> </td> </tr> <tr id="cloneTr4"> <td> <label for="someSelectBox" name="aSelectbox_cln01_Label">Selecting option will alert the current TR id this select is in.</label> </td> <td> <select id="someSelectBox" name="aSelectbox_cln01_Choices" onchange="javascript:alert('cloneTr4');"> <option value="--Select One--">--Select One--</option> <option value="Choice1">Choice1</option> <option value="Choice2">Choice2</option> <option value="Choice3">Choice3</option> </select> </td> </tr> </tbody> </table> </td> </tr><!-- End of Instance 1. Clone inserted as the next TR block. --> </tbody> </table> <hr /> <input type="button" id="cloneBase_Add" name="cloneBase_Add" value="Clone Block" onclick="javascript:cloneCollection(this.id);"> </body> </html>