How to achieve this? In an HTML page, there is a p tag with some content (but only with indentations through and new line tags <br>). I'd like to offer two buttons: one to convert the p tag into a text area so that the existing content can be adapted by the user, one to copy the content (if the content was not adapted, the original content should be copied, if adapted, certainly the adapted code should be copied). I have prepared the code below so far. The final functionality should be (most of it not working/implemented in the snippet; the solution should be JS only):
Any further ideas? Thanks!
<button onclick="edit(this)">Adapt</button>
<p>some text 1<br> some text 2<br> some text 3 some text 4 && .... <br> ..... <br> ...... <br> ...... <br>...... <br><br></p>
<button title="Copy to clipboard" onclick="copy_text(this)">Copy</button>
<script>
function edit(item) {
var a = item.nextElementSibling;
a.outerHTML = a.outerHTML.replace(/<p>/g, '<textarea style="width: 100%; height: 100px ">').replace(/<\/p>/g, '</textarea>');
}
</script>
<script>
function copy_text(item) {
const str = item.previousElementSibling.innerText;
const el = document.createElement("textarea");
el.value = str;
el.setAttribute("readonly", "");
el.style.position = "absolute";
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand("copy");
document.body.removeChild(el);
};
</script>
Test it here in StackBlitz
I don't know how you intend finding the p
element an id
or a class
or an attribute
but for this answer I just used the tag.
Check this answer
for why I used the Clipboard API
let original = '';
const buttons = [...document.querySelectorAll('button')];
function edit(button) {
let paragraph = button.nextElementSibling.nextElementSibling;
button.innerText = paragraph.tagName == 'P' ? 'Revert' : 'Adapt';
if (paragraph.tagName == 'P') {
original = paragraph.innerHTML;
const textarea = Object.assign(document.createElement('textarea'), {
innerHTML: paragraph.innerText, // I use the innerText so that the HTML tags will be stripped but the space and new lines will be kept
style: 'width: 100%; height: 100px;' // Style for the textarea
});
paragraph.replaceWith(textarea); // Replace the p tag directly with the new textarea
} else {
const p = Object.assign(document.createElement('p'), {
innerHTML: original
});
paragraph.replaceWith(p);
}
}
function copy_text(button) {
let paragraph = button.nextElementSibling;
const str = paragraph.value || paragraph.innerText;
navigator.clipboard.writeText(str).then(_ => {
if (paragraph.tagName !== 'P') { // To convert the textarea back to the p
const p = Object.assign(document.createElement('p'), {
innerHTML: original // Convert the new lines back to br tag and the spaces to  
});
paragraph.replaceWith(p);
}
button.previousElementSibling.innerText = 'Adapt';
alert('Copied');
}, e => alert(`Failed: ${e}`));
};
// Event Listeners
buttons.forEach(button => button.addEventListener('click', e => {
const buttonType = button.innerText.toLowerCase();
if (['adapt', 'revert'].includes(buttonType)) edit(button);
else if (buttonType == 'copy') copy_text(button);
}));
<h1>Paragraph 1</h1>
<button>Adapt</button>
<button title="Copy to clipboard">Copy</button>
<p>some text 1<br> some text 2<br> some text 3 some text 4 && .... <br> ..... <br> ...... <br> ...... <br>...... <br><br></p>
<h1>Paragraph 2</h1>
<button>Adapt</button>
<button title="Copy to clipboard">Copy</button>
<p>some text 1<br> some text 2<br> some text 3 some text 4 && .... <br> ..... <br> ...... <br> ...... <br>...... <br><br></p>