Working clipboard script not compatible with Chrome. Works with Edge/IE - javascript

I have a working clipboard script that I have to use on our portal page to utilize clipboard functionality. We are moving from IE/Edge to Chrome, and it seems this script will not function in Google Chrome. I would love it if we can find a way to make the code chrome/multi browser compatible without having to make a new script for Chrome-only.
While I do have a working script for Chrome, it would mean i would have to re-build hundreds of pages using clipboard, and I would rather make the script already embedded in all these pages chrome compatible. Below is the script i am using:
(function() {
'use strict';
// click events
document.body.addEventListener('click', copy, true);
// event handler
function copy(e) {
// find target element
var
t = e.target,
c = t.dataset.copytarget,
inp = (c ? document.querySelector(c) : null);
// is element selectable?
if (inp && inp.select) {
// select text
inp.select();
try {
// copy text
document.execCommand('copy');
inp.blur();
// copied animation
t.classList.add('copied');
setTimeout(function() { t.classList.remove('copied'); }, 1500);
}
catch (err) {
alert('please press Ctrl/Cmd+C to copy');
}
}
}
})();
// Button must include data-copytarget="#website" with the #xxx matching the element id
Results: In IE/Edge, you click on the button and the assigned text to that button is added to the clipboard for pasting. In Chrome however, clicking on the button and nothing happens.

Your code works fine in Chrome as long as the input is visible.
Chrome does not allow copying from a hidden input. There are multiple workarounds. In the example below, I've moved the input of screen using absolute positioning.
(function() {
"use strict";
// click events
document.body.addEventListener("click", copy, true);
// event handler
function copy(e) {
// find target element
var t = e.target,
c = t.dataset.copytarget,
inp = c ? document.querySelector(c) : null;
// is element selectable?
if (inp && inp.select) {
// select text
inp.select();
try {
// copy text
document.execCommand("copy");
inp.blur();
// copied animation
t.classList.add("copied");
setTimeout(function() {
t.classList.remove("copied");
}, 1500);
} catch (err) {
alert("please press Ctrl/Cmd+C to copy");
}
}
}
})();
#vishidden {
position: absolute;
top: -9999px;
left: -9999px;
}
<div>
<input type="text" id="text" value="visible test" readonly="true">
<button type="button" data-copytarget="#text">copy</button>
</div>
<div>
<input type="hidden" id="hidden" value="hidden test" readonly="true">
<button type="button" data-copytarget="#hidden">copy hidden</button>
</div>
<div>
<input type="text" id="vishidden" value="visually hidden test" readonly="true">
<button type="button" data-copytarget="#vishidden">copy visually hidden</button>
</div>
<div>
<textarea cols="30" rows="10" placeholder="paste here to test"></textarea>
</div>
Another example: Using execCommand (Javascript) to copy hidden text to clipboard
Clipboard.js is a useful library to do this. It also uses a visually hidden input behind the scenes (in a similar but more robust way than in my example).

Related

Unable to input spaces into a span, inside a button in Firefox

I have a button element, which needs to have text which can be modified dynamically. I was having trouble with adding spaces which is when I refered this answer to have a span, which is contenteditable. During this time, I was testing on Chrome and it was working.
However, when I was testing this feature in Firefox, I was not able to insert spaces in the span element. I do not see anything about this online either. Is there anyway I can have this supported on Firefox too?
I should also note that, I am doing this for an Extension that I am building for Chrome and Firefox.
This is what my code looks like:
<!-- HTML -->
<button id="editableBtn">
<span id="titleText" contenteditable="false" style="border: solid; border-color: green;">Button</span>
</button>
<button id="editorBtn">Click me to edit</button>
<!-- JS -->
<script>
var spanText = document.getElementById("titleText");
var editableBtn = document.getElementById("editableBtn");
var editorBtn = document.getElementById("editorBtn");
spanText.addEventListener('keydown', (event) => {
console.log("Span keydown = ", event)
})
editorBtn.addEventListener('click', (event) => {
spanText.contentEditable = "true"
})
</script>
Firefox Version: 110.0
Google Chrome Verion: 110.0
You could add an event listener to the span element for the "keydown" event, so when the space bar is pressed it manually inserts a non-breaking space character (which shows up as a space) at the current cursor position using the document.execCommand function.
var spanText = document.getElementById("titleText");
var editableBtn = document.getElementById("editableBtn");
var editorBtn = document.getElementById("editorBtn");
spanText.addEventListener('keydown', (event) => {
if (event.keyCode === 32) { // 32 is the keycode for the spacebar
// prevent default behavior, since we're handling it ourselves
event.preventDefault();
// insert the space character at the current cursor position
document.execCommand('insertHTML', false, ' ');
}
});
editorBtn.addEventListener('click', (event) => {
spanText.contentEditable = "true"
});
<button id="editableBtn">
<span id="titleText" contenteditable="false" style="border: solid; border-color: green;">Button</span>
</button>
<button id="editorBtn">Click me to edit</button>

How can I copy text (<p>) to the clipboard on an image click using jQuery in the most simple way?

I am looking for the simplest possible solution to copy text within a html p tag on an image click to the clipboard.
I tried some small (code wise) solutions from this thread Click button copy to clipboard using jQuery, but it just won't copy the text. In my case I need it to work with an image click rather than a button click.
$("#clipboardImage").click(function() {
$("#didText").select();
document.execCommand("copy");
alert("Text copied")
});
#didText {
color: #1816A9;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<div id="didContainer">
<p id="didText" type="text">I hopefully end up in the form field anytime soon!</p>
<img id="clipboardImage" src="" alt="Click me, to bring him down!">
</div>
<br>
<form>
Worked?
<input type="text" name="copied Text">
</form>
</html>
If I understand well your goal is to put the text from the p tag into the input field.
Just select the text with JQuery .text() and put it into the input filed as a value
EDIT
So, if the main goal is to put some text from an element to the clipboard I suggest to use a dedicated function, there's a workaround that create an invisible and readonly textarea and use it as a "proxy" to store and copy the text to your clipboard.
NB: to avoid passing the text to the input field just get rid of $("input").val(text); row.
function copyToClipboard (str) {
var 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
var selected = document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : 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
}
};
$("#clipboardImage").click(function() {
var didText = $("#didText");
var text = didText.text();
copyToClipboard(text);
$("input").val(text);
alert("Text copied")
});
#didText {
color: #1816A9;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<div id="didContainer">
<p id="didText" type="text">I hopefully end up in the form field anytime soon!</p>
<img id="clipboardImage" src="" alt="Click me, to bring him down!">
</div>
<br>
<form>
Worked?
<input type="text" name="copied Text">
</form>
</html>

Use XPath or onClick or onblur to select an element and use jQuery to blur this element

*UPDATE:I am new to jQuery, as well as using XPath, and I am struggling with getting a proper working solution that will blur a dynamically created HTML element. I have an .onblur event hooked up (doesn't work as expected), and have tried using the $(document.activeElement), but my implementation might be incorrect. I would appreciate any help in creating a working solution, that will blur this element (jqInput) when a user clicks anywhere outside the active element. I have added the HTML and jQuery/JavaScript below.
Some ideas I have had:
(1) Use XPath to select a dynamic HTML element (jqInput), and then use jQuery's .onClick method to blur a this element, when a user clicks anywhere outside of the area of the XPath selected element.
(2) Use the $(document.activeElement) to determine where the .onblur should fire:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
I am open to all working solutions. And hopefully this will answer someone else's question in the future.
My challenge: Multiple elements are active, and the .onblur does not fire. See the image below:
NOTE: The <input /> field has focus, as well as the <div> to the left of the (the blue outline). If a user clicks anywhere outside that <input />, the blur must be applied to that element.
My Code: jQuery and JavaScript
This is a code snippet where the variable jqInput and input0 is created:
var jqInput = null;
if (jqHeaderText.next().hasClass("inline-editable"))
{
//Use existing input if it already exists
jqInput = jqHeaderText.next();
}
else
{
//Creaet a new editable header text input
jqInput = $("<input class=\"inline-editable\" type=\"text\"/>").insertAfter(jqHeaderText);
}
var input0 = jqInput.get(0);
//Assign key down event for the input when user preses enter to complete entering of the text
input0.onkeydown = function (e)
{
if (e.keyCode === 13)
{
jqInput.trigger("blur");
e.preventDefault();
e.stopPropagation();
}
};
This is my .onblur event, and my helper method to blur the element:
input0.onblur = function ()
{
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
};
inputOnBlurHandler: function (canvasObj, jqHeaderText, jqInput)
{
// Hide input textbox
jqInput.hide();
// Store the value in the canvas
canvasObj.headingText = jqInput.val();
_layout.updateCanvasControlProperty(canvasObj.instanceid, "Title", canvasObj.headingText, canvasObj.headingText);
// Show header element
jqHeaderText.show();
_layout.$propertiesContent.find(".propertyGridEditWrapper").filter(function ()
{
return $(this).data("propertyName") === "Title";
}).find("input[type=text]").val(canvasObj.headingText); // Update the property grid title input element
}
I have tried using the active element, but I don't think the implementation is correct:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
My HTML code:
<div class="panel-header-c">
<div class="panel-header-wrapper">
<div class="panel-header-text" style="display: none;">(Enter View Title)</div><input class="inline-editable" type="text" style="display: block;"><div class="panel-header-controls">
<span></span>
</div>
</div>
</div>
I thank you all in advance.

How to change <input type="file"> design so it won't display the text-field? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
input type=file show only button
The has this kind of design:
Can I modify it so it won't show the text field?
a very good guide is found in quirksmode - Styling an input type="file"
quote with some modifications to match question:
Take a normal <input type="file"> and put it in an element with position: relative. or absolute
To this same parent element, add an image or a button, which have the correct styles. Position this element absolutely, so
that they occupy the same place as the <input type="file">.
Set the z-index of the <input type="file"> to 2 so that it lies on top of the styled image or button.
Finally, set the opacity of the <input type="file"> to 0. The <input type="file"> now becomes effectively invisible, and the styled
image or button shines through, but you can still click on the "Browse"
button. (Note that you can't use visibility: hidden, because a truly
invisible element is unclickable, too, and we need the <input
type="file"> to remain clickable)
Suggestion: You can use the uploadify plugin.
Don't see a jQuery tag in your question but hey, it's helpful, and possibly quite easy to rewrite in vanilla JS. This is a little jQuery plugin I extracted from Ideal Forms, a plugin I maintain at github. It covers all the basics to do what you want, with fallback for IE and multiple for HTML5 browsers. Plus handling events and markup replacement. CSS is on your own, but nothing too complicated to style as you can see. You can hide the text field too if you want. The idea here is that this allows for ANY customization possible with CSS.
$.fn.toCustomFile = function () {
return this.each(function () {
var
$file = $(this), // The file input
// Necessary markup
$wrap = $('<div class="wrap">'),
$input = $('<input type="text" class="filename" />'),
$button = $('<button type="button" class="upload">Open</button>')
// Hide by shifting to the left, that way can
// still use events that are otherwise problematic
// if the field is hidden as in "display: none"
$file.css({
position: 'absolute',
left: '-9999px'
})
// Events
$button
.attr('tabIndex', -1) // disable focus on button for better usability
.click(function () {
$file.trigger('click') // Yes, `click`, not `change`. Crossbrowser compat.
})
$file
.attr('tabIndex', -1)
.on({
change: function () {
// Detect if browser supports HTML5 "file multiple"
var multipleSupport = typeof $('input')[0].multiple !== 'undefined',
files = [],
fileArr,
filename
if (multipleSupport) {
fileArr = $file[0].files
for (var i = 0, len = fileArr.length; i < len; i++)
files.push(fileArr[i].name)
filename = files.join(', ')
} else {
filename = $file.val().split('\\').pop() // Remove fakepath
}
$input.val(filename)
// Set filename as title tooltip on
// input field for better usability
$input.attr('title', filename)
},
focus: function () {
$input.trigger('focus')
}
})
$input
.on({
keyup: function () { $file.trigger('change') },
focus: function () { $file.trigger('change') },
blur: function () { $file.trigger('blur') },
// Open files when pressing [ENTER]
// on the input field
keydown: function (e) { if (e.which === 13) $file.trigger('click') }
})
// Append to DOM
$wrap.append($button, $input).insertAfter($file)
})
}
Here's a gist for ease of use: https://gist.github.com/3051209

Default text on input

How to set blank default text on input field and clear it when element is active.
In modern browsers, you may set the placeholder attribute on a field to set its default text.
<input type="text" placeholder="Type some text" id="myField" />
However, in older browsers, you may use JavaScript to capture the focus and blur events:
var addEvent = function(elem, type, fn) { // Simple utility for cross-browser event handling
if (elem.addEventListener) elem.addEventListener(type, fn, false);
else if (elem.attachEvent) elem.attachEvent('on' + type, fn);
},
textField = document.getElementById('myField'),
placeholder = 'Type some text'; // The placeholder text
addEvent(textField, 'focus', function() {
if (this.value === placeholder) this.value = '';
});
addEvent(textField, 'blur', function() {
if (this.value === '') this.value = placeholder;
});
Demo: http://jsbin.com/utecu
Using the onFocus and onBlur events allows you to achieve this, I.e.:
onfocus="if(this.value=='EGTEXT')this.value=''"
and
onblur="if(this.value=='')this.value='EGTEXT'"
The full example is as follows:
<input name="example" type="text" id="example" size="50" value="EGTEXT" onfocus="if(this.value=='EGTEXT')this.value=''" onblur="if(this.value=='')this.value='EGTEXT'" />
Or simply
<input name="example" type="text" id="example" value="Something" onfocus="value=''" />
This will not post back the default text once the box is cleared but also will allow the user to clear the box and see all results in the case of an autocomplete script.
Declare styles for inactive and active states:
.active {
color: black;
}
.inactive {
color: #909090;
}
Add the Javascript to handle the changing of state:
function toggleText(el)
{
var v = el.value;
//Remove text to allow editing
if(v=="Default text") {
el.value = "";
el.className = "active";
}
else {
//Remove whitespace
if(v.indexOf(" ")!=-1) {
split = v.split(" ").join("");
v = split;
}
//Change to inactive state
if(v=="") {
el.value = "Default text";
el.className = "inactive";
}
}
}
Add your input box, with the default value set, the inactive class set and Javascript handlers pointing to the toggleText() function (you could use event listeners to do this if you wish)
<input type="text" value="Default text" class="inactive" onFocus="toggleText(this);" onBlur="toggleText(this);">
From a usability point of view the text in the input component should be preserved only for user's input purposes. The possible default value in the input should be valid if left untouched by the user.
If the placeholder text is meant to be a hint for how to fill the input, it is better to be blaced near the input where it can be seen also when the input has been filled. Moreover, using a placeholder text inside text components can cause troubles e.g. with braille devices.
If a placeholder text is used, regardless of usability guidelines, one should make sure that it is done in an unobtrusive way so that it works with user agents without javascript or when js is turned off.
I have found jQuery plugin (http://www.jason-palmer.com/2008/08/jquery-plugin-form-field-default-value/) and use it :)
What I did is put a placeholder attribute for modern browsers:
<input id='search' placeholder='Search' />
Then, I made a fallback for older browsers using JQuery:
var placeholder = $('search').attr('placeholder');
//Set the value
$('search').val(placeholder);
//On focus (when user clicks into the input)
$('search').focus(function() {
if ($(this).val() == placeholder)
$(this).val('');
});
//If they focus out of the box (tab or click out)
$('search').blur(function() {
if ($(this).val() == '')
$(this).val(placeholder);
});
This works for me.
You can use this plugin (I'm an co-author)
https://github.com/tanin47/jquery.default_text
It clones an input field and put it there.
It works on IE, Firefox, Chrome and even iPhone Safari, which has the famous focus problem.
This way you do not have to be worried about clearing input field before submitting.
OR
If you want to HTML5 only, you can just use attribute "placeholder" on input field
You can use placeholder attribute.
np. <input type="text" name="fname" placeholder="First name">
check http://www.w3schools.com/tags/att_input_placeholder.asp

Categories

Resources