A widget I'm using modifies an HTML textarea element. I need to know when that element has been modified and preferably I'd like to actually hide that element as well. I'm using jQuery, so I naturally tried the $('#textarea_id').change() event. But it's never triggered because I guess the textarea never loses focus.
What's the best way to monitor that textarea, preferably hidden (CSS has display:none)? Please don't tell me setInterval...
You could manage this with a global variable.
var text = "";
$('#textarea_id').bind("keyup paste", function(e){
if ($(this).val() != text)
{
// text changed
text = $(this).val();
}
});
working example: http://jsfiddle.net/n8keN/
I would use .keyup(). If you don't want the event to fire every keypress, have it restart a half second timer every keypress and have the timer trigger the things you want to happen when the user stops typing. You can play with the time to get it to your liking.
Related
So, I have a simple question and I actually already wrote it in the title. :) But I will repeat it one more time, just to be completely clear. And the questions is:
Is there a way to know if "blur" was called by "element.blur()" or if it was "actual" blur? By saying "actual" I mean, clicking on some random area to make input lose focus, or by clicking TAB. :)
Of course. You should attach the blur event to the specific element you want.
An example would be:
<input id="myInput" type="text" />
function handleBlur(event){
console.log(event.target); // outputs: <input id="myInput" type="text">
}
document.getElementById('myInput').addEventListener('blur', handleBlur);
This function will only be called when blur event occurs for that input only. Nevertheless, you could use event.target to see the element that triggered the blur event.
EDIT:
Tested only on Chrome, but the following achieves what you are requesting.
<input id="myInput" type="text" />
function handleBlur(event){
if(event.sourceCapabilities !== null){
console.log('blur by user');
}
else{
console.log('blur programmatically')
}
}
var elem = document.getElementById('myInput');
elem.addEventListener('blur', handleBlur);
elem.focus();
elem.blur();
Try it online on jsfiddle.
Since each browser handles event differently though, my suggestion is to trigger a different, custom event to handle this case.
ooooo there's 2 different types of blur, one is an event called blur or onBlur for jQuery users which is for 'out of focus' basically the user clicks it and then clicks somewhere else. That's onBlur. Another is blur the CSS filter value for the filter property.
So! There's a few ways to see if an element is 'out of focus' one is like this:
var blur = true;//we start off not focused
element.addEventListener('blur', function() {
blur = true;
});
element.addEventListener('focus', function() {
blur = false;
});
So basically the above is "If it's not focused we are blured, if we are out of focus we blur". (Feel I'm making this more complicated to understand?). Try using element.blur() and element.focus() in the console and see what happens!
Another method is simply to check that the active element (focused element) is not your element.
document.getActiveElement.id !== element.
In jQuery there is a :focus prop you can use in the selector like so $('element:focus') which is also handy for :checked to get a checked radio button $('input[type="radio"]:checked')
Unfortunately though I don't think there's a way to see if another tab has been click. There probably is a way but in my experience, I had previously made a JS clock which I added to the title which appears as the tab's name. It didn't update when the tab was not opened so I think there's probably some more voodoo to look at to run your JS when the page is not in focus
I know this can be done with the .change() event and put $('#console').scrollTop($('#console')[0].scrollHeight); in it.But problem is that textarea is readonly and I am using javascript to enter the text in textarea.
For ex:-
$('#console').text($('#console').text()+'\n>_ Optained Trigger');
In this case the textarea is not scrolltobottom because change event it not responding.
Any alternative for it or any other event that capture javascript text change in textarea?
You can chain jQuery operations that affect your element without the need of events:
$('#console').text($('#console').text()+'\n>_ Optained Trigger').scrollTop($('#console')[0].scrollHeight);
edit: Ok, I read your comments, and to solve that you could trigger the change event manually
//first define the event behaviour
$('#console').on('change', function(e){
var console = $(this);
console.scrollTop($('#console')[0].scrollHeight);
}
//then every time you modify the text, trigger the event
$('#console').text($('#console').text()+'\n>_ Optained Trigger').trigger('change')
I'm catching paste events with $('selector').on('input', function(event) { ... });
Then I'm trying to test what's been pasted and if it doesn't pass validation, cancel the paste with event.preventDefault(). Unfortunately, by the time the listener function is executed, the text has already been pasted and event.preventDefault() does nothing.
So what's a good way to catch paste events, and if what's been pasted doesn't validate, undo/prevent the paste?
I know I can use .on('paste', function(event) { ... }), but that doesn't give me the text that's been pasted or the contents of the input element after the paste, unless I use setTimeout() with some minute wait time, and I'd like to avoid using setTimeout().
First of all some background on event trigger order for the input element:
keydown -> keypress -> paste -> input -> keyup -> change
Whenever you call preventDefault it stops the chains, like nothing happened.
So my suggestion is to catch the paste event, prevent its default behavior and do your logic there.
I know I can use .on('paste', function(event) { ... }), but that
doesn't give me the text that's been pasted or the contents of the
input element after the paste
Actually you can retrieve the content of the clipboard. See this doc. Support is all major browser (but only IE11+). I do not know if by the time of the writing of the question this functionality was available or not.
Fiddle example
$('#myInput').on('paste', function(e) {
// Cancel the event - this prevents the text from being entered into the input and stops the event chain
e.preventDefault();
// Get the content of the clipboard
let paste = (event.clipboardData || window.clipboardData).getData('text');
// Validate what it is pasted
if (paste == "text to paste") {
// If condition is satisfied manually set the value of the input
$(this)
.val(paste)
// Manually trigger events if you want
.trigger('input')
.trigger('change');
}
});
Notes on the code:
This solution does not include setTimeout. Whenever you make it with setTimeout you see for a very short time the text being pasted, like a blinking effect.
If text meets condition I manually set it in the input. However this does not trigger input and change events. If you need them, just manually trigger them
Similar approach is to first check the text and if it does not meet requirements then call preventDefault, otherwise do nothing. This way you avoid manually setting value in the input and triggering events afterward.
Try using .change event of jquery.
Set value to blank if value doesn't satisfy your condition.
Using
$('selector').on('input', function(event) { ... });
and in case the validation does not pass deleting the pasted text seems to work for me.
Sadly accessing the clipboard has some flaws (browser asking if it is allowed to inspect the clipboard, cross browser compatibility, etc.)
If you are okay with saving the last value of the input, the pasted text can be calculated anyway.
Here is my approach for calculating the pasted text
https://jsfiddle.net/f710o9qd/2/
I hope this helps you :)
(Feel free to refine the calculation of the pasted text if you find any flaws)
My understanding from the question is, we must not allow any data to be pasted inside the text box until and unless it pass a specific validation. Instead of using event.preventDefault(), we can capture the value when user input any content, using on('input') listener and validate it against the specific condition and if the validation gets failed, empty the text box value.
(This is the workaround if we still need to use on('input') event listener)
Sample Code (I am using console.log() for printing the pasted value):
HTML:
<input type='text' id="selector" />
JS:
$(document).ready(function() {
$('#selector').on('input', function (e){
if(e.target.value !== "myValue"){
$('#selector').val('');
}
else{
console.log(e.target.value);
}
});
});
How can I reliably detect all events that cause the the value of an HTML select to change, while that element still has the focus?
For regular mouse input, either the click or change event works fine. For keyboard input (and for mouse input using the scroll wheel), however, the change event doesn't fire until focus is lost. I get around this by using the keyup event for keyboard changes (and ignoring the mouse wheel problem) but find my code is littered with a lot of stuff like this:
$(".my-select").keyup(handleSelect).change(handleSelect);
function handleSelect() {
var $this = $(this);
// don't process keyup events that don't result in change
if ($this.data('old-val') == $this.val()) { return; }
$this.data('old-val', $this.val());
// ... other stuff ...
}
Is there a simpler pattern/recipe that solves this problem (jQuery or straight JavaScript)?
"change" doesn't fire until the element loses focus, by design. What you're doing may be the only way to solve this. You can also look at selectedIndex as well as value.
As Diodeus said, the change event is fired when the element loses focus. But you could check if the pressed key is the enter key and then call your function. And I think hardly anybody uses the mouse wheel to change the value of a select box...
Here's what I want to do. I want to trigger an event every time a select element changes. I have a multiline select and when I make changes (click on elements), it does not change until the select box loses focus. So I'm trying to force a blur every time the select box is clicked. That way if it changes, it will trigger the changed event. If it doesn't change, nothing will happen.
How do I do this? Am I even approaching this the right way? Jquery answers are okay as well.
In addition to Ender the full code could be something like this.
$('#mySelectBox').change(function() {
$('#thingToBlur').blur();
})
Reference: http://api.jquery.com/blur/
This will find the element with the focus and trigger the blur event.
function blur(){
document.querySelectorAll('input,textarea').forEach(function(element){
if(element === document.activeElement) {
return element.blur();
}
});
}
Using jQuery do:
$('#mySelectBox').change(function() {
//do things here
});
According to the documentation at http://api.jquery.com/change/, the event is triggered immediately when the user makes a selection.
Check out this demo to verify that this works: http://jsfiddle.net/AHM8j/
You could attach an onclick handler to the select and the individual options. basically onclick="this.blur();". I've always found that click events on <select> elements to be a pain, as nothing happens at the point you expect it to.
Okay, Here's what was going on. I was including the -vsdoc version of JQuery instead of the actual JQuery library. This also fixes some issues I was having with some plugins such as blockUI.