How to get copied value from ctrl+v key event in javascript - javascript

This method detects ctrl + v event but I couldnt find how to get the value of it ?
Thanks in advance,
$(".numeric").keydown(function (event) {
if (event.shiftKey) {
event.preventDefault();
}
switch (event.keyCode) {
case 86:
if (event.ctrlKey) { // detects ctrl + v
var value = $(this).val();
alert(value); // returns ""
}
break;
}

All you have to do it hook into the paste event, let it finish by breaking the callstack and then read the value.
It might seem ugly but it is very crossbrowser friendly and saves you creating a lot of crappy code just to read the actual clipboard.
$(".numeric").bind('paste', function (event) {
var $this = $(this); //save reference to element for use laster
setTimeout(function(){ //break the callstack to let the event finish
alert($this.val()); //read the value of the input field
},0);
});
See it in action here: http://jsfiddle.net/Yqrtb/2/
Update:
Since i just recently had to do something similar, i thought i'd share my final implementation, it goes like this:
$('textarea').on('paste',function(e) {
//store references for lateer use
var domTextarea = this,
txt = domTextarea.value,
startPos = domTextarea.selectionStart,
endPos = domTextarea.selectionEnd,
scrollTop = domTextarea.scrollTop;
//clear textarea temporarily (user wont notice)
domTextarea.value = '';
setTimeout(function () {
//get pasted value
var pastedValue = domTextarea.value;
//do work on pastedValue here, if you need to change/validate it before applying the paste
//recreate textarea as it would be if we hadn't interupted the paste operation
domTextarea.value = txt.substring(0, startPos) + pastedValue + txt.substring(endPos, txt.length);
domTextarea.focus();
domTextarea.selectionStart = domTextarea.selectionEnd = startPos + pastedValue.length;
domTextarea.scrollTop = scrollTop;
//do work on pastedValue here if you simply need to parse its ccontents without modifying it
}, 0);
});

It's very much browser dependent. The data is in the event passed to your handler. In safari/chrome, we are listening for the paste event on the input and then doing
event.clipboardData.getData('text/plain')
in the callback and it seems to work ok. You should use your favorite debugger and put a breakpoint into your paste event handler, and look at the event that is passed in.

You need a hack. I've detailed one on Stack Overflow a few times before:
How can I get the text that is going to be pasted in my html text editor?
Pasting into contentedittable results in random tag insertion
JavaScript get clipboard data on paste event (Cross browser)

It's very simple, code below works fine, in my case takes text contained on clipboard.
function onPaste(info) {
var copied = event.view.clipboardData.getData("Text");
alert(copied);
}
In this case variable called copied contains the value that you need.

Related

How to tell if pasted data was copied from my page?

I'm trying to write a wysiwyg editor. I don't want people to be able to paste in foriegn html, so I figured I could convert it to text. But I still want the html to be pasted if it originated from the same element (or across the site if possible).
So is there a way to detect from a paste event where the content came from?
Detect the copy event (https://developer.mozilla.org/en-US/docs/Web/API/Element/copy_event).
Use the setData API to include a custom data type e.g. text/whatever. This can include pretty much anything, like where the user copied from, when, etc. You can even upload your own custom data representation in there.
When pasting, grab the corresponding event and look for your custom data type.
Edit: My bad, didn't read carefully about having to preventDefault.
document.addEventListener('copy', (event) => {
event.clipboardData.setData('text/test', 'sum text here');
const selection = document.getSelection();
// Essentially brute force copying selection.
const range = selection.getRangeAt(0);
const div = document.createElement('div');
div.appendChild(range.cloneContents());
const copy = div.innerHTML;
event.clipboardData.setData('text/html', copy);
event.preventDefault();
});
document.addEventListener('paste', (event) => {
const clipboard = (event.clipboardData || window.clipboardData);
let pasteTest = clipboard.getData('text/test');
let paste = clipboard.getData('text/html');
console.log (paste, '###########', pasteTest);
});
In the copy event of your editor you should add something (unique sign) into it just like a special wrap, so when in paste event you just need to judge whether the data is from your editor according to your sign.
var let_paste = false;
function handleCopy (e) {
var clipboardData, pastedData;
pastedData = e.clipboardData.getData('Text');
// When let_paste is true the content have been copied from this site
let_paste = true;
alert('let it paste!')
}
document.getElementById('myDiv').addEventListener('copy', handleCopy);
<div id='myDiv' contenteditable='true'>Copy</div>
Consider this code above - my idea is that you set a global variable that control if the content has been copied from this site or not - make an event to set it to true when the content is copied from your site. Then, save the content itself in a variable and compare with the pasted content when the user do the "paste" event.

JS event function being fired only once

I'm trying to create a simple form validator for a Handlebars template. So, I used addEventListener on blur to validate the inputs but the event is being fired only once. Am I doing this right? Or is there a better way / recommended good practice for this ?
Here is JSFiddle: http://jsfiddle.net/jj4fsn9j/
function addInputValidation(el, event) {
el.addEventListener(event, function() {
var data = {
invalid: {}
};
data.invalid[el.id] = false;
data[el.id] = el.value;
console.log(el.value);
if (typeof el.value === 'undefined' || el.value === '') {
data.invalid[el.id] = true;
}
console.log(data);
updateTemplate(data);
});
Can someone help me with this ?
With each onblur-event you are calling updateTemplate(data) which in turn leads to this line:
document.getElementById('body').innerHTML = html;
Which means that everytime the event is fired, you overwrite the entire document with new content. Therefore, all the event handlers get lost.
See your updated fiddle where i - just as an example - have removed the updateTemplate() function. You will notice that here the event handlers fire accordingly, as many times as needed.
It is not good practice anyway to overwrite your entire document with every firing of an event. Either overwrite only the part of it that requires overwriting, or - if you need to stick to overwriting the entire document - make sure that you run addInputValidations() again after you change the innerHTML of the body. Again, i would like to stress though, that overwriting your body's content over and over is bad practice.

always trigger "change"-event for <select>, even if the select2-option clicked is already selected

I have a native <select>-element based on which I'm initializing a select2-dropdown-menu.
I bound a change-event via select2 which is called whenever the select2/select-option is changed. However, I need to fire the event even if the currently selected option is selected again.
function onSelectChange(){
alert('changed');
};
$("#select").select2().bind('change', onSelectChange);
I prepared a http://jsfiddle.net/rb6pH/1/ - if "Alaska" is currently selected and then selected again via the select2-dropdown, onSelectChange() should fire again, triggering the alert.
I have a hard time expressing myself, please ask if something isn't clear enough.
Motivated by the absolutely valid remarks by #FritsvanCampen, I sat my ass down and figured out a way myself: What I really needed was a way to access the currently selected val, even if it hadn't changed. By using select2's undocumented close-event instead of change, I can access just that like so:
function onSelectChange(event){
alert( $("#select").select2("val") );
};
$("#select").select2().bind('close', onSelectChange);
Find an updated jsFiddle at http://jsfiddle.net/rb6pH/42/
A similar question was asked here. I have made a fiddle for your question based on the code in the link.
http://jsfiddle.net/rb6pH/55/
function onSelectChange(){
alert('changed');
};
var select2 = $("#select").select2().data('select2');
select2.onSelect = (function(fn) {
return function(data, options) {
var target;
if (options != null) {
target = $(options.target);
}
if (target) {
onSelectChange();
return fn.apply(this, arguments);
}
}
})(select2.onSelect);
I think you might refer to this link, i stuck once in same situation,
Change event is not fired when the selection is changed using Select2's val() method.
The event object contains the following custom properties:
val
the current selection (taking into account the result of the change) - id or array of ids.
added
the added element, if any - the full element object, not just the id
removed
the removed element, if any - the full element object, not just the id
For more information you might refer to this.
Thanks!
I read the question and it's so close to my problem so I decided not to post another question. What I want to do is after select2 closed, a simple text input become focused but it doesn't work. please check
function onSelectChange(){
alert('closed');
$('#hey').focus();
};
$("#select").select2().bind('close', onSelectChange);
$('#hey').on('focusin)', function(){alert('in');}
http://jsfiddle.net/sobhanattar/x49F2/5/
I tried to make sure that the input become focused and it showed that the input become focused but I don't know why it doesn't show the curser
a little old question but i spent a few hours last week to find a solution.
I am using Select2 version: 4.0.5.
My working solution is this one:
$("#exampleId").on("select2:open", function() {
var checkExist = setInterval(function() {
var $selectedChoiceInsideSelect2Dropdown = $("li.select2-results__option[id^='select2-" + exampleId + "-result'][aria-selected=true]");
if ($selectedChoiceInsideSelect2Dropdown.length) {
$selectedChoiceInsideSelect2Dropdown.on("mouseup", function() {
$(this).trigger("change");
});
clearInterval(checkExist);
}
}, 100); // check every 100ms
});
It's very important to use the interval!
var prev_val = $('#select2').val();
$('#select2').blur( function() {
if( $(this).val() == prev_val )
// not changed
else {
// changed
prev_val = $(this).val();
}
});

Copy to Clipboard for all Browsers using javascript

I was trying to make "Copy to Clipboard" work on all browsers but no luck.
Am using javascript and I don't want to use Zero Clipboard to do.
Please let us know what wrong in my code.
Appreciate for your help.
Below is the code (Currently my code is working only on IE browser):-
<script type="text/javascript">
function copyToClipboard(s)
{
if( window.clipboardData && clipboardData.setData )
{
clipboardData.setData("Text", s);
}
else
{
// You have to sign the code to enable this or allow the action in about:config by changing
user_pref("signed.applets.codebase_principal_support", true);
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var clip = Components.classes['#mozilla.org/widget/clipboard;[[[[1]]]]'].createInstance(Components.interfaces.nsIClipboard);
if (!clip) return;
// create a transferable
var trans = Components.classes['#mozilla.org/widget/transferable;[[[[1]]]]'].createInstance(Components.interfaces.nsITransferable);
if (!trans) return;
// specify the data we wish to handle. Plaintext in this case.
trans.addDataFlavor('text/unicode');
// To get the data from the transferable we need two new objects
var str = new Object();
var len = new Object();
var str = Components.classes["#mozilla.org/supports-string;[[[[1]]]]"].createInstance(Components.interfaces.nsISupportsString);
var copytext=meintext;
str.data=copytext;
trans.setTransferData("text/unicode",str,copytext.length*[[[[2]]]]);
var clipid=Components.interfaces.nsIClipboard;
if (!clip) return false;
clip.setData(trans,null,clipid.kGlobalClipboard);
}
}
</script>
<textarea id='testText' rows="10" cols="100">Enter your Sample text</textarea><br />
<button onclick="copyToClipboard(document.getElementById('testText').value);" >clipboard</button><br /><br />
<textarea rows="10" cols="100">Paste your text here</textarea><br />
This works on firefox 3.6.x and IE:
function copyToClipboardCrossbrowser(s) {
s = document.getElementById(s).value;
if( window.clipboardData && clipboardData.setData )
{
clipboardData.setData("Text", s);
}
else
{
// You have to sign the code to enable this or allow the action in about:config by changing
//user_pref("signed.applets.codebase_principal_support", true);
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var clip = Components.classes["#mozilla.org/widget/clipboard;1"].createInstance(Components.interfaces.nsIClipboard);
if (!clip) return;
// create a transferable
var trans = Components.classes["#mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
if (!trans) return;
// specify the data we wish to handle. Plaintext in this case.
trans.addDataFlavor('text/unicode');
// To get the data from the transferable we need two new objects
var str = new Object();
var len = new Object();
var str = Components.classes["#mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
str.data= s;
trans.setTransferData("text/unicode",str, str.data.length * 2);
var clipid=Components.interfaces.nsIClipboard;
if (!clip) return false;
clip.setData(trans,null,clipid.kGlobalClipboard);
}
}
I spent a lot of time looking for a solution to this problem too. Here's what i've found thus far:
If you want your users to be able to click on a button and copy some text, you may have to use Flash.
If you want your users to press Ctrl+C anywhere on the page, but always copy xyz to the clipboard, I wrote an all-JS solution in YUI3 (although it could easily be ported to other frameworks, or raw JS if you're feeling particularly self-loathing).
It involves creating a textbox off the screen which gets highlighted as soon as the user hits Ctrl/CMD. When they hit 'C' shortly after, they copy the hidden text. If they hit 'V', they get redirected to a container (of your choice) before the paste event fires.
This method can work well, because while you listen for the Ctrl/CMD keydown anywhere in the body, the 'A', 'C' or 'V' keydown listeners only attach to the hidden text box (and not the whole body).
It also doesn't have to break the users expectations - you only get redirected to the hidden box if you had nothing selected to copy anyway!
Here's what i've got working on my site, but check http://at.cg/js/clipboard.js for updates if there are any:
YUI.add('clipboard', function(Y) {
// Change this to the id of the text area you would like to always paste in to:
pasteBox = Y.one('#pasteDIV');
// Make a hidden textbox somewhere off the page.
Y.one('body').append('<input id="copyBox" type="text" name="result" style="position:fixed; top:-20%;" onkeyup="pasteBox.focus()">');
copyBox = Y.one('#copyBox');
// Key bindings for Ctrl+A, Ctrl+C, Ctrl+V, etc:
// Catch Ctrl/Window/Apple keydown anywhere on the page.
Y.on('key', function(e) {
copyData();
// Uncomment below alert and remove keyCodes after 'down:' to figure out keyCodes for other buttons.
// alert(e.keyCode);
// }, 'body', 'down:', Y);
}, 'body', 'down:91,224,17', Y);
// Catch V - BUT ONLY WHEN PRESSED IN THE copyBox!!!
Y.on('key', function(e) {
// Oh no! The user wants to paste, but their about to paste into the hidden #copyBox!!
// Luckily, pastes happen on keyPress (which is why if you hold down the V you get lots of pastes), and we caught the V on keyDown (before keyPress).
// Thus, if we're quick, we can redirect the user to the right box and they can unload their paste into the appropriate container. phew.
pasteBox.select();
}, '#copyBox', 'down:86', Y);
// Catch A - BUT ONLY WHEN PRESSED IN THE copyBox!!!
Y.on('key', function(e) {
// User wants to select all - but he/she is in the hidden #copyBox! That wont do.. select the pasteBox instead (which is probably where they wanted to be).
pasteBox.select();
}, '#copyBox', 'down:65', Y);
// What to do when keybindings are fired:
// User has pressed Ctrl/Meta, and is probably about to press A,C or V. If they've got nothing selected, or have selected what you want them to copy, redirect to the hidden copyBox!
function copyData() {
var txt = '';
// props to Sabarinathan Arthanari for sharing with the world how to get the selected text on a page, cheers mate!
if (window.getSelection) { txt = window.getSelection(); }
else if (document.getSelection) { txt = document.getSelection(); }
else if (document.selection) { txt = document.selection.createRange().text; }
else alert('Something went wrong and I have no idea why - please contact me with your browser type (Firefox, Safari, etc) and what you tried to copy and I will fix this immediately!');
// If the user has nothing selected after pressing Ctrl/Meta, they might want to copy what you want them to copy.
if(txt=='') {
copyBox.select();
}
// They also might have manually selected what you wanted them to copy! How unnecessary! Maybe now is the time to tell them how silly they are..?!
else if (txt == copyBox.get('value')) {
alert('This site uses advanced copy/paste technology, possibly from the future.\n \nYou do not need to select things manually - just press Ctrl+C! \n \n(Ctrl+V will always paste to the main box too.)');
copyBox.select();
} else {
// They also might have selected something completely different! If so, let them. It's only fair.
}
}
});
Hope someone else finds this useful :]
For security reasons most browsers do not allow to modify the clipboard (except IE, of course...).
The only way to make a copy-to-clipboard function cross-browser compatible is to use Flash.
I think zeroclipboard is great. this version work with latest Flash 11: http://www.itjungles.com/javascript/javascript-easy-cross-browser-copy-to-clipboard-solution.

How do I capture the input value on a paste event?

On my site users can paste text (in this case a url) into an input field. I'd like to capture the value of the text that was pasted using jQuery. I've got this to work in FF using the code below, but it doesn't work in IE (I don't think IE supports the "paste" event).
Anyone know how to make this work across all modern browsers? I've found a few other answers to this on SO but most are FF-only and none seemed to offer a complete solution.
Here's the code I have so far:
$("input.url").live('paste', function(event) {
var _this = this;
// Short pause to wait for paste to complete
setTimeout( function() {
var text = $(_this).val();
$(".display").html(text);
}, 100);
});
JSFiddle: http://jsfiddle.net/TZWsB/1/
jQuery has a problem with the live-method with the paste-event in the IE; workaround:
$(document).ready(function() {
$(".url").bind('paste', function(event) {
var _this = this;
// Short pause to wait for paste to complete
setTimeout( function() {
var text = $(_this).val();
$(".display").html(text);
}, 100);
});
});
Fiddle: http://jsfiddle.net/Trg9F/
$('input').on('paste', function(e) {
// common browser -> e.originalEvent.clipboardData
// uncommon browser -> window.clipboardData
var clipboardData = e.clipboardData || e.originalEvent.clipboardData || window.clipboardData;
var pastedData = clipboardData.getData('text');
});
Listen for the change event as well as paste. change will reliably fire on a changed field before submission, whereas paste only happens on browsers that support it on an explicit paste; it won't be triggered by other editing actions such as drag-and-drop, cut-copy, undo-redo, spellcheck, IME substitution etc.
The problem with change is that it doesn't fire straight away, only when editing in a field is finished. If you want to catch all changes as they happen, the event would be input... except that this is a new HTML5 feature that isn't supported everywhere (notably: IE<9). You could nearly do it by catching all these events:
$('.url').bind('input change paste keyup mouseup',function(e){
...
});
But if you want to definitely catch every change quickly on browsers that don't support input, you have no choice but to poll the value on a setInterval.
Even better is it to use e.originalEvent.clipboardData.getData('text'); to retrieve pasted data;
$("input").on("paste", function(e) {
var pastedData = e.originalEvent.clipboardData.getData('text');
// ... now do with pastedData whatever you like ...
});
This way you can avoid timeouts and it is supported on all major browsers.
Maybe try using the onblur event instead. So the user c/p into the input and when they leave the field the script checks what's there. This could save a whole lot of hassle, since it works for mouse and key c/p as well as manually entered input.

Categories