以下是使用纯 JavaScript 解决问题的一种方法(请记住,这确实需要更改您的 HTML,因为包含您希望复制的 <input> 元素的部分需要一个类名(此处它是"clinicalInformation",但可以根据您自己的要求进行调整 - 记住更改<button> 元素的data-duplicates 属性中保存的选择器):
// the event is passed automagically from the addEventListener()
// method:
function duplicate(event) {
// preventing the clicked-element's default behaviour
// (which in many cases could cause a page reload):
event.preventDefault();
// using Array.prototype.slice, with Function.prototype.call,
// on the NodeList returned by document.querySelectorAll(),
// to create an array of element nodes;
// 'this.dataset.duplicates' retrieves the attribute-value from
// the 'data-duplicates' attribute of the clicked element:
var allCurrent = Array.prototype.slice.call(document.querySelectorAll(this.dataset.duplicates), 0),
// getting the last element from the array of nodes:
toClone = allCurrent[allCurrent.length - 1],
// cloning that node, including its child elements:
clone = toClone.cloneNode(true),
// creating a RegExp (regular expression) literal,
// to match a sequence of one, or more, numbers (\d+)
// followed by the end of the string ($):
reg = /\d+$/,
// creating an 'empty'/unitialised variable for use
// within the (later) loop:
childElems;
// adding the created clone to the allCurrent array:
allCurrent.push(clone);
// using Array.prototype.forEach() to iterate over the
// array, the arguments (names are user-defined):
// - first (here 'fieldset') is the current array element
// over which we're iterating,
// - second (here 'index') is the index of the current
// array element in the array:
allCurrent.forEach(function(fieldset, index) {
// finding all descendant elements contained within
// the current array-element that have a 'name' attribute,
// using a CSS attribute-selector within
// document.querySelectorAll():
childElems = fieldset.querySelectorAll('[name]');
// iterating over those descendant elements in the
// array-like NodeList:
Array.prototype.forEach.call(childElems, function(elem) {
// if the regular expression matches the name (
// RegExp.prototype.test() returning a Boolean true/false
// based on the string matching, or not matching, the
// regular expression) we replace that match with the index
// (from the outer loop), or if not we simply append the
// index to the current name property-value:
elem.name = reg.test(elem.name) ? elem.name.replace(reg, index) : elem.name + index;
});
// navigating from the cloned node to its parent and, using
// Node.insertBefore(), we insert the created clone before
// the nextSibling of that cloned node:
toClone.parentNode.insertBefore(clone, toClone.nextSibling);
});
}
// getting a reference to the element that should trigger
// the duplication:
var addMore = document.getElementById('duplicate');
// adding an event-handler for the 'click' event
// (note the lack of parentheses):
addMore.addEventListener('click', duplicate)
function duplicate(event) {
event.preventDefault();
var allCurrent = Array.prototype.slice.call(document.querySelectorAll(this.dataset.duplicates), 0),
toClone = allCurrent[allCurrent.length - 1],
clone = toClone.cloneNode(true),
reg = /\d+$/,
childElems;
allCurrent.push(clone);
allCurrent.forEach(function(fieldset, index) {
childElems = fieldset.querySelectorAll('[name]');
Array.prototype.forEach.call(childElems, function(elem) {
elem.name = reg.test(elem.name) ? elem.name.replace(reg, index) : elem.name + index;
});
toClone.parentNode.insertBefore(clone, toClone.nextSibling);
});
}
var addMore = document.getElementById('duplicate');
addMore.addEventListener('click', duplicate)
label {
display: block;
}
<!-- here we're using an actual <form> element -->
<form action="#" method="post">
<!-- using a fieldset to group the related fields together -->
<fieldset class="clinicalInformation">
<!-- the <legend> element semantically titles that group
of related fields -->
<legend class="form-title">
Clinical Information
</legend>
<!-- the <label> semantically associates a text-label
with a specific form-element; that form-element
(<input />, <textarea>, <select>) can appear within
the <label>, or the <label> can have a 'for' attribute
equal to the 'id' of the associated element. -->
<label class="form-title">Time Assesed:
<input class="form-field" type="time" name="timeassessd" />
</label>
<label class="form-title">Blood Pressure:
<input class="form-field" type="text" name="bp" />
</label>
<label class="form-title">Pulse:
<input class="form-field" type="date" name="pulse" />
</label>
<label class="form-title">Resp. Rate:
<input class="form-field" type="text" name="breathing" />
</label>
<label class="form-title">Temp:
<input class="form-field" type="text" name="temp" />
</label>
<label class="form-title">SPO<sub>2</sub>:
<input class="form-field" type="text" name="spo2" />
</label>
<label class="form-title">GCS:
<input class="form-field" type="text" name="gcs" />
</label>
<label class="form-title">AVPU:
<input class="form-field" type="text" name="avpu" />
</label>
</fieldset>
<fieldset>
<button id="duplicate" data-duplicates=".clinicalInformation">Add more</button>
</fieldset>
</form>
但是,使用 jQuery,因为您已使用该标签来回答您的问题:
// binding an anonymous click event-handler, using on():
$('#duplicate').on('click', function(event) {
// preventing the default action:
event.preventDefault();
// finding all elements that match the selector from
// the clicked-element's 'data-duplicates' attribute:
var allCurrent = $(this.dataset.duplicates),
// finding the last of those elements:
toClone = allCurrent.last(),
// creating the clone, including the child elements:
clone = toClone.clone(true),
// the regular expression (as above):
reg = /\d+$/;
// adding the clone to the 'allCurrent' collection,
// then iterating over them with each(), getting a
// reference to the index of each element in the collection:
allCurrent.add(clone).each(function(index) {
// finding all descendant elements that have a name attribute,
// updating the 'name' property of each of those found
// elements using prop():
$(this).find('[name]').prop('name', function(i, n) {
// the first argument (here: 'i') is the index of the
// current element in the collection,
// the second (here: 'n') is the current value of the
// current element's property.
// exactly the same as above:
return reg.test(n) ? n.replace(reg, index) : n + index;
});
});
// inserting the clone into the document
// after the toClone element:
clone.insertAfter(toClone);
});
$('#duplicate').on('click', function(event) {
event.preventDefault();
var allCurrent = $(this.dataset.duplicates),
toClone = allCurrent.last(),
clone = toClone.clone(true),
reg = /\d+$/;
allCurrent.add(clone).each(function(index) {
$(this).find('[name]').prop('name', function(i, n) {
return reg.test(n) ? n.replace(reg, index) : n + index;
});
});
clone.insertAfter(toClone);
});
label {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post">
<fieldset class="clinicalInformation">
<legend class="form-title">
Clinical Information
</legend>
<label class="form-title">Time Assesed:
<input class="form-field" type="time" name="timeassessd" />
</label>
<label class="form-title">Blood Pressure:
<input class="form-field" type="text" name="bp" />
</label>
<label class="form-title">Pulse:
<input class="form-field" type="date" name="pulse" />
</label>
<label class="form-title">Resp. Rate:
<input class="form-field" type="text" name="breathing" />
</label>
<label class="form-title">Temp:
<input class="form-field" type="text" name="temp" />
</label>
<label class="form-title">SPO<sub>2</sub>:
<input class="form-field" type="text" name="spo2" />
</label>
<label class="form-title">GCS:
<input class="form-field" type="text" name="gcs" />
</label>
<label class="form-title">AVPU:
<input class="form-field" type="text" name="avpu" />
</label>
</fieldset>
<fieldset>
<button id="duplicate" data-duplicates=".clinicalInformation">Add more</button>
</fieldset>
</form>
参考资料:
- CSS:
- HTML:
- JavaScript:
- jQuery: