jQuery blur if new focused element is not a child - javascript

I have a blur event attached to a container (in this case, a table cell) with one or more clickable items (e.g. input fields and buttons).
Two things can happen in my cell-embedded form. If a value changes in one of the input fields, the form is processed. If a value hasn't changed, but focus is lost, then the form is cleared.
I don't want the cell to blur if the user has clicked another item within the cell.
Here's something I attempted - checking the number of focused children in the blur event.
HTML
<table>
<tr>
<td id="edit">
<input type="text"></input>
<input type="checkbox"></input>
<button>Test</button>
</td>
</tr>
</table>
JavaScript
$('table').on('change', '#edit input', function () {
alert('An input field has changed');
});
$('table').on('blur', '#edit', function () {>
if ($(this).children(':focus').length == 0) {
alert('The user has clicked away from the form');
} else {
alert('The user hasn\'t finish editing yet');
}
});
But unfortunately, the length of the focused children is always reported as 0!
Then I tried
$('body').not('#edit, #edit > *').on('focus', function () {
alert('The user has clicked something else');
});
But this doesn't work at all! And I'm also dubious about it because I require the change handler to be fired before the focus handler so the form doesn't get cancelled if the user has made changes.
Here's a jsfiddle for you lazy kids: http://jsfiddle.net/QmVsr/

A possible solution is to use a timer based approach
$('table').on('blur', '#edit', function () {
var timer = setTimeout(function(){
console.log('The user has clicked away from the form');
}, 20);
$(this).closest('td').data('blurTimer', timer)
}).on('focus', '#edit', function () {
clearTimeout($(this).closest('td').data('blurTimer'))
});
Demo: Fiddle
Note: While debugging prefer console logging instead of alerts

Related

How can I click on one element and listen for a change in another element's value?

upon clicking element with attribute 'data-one' above, an update to an email field's value occurs. how can I detect if there was a change - the new update? note that there is an async process that updates the email address post-clicking
$('a[data-one]').on('click', function() {
$('input#field_email_address').on('change', function() {
console.log('email value was change detected');
});
});
Move the change event code out of the click event code and in the click event code just update the email field as needed.
But, you'll need to manually trigger the change event of that field because change only fires when the field loses focus, which it won't if done with code.
$('a[data-one]').on('click', function() {
$('input#field_email_address').val("CHANGED!");
$('input#field_email_address').trigger("change");
});
$('input#field_email_address').on('change', function() {
console.log('email value was changed');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Test
<input id="field_email_address">
Right now you are adding a change event listener every time that you click on the a[data-one] button.
You can check the value of the email field by using the .val() method. Compare the current value against a previously stored value and see if it differs. If it does, store the new value and log your message.
var emailValue = '';
$('a[data-one]').on('click', function() {
var newEmailValue = $('input#field_email_address').val();
if (emailValue !== newEmailValue) {
console.log('email value was changed');
emailValue = newEmailValue;
}
});

javascript event handlers list

I am trying to prioritize click event in case two events click and change are fired.
I have a global function similar to "ValidateOnChange" and "ValidateOnClick" to validate input of text box on change and on click event.
Enter some text, it shows up error message. Then try to input correct value and click the Submit button, the error vanishes and this makes user to click the button twice. Here I am trying to fix this double click.
Here is mock up code:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>
<div>Enter any string:</div>
<div><input type="text" id="txtInput" ></input></div>
<div id="divError" style="color: red; display: none;">Please enter 0</div>
<input type="button" value="Submit" id="btnSubmit" ></input>
<script type="text/javascript">
var mouseevent_var = null;
function ValidateOnChange(e) {
var input = $('#txtInput').val();
if (input == '0') {
$('#divError').hide();
} else {
$('#divError').show();
}
}
function ValidateOnClick(e){
alert("Hurray!!! You got it right!");
}
$('#txtInput').mousedown(function (e) {
mouseevent_var = e;
});
jQuery(document).ready(function(){
$('#btnSubmit').click(function(e){
ValidateOnClick(e);
});
$('#txtInput').change(function(e){
ValidateOnChange(e);
});
//User don't want error when they are typing in.
//$('#txtInput').keyup(function() {
//$('#txtInput').trigger("change");
//});
});
</script>
</body>
</html>
The keyup event seemed to be solution but users don't want the error to popup when they are typing in.
Is there any way to list all the triggered events so that I could filter "mousedown" and "mouseup" events for submit button? Or is there any alternative way to prioritize click event ?
There can be many alternatives depending on the situations. I have made few minor changes to avoid the double click issue (comments amended). Basically we need to bind the mousedown event on the button object. There we will set a temporary flag variable to true. In the same time if input's change event gets fired then you can skip the checking if the temporary flag variable is true. Reason behind the double click for triggering the button's click event is better explained here: How to get jQuery click event after append in change event handler
Your updated js code below:
var mouseevent_var = false;
function ValidateOnChange(e) {
// Skip validation if the change event is fired due to user's click on submit button
if(mouseevent_var){ return false; }
var input = $('#txtInput').val();
if (input == 0) {
$('#divError').hide();
} else {
$('#divError').show();
}
}
function ValidateOnClick(e){
mouseevent_var = false; // Reset mouseevent_var to false
alert("Hurray!!! You got it right!");
}
$('#btnSubmit').mousedown(function (e) {
mouseevent_var = true;
});
jQuery(document).ready(function(){
$('#btnSubmit').click(function(e){
ValidateOnClick(e);
});
$('#txtInput').change(function(e){
ValidateOnChange(e);
});
//User don't want error when they are typing in.
//$('#txtInput').keyup(function() {
//$('#txtInput').trigger("change");
//});
});
The above code is just a fix as per your need. But there are other better alternatives too. Ideally you should not have two different validation functions for validating same fields on different events. You must think of managing it with a single function.

Trigger functions from checkbox on click by clicking on a button

I have a couple of checkboxes and a button. When I click on checkbox - function is triggered. This is the desired behavior but I want to trigger it by clicking on the button. I want to have the possibility to first select checkboxes (I tried with return false and event.preventDefault but these completely switch the selection off) and then by clicking the button - trigger functions from checkboxes. Here is a link to jsfiddle:
http://jsfiddle.net/j93k2xns/6/
So for instance: I can select 3 checkboxes (nothing should happen) and after I click the button - three alerts should appear.
The code:
HTML:
<input type="checkbox" name='check[]' id="first">first</input>
<input type="checkbox" name='check[]'>second</input>
<input type="checkbox" name='check[]'>third</input>
<input type="checkbox" name='check[]'>fourth</input>
<input type="button" value="validate" id="val-button">
JS:
var check_state;
$(document).on('click','input[name="check[]"]', function(e){
if(check_state === true) {
alert('a');
} else {
return false;
}
});
$(document).on('click','#val-button', function(){
check_state = true;
});
There are a few interpretations to his question. If I'm reading it correctly, he wants to bind an arbitrary function to the checkboxes. Clicking the button should fire this event. This is how you can achieve that using custom events in jQuery:
$(function () {
$("input[name='check[]']").bind("myCustomButtonClick", function() {
if(this.checked) {
alert('a');
}
});
})
$(document).on('click','#val-button', function(){
$("input[name='check[]']").trigger("myCustomButtonClick");
});
And the associated jsfiddle: http://jsfiddle.net/3yf7ymos/
$(document).on('click','#val-button', function(){
$( 'input[name="check[]"]' ).each(function( index ) {
if($(this).is(':checked')) {
alert("a");
return true;
}
});
});
If you want to do something when the user checks a checkbox, add an event listener:
$('input[type="checkbox"]').click(function() {
if ($(this).is(':checked')) {
// do something
}
});
If the idea is run a couple of functions after the inputs are checked by clicking on a button:
function myFunction() {
if ($('input[id="something"]:checked').length == 0) {
// do something
} else if ($('input[id="something_2"]:checked').length == 0) {
// do something
}
//and so on..
}
$('#val-button').click(function() {
myFunction();
});
I have a similar inquiry. I have a number of check boxes. Each checkbox is linked to a different URL that opens a PDF form. I want my team to be able to select which forms they need by ticking the checkbox. Once they have done that, I would like a button to trigger the opening of each form based on which check box is checked. I have it so the checkbox upon being checked opens the form right away but it is very distracting. Its preferable they all get opened at once by a "button". Help. I am quite new to JavaScript so may need additional clarity.

Why isn't jquery detecting when a radio button is unchecked? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JQuery $(#radioButton).change(…) not firing during de-selection
I have the following HTML/jQuery:
<input id="rb1" type="radio" name="rb" checked="true">
<input id="rb2" type="radio" name="rb">
$("#rb2").change(function () {
if ($(this).is(":checked")) {
alert('checked');
}
else {
alert('unchecked');
}
});
When my rb2 radio button is unselected by selecting rb1, the change event does not fire. Why is this? Is it possible to get this working without changing my selector to match both inputs and then looking at the ID?
Fiddle: http://jsfiddle.net/4uRWR/
The change event only gets sent when you actually modify the item itself. When you click the other radio, you aren't modifying it. A fix would be to watch the change event on every input:radio, then just check the state of the relevant radio button:
$("input:radio").change(function () {
if ($("#rb2").is(":checked")) {
alert('checked');
}
else {
alert('unchecked');
}
});
http://codepen.io/AlienHoboken/pen/akwjB
Listen for change on every input related to your group of radios and then check if a specific one is selected.
$("input[name=rb]").change(function () {
if ($('#rb2').is(":checked")) {
alert('checked');
} else {
alert('unchecked');
}
});
http://jsfiddle.net/4uRWR/2/
You can artificially trigger a "change" on radio buttons from the same group so that the original bound handler would get picked up and output "unchecked". The trick is to avoid being stuck in an infinite loop by recursively re-triggering the event, we can avoid that by ignoring artificial events that lack the originalEvent property:
$("input[type=radio]").on("change", function (e) {
var $this = $(this);
//all inputs with the same name
var $targetInputSelector = $("input[name=" + $this.attr("name") + "]");
//check if the handler was fired "naturally"
//if yes, trigger the change handler "artificially" for inputs with the same name
if (e.hasOwnProperty('originalEvent')) {
//exclude the element that was changed "naturally"
//from the subset of all the elements with the same name
$targetInputSelector.not($this).triggerHandler("change");
}
});
This code works when added on top of your current handler and satisfies the without changing my selector to match both inputs and then looking at the ID criteria ;)
http://jsfiddle.net/a73tn/24/
I sorta ran into this issue a few days ago. Instead of listening for an individual click on a radio button, I listen for a click on the <ul> I have them in and then call this function to check if one has been selected.
// Iterate over the radio group and determine if one of them is selected
function loopRadBtns(btnGroup)
{
var isChecked = false;
btnGroup.find('input[type="radio"]').each(function()
{
if($(this).attr('checked'))
{
isChecked = true;
}
});
return isChecked;
}

What is wrong with my body-click event?

I have that text field:
<input type='text' id='title' name='title'>
<div id='error' class='error'></div>
When user clicks out of the text field and there is a validation problem, the div "error" appears.
What I want to do is to hide that little div when user clicks anywhere in the body.
I tried e.stopPropagation in the body click event but didn't work.
The div never appears because when I blur out of the textfield, it's considered a body click
Please let me know if you have any idea. Regards
EDIT:
I have updated the code. The code inside the body click event is supposed to hide the "error" div when anything but the text field is clicked, but can't get it to work.
$('body').click(function(event){
if ($(event.target).closest('#title').get(0) == null ) {
$("#error").hide();
}});
// Validation
$('#title').blur(function(){
var titleinput=$('#title').val();
if (titleinput.length <30 || titleinput.length >50){
$('#error').text('Your title must be between 30 and 50 characters').show();
}
});
Unfortunately, since blur and click are different events, you can't use stopPropagation. The only way I can think to do this is to fake it. You can ignore the first click that happens within a fraction of a second of the blur event.
http://jsfiddle.net/LeNDp/1
var ignoreClicks = false;
var timer;
$("body").click(function() {
if(!ignoreClicks){
$("#msg").fadeOut();
}else{
if(timer) clearTimeout(timer);
ignoreClicks = false;
}
});
$("input").blur(function(e) {
ignoreClicks = true;
$("#msg").stop(true,true).show();
if(timer) clearTimeout(timer);
timer = setTimeout(function(){ignoreClicks=false;}, 250);
});​

Categories

Resources