Copy to clipboard buttons - javascript

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

Related

Javascript to pre-select row 1 of html table on page load

I am using the following JavaScript code (found on Stackoverflow) to populate a div id ='article_title' from a cell value chosen from a table on the page.
The issue I am having is that the code does not run automatically on page load - unless I click on the table.
I would like to:
retain the existing functionality ie run the code on clicking a row on the table
But I also want to:
run the code on page load using row 1 (or any random row) from the table.
<script>
(function () {
if (window.addEventListener) {
window.addEventListener('load', run, false);
} else if (window.attachEvent) {
window.attachEvent('onload', run);
}
function run() {
var t = document.getElementById('table_id');
t.onclick = function (event) {
event = event || window.event; //IE8
var target = event.target || event.srcElement;
while (target && target.nodeName != 'TR') {
target = target.parentElement;
}
var cells = target.cells;
if (!cells.length || target.parentNode.nodeName == 'THEAD') {
return;
}
var article_title = cells[11].innerHTML;
//Assign Article Title to text box
let h4 = document.createElement('h4');
h4.textContent = article_title;
document.getElementById("article_title").innerHTML = "";
document.getElementById("article_title").appendChild(h4);
document.getElementById("article_title").style.color='black'
};
}
})();
</script>
Used the solution offered by #coderLMN to build the following code and add to the body section of the page. This works now:
<script>
window.onload = function() {
var table = document.getElementById('table_id');
var article_title = table.rows[1].cells[11].innerHTML;
//Assign Article Title to text box
let h4 = document.createElement('h4');
h4.textContent = article_title;
document.getElementById("article_title").innerHTML = "";
document.getElementById("article_title").appendChild(h4);
document.getElementById("article_title").style.color='black'
}
</script>

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
});

How to copy input of type date, if there is no selection being created?

I have a simple input:
<input type="date" class="self-select" value="1980-05-04">
<input type="text" class="self-select" value="my birthday">
And I have a listener for all such inputs:
$(document).on('focus', '.self-select', function(){
$(this).select();
});
The idea is that when user clicks to the input field, its' contents are selected, so he needs just ctrl+c to copy.
But this doesnt work with type="date" in Chrome. There is no selection and basically no way to copy date value from an input field.
Here is the fiddle:
https://fiddle.jshell.net/Dmatafonov/s8r9dt6j/
I managed to write some kind of a "hacky" walk around...
The trick is to copy to clipboard (using this other great SO answer) while the date input type is temporarely setted to "text" on CTRL+C keydown...
It's not perfect since only a segment of the date is selected on focus...
And some users will scratch their head a little until they notice that the whole date is copied anyway.
I have no solution for this.
What's important is that copying to clipboard is works.
Try the snippet!
// Your on focus -> select event handler
$(document).on('focus', '.self-select', function(){
$(this).select();
});
// An on keydown event handler to copy to clipboard when [ctrl]+[C] is pressed
// Exclusively for the "date" inputs.
$(document).on('keydown', 'input[type="date"]', function(e){
if( e.which == 67 && e.ctrlKey ){
var copiedDate = $(this).val();
//console.log( copiedDate );
// First, get the value and fix the date format from YYYY-MM-DD to MM/DD/YYYY
var tempDate = copiedDate.split("-");
var year = tempDate.shift();
//console.log( year );
tempDate.push(year);
var fixedDate = tempDate.join("/");
console.log( fixedDate );
// Then temporarly change the input type from "date" to "text"
$(this).attr("type","text").val(fixedDate);
// Use the copy to clipboard function
$(this).select();
copyToClipboard($(this));
// Set the input type back to "date" a small delay later
var that=$(this);
setTimeout(function(){
that.attr("type","date").val(copiedDate); // And restore original value
},20)
}
});
// ---------------------------------
// A nice JavaScript "copy to clipboard" function found here : https://stackoverflow.com/a/22581382/2159528
// ---------------------------------
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;
}
/* Textarea sizing for this snippet */
#pasteIt{
width:316px;
height:150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="date" class="self-select" value="1980-05-04">
<input type="text" class="self-select" value="my birthday">
<br>
<br>
<textarea id="pasteIt" placeholder="Paste here to test your clipboard."></textarea>
I ran into this same issue but also needed to be able to paste to another date field. I did something similar to the above but made it obvious to the user that the full date is being copied.
My use case also included the need to copy from and paste to datetime-local type fields.
https://jsfiddle.net/h444uL45/23/
var control_pressed = false;
function changeInputType(oldObject, oType) {
var newObject = document.createElement("input");
newObject.type = oType;
if(oldObject.size) {newObject.size = oldObject.size;}
if(oldObject.value) {newObject.value = oldObject.value;}
if(oldObject.name) {newObject.name = oldObject.name;}
if(oldObject.id) {newObject.id = oldObject.id;}
if(oldObject.className) {newObject.className = oldObject.className;}
oldObject.parentNode.replaceChild(newObject,oldObject);
newObject.select();
return newObject;
}
function swapToText(date_type) {
$('input[type="'+date_type+'"]').on("keydown", function(event) {
if ((event.keyCode == 17) && (control_pressed != true)) {
$(this).addClass("revert_date_to_text");
changeInputType(this, "text");
swapToDate(date_type);
control_pressed = true;
}
})
}
function swapToDate(date_type) {
$(".revert_date_to_text").on("keyup", function(event) {
if ((event.keyCode == 17) && (control_pressed != false)) {
$(this).removeClass("revert_date_to_text");
if (date_type == 'datetime-local') {
$(this).val($.format.date($(this).val().replace(/\//g,"-").replace("T"," ")+':00.000', "yyyy-MM-ddTHH:mm"));
} else {
$(this).val($.format.date($(this).val().replace(/\//g,"-"), "yyyy-MM-dd"));
}
changeInputType(this, date_type);
swapToText(date_type);
control_pressed = false;
}
})
}
$(function() {
$.getScript('https://cdnjs.cloudflare.com/ajax/libs/jquery-dateFormat/1.0/jquery.dateFormat.min.js');
swapToText('date');
swapToText('datetime-local');
});

Dynamically detect textarea empty or not

I'm trying to dynamically detect if a textarea is empty or not. I'm doing this so I can show a send button only when there's text entered in the textarea.
I tried this code below, but it's not working.
var text = document.getElementById("text").value;
if (text !== ''){
alert("works");
document.getElementById("sendicon1").style.display = "none";
document.getElementById("sendicon2").style.display = "inline";
}
else{
alert("not working");
document.getElementById("sendicon2").style.display = "none";
document.getElementById("sendicon1").style.display = "inline";
}
Are you putting that code inside an onkeyup or onchange function? You could do something like:
window.onload = function() {
var text = document.getElementById("text");
var func = function() {
if (text.value !== '') {
alert("works");
document.getElementById("sendicon1").style.display = "none";
document.getElementById("sendicon2").style.display = "inline";
} else {
alert("not working");
document.getElementById("sendicon2").style.display = "none";
document.getElementById("sendicon1").style.display = "inline";
}
}
text.onkeyup = func;
text.onchange = func;
}
You don't need both the onkeyup and onchange, it depends on when you are looking for it to fire. onchange will be after you have taken focus away (blur) and onkeyup will be after each key is pressed inside the textarea.
It's very easy with input event.
var textarea = document.getElementById("text");
textarea.addEventListener('input', hideOnEmpty);
function hideOnEmpty() {
var text = this.value;
if (text !== ''){
alert("works");
document.getElementById("sendicon1").style.display = "none";
document.getElementById("sendicon2").style.display = "inline";
}
else{
alert("not working");
document.getElementById("sendicon2").style.display = "none";
document.getElementById("sendicon1").style.display = "inline";
}
}
See input event documentation for further details (MDN, W3schools). This code will fire hideOnEmpty function every time that content of textarea is changed.
Beware - this code will not work in IE8 or lower, and can fail to detect deletions in IE9 (but there is no reliable way to check if input has changed without polling in IE9).
You haven't listed jQuery as a dependency, but this is definitely an area where it would come it handy.
$('#text').on('input propertychange', function () {
if ($(this).val() !== "") {
$("#sendicon1").hide();
$("#sendicon2").show();
}
else {
$("#sendicon2").hide();
$("#sendicon1").show();
}
});
The input event will detect all changes to the textarea- key presses, copying and pasting, and more.

Javascript: How to detect if a word is highlighted

I'm writing a Firefox addon that is triggered whenever a word is highlighted. However I need a script that detects when a word is highlighted, and I'm stuck. An example would be nytimes.com (when you're reading an article and you highlight a word, the reference icon pops up). However the nytimes.com script is super complex. I'm 16 and not much of a programmer, so that is definitely way out of my league.
The easiest way to do this is to detect mouseup and keyup events on the document and check whether any text is selected. The following will work in all major browsers.
Example: http://www.jsfiddle.net/timdown/SW54T/
function getSelectedText() {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof document.selection != "undefined" && document.selection.type == "Text") {
text = document.selection.createRange().text;
}
return text;
}
function doSomethingWithSelectedText() {
var selectedText = getSelectedText();
if (selectedText) {
alert("Got selected text " + selectedText);
}
}
document.onmouseup = doSomethingWithSelectedText;
document.onkeyup = doSomethingWithSelectedText;
Here is a script:
<script>
function getSelText()
{
    var txt = '';
    if (window.getSelection)
    {
        txt = window.getSelection();
    }
    else if (document.getSelection)
    {
        txt = document.getSelection();
    }
    else if (document.selection)
    {
        txt = document.selection.createRange().text;
    }
    else return;
document.aform.selectedtext.value = txt;
}
</script>
<input type="button" value="Get selection" onmousedown="getSelText()">
<form name="aform">
<textarea name="selectedtext" rows="5" cols="20"></textarea>
</form>
Courtesy of Code Toad:
http://www.codetoad.com/javascript_get_selected_text.asp
In your case, you would want to call this script when the selection is made, and then you can process it however you wish, with an AJAX request to get relevant information for example, like NYtimes probably does.
In my case I wanted to be able to either highlight a text in a row of the and click in the row and send me to other route like "/entity/:id";
I created one function that detects the mouse is highlighting some text:
export const isHighlighting = () => {
// detects mouse is highlighting a text
return window.getSelection && window.getSelection().type === 'Range';
};
then I added this to the row of the
const handleClick = (id) => {
if (!isHighlighting() {
history.push(`/entity/${id}`)
}
}
{data.map((item) => (
<tr>
<td onClick={() => handleClick(item.id)}>{item.name}</>
</tr>
))}
in this way the user can hightlight then name field or click somewhere else and goes to "/entity/:id"
Using rangy.js and jQuery:
$('#elem').on('keyup mouseup', function(){
var sel = rangy.getSelection()
if (sel.rangeCount === 0 || sel.isCollapsed) return
alert(sel.toString())
})

Categories