Paste Event on html div without content editable - javascript

I need to bind the paste event on div, so that i can grab the image from clipboard and assign it to a angular scope variable. This works fine in chrome but it doesn't work on IE 11 without adding contenteditable=true attribute. The problem with content editable is it breaks existing drag and drop featue of div.
I was looking similar to snag.gy where we can paste without contenteditable.
Any guidance please
[update]
Js Fiddle for test https://jsfiddle.net/sfL6ympx/
- you can remove contenteditable=true and check

I think I understand what you're trying to do. But, snag.gy does it without contenteditable=true because their pasting event is not dependent on a particular element in their DOM. So, it's a window.onkeyDown event.
You can combine them both for your need. Once, the div is clicked, set the focus on it. And when there is a keyDown event on that div, check:
if( (event.keyCode == 86 || event.which == 86) && event.ctrlKey )
'86' is the keyCode for V. Then, execute your code within that block!

Actually, with a little bit of reverse engineering we can see that snag.gy does use contenteditable=true, with some css to hide it and some javascript to make sure it gets the focus before the paste event.
Here's how to do it:
Demo: https://jsfiddle.net/raine/zyf40Lnc/40/show
Fiddle: https://jsfiddle.net/raine/zyf40Lnc/40/
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
/* invisible paste capture element */
#paste-capture-parent {
z-index: -500;
width: 0;
height: 0;
overflow: hidden;
position: fixed;
}
#paste-capture-area {
-webkit-user-select: auto !important
}
</style>
</head>
<body>
<div id="paste-capture-parent">
<div id="paste-capture-area" contenteditable="true"></div>
</div>
<pre id="output"></pre>
<script type="text/javascript">
// get elements
const captureArea = document.getElementById('paste-capture-area')
const output = document.getElementById('output')
// focus the capture area when a key is pressed
document.addEventListener('keydown', () => captureArea.focus())
// detect paste on capture area
captureArea.addEventListener('paste', e => {
const text = e.clipboardData.getData('text/plain')
output.innerHTML += `You pasted: "${text}"\n`
})
</script>
</body>
</html>

Related

Range text is same after deselect in contenteditable

I have a "mouseup" event handler inside a contenteditable to check wether text has been selected or not. If you highlight text after typing, all is good, but if you click again (to deselect text) the console shows that range.toString() is the same despite no text being selected.
http://jsfiddle.net/xpvt214o/857876/
type something in the contenteditable, then select it, then click again (to deselect) and check the console. Both console.logs will be the same.
I need to differentiate between a real selection and a deselection. If this is normal behavior, how can I tell the two events apart, or how can I do it differently to prevent this behavior?
Indeed, Chrome does change the active selection after the mouseup event.
You could add an hackish timeout to this event, which might break some times...
Or you could use the Selection API's selectionchange event.
This event will fire every time the selection does change:
$(document).on('selectionchange', function() {
console.log(getSelection().toString());
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true" id="container">Select this dummy text</div>
Added benefit is that it will also work for keyboard selections.
And to get whether this event was a selection or an unselection, you can check if the content of the selection is empty, or if the current range is collapsed:
$(document).on('selectionchange', function() {
var isUnselect = getSelection().getRangeAt(0).collapsed;
viewer.style.backgroundColor = isUnselect ? 'red' : 'green';
})
#viewer{
width: 20px;
height: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="viewer"></div>
<div contenteditable="true" id="container">Select this dummy text</div>
Please check if this helps.
$('#container').mouseup(function() {
console.log(getSelectedText());
});
function getSelectedText() {
if (window.getSelection) {
return window.getSelection().toString();
}
return '';
}

Safari IOS - Input doesnt lose focus on click outside (Blur dont trigger)

I dont know why the blur event does not trigger when I click outside the input text (on the paragraph in yellow). So the keyboard cant close. The only way I can trigger it is when I click on the body (in blue in the snippet).
I have put many console.log for debugging.
What is even more weird is that when I remove the event click on the document, the click on body dont work anymore!
The problem occurs on Safari IOS. I have tested on Iphone 6.
Any idea ?
Thanks for your help
<!DOCTYPE html>
<html lang="en" style="height:200px; background:blue">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body style="height:200px; background:gray">
<form action="" style="background:purple">
<input type="text" name="test" id="test">
</form>
<p style="height:50px; background:yellow" >Paragraph</p>
<script>
$(document).ready(function() {
$(document).on('click', function() {
console.log('document click')
});
$('input').click(function(event) {
console.log("input click");
});
$('input').blur(function(event) {
console.log('input blur');
});
$('input').focusout(function(event) {
console.log('input focustout')
});
$('body').on('click', function(event) {
console.log('body click');
console.log(event);
});
});
</script>
</body>
</html>
I found a hack for this:
document.body.firstElementChild.tabIndex = 1
This makes the first element in the body focusable thus when you click "outside" the input it loses focus. At the same time you don't see any visual glitches on that focused element because there is not style defined (unless your first body child element is something other than div)
A less hacky solution might be to call
document.activeElement.blur()
in the event listener that triggers on clicks outside the <input /> element. activeElement has great browser support.
You might also want to check in the event listener that the intended input currently has focus with something like
if (document.activeElement.id === 'foo') document.activeElement.blur()
or
if (document.activeElement.hasAttribute('bar')) document.activeElement.blur()
to ensure you're not randomly blurring some other active element whenever tapping outside your input field.
Update Dec 7, 2019
Turns out there's an even simpler solution. Unlike blur, the mouseleave event does fire on mobile Safari if you tap outside an input element. If you're using React, it's as simple as
<input onMouseLeave={e => e.target.blur()} />
Or, in plain JS:
const input = document.getElementById('foo')
input.addEventListener('mouseleave', e => e.target.blur())
event.currentTarget.blur() may be even safer than event.target (i.e. certain to be the intended input element) but I found both work fine.

Scrollable textarea in Phonegap/Cordova

I have some textarea elements where a user can enter a message to a companion.
These are presented in a modal in the Phonegap WebView.
When the modal is present on screen I disable the scrolling on the WebView body like so:
document.ontouchmove = function(e) {
e.preventDefault();
};
Likewise when I hide the modal I re-enable it like so:
document.ontouchmove = function(e) {
return true;
};
The textarea elements do not seem to be able to scroll on touch events. I looked into this and tried applying the following CSS:
overflow-y: scroll; /* has to be scroll, not auto */
-webkit-overflow-scrolling: touch;
But this did not help.
When the user enters some long text the textarea moves in line with the amount of text but a user cannot scroll back to a previous position.
Is there a solution to this?
You could just look to see if the move event was coming from a textarea and allow those events to pass through.
document.ontouchmove = function(e){
if(e.srcElement.type !== "textarea"){
e.preventDefault();
}
};
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.3/jquery.mobile-1.4.3.min.js"></script>
Add jquery Mobile js in head tag .. it will work

How can I execute a function when a disabled checkbox is clicked?

I have a checkbox on a page that is disabled until some criteria is met.
In an effort to give the user some information, I'd like to have a 'tool tip' display when the user tries to click on the disabled checkbox. The problem I'm having is that I can't get the onClick event to trigger on the checkbox.
Here is some sample code:
<script>
function notify() {
alert("Hello");
}
</script>
<input type="checkbox" onclick="notify();" id="thisOneWorks"/>
<input type="checkbox" onclick="notify();" id="thisOneDoesnt" disabled/>
When the checkbox is enabled, the onClick event will fire.
When the checkbox is disabled, the onClick event will not fire.
My question is: How can I execute a function when a disabled checkbox is clicked?
I was looking through StackOverflow yesterday and found this solution in a question somewhere, but I now I can't find it again. When I find it, I'll link back to it.
The Fix
In order to capture clicks on a disabled checkbox, you can overlay a div above the disabled checkbox, and the div will receive all the onClick events (demo here):
<style type="text/css">
.checkboxWrapper {
position: relative;
}
.checkboxOverlay {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
</style>
<script type="text/javascript">
function notify() {
alert("Hello");
}
</script>
<span class="checkboxWrapper">
<input type="checkbox" disabled/>
<div class="checkboxOverlay" onclick="notify();"></div>
</span>
This places the div over the checkbox.
Internet Explorer
There's a bug in Internet Explorer, where the div is forced beneath the checkbox, and so the div can't receive click events because the checkbox blocks it. I've read that this happens because Internet Explorer treats the checkbox as an ActiveX control, and ActiveX controls get placed above all other elements.
In order to get around this Internet Explorer bug, we need to place a background on the div. I'm not sure why, but that causes the div to pop to the top. We can just create a transparent image and use it as the background for the div. I created a 1x1 transparent gif and set it as the background on the checkboxOverlay div:
.checkboxOverlay {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: url(img/transparent.gif) repeat;
}
Now it will work in Internet Explorer.
$('.mycontainer').delegate(':checkbox:disabled', 'click', function(e) {
//do stuff
});
Try wrapping each input in a div and attaching the onclick to the div. On a side note, you'd probably want the tooltip to show on hover instead of on click. Take a look at YUI's event utility if you're not using a library.
If you don't want to wrap the checkbox in a div, then consider not diabling checkbox and modifying the built-in click event on the checkbox:
document.getElementById("checkboxId").addEventListener("click", function (event) {
event.preventDefault();
//The code you want to be run when the checkbox is clicked
});
In Angular 4+
.html ->
<label class="round-check" (click)="validate()">
<input type="checkbox" [(ngModel)]="item.isChecked" [disabled]="true">
<span> {{item.text}}</span>
</label>
.ts ->
validate(){
this._toastr.warning('your warning msg')
}
Using jQuery it is simple: $('#thisOneDoesnt').trigger('click'); Live demo here. Using clean javascript doesn't work: document.getElementById('thisOneDoesnt').click(); - i don't know why, but i'm working on it.
EDIT
In JavaScript You can enable, click and disable checkbox. Live demo here.
document.getElementById('thisOneDoesnt').disabled = false;
document.getElementById('thisOneDoesnt').click();
document.getElementById('thisOneDoesnt').disabled = true;

How do a get buttons not to take the focus?

I want my (ExtJS) toolbar buttons not to grab the focus on the web page when they are clicked, but to do their "thing" while leaving the focus unchanged by the click. How do I do that?
Cancelling the default behavior of onmousedown prevents an element from getting the focus:
// Prevent capturing focus by the button.
$('button').on('mousedown',
/** #param {!jQuery.Event} event */
function(event) {
event.preventDefault();
}
);
document.activeElement stores the currently focussed element.
So on your toolbar, you can add a "mousedown" handler to this function :
function preventFocus() {
var ae = document.activeElement;
setTimeout(function() { ae.focus() }, 1);
}
Try this example :
<html>
<head>
<script>
function preventFocus() {
var ae = document.activeElement;
setTimeout(function() { ae.focus() }, 1);
}
</script>
</head>
<body>
<input type="text"/>
<input type="button" onmousedown="preventFocus()" onclick="alert('clicked')" value="Toolbar" />
</body>
</html>
This usually does the trick for me:
<button
tabindex="-1"
onclick="javascript:console.log('do your thing')"
>My Button</button>
From https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex:
A negative value (usually tabindex="-1") means that the element should be focusable, but should not be reachable via sequential keyboard navigation. It's mostly useful to create accessible widgets with JavaScript.
I don't think there's an easy way to do what you want to do because it's the browser's default behaviour.
You could of course blur() the button as soon as it is clicked, but that would simply unselect everything. To have the previously active object regain focus, you'd have to create a "memory" of sorts by adding a blur handler for every element to keep track of which element had/lost focus last (store the id of the element in a global and update it when an element loses focus).
The top-voted answer is technically correct, but depends on jQuery...
Here's a simpler example:
<span onclick="document.execCommand('bold', false);" onmousedown="event.preventDefault();"></span>
My solution is to replace <button /> with <div /> and style it as a button.
Looks like Div doesn't take a focus on it when you click it.
Because the toolbar buttons are just styled ordinary HTML button elements then this is an actual browser behavior, and you should think twice before changing it. But nevertheless...
You should be able to prevent the botton from receiving focus by just returning false from its onclick handler.
Maybe you should try to use stateful and state change properties for form fields or whatever to get focus back?
I would attach one blur event listener to all fields. This listener should save the field, that lost the focus, in a global variable.
Then all the toolbar button should get one focus event listener. This listener should focus the field, that was saved as described above.
This code should work, although it didn't test it
<script>
function focusor(){
document.getElementById('focus').focus;
}
document.onkeydown = focusor;
document.onclick = focusor;
</script>
<div style="width: 0px; height: 0px; overflow: hiddden;">
<button id="focus"></button>
</div>
What I have found, is you will have to make a dummy element, I found buttons to work best in this situation. put the button in a div and make the div 0px.
[do not make the div display none, some browsers will just ignore it]
Basically any click or button presses, it will focus on this dummy button.
I had a project very similar and whenever they pressed the down key it selected the first button on the page, this just focuses on the button over and over again.
Sort of jacked up, but it works.
All these answers are wack. Here's a very excellent trick that only uses CSS
<button type="submit" disabled>
<span>Submit</span> <!-- the <span> is the secret -->
</button>
Now in your css:
button[disabled] > * {
pointer-events: none;
}
The trick is the inner span has to be used, otherwise the button will still steal focus away from inputs.

Categories

Resources