JavaScript undo-buffer cleared after manipulativ textarea - javascript

In my Web App I have have an TextEditor, which can be manipulated by some buttons.
For example:
<textarea id="textareaId"></textarea>
<button onclick="add()">Click me</button>
<script>
add() {
document.getElementById('textareaId').value += 'some content';
}
</script>
The issue is, that the user cant undo this (for example by shortcut ctrl + z).
It looks like that the the undo-buffor for the textarea gets cleared by that. Is there any way to do the changes without losing the option of undoing?

You can cache the textarea's value using an array as stack:
var valuesStack = [];
var textarea = document.getElementById('textareaId');
textarea.addEventListener('keydown', function(event) {
if (event.ctrlKey && event.key === 'z') restore();
});
function cache() {
valuesStack.push(textarea.value);
}
function add() {
cache();
textarea.value += 'some content';
}
function restore() {
var value = valuesStack.pop();
if (value === undefined) textarea.value = "";
else textarea.value = value;
}
<textarea id="textareaId" onchange="cache()"></textarea>
<button onclick="add()">Click me</button>

Related

How to remove all children of contenteditable element?

I need to delete all children of a div after clicking enter.
There is a div and event listener below.
<div id = "area" contenteditable="true"></div>
document.onreadystatechange = function(){
if(document.readyState == 'complete'){
document.getElementById("area").addEventListener("keypress" , public_mode);
}
function public_mode(){
var key = window.event.keyCode;
if (key == 13) {
sendMessage();
}
}
function sendMessage(){
var area = document.getElementById("area");
while (area.firstChild) {
area.removeChild(area.firstChild);
}
}
As you can see the contenteditable elements is added an element in according with clicking enter - it depends on browser what element will be added.In my case I use chrome and here are inserted div.
So, the result after clicking enter on the area but without removing
<div id = "area" contenteditable = "true">
Sckoriy
<div></div>
</div>
and , with removing
<div id = "area" contenteditable = "true">
<div></div>
<div></div>
</div>
But , the needed result is
<div id = "area" contenteditable = "true">
//Empty
</div>
The code mostly works, however there were two main issues.
keyCode is deprecated. you should be using key which turns the syntax of searching for a key into looking for a string. This means instead of 13 you just check to see if key is Enter.
Secondly you need to pass the event to your public_mode function so that you can read the key that has been pressed when the event occurs. You also need to use preventDefault to prevent it from adding a new line after removing everything from the original contentEditable area when it does detect Enter
document.onreadystatechange = function() {
if (document.readyState == 'complete') {
document.getElementById("area").addEventListener("keypress", public_mode);
}
function public_mode(event) {
var key = event.key;
if (key === "Enter") {
event.preventDefault();
sendMessage();
}
}
function sendMessage() {
var area = document.getElementById("area");
while (area.firstChild) area.removeChild(area.firstChild);
}
}
#area {
min-width: 100vw;
border: 1px solid black;
}
<div id="area" contenteditable="true"></div>
You could just set the innerHTML proprety to an empty string;
area.innerHTML = '';
target the dom by id
var s = document.getElementById("area");
save the number of childrens
var num = s.children.length;
and remove the num of childs of element
for(var i=0;i<num;i++){
s.children[0].remove()
}
and inner for some thext
s.innerHTML = "";
Pass the key event as an argument to your function.
Also, if you do not want the newline entered in your div, you can prevent the event from continuing with event.preventDefault().
document.onreadystatechange = function() {
if (document.readyState == 'complete') {
const area = document.getElementById('area')
area.addEventListener('keypress', public_mode);
area.focus();
}
}
function public_mode(event) {
if (window.event.keyCode == 13) {
sendMessage();
event.preventDefault();
}
}
function sendMessage() {
const area = document.getElementById('area');
while (area.firstChild) {
area.removeChild(area.firstChild);
}
}
<div id="area" contenteditable="true">Press Enter to erase me!</div>

Have any selection on page to be auto copied to clipboard [duplicate]

This question already has answers here:
How do I copy to the clipboard in JavaScript?
(27 answers)
Closed 4 years ago.
I need to copy any selection from a webpage to the clipboard, it can be on a div, text input, password input, span, etc.
I have the following function that does this for me, but the challenge is have the returned value from the function to be set on the clipboard
const getSelectionText = () => {
let text = "";
let activeDomElement = document.activeElement;
let activeDomElementTagName = activeDomElement ? activeDomElement.tagName.toLowerCase() : null;
if (
(activeDomElementTagName === 'textarea') || (activeDomElementTagName === 'input' &&
/^(?:text|search|password|tel|url)$/i.test(activeDomElement.type)) &&
(typeof activeDomElement.selectionStart === "number")
) {
text = activeDomElement.value.slice(activeDomElement.selectionStart, activeDomElement.selectionEnd);
} else if (window.getSelection) {
text = window.getSelection().toString();
}
return text;
}
Any idea, or links to resources would be helpful, thanks
Have a look at the example from w3schools.It is a basic example.
https://www.w3schools.com/howto/howto_js_copy_clipboard.asp
You can also use this -
Just call myFunction with your returned text as an argument.
function myFunction(arg) {
var x = document.createElement("INPUT");
x.setAttribute("type", "text");
x.setAttribute("value",arg);
x.select();
document.execCommand("Copy");
alert("Copied the text: " + x.value);
document.removeChild(x);
}
document.execCommand("copy") this will copied all your selected text !
function copySelectionText(){
var copysuccess // var to check whether execCommand successfully executed
try{
copysuccess = document.execCommand("copy") // run command to copy selected text to clipboard
} catch(e){
copysuccess = false
}
return copysuccess
}
document.body.addEventListener('mouseup', function(e){
var copysuccess = copySelectionText() // copy user selected text to clipboard
if(copysuccess) {
document.getElementById('paste').style.display = "block";
}
}, false)
<h3>Late</h3>
<p>dsfjdslkfjdslkfjdsklfj</p>
<code>Cdoing is godo for a wite </code>
<textarea placeholder="Paste Here with [Ctrl + V ]" style="display:none;" id="paste"> </textarea>

Copy div text content using javascript/jQuery

There are quite a few posts on this but after spending several hours trying to adapt the solutions that already exist, it's become clear to me that this is a little bit more complicated.
I'm attempting to create 'copy to clipboard' functionality so that our users can copy their serial number with a single click (I managed to achieve this functionality with 2 different solutions) but there's a major catch.
As the serial number is generated dynamically using a shortcode I cannot place it inside a HTML 'text'/'value' field, like so:
<input id="serial" value="[shortcode here]">
as this breaks the shortcode, so it has to be placed inside it's own div, which I have done like this:
<div id="serial">[shortcode here]</div>
This outputs the shortcode on the page with the direct parent ID of 'serial', so the JS I'm using should then select the text from the element ID - #serial.
Unfortunately it doesn't...
I've tried to adapt this method also with no luck:
From the Roll Your Own section: https://www.sitepoint.com/javascript-copy-to-clipboard/
This one was working with with plain text but not with the shortcode or custom div.
Can anyone provide me with a working clipboard solution as shown in the example above that won't break the shortcode?
document.getElementById("copyButton").addEventListener("click", function() {
copyToClipboardMsg(document.getElementById("copyTarget"), "msg");
});
document.getElementById("copyButton2").addEventListener("click", function() {
copyToClipboardMsg(document.getElementById("copyTarget2"), "msg");
});
document.getElementById("pasteTarget").addEventListener("mousedown", function() {
this.value = "";
});
function copyToClipboardMsg(elem, msgElem) {
var succeed = copyToClipboard(elem);
var msg;
if (!succeed) {
msg = "Copy not supported or blocked. Press Ctrl+c to copy."
} else {
msg = "Text copied to the clipboard."
}
if (typeof msgElem === "string") {
msgElem = document.getElementById(msgElem);
}
msgElem.innerHTML = msg;
setTimeout(function() {
msgElem.innerHTML = "";
}, 2000);
}
function copyToClipboard(elem) {
// create hidden text element, if it doesn't already exist
var targetId = "_hiddenCopyText_";
var isInput = elem.tagName === "INPUT" || elem.tagName === "TEXTAREA";
var origSelectionStart, origSelectionEnd;
if (isInput) {
// can just use the original source element for the selection and copy
target = elem;
origSelectionStart = elem.selectionStart;
origSelectionEnd = elem.selectionEnd;
} else {
// must use a temporary form element for the selection and copy
target = document.getElementById(targetId);
if (!target) {
var target = document.createElement("textarea");
target.style.position = "absolute";
target.style.left = "-9999px";
target.style.top = "0";
target.id = targetId;
document.body.appendChild(target);
}
target.textContent = elem.textContent;
}
// select the content
var currentFocus = document.activeElement;
target.focus();
target.setSelectionRange(0, target.value.length);
// copy the selection
var succeed;
try {
succeed = document.execCommand("copy");
} catch(e) {
succeed = false;
}
// restore original focus
if (currentFocus && typeof currentFocus.focus === "function") {
currentFocus.focus();
}
if (isInput) {
// restore prior selection
elem.setSelectionRange(origSelectionStart, origSelectionEnd);
} else {
// clear temporary content
target.textContent = "";
}
return succeed;
}
<input id="copyTarget" value="Some initial text"> <button id="copyButton">Copy</button><br><br>
<span id="copyTarget2">Some Other Text</span> <button id="copyButton2">Copy</button><br><br>
<input id="pasteTarget"> Click in this Field and hit Ctrl+V to see what is on clipboard<br><br>
<span id="msg"></span><br>
Would you please try above snippet?
Second #pruvik7373 answer
I think [shortcode] may contain some code which can translate into anything else so instead of using textContent use innerHTML it will make sure to copy everything as it is.
document.getElementById("copyButton").addEventListener("click", function() {
copyToClipboardMsg(document.getElementById("copyTarget"), "msg");
});
document.getElementById("copyButton2").addEventListener("click", function() {
copyToClipboardMsg(document.getElementById("serial"), "msg");
});
document.getElementById("pasteTarget").addEventListener("mousedown", function() {
this.value = "";
});
function copyToClipboardMsg(elem, msgElem) {
var succeed = copyToClipboard(elem);
var msg;
if (!succeed) {
msg = "Copy not supported or blocked. Press Ctrl+c to copy."
} else {
msg = "Text copied to the clipboard."
}
if (typeof msgElem === "string") {
msgElem = document.getElementById(msgElem);
}
msgElem.innerHTML = msg;
setTimeout(function() {
msgElem.innerHTML = "";
}, 2000);
}
function copyToClipboard(elem) {
// create hidden text element, if it doesn't already exist
var targetId = "_hiddenCopyText_";
var isInput = elem.tagName === "INPUT" || elem.tagName === "TEXTAREA";
var origSelectionStart, origSelectionEnd;
if (isInput) {
// can just use the original source element for the selection and copy
target = elem;
origSelectionStart = elem.selectionStart;
origSelectionEnd = elem.selectionEnd;
} else {
// must use a temporary form element for the selection and copy
target = document.getElementById(targetId);
if (!target) {
var target = document.createElement("textarea");
target.style.position = "absolute";
target.style.left = "-9999px";
target.style.top = "0";
target.id = targetId;
document.body.appendChild(target);
}
target.textContent = elem.innerHTML;
}
// select the content
var currentFocus = document.activeElement;
target.focus();
target.setSelectionRange(0, target.value.length);
// copy the selection
var succeed;
try {
succeed = document.execCommand("copy");
} catch(e) {
succeed = false;
}
// restore original focus
if (currentFocus && typeof currentFocus.focus === "function") {
currentFocus.focus();
}
if (isInput) {
// restore prior selection
elem.setSelectionRange(origSelectionStart, origSelectionEnd);
} else {
// clear temporary content
target.textContent = "";
}
return succeed;
}
<input id="copyTarget" value="Some initial text"> <button id="copyButton">Copy</button><br><br>
<div id="serial"><div>[pw_map address="New York City"</div> enablescrollwheel="false" key="YOUR API KEY"]</div> <button id="copyButton2">Copy</button><br><br>
<input id="pasteTarget"> Click in this Field and hit Ctrl+V to see what is on clipboard<br><br>
<span id="msg"></span><br>
Below code did the trick for me.
Note: Below snippet might not work as window object is not accessible.
$(function() {
$('#serial').click(function() {
window.clipboardData.setData('text', $(this).text());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="serial">[shortcode here]</div>
You can do it like:
<div id="serial">[shortcode here]</div>
<input id="some_other_id" type="text" />
And the javascript code:
//first get text from your div and put it inside input field
//then apply code to copy that text from input field
$(document).ready(function(){
var text = $("#serial").text();
$("#some_other_id").val(text);
//your code for copying text from input field goes here
});

Copy to clipboard buttons

I want to create "copy to clipboard" buttons to work on our sharepoint. They should be placed in a few different places, and what I need to copy is some text from from a specific field on the page (ex. a list of emails).
I know, I can just select the text and copy it, but we do it quite often, so having a button that automatically copies the text to the clipboard would be very useful.
I did manage to create one in a Script Editor, where I pasted the whole code below (which I found on the internet)
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript'>//<![CDATA[
window.onload=function(){
document.getElementById("copyButton").addEventListener("click", function() {
copyToClipboardMsg(document.getElementById("copyTarget"), "msg");
});
document.getElementById("copyButton2").addEventListener("click", function() {
copyToClipboardMsg(document.getElementById("copyTarget2"), "msg");
});
document.getElementById("pasteTarget").addEventListener("mousedown", function() {
this.value = "";
});
function copyToClipboardMsg(elem, msgElem) {
var succeed = copyToClipboard(elem);
var msg;
if (!succeed) {
msg = "Copy not supported or blocked. Press Ctrl+c to copy."
} else {
msg = "Text copied to the clipboard."
}
if (typeof msgElem === "string") {
msgElem = document.getElementById(msgElem);
}
msgElem.innerHTML = msg;
setTimeout(function() {
msgElem.innerHTML = "";
}, 2000);
}
function copyToClipboard(elem) {
// create hidden text element, if it doesn't already exist
var targetId = "_hiddenCopyText_";
var isInput = elem.tagName === "INPUT" || elem.tagName === "TEXTAREA";
var origSelectionStart, origSelectionEnd;
if (isInput) {
// can just use the original source element for the selection and copy
target = elem;
origSelectionStart = elem.selectionStart;
origSelectionEnd = elem.selectionEnd;
} else {
// must use a temporary form element for the selection and copy
target = document.getElementById(targetId);
if (!target) {
var target = document.createElement("textarea");
target.style.position = "absolute";
target.style.left = "-9999px";
target.style.top = "0";
target.id = targetId;
document.body.appendChild(target);
}
target.textContent = elem.textContent;
}
// select the content
var currentFocus = document.activeElement;
target.focus();
target.setSelectionRange(0, target.value.length);
// copy the selection
var succeed;
try {
succeed = document.execCommand("copy");
} catch(e) {
succeed = false;
}
// restore original focus
if (currentFocus && typeof currentFocus.focus === "function") {
currentFocus.focus();
}
if (isInput) {
// restore prior selection
elem.setSelectionRange(origSelectionStart, origSelectionEnd);
} else {
// clear temporary content
target.textContent = "";
}
return succeed;
}
}//]]>
</script>
</head>
<body>
<input id="copyTarget" value="Some initial text"> <button id="copyButton">Copy</button><br><br>
<span id="copyTarget2">Some Other Text</span> <button id="copyButton2">Copy</button><br><br>
<input id="pasteTarget"> Click in this Field and hit Ctrl+V to see what is on clipboard<br><br>
<span id="msg"></span><br>
</body>
</html>
But we have main problems with it:
1) it reloads the page every time we click the "copy" button
2) it is not very elegant and friendly, when we think about updating our documents
I would be very grateful for any hints you may have for me, on how to make it work better.
This project may help: clipboardjs

Programmatic way to cancel editing mode when using contenteditable?

I've got a small contenteditable span on a page. Under some circumstances (pressing the escape key, for example), I'd like to programmatically cancel editing mode.
Is there a way to do that?
So far, I've found only the hack of removing the contenteditable attr and restoring it shortly thereafter (e.g. 100ms later or so) which is cannot possibly be the right way :-( I would imagine I could change the focus for the same effect.
What I really want is elem.endEdit() or some such...
Thanks!
You can call blur() on the element that is being edited.
Here is an example: https://codepen.io/MarcMouries/pen/PowEYRv
<h3>Editable content</h3>
<div contenteditable="true" id="editor">Click me, type something, then press the ESC key</div>
<h3>Events</h3>
<textarea id="log" rows="10" cols="100" readonly></textarea>
var element = document.getElementById("editor");
var eventsLog = document.getElementById("log");
var oldValue = "";
document.addEventListener('keyup', (e) => {
if (event.keyCode == 27) {
eventsLog.value += "ESC key pressed => UNDO reset to (" + oldValue + ")\n";
var element = event.target;
element.textContent = oldValue;
element.blur();
}
}, false);
element.addEventListener("focus", function(event) {
var element = event.target;
oldValue = element.textContent;
eventsLog.value += "FOCUS: value = " + oldValue + "\n";
});
element.addEventListener("blur", function(event) {
var element = event.target;
var newValue = element.textContent;
if(newValue != oldValue) {
eventsLog.value += "Input changed value to: " + newValue + " \n";
}
}, false);

Categories