I'm trying to build something similar to a virtual keyboard for french special characters, so the user can copy them easy by clicking on the special character button and paste them wherever they need.
I'm not very good in javascript and have been struggling with bits of code I found to create what I need. So far, I can make it work for just one button with this code.
For my html (just an excerpt)
<div class="copy_btn_container">
<div class="copy_btn_block">
<p>Accents graves et accents aigüs<p>
<button onclick="copyStringToClipboard()" id = 'accbtn1' data-target="accbtn1" class="copy_btn">é</button>
<button onclick="copyStringToClipboard()" id = 'accbtn2' data-target="accbtn2" class="copy_btn">è</button>
<button onclick="copyStringToClipboard()" id = 'accbtn3' data-target="accbtn3" class="copy_btn">à</button>
<button onclick="copyStringToClipboard()" id = 'accbtn4' data-target="accbtn4" class="copy_btn">ù</button>
</div>
</div>
And my javascript is
function copyStringToClipboard () {
var str = document.getElementById("accbtn1").innerText;
// Create new element
var el = document.createElement('textarea');
// Set value (string to be copied)
el.value = str;
// Set non-editable to avoid focus and move outside of view
el.setAttribute('readonly', '');
el.style = {position: 'absolute', left: '-9999px'};
document.body.appendChild(el);
// Select text inside element
el.select();
// Copy text to clipboard
document.execCommand('copy');
// Remove temporary element
document.body.removeChild(el);
}
So I know that document.getElementById accepts only one element, so I tried document.getElementsByClassName but it return a "undefined" value.
I'm open to other ways for the js too, as I saw that it was possible to use constants or such, but all of the example are designed to copy values from input fields, and for some reason I can't manage dont tweak them into working for copying the button's text.
Any help would be appreciated ! Thanks
You could pass the id or data attribute into your function like so:
function copyStringToClipboard (target) {
var str = document.getElementById(target).innerText;
// Create new element
var el = document.createElement('textarea');
// Set value (string to be copied)
el.value = str;
// Set non-editable to avoid focus and move outside of view
el.setAttribute('readonly', '');
el.style = {position: 'absolute', left: '-9999px'};
document.body.appendChild(el);
// Select text inside element
el.select();
// Copy text to clipboard
document.execCommand('copy');
// Remove temporary element
document.body.removeChild(el);
}
<div class="copy_btn_container">
<div class="copy_btn_block">
<p>Accents graves et accents aigüs<p>
<button onclick="copyStringToClipboard(this.getAttribute('data-target'))" id = 'accbtn1' data-target="accbtn1" class="copy_btn">é</button>
<button onclick="copyStringToClipboard(this.getAttribute('data-target'))" id = 'accbtn2' data-target="accbtn2" class="copy_btn">è</button>
<button onclick="copyStringToClipboard(this.getAttribute('data-target'))" id = 'accbtn3' data-target="accbtn3" class="copy_btn">à</button>
<button onclick="copyStringToClipboard(this.getAttribute('data-target'))" id = 'accbtn4' data-target="accbtn4" class="copy_btn">ù</button>
</div>
</div>
Related
I've got a formula that calculates a value. This value I want to insert to an Excel sheet. To make it comfortable to the user I want to put it to the clipboard automatically.
I try to do my first steps in JS and encountered this (probably) very simple problem. But all methods I found are related to raw values of html input-tags. I never have seen any copy-to-clipboard functions from values created in js.
var EEFactor = 1*1; // just a formula to calculate a value
copyValue2Clipboard(EEFactor);
function value2Clipboard(value) {
// please help
}
There is an example with a great explanation here
Try like this.
function copyToClipboard(str) {
var el = document.createElement('textarea');
// Set value (string to be copied)
el.value = str;
// Set non-editable to avoid focus and move outside of view
el.setAttribute('readonly', '');
el.style = {position: 'absolute', left: '-9999px'};
document.body.appendChild(el);
// Select text inside element
el.select();
// Copy text to clipboard
document.execCommand('copy');
// Remove temporary element
document.body.removeChild(el);
};
var EEFactor = 1*1;
copyToClipboard(EEFactor);
const copyToClipboard = str => {
const el = document.createElement('textarea'); // Create a <textarea> element
el.value = str; // Set its value to the string that you want copied
el.setAttribute('readonly', ''); // Make it readonly to be tamper-proof
el.style.position = 'absolute';
el.style.left = '-9999px'; // Move outside the screen to make it invisible
document.body.appendChild(el); // Append the <textarea> element to the HTML document
const selected =
document.getSelection().rangeCount > 0 // Check if there is any content selected previously
? document.getSelection().getRangeAt(0) // Store selection if found
: false; // Mark as false to know no selection existed before
el.select(); // Select the <textarea> content
document.execCommand('copy'); // Copy - only works as a result of a user action (e.g. click events)
document.body.removeChild(el); // Remove the <textarea> element
if (selected) { // If a selection existed before copying
document.getSelection().removeAllRanges(); // Unselect everything on the HTML document
document.getSelection().addRange(selected); // Restore the original selection
}
};
I am trying to create checkboxes and insert a blank line after each one. When the checkbox is changed, I want to execute a function.
My code:
var div = document.getElementById("test");
var cb1 = document.createElement('input');
cb1.id = "cb_test1";
cb1.type = "checkbox";
cb1.defaultChecked = true;
cb1.onchange = function(){alert("hi")};
div.appendChild(cb1);
div.innerHTML += "box1<br/>";
var cb2 = document.createElement('input');
cb2.id = "cb_test1";
cb2.type = "checkbox";
cb2.defaultChecked = true;
cb2.onchange = function(){alert("hi")};
div.appendChild(cb2);
div.innerHTML += "box2<br/>";
The problem is, setting the innerHTML of the containing DIV seems to erase the event listener, so when the onchange event is fired, nothing happens.
How can I modify the innerHTML to add text and a new line without losing the event handler?
My actual code is much more dynamic and done in a loop, but the issue of the event handler getting dropped can be duplicated with the above code.
Whenever you assign (or concatenate) an innerHTML property of a container, any listeners inside that container that were attached via Javascript will be corrupted. If you want to insert HTML strings, use insertAdjacentHTML instead:
document.querySelector('#child').onclick = () => console.log('child');
document.querySelector('#container').insertAdjacentHTML('beforeend', '<div>newchild</div>');
<div id="container">
<div id="child">
child
</div>
</div>
But it would generally be better to create and append elements explicitly rather than insert strings of HTML markup that then get parsed into elements. For example, instead of
div.innerHTML += "box1<br/>";
you could
div.appendChild(document.createTextNode('box1');
div.appendChild(document.createElement('br');
const div = document.querySelector('div');
div.appendChild(document.createTextNode('box1'));
div.appendChild(document.createElement('br'));
<div>
content
</div>
I spent a good 20 min searching online for this, but couldn't find it. What I want is to to be able to copy a text string on click without a button. The text string will be inside a "span" class.
User hovers over text string
User clicks text string
Text string is copied to clipboard
Any help would be greatly appreciated. Thanks!
You can attach copy event to <span> element, use document.execCommand("copy") within event handler, set event.clipboardData to span .textContent with .setData() method of event.clipboardData
const span = document.querySelector("span");
span.onclick = function() {
document.execCommand("copy");
}
span.addEventListener("copy", function(event) {
event.preventDefault();
if (event.clipboardData) {
event.clipboardData.setData("text/plain", span.textContent);
console.log(event.clipboardData.getData("text"))
}
});
<span>text</span>
Try this .document.execCommand('copy')
click the element and copy the text and post with tmp input element
Then copy the text from this input
function copy(that){
var inp =document.createElement('input');
document.body.appendChild(inp)
inp.value =that.textContent
inp.select();
document.execCommand('copy',false);
inp.remove();
}
<p onclick="copy(this)">hello man</p>
This is the Code pen.
<link href='https://fonts.googleapis.com/css?family=Oswald' rel='stylesheet' type='text/css'>
<p style="color:wheat;font-size:55px;text-align:center;">How to copy a TEXT to Clipboard on a Button-Click</p>
<center>
<p id="p1">This is TEXT 1</p>
<p id="p2">This is TEXT 2</p><br/>
<button onclick="copyToClipboard('#p1')">Copy TEXT 1</button>
<button onclick="copyToClipboard('#p2')">Copy TEXT 2</button>
<br/><br/><input class="textBox" type="text" id="" placeholder="Dont belive me?..TEST it here..;)" />
</center>
Jquery Code here
function copyToClipboard(element) {
var $temp = $("<input>");
$("body").append($temp);
$temp.val($(element).text()).select();
document.execCommand("copy");
$temp.remove();
}
Use the Clipboard API!
The simplest modern solution is:
navigator.clipboard.writeText(value)
That value can later be accessed with:
navigator.clipboard.readText()
NOTE: To use in an iframe, you'll need to add write (and maybe read) permissions
<iframe src='' allow='clipboard-read; clipboard-write'/>
NOTE: To use in an browser extension (on a webpage), you'll need either to:
call from a user triggered event (click...)
add the 'clipboardWrite' permission to the manifest
NOTE: To use in the dev console, use copy() instead
copy('string')
W3Schools Tutorial
CanIUse
Along with copying the text , you also have to make sure that any previously selected component remains selected after copying to clipboard.
Here's the full code :
const copyToClipboard = str => {
const el = document.createElement('textarea'); // Create a <textarea> element
el.value = str; // Set its value to the string that you want copied
el.setAttribute('readonly', ''); // Make it readonly to be tamper-proof
el.style.position = 'absolute';
el.style.left = '-9999px'; // Move outside the screen to make it invisible
document.body.appendChild(el); // Append the <textarea> element to the HTML document
const selected =
document.getSelection().rangeCount > 0 // Check if there is any content selected previously
? document.getSelection().getRangeAt(0) // Store selection if found
: false; // Mark as false to know no selection existed before
el.select(); // Select the <textarea> content
document.execCommand('copy'); // Copy - only works as a result of a user action (e.g. click events)
document.body.removeChild(el); // Remove the <textarea> element
if (selected) { // If a selection existed before copying
document.getSelection().removeAllRanges(); // Unselect everything on the HTML document
document.getSelection().addRange(selected); // Restore the original selection
}
};
ps adding the source
HTML:
<button type='button' id='btn'>Copy</button>
JS
document.querySelect('#btn').addEventListener('click', function() {
copyToClipboard('copy this text');
});
JS / Function:
function copyToClipboard(text) {
var selected = false;
var el = document.createElement('textarea');
el.value = text;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
if (document.getSelection().rangeCount > 0) {
selected = document.getSelection().getRangeAt(0)
}
el.select();
document.execCommand('copy');
document.body.removeChild(el);
if (selected) {
document.getSelection().removeAllRanges();
document.getSelection().addRange(selected);
}
};
guest271314's answer applied to multiple elements:
spans = document.querySelectorAll(".class");
for (const span of spans) {
span.onclick = function() {
document.execCommand("copy");
}
span.addEventListener("copy", function(event) {
event.preventDefault();
if (event.clipboardData) {
event.clipboardData.setData("text/plain", span.textContent);
console.log(event.clipboardData.getData("text"))
}
});
}
<span class="class">text</span>
<br>
<span class="class">text2</span>
This is the most suitable way to do it. It will copy all text in elements with the class "copy" in them.
var copy = document.querySelectorAll(".copy");
for (const copied of copy) {
copied.onclick = function() {
document.execCommand("copy");
};
copied.addEventListener("copy", function(event) {
event.preventDefault();
if (event.clipboardData) {
event.clipboardData.setData("text/plain", copied.textContent);
console.log(event.clipboardData.getData("text"))
};
});
};
.copy {
cursor: copy;
}
<p><span class="copy">Text</span></p>
<p><span class="copy">More Text</span></p>
<p><span class="copy">Even More Text</span></p>
u can also use onclick like
function copyCode() {
const Code = document.querySelector("input");
Code.select();
document.execCommand("copy", false);
}
<input type="input" />
<button onclick={copyCode()}>Copy</button>
function copy(that){
var inp =document.createElement('input');
document.body.appendChild(inp)
inp.value =that.textContent
inp.select();
document.execCommand('copy',false);
inp.remove();
}
<p onclick="copy(this)">hello man</p>
I wonder if it's possible to replace certain words inside an iframe.
I've used jQuery to change the content inside the iframe with the same content, but with replacements. The problem here is that 'the cursor resets' to the start of the input field, so you have to write from start again.
So here is what I did
<html>
<head>
<script>
function iFrameOn(){
richTextField.document.designMode = 'On';
}
</script>
</head>
<body onLoad="iFrameOn();">
<!-- Hide(but keep)your normal textarea and place in the iFrame replacement for it -->
<textarea style="display:none;" name="myTextArea" id="myTextArea" cols="100" rows="14"></textarea>
<iframe name="richTextField" id="richTextField" style="border:#000000 1px solid; width:100px; height:20px;">
</iframe>
<!--End replacing your normal textarea -->
</p>
<script>
function ReplaceWords(){
var textfield = document.getElementById("richTextField");
textfield.contentWindow.document.body.onkeyup = function(e){
var content = textfield.contentWindow.document.body.innerHTML;
var Fixed_Content = content.replace("hey", "yo");
$(document).ready(function() {
$('#richTextField').contents().find('body').html(Fixed_Content);
});
};
};
ReplaceWords();
</script>
</body>
</html>
The question is: if you can replace some of the content inside the iframe without the cursor resets, because it's not appreciated when you type and it just starts from start again.
Update: Basically it's not the textarea that is in focus, it's hidden inside the iframe therefore I use document.designMode = 'On';.
I have updated the post again, this is how it should have been from the start.
Link to jsfiddle:
https://jsfiddle.net/tqf3v2sk/8/
Working with iFrames in the same domain is not much different from working with DOM elements. You just have to make sure the methods you use are called on the proper window and document object. But once you target correctly the window and document, you can call them from the parent window pretty much in the same way as if it was in the same window as your script.
As for replacement while you type, there are a couple of ways to to it. One way would be to use document.execCommand('insertText') and Selection. You detect if the key being entered matches last character of the word to replace, if so you select the length of the word to replace and check if it matches. If it matches, you call execCommand and it'll replace it leaving the cursor at the end of the replacement.
function replaceOnKeyDown(e, toReplace, replaceWith) {
var iptFld = e.target;
var lastLetter = toReplace[toReplace.length - 1];
var keyEntered = String.fromCharCode(e.keyCode);
console.log(keyEntered)
// To make it more efficient, you can call the rest only if the
// key just pressed is the same as the last of the word you
// need to replace.
if (lastLetter.toLowerCase() === keyEntered.toLowerCase()) {
// Set selection to your word length
var range = frameWindow.getSelection().getRangeAt(0);
var caretPosition = range.startOffset;
// Since you're on key down, the caret position is before the
// last letter is entered.
var toReplaceStart = caretPosition - toReplace.length + 1;
range.setEnd(range.startContainer, caretPosition);
range.setStart(range.startContainer, toReplaceStart);
frameWindow.getSelection().addRange(range);
// Check if the selection matches the word to replace
// Since you're on mouse down, the range will only include
// up until the letter being entered. So you need to validate
// that the word without the last letter equals
// the selection.
if (range.toString() + lastLetter === toReplace) {
frameDocument.execCommand('insertText', false, replaceWith);
// prevent last letter to be entered
e.preventDefault();
} else {
frameWindow.getSelection().collapse(range.startContainer, caretPosition);
}
}
}
var textfield = document.getElementById("richTextField");
var frameWindow = textfield.contentWindow
var frameDocument = frameWindow.document
frameDocument.designMode = 'on'
frameDocument.body.onkeydown = function(e) {
replaceOnKeyDown(e, 'hey', 'yo')
};
https://jsfiddle.net/k0qpmmw1/6/
What I am trying to figure out is how to make a button, that when you click, will replace itself with a textbox. I found this code on the W3Schools website, and can't figure out how to put javascript (or HTML) elements in.
<p>Click the button to replace "Microsoft" with "W3Schools" in the paragraph below:</p>
<p id="demo">Visit Microsoft!</p>
<button onclick="myFunction()">Try it</button>
<script>
function myFunction() {
var str = document.getElementById("demo").innerHTML;
var res = str.replace("Microsoft", "W3Schools");
document.getElementById("demo").innerHTML = res;
}
</script>
</body>
</html>
<input type="text" name="textbox" value="textbox"><br>
In the end I want to be able to replace a button with the textbox I put outside the html tags
I would not suggest you the innerHTML replacement method.
Here are the steps where you can use replaceChild
Get the parent node of the selected element
use replaceChild
Here the code
// create the new element (input)
var textBox = document.createElement("input");
textBox.type = "text";
// get the button
var button = document.getElementById("demo");
// reference to the parent node
var parent = element.parentNode;
// replace it
parent.replaceChild(textBox, button);
On older browser you probably need a slighlty different solution.
var parent = button.parentNode;
var next = button.nextSibling;
// remove the old
parent.removeChild(button);
// if it was not last element, use insertBefore
if (next) {
parent.insertBefore(textBox, next);
} else {
parent.appendChild(textBox);
}
I ended up finding a code that works off of http://www.webdeveloper.com/forum/showthread.php?266743-Switch-Div-Content-Using-Javascript