Related
How to copy text from a div to clipboard.
What I can do then only get one data in clipboard .
<div id="div1">Text To Copy</div>
<div id="div2">Text To Copy</div>
<div id="div3">Text To Copy</div>
<div id="div4">Text To Copy</div>
<script>
function copyDivToClipboard() {
var range = document.createRange();
range.selectNode(document.getElementById("e.target(id)"));
window.getSelection().removeAllRanges(); // clear current selection
window.getSelection().addRange(range); // to select text
document.execCommand("copy");
window.getSelection().removeAllRanges();// to deselect
}
</script>
You can try it this way. Call the function on onclick event
function copyDivToClipboard(id) {
var range = document.createRange();
range.selectNode(document.getElementById(id));
window.getSelection().removeAllRanges(); // clear current selection
window.getSelection().addRange(range); // to select text
document.execCommand("copy");
window.getSelection().removeAllRanges();// to deselect
alert("Text Copied: "+range);
}
<div id="div1" onclick="copyDivToClipboard(this.id);">Text To Copy div1</div>
<div id="div2" onclick="copyDivToClipboard(this.id);">Text To Copy div2</div>
<div id="div3" onclick="copyDivToClipboard(this.id);">Text To Copy div3</div>
<div id="div4" onclick="copyDivToClipboard(this.id);">Text To Copy div4</div>
I was also stuck in same kind of problem. I found the solution.
If you want to show the message in the same div do this, just try
function copyDivToClipboard(id) {
var range = document.createRange();
oldvalue = document.getElementById(id).innerHTML;
range.selectNode(document.getElementById(id));
window.getSelection().removeAllRanges(); // clear current selection
window.getSelection().addRange(range); // to select text
document.execCommand("copy");
window.getSelection().removeAllRanges();// to deselect
document.getElementById(id).innerHTML = "Text Copied";
setTimeout(function(){document.getElementById(id).innerHTML = oldvalue }, 2000); //you can change the time
}
<div id="div1" onclick="copyDivToClipboard(this.id);">Text To Copy div1</div>
<div id="div2" onclick="copyDivToClipboard(this.id);">Text To Copy div2</div>
<div id="div3" onclick="copyDivToClipboard(this.id);">Text To Copy div3</div>
<div id="div4" onclick="copyDivToClipboard(this.id);">Text To Copy div4</div>
You can also do this if you are using jQuery
$("div").click(function(e){
var range = document.createRange();
range.selectNode(document.getElementById(e.target.id));
window.getSelection().removeAllRanges(); // clear current selection
window.getSelection().addRange(range); // to select text
document.execCommand("copy");
window.getSelection().removeAllRanges();// to deselect
console.log("Text Copied: "+range);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="div1">Text To Copy1</div>
<div id="div2">Text To Copy2</div>
<div id="div3">Text To Copy3</div>
<div id="div4">Text To Copy4</div>
I think shirshak007 answered. But I would like to share an alternative code snippet to it.
<script>
function CopyToClipboard(id) {
var copyBoxElement = document.getElementById(id);
copyBoxElement.contenteditable = true;
copyBoxElement.focus();
document.execCommand("copy");
copyBoxElement.contenteditable = false;
alert("Text has been copied : " + copyBoxElement.innerHTML)
}
</script>
<div id="div1" onclick="CopyToClipboard(this.id)">Codebay</div>
<div id="div2" onclick="CopyToClipboard(this.id)">Software</div>
I'd like to update element's text dynamically:
<div>
**text to change**
<someChild>
text that should not change
</someChild>
<someChild>
text that should not change
</someChild>
</div>
I'm new to jQuery, so this task seems to be quite challenging for me.
Could someone point me to a function/selector to use?
If it is possible, I'd like to do it without adding a new container for the text I need to change.
Mark’s got a better solution using jQuery, but you might be able to do this in regular JavaScript too.
In Javascript, the childNodes property gives you all the child nodes of an element, including text nodes.
So, if you knew the text you wanted to change was always going to be the first thing in the element, then given e.g. this HTML:
<div id="your_div">
**text to change**
<p>
text that should not change
</p>
<p>
text that should not change
</p>
</div>
You could do this:
var your_div = document.getElementById('your_div');
var text_to_change = your_div.childNodes[0];
text_to_change.nodeValue = 'new text';
Of course, you can still use jQuery to select the <div> in the first place (i.e. var your_div = $('your_div').get(0);).
Update 2018
Since this is a pretty popular answer I decided to update and beautify it a little by adding the textnode selector to jQuery as a plugin.
In the snippet below you can see that I define a new jQuery function that gets all (and only) the textNodes. You can chain of this function as well with for example the first() function.
I do a trim on the text node and check if it's not empty after the trim because spaces, tabs, new lines, etc. are also recognized as text nodes. If you need those nodes too then simple remove that from the if statement in the jQuery function.
I added an example how to replace first text node and how to replace all text nodes.
This approach makes it easier to read the code and easier to use it multiple times and with different purposes.
The Update 2017 (adrach) should still work as well if you prefer that.
As jQuery extension
//Add a jQuery extension so it can be used on any jQuery object
jQuery.fn.textNodes = function() {
return this.contents().filter(function() {
return (this.nodeType === Node.TEXT_NODE && this.nodeValue.trim() !== "");
});
}
//Use the jQuery extension
$(document).ready(function(){
$('#replaceAll').on('click', () => {
$('#testSubject').textNodes().replaceWith('Replaced');
});
$('#replaceFirst').on('click', () => {
$('#testSubject').textNodes().first().replaceWith('Replaced First');
});
});
p {
margin: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="testSubject">
**text to change**
<p>text that should not change</p>
<p>text that should not change</p>
**also text to change**
<p>text that should not change</p>
<p>text that should not change</p>
**last text to change**
</div>
<button id="replaceFirst">Replace First</button>
<button id="replaceAll">Replace All</button>
Javascript (ES) equivalent
//Add a new function to the HTMLElement object so it can be used on any HTMLElement
HTMLElement.prototype.textNodes = function() {
return [...this.childNodes].filter((node) => {
return (node.nodeType === Node.TEXT_NODE && node.nodeValue.trim() !== "");
});
}
//Use the new HTMLElement function
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('#replaceAll').addEventListener('click', () => {
document.querySelector('#testSubject').textNodes().forEach((node) => {
node.textContent = 'Replaced';
});
});
document.querySelector('#replaceFirst').addEventListener('click', function() {
document.querySelector('#testSubject').textNodes()[0].textContent = 'Replaced First';
});
});
p {
margin: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="testSubject">
**text to change**
<p>text that should not change</p>
<p>text that should not change</p>
**also text to change**
<p>text that should not change</p>
<p>text that should not change</p>
**last text to change**
</div>
<button id="replaceFirst">Replace First</button>
<button id="replaceAll">Replace All</button>
Update 2017 (adrach):
It looks like several things changed since this was posted. Here is an updated version
$("div").contents().filter(function(){ return this.nodeType == 3; }).first().replaceWith("change text");
Original answer (Not working for current versions)
$("div").contents().filter(function(){ return this.nodeType == 3; })
.filter(':first').text("change text");
Source: http://api.jquery.com/contents/
See In action
Markup :
$(function() {
$('input[type=button]').one('click', function() {
var cache = $('#parent').children();
$('#parent').text('Altered Text').append(cache);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">Some text
<div>Child1</div>
<div>Child2</div>
<div>Child3</div>
<div>Child4</div>
</div>
<input type="button" value="alter text" />
Just wrap the text you want to change in a span with a class to select.
Doesn't necessarily answer your question I know, but, probably a better coding practice. Keep things clean and simple
<div id="header">
<span class="my-text">**text to change**</span>
<div>
text that should not change
</div>
<div>
text that should not change
</div>
</div>
Voilà!
$('#header .mytext').text('New text here')
<div id="divtochange">
**text to change**
<div>text that should not change</div>
<div>text that should not change</div>
</div>
$(document).ready(function() {
$("#divtochange").contents().filter(function() {
return this.nodeType == 3;
})
.replaceWith("changed text");
});
This changes only the first textnode
For the specific case you mentioned:
<div id="foo">
**text to change**
<someChild>
text that should not change
</someChild>
<someChild>
text that should not change
</someChild>
</div>
... this is very easy:
var div = document.getElementById("foo");
div.firstChild.data = "New text";
You don't state how you want to generalize this. If, say, you want to change the text of the first text node within the <div>, you could do something like this:
var child = div.firstChild;
while (child) {
if (child.nodeType == 3) {
child.data = "New text";
break;
}
child = child.nextSibling;
}
$.fn.textPreserveChildren = function(text) {
return this.each(function() {
return $(this).contents().filter(function() {
return this.nodeType == 3;
}).first().replaceWith(text);
})
}
setTimeout(function() {
$('.target').textPreserveChildren('Modified');
}, 2000);
.blue {
background: #77f;
}
.green {
background: #7f7;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="target blue">Outer text
<div>Nested element</div>
</div>
<div class="target green">Another outer text
<div>Another nested element</div>
</div>
Simple answer:
$("div").contents().filter(function(){
return this.nodeType == 3;
})[0].nodeValue = "The text you want to replace with"
Here is yet another method : http://jsfiddle.net/qYUBp/7/
HTML
<div id="header">
**text to change**
<div>
text that should not change
</div>
<div>
text that should not change
</div>
</div>
JQUERY
var tmp=$("#header>div").html();
$("#header").text("its thursday").append(tmp);
Problem with Mark's answer is that you get empty textnodes aswell. Solution as jQuery plugin:
$.fn.textnodes = function () {
return this.contents().filter(function (i,n) {
return n.nodeType == 3 && n.textContent.trim() !== "";
});
};
$("div").textnodes()[0] = "changed text";
Lots of great answers here but they only handle one text node with children. In my case I needed to operate on all text nodes and ignore html children BUT PRESERVE THE ORDERING.
So if we have a case like this:
<div id="parent"> Some text
<div>Child1</div>
<div>Child2</div>
and some other text
<div>Child3</div>
<div>Child4</div>
and here we are again
</div>
We can use the following code to modify the text only AND PRESERVE THE ORDERING
$('#parent').contents().filter(function() {
return this.nodeType == Node.TEXT_NODE && this.nodeValue.trim() != '';
}).each(function() {
//You can ignore the span class info I added for my particular application.
$(this).replaceWith(this.nodeValue.replace(/(\w+)/g,"<span class='IIIclassIII$1' onclick='_mc(this)' onmouseover='_mr(this);' onmouseout='_mt(this);'>$1X</span>"));
});
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<div id="parent"> Some text
<div>Child1</div>
<div>Child2</div>
and some other text
<div>Child3</div>
<div>Child4</div>
and here we are again
</div>
Here is the jsfiddle of it working
I think you're looking for .prependTo().
http://api.jquery.com/prependTo/
We can also select an element on the
page and insert it into another:
$('h2').prependTo($('.container'));
If an element selected this way is
inserted elsewhere, it will be moved
into the target (not cloned):
<div class="container">
<h2>Greetings</h2>
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
If there is more than one target
element, however, cloned copies of the
inserted element will be created for
each target after the first.
This is an old question but you can make a simple function like this to make your life easier:
$.fn.toText = function(str) {
var cache = this.children();
this.text(str).append(cache);
}
Example:
<div id="my-div">
**text to change**
<p>
text that should not change
</p>
<p>
text that should not change
</p>
</div>
Usage:
$("#my-div").toText("helloworld");
2019 vesrsion - Short & Simple
document.querySelector('#your-div-id').childNodes[0].nodeValue = 'new text';
Explanation
document.querySelector('#your-div-id') is used for selecting the parent (the element which text you are about to change)
.childNodes[0] selects the text node
.nodeValue = 'new text' sets text node value to "new text"
This answer is possibly inspired by Dean Martin's comment. Can't say for sure since I've been using this solution for years now. Just thought I should post this probability here because some people care about it more than the fact that this is the best solution.
Javascript approach. select the parent div and we can use the firstChild.textContent
let myDiv = document.getElementById("parentDiv");
myDiv.firstChild.textContent = "** New Text **"
Here's a recursive way:
function changeInnerText(elm,text,newText) {
if (elm == null) {
return;
}
changeInnerTextHelper(elm.firstChild, text, newText);
}
function changeInnerTextHelper(elm, text, newText) {
if (elm == null) {
return;
}
if (elm.nodeType == 3 && elm.data == text) {
elm.data = newText;
return;
}
changeInnerTextHelper(elm.firstChild, text, newText);
changeInnerTextHelper(elm.nextSibling, text, newText);
}
I am using the following script to copy a div to clipboard. But I am trying to copy multiple divs (DivA + DivB) with the same button, while adding some quotes and brackets around each div. I saw some answers (like this one, and this), but I can't seem to be able to implement them to the current script.
So the output should be like:
"A certain quote" (Author Name).
This is the current script to copy one div.
function copyToClipboard(element) {
var $temp = $("<input>");
$("body").append($temp);
$temp.val($(element).text()).select();
document.execCommand("copy");
$temp.remove();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="divA">
<p>A certain quote</p>
</div>
<div id="divB">
<p>Author Name</p>
</div>
<button onclick="copyToClipboard('#divA')">Copy</button>
The issue is because you're only reading the text from '#divA', as that's the selector passed to the copyToClipboard() function.
To do what you require amend the logic to create a string in the format you require containing the text of both #divA and #divB:
let $divA = $('#divA');
let $divB = $('#divB');
$('button').on('click', e => {
copyToClipboard(`"${$divA.text().trim()}" (${$divB.text().trim()}).`);
});
function copyToClipboard(text) {
var $temp = $("<input>");
$("body").append($temp);
$temp.val(text).select();
document.execCommand("copy");
$temp.remove();
}
textarea {
width: 300px;
height: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="divA">
<p>A certain quote</p>
</div>
<div id="divB">
<p>Author Name</p>
</div>
<button type="button">Copy</button><br /><br />
Paste here to test:<br />
<textarea></textarea>
I'd like to update element's text dynamically:
<div>
**text to change**
<someChild>
text that should not change
</someChild>
<someChild>
text that should not change
</someChild>
</div>
I'm new to jQuery, so this task seems to be quite challenging for me.
Could someone point me to a function/selector to use?
If it is possible, I'd like to do it without adding a new container for the text I need to change.
Mark’s got a better solution using jQuery, but you might be able to do this in regular JavaScript too.
In Javascript, the childNodes property gives you all the child nodes of an element, including text nodes.
So, if you knew the text you wanted to change was always going to be the first thing in the element, then given e.g. this HTML:
<div id="your_div">
**text to change**
<p>
text that should not change
</p>
<p>
text that should not change
</p>
</div>
You could do this:
var your_div = document.getElementById('your_div');
var text_to_change = your_div.childNodes[0];
text_to_change.nodeValue = 'new text';
Of course, you can still use jQuery to select the <div> in the first place (i.e. var your_div = $('your_div').get(0);).
Update 2018
Since this is a pretty popular answer I decided to update and beautify it a little by adding the textnode selector to jQuery as a plugin.
In the snippet below you can see that I define a new jQuery function that gets all (and only) the textNodes. You can chain of this function as well with for example the first() function.
I do a trim on the text node and check if it's not empty after the trim because spaces, tabs, new lines, etc. are also recognized as text nodes. If you need those nodes too then simple remove that from the if statement in the jQuery function.
I added an example how to replace first text node and how to replace all text nodes.
This approach makes it easier to read the code and easier to use it multiple times and with different purposes.
The Update 2017 (adrach) should still work as well if you prefer that.
As jQuery extension
//Add a jQuery extension so it can be used on any jQuery object
jQuery.fn.textNodes = function() {
return this.contents().filter(function() {
return (this.nodeType === Node.TEXT_NODE && this.nodeValue.trim() !== "");
});
}
//Use the jQuery extension
$(document).ready(function(){
$('#replaceAll').on('click', () => {
$('#testSubject').textNodes().replaceWith('Replaced');
});
$('#replaceFirst').on('click', () => {
$('#testSubject').textNodes().first().replaceWith('Replaced First');
});
});
p {
margin: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="testSubject">
**text to change**
<p>text that should not change</p>
<p>text that should not change</p>
**also text to change**
<p>text that should not change</p>
<p>text that should not change</p>
**last text to change**
</div>
<button id="replaceFirst">Replace First</button>
<button id="replaceAll">Replace All</button>
Javascript (ES) equivalent
//Add a new function to the HTMLElement object so it can be used on any HTMLElement
HTMLElement.prototype.textNodes = function() {
return [...this.childNodes].filter((node) => {
return (node.nodeType === Node.TEXT_NODE && node.nodeValue.trim() !== "");
});
}
//Use the new HTMLElement function
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('#replaceAll').addEventListener('click', () => {
document.querySelector('#testSubject').textNodes().forEach((node) => {
node.textContent = 'Replaced';
});
});
document.querySelector('#replaceFirst').addEventListener('click', function() {
document.querySelector('#testSubject').textNodes()[0].textContent = 'Replaced First';
});
});
p {
margin: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="testSubject">
**text to change**
<p>text that should not change</p>
<p>text that should not change</p>
**also text to change**
<p>text that should not change</p>
<p>text that should not change</p>
**last text to change**
</div>
<button id="replaceFirst">Replace First</button>
<button id="replaceAll">Replace All</button>
Update 2017 (adrach):
It looks like several things changed since this was posted. Here is an updated version
$("div").contents().filter(function(){ return this.nodeType == 3; }).first().replaceWith("change text");
Original answer (Not working for current versions)
$("div").contents().filter(function(){ return this.nodeType == 3; })
.filter(':first').text("change text");
Source: http://api.jquery.com/contents/
See In action
Markup :
$(function() {
$('input[type=button]').one('click', function() {
var cache = $('#parent').children();
$('#parent').text('Altered Text').append(cache);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">Some text
<div>Child1</div>
<div>Child2</div>
<div>Child3</div>
<div>Child4</div>
</div>
<input type="button" value="alter text" />
Just wrap the text you want to change in a span with a class to select.
Doesn't necessarily answer your question I know, but, probably a better coding practice. Keep things clean and simple
<div id="header">
<span class="my-text">**text to change**</span>
<div>
text that should not change
</div>
<div>
text that should not change
</div>
</div>
Voilà!
$('#header .mytext').text('New text here')
<div id="divtochange">
**text to change**
<div>text that should not change</div>
<div>text that should not change</div>
</div>
$(document).ready(function() {
$("#divtochange").contents().filter(function() {
return this.nodeType == 3;
})
.replaceWith("changed text");
});
This changes only the first textnode
For the specific case you mentioned:
<div id="foo">
**text to change**
<someChild>
text that should not change
</someChild>
<someChild>
text that should not change
</someChild>
</div>
... this is very easy:
var div = document.getElementById("foo");
div.firstChild.data = "New text";
You don't state how you want to generalize this. If, say, you want to change the text of the first text node within the <div>, you could do something like this:
var child = div.firstChild;
while (child) {
if (child.nodeType == 3) {
child.data = "New text";
break;
}
child = child.nextSibling;
}
$.fn.textPreserveChildren = function(text) {
return this.each(function() {
return $(this).contents().filter(function() {
return this.nodeType == 3;
}).first().replaceWith(text);
})
}
setTimeout(function() {
$('.target').textPreserveChildren('Modified');
}, 2000);
.blue {
background: #77f;
}
.green {
background: #7f7;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="target blue">Outer text
<div>Nested element</div>
</div>
<div class="target green">Another outer text
<div>Another nested element</div>
</div>
Simple answer:
$("div").contents().filter(function(){
return this.nodeType == 3;
})[0].nodeValue = "The text you want to replace with"
Here is yet another method : http://jsfiddle.net/qYUBp/7/
HTML
<div id="header">
**text to change**
<div>
text that should not change
</div>
<div>
text that should not change
</div>
</div>
JQUERY
var tmp=$("#header>div").html();
$("#header").text("its thursday").append(tmp);
Problem with Mark's answer is that you get empty textnodes aswell. Solution as jQuery plugin:
$.fn.textnodes = function () {
return this.contents().filter(function (i,n) {
return n.nodeType == 3 && n.textContent.trim() !== "";
});
};
$("div").textnodes()[0] = "changed text";
Lots of great answers here but they only handle one text node with children. In my case I needed to operate on all text nodes and ignore html children BUT PRESERVE THE ORDERING.
So if we have a case like this:
<div id="parent"> Some text
<div>Child1</div>
<div>Child2</div>
and some other text
<div>Child3</div>
<div>Child4</div>
and here we are again
</div>
We can use the following code to modify the text only AND PRESERVE THE ORDERING
$('#parent').contents().filter(function() {
return this.nodeType == Node.TEXT_NODE && this.nodeValue.trim() != '';
}).each(function() {
//You can ignore the span class info I added for my particular application.
$(this).replaceWith(this.nodeValue.replace(/(\w+)/g,"<span class='IIIclassIII$1' onclick='_mc(this)' onmouseover='_mr(this);' onmouseout='_mt(this);'>$1X</span>"));
});
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<div id="parent"> Some text
<div>Child1</div>
<div>Child2</div>
and some other text
<div>Child3</div>
<div>Child4</div>
and here we are again
</div>
Here is the jsfiddle of it working
I think you're looking for .prependTo().
http://api.jquery.com/prependTo/
We can also select an element on the
page and insert it into another:
$('h2').prependTo($('.container'));
If an element selected this way is
inserted elsewhere, it will be moved
into the target (not cloned):
<div class="container">
<h2>Greetings</h2>
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
If there is more than one target
element, however, cloned copies of the
inserted element will be created for
each target after the first.
This is an old question but you can make a simple function like this to make your life easier:
$.fn.toText = function(str) {
var cache = this.children();
this.text(str).append(cache);
}
Example:
<div id="my-div">
**text to change**
<p>
text that should not change
</p>
<p>
text that should not change
</p>
</div>
Usage:
$("#my-div").toText("helloworld");
2019 vesrsion - Short & Simple
document.querySelector('#your-div-id').childNodes[0].nodeValue = 'new text';
Explanation
document.querySelector('#your-div-id') is used for selecting the parent (the element which text you are about to change)
.childNodes[0] selects the text node
.nodeValue = 'new text' sets text node value to "new text"
This answer is possibly inspired by Dean Martin's comment. Can't say for sure since I've been using this solution for years now. Just thought I should post this probability here because some people care about it more than the fact that this is the best solution.
Javascript approach. select the parent div and we can use the firstChild.textContent
let myDiv = document.getElementById("parentDiv");
myDiv.firstChild.textContent = "** New Text **"
Here's a recursive way:
function changeInnerText(elm,text,newText) {
if (elm == null) {
return;
}
changeInnerTextHelper(elm.firstChild, text, newText);
}
function changeInnerTextHelper(elm, text, newText) {
if (elm == null) {
return;
}
if (elm.nodeType == 3 && elm.data == text) {
elm.data = newText;
return;
}
changeInnerTextHelper(elm.firstChild, text, newText);
changeInnerTextHelper(elm.nextSibling, text, newText);
}
I'm trying to find out if it's possible to clone an HTML div with JS, edit it and append it again as a new element. So my source is, for example, this code here:
<div class="wrapper">
<div class="element">
<input id="test--1" value="ABC"/>
</div>
</div>
After copying this element, I need to find a way to change the attribute id of the new cloned input, clear the input value and paste it again in the wrapper so that it looks like this at the end:
<div class="wrapper">
<div class="element">
<input id="test--1" value="ABC"/>
</div>
<div class="element">
<input id="test--2" value=""/>
</div>
</div>
Does that make sense to you? If yes, how can I get this done? Or is it better to assign the content to a variable to append it? I'm looking for the best way here and maybe my idea is a solution too.
You can use pure JavaScript to do this by just cloning the .element div using the cloneNode() method, assign new id and value to the clone div and finally append it back to the document using the insertBefore() method like this:
let x = document.querySelector(".element");
let y = x.cloneNode(true);
y.children[0].id = "test--2";
y.children[0].defaultValue = "";
x.parentNode.insertBefore(y, x.nextSibling);
<div class="wrapper">
<div class="element">
<input id="test--1" value="ABC"/>
</div>
</div>
JSFiddle with the above code: https://jsfiddle.net/AndrewL64/jvc7reza/18/
Based on this answer you could do like:
$('#cloneBtn').on('click', function() {
// get the last input having ID starting with test--
var $inp = $('[id^="test--"]:last'); // Or use :first if you need
// Get parent element
var $div = $inp.closest('.element');
// Create clone
var $div_clone = $div.clone();
// Retrieve number from ID and increment it
var num = parseInt($inp.prop("id").match(/\d+/g), 10) + 1;
// Generate new number and assign to input
$div_clone.find('[id^="test--"]').prop({id: 'test--' + num, value: ''});
// Insert cloned element
$div.after($div_clone); // Or use .before() if you need
});
.element {
padding: 10px;
outline: 2px solid #0bf;
}
<button id="cloneBtn">CLICK TO CLONE</button>
<div class="wrapper">
<div class="element">
<input id="test--1" value="ABC" />
</div>
</div>
Once done inspect the input elements to see the new IDs
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
Scrambled elements, retrieve highest ID, increment, clone, append.
If your numbered IDs are scrambled, we first need a way to retrieve the highest ID number. Here's an implementation in pure JavaScript:
function cloneElement () {
const inpAll = document.querySelectorAll('[id^="test--"]');
if (!inpAll.length) return; // do nothing if no elements to clone
const maxID = Math.max.apply(Math, [...inpAll].map(el => +el.id.match(/\d+$/g)[0]));
const incID = maxID + 1;
const element = document.querySelector('.element'); // Get one for cloning
const eleClone = element.cloneNode(true);
const inpClone = eleClone.querySelector('[id^="test--"]');
inpClone.id = 'test--'+ incID;
inpClone.value = incID; // just for test. Use "" instead
document.querySelector('.wrapper').prepend(eleClone);
}
document.querySelector('#cloneBtn').addEventListener('click', cloneElement);
.element {
padding: 10px;
outline: 2px solid #0bf;
}
<button id="cloneBtn">CLICK TO CLONE</button>
<div class="wrapper">
<div class="element">
<input id="test--1" value="1" />
</div>
<div class="element">
<input id="test--23" value="23" />
</div>
<div class="element">
<input id="test--7" value="7" />
</div>
</div>
Once done inspect the input elements to see the new IDs
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
I don't know what data you know, why you want to do such a thing but it can be done :-)
One way is like that:
const elemToCopy = document.getElementById("test--1").parentNode; // I assume you know id
const copiedElem = elemToCopy.cloneNode(true);
const newInput = copiedElem.querySelector("#test--1");
newInput.id = "test--2";
newInput.value = "";
elemToCopy.parentNode.append(copiedElem);
Let me know in a comment if something is not clear :-)
Yes, use jQuery's .clone().
Here is an example that might be relevant to your situation:
let newElement = $('.element').clone();
newElement.find('input').attr('id', 'test--2').val('');
$('.wrapper').append(newElement);
Explanation
In the first line, we created a new cloned element by using jQuery clone().
Then, we found it's child input, changed it's ID and reset the val().
Finally, we found the .wrapper element and appended the new cloned element to it.