JQuery conflict between .hide() and .onclick() - javascript

So I'm developing a script that makes use of a dropdown (class typeahead_list) and a textbox (class et_email) in Bootstrap. Whenever the text box loses focus, I need the dropdown to close. But if someone clicks on one of the list items in the dropdown (class et_li), the contents of that list item must populate the text box before closing the dropdown.
Note: All of the lis are dynamically generated. I don't know if that makes a difference or not.
This code puts the li contents into the textbox, but does not close the dropdown.
$( ".et_email" ).focusout(function() {
$(".typeahead_list").on("click", "li", function() {
$(".et_email").val($(this).text());});
//$(".typeahead_list").hide();
});
This code closes the dropdown, but does not put the contents of the li into the text box.
$( ".et_email" ).focusout(function() {
$(".typeahead_list").on("click", "li", function() {
$(".et_email").val($(this).text());});
$(".typeahead_list").hide();
});
Any idea on how to fix this? Where is the conflict coming from?
UPDATE:
Alex Cassady suggested the following fix:
$(".typeahead_list").on("click", "li", function() {
$(".et_email").val($(this).text()); // copy value
$(".typeahead_list").hide(); // then hide
});
Thank you for your help. I've looked into a solution similar to this before. However, I was having an issue because I need the dropdown to close whenever the email box loses focus for any reason at all... while still responding to the li click. With this example, the dropdown only closes when someone clicks on the li.
But if I try to add another handler for $( ".et_email" ).focusout() within the $(document).ready(), it completely invalidates the effects of this function. It's like $( ".et_email" ).focusout() and $(".typeahead_list").on("click", "li", function(){}) can't live in the same universe together. There is some kind of conflict.
Basically, the rule I need to implement is: Always close the dropdown when et_email loses focus for any reason... but if focus is lost because of an li click with the typeahead_list div, then populate the text box with the contents of that li before closing the dropdown.

You're binding a click listener to an element which will be hidden right away and so can not be clicked! The reason it works if you comment the hide() line is because it can be clicked.
If you just want the text before hiding:
$( ".et_email" ).focusout(function() {
$(".et_email").val($(".typeahead_list").text());
$(".typeahead_list").hide();
});
EDIT:
Alright I think I have a better understanding of what you're trying to do. This is not a clean solution, but will do the job.
Have a global variable 'focusLost' or anything, It'll be set to true every time .et_email loses focus and set to false in a second. In .typeahead_list click listener we check whether focusLost is true.
var focusLost = false;
$('.typeahead_list').on('click', function () {
if (focusLost) {
$('.et_email').val(($(this).text()));
$(this).hide();
}
});
$('.et_email').focusout(function () {
focusLost = true;
setTimeout(function () {
$('.typeahead_list').hide();
focusLost = false;
}, 1000);
});
jsfiddle DEMO

As A. Wolff said, don't nest handlers. The focusout event is binded to all .et_email, but the click event isn't binded to the .typeahead_list until the focusout event is triggered.
The .typeahead_list is being hidden before the value can be changed. Focusout is the same as clicking outside of .et_email and it's being called first.
Removing the focusout event handler completely should solve the problem.
$(".typeahead_list").on("click", "li", function() {
$(".et_email").val($(this).text()); // copy value
$(".typeahead_list").hide(); // then hide
});
Edit: You could also try copying the value in a callback function for $.hide()
$(".typeahead_list").on("click", "li", function() {
$(".typeahead_list").hide( function() {
$(".et_email").val($(this).text()); // copy value
}); // then hide
});

Related

jQuery click event works only after second click

I've click event bind to a class called ".reportfile" as follow.
$('body').on('click','.reportfile',function(e){
e.preventDefault();
e.stopPropagation();
var id=$(this).attr('id');
if(!$(this).hasClass('brc')) {
// Perform some action here.
}
});
Now I'm creating LI element dynamically with ".reportfile" class. Like this,
var inLi=$('<li>');
inLi.addClass('reportfile');
$(containerdiv).append(inLi);
Now when I try to click on the dynamic generated LI elements it only works on second click.
https://jsfiddle.net/mt7km8bz/
There is input box on the top of the UL to filter the list. This is where I'm creating new LI dynamically. LI element in filtered list has to be clicked twice to get it working.
The problem was the focus on the input box, on first click input box still have the focus so the click event on list doesn't trigger.
So on the first click it losses focus on the input box and on second click event get triggered.
Changes to following worked for me.
$('body').on('keyup','.searchable',function(){
// Some code
});
I guess jQuery click event works only after second click because the focus of the input.So I did a fool way that is trigger LostFocus Event using timer.
setTimeout(function(){
$('.searchable').blur();
},1500);
This is the code...
https://jsfiddle.net/2hkn2jpk/
try this.....
$(document).on('click','.reportfile',function(e){
var id=$('.reportfile').attr('id');
if(!$('.reportfile').hasClass('brc')) {
// Perform some action here.
}
});
change this to keypress , Its working.
I cheked in fiddle.
Jsfiddle
$( ".searchable" ).keypress(function(){
$('.ul2').html('');
var value=$(this).val().trim().toLowerCase();
if(value=="") {
$('.ul1').show();
$('.ul2').hide();
} else {
$('.ul1').hide();
$('.ul2').show();
}
$('.ul1').find('.reportfile').each(function(index){
var title=$(this).attr('title').toLowerCase();
if(title.indexOf(value)>=0) {
var LIin=$("<li>");
LIin.addClass('reportfile');
LIin.text(title);
$('.ul2').append(LIin);
}
});
});

Nesting JQuery .click() events

I want to nest one .click() event with another but its not working. I looked at the .on() event, but I don't think its what I need. Below is basically what I have so far, but its not working as intended.
I want to click on the 'adress1' button, get directed to the next page where I either click the 'profession1' button or the 'profession2' button, and depending on which of the last two buttons is clicked, something respective happens.
//HTML code for first button
adress1
//HTML code on a different page for last two buttons
profession1
profession2
//Javascript/JQuery code
$("#adress").click(function(){
//Some action here based on #address click event
$("#profession-1").click(function(){
//Some action if #profession was clicked after #address
});
$("#profession-2").click(function(){
//Some other action if #profession2 was clicked instead
of profession1
});
});
Someone had told me to use the following:
$('#adress').on('click', '#profession-1', function() {alert("x1")}).on('click', '#profession-2', function() {alert("x2")});
but its not working either. I feel like my program is not registering the click.
Your help is much appreciated!
The "root" element, in this case #address, isn't a proper element to attach the click event. You want to attach to some parent element and target a child element. Events in JavaScript bubble up and trickle back down to the element that initiated the event Event Propagation.
To remedy the issue:
$('#someParentEl').on(
'click',
'#profession-1',
function() {alert("x1")}
).on(
'click',
'#profession-2',
function() {alert("x2")}
);
Further Reading:
http://www.quirksmode.org/js/events_order.html
https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation
http://learn.jquery.com/events/event-delegation/
The best way to accomplish something like this, is to have data attributes store whether or not something was clicked on... assuming this is a single page web app. Also make sure each id is unique, and referenced correctly for each click event.
address1
Then, when you click on that element, check if the data attribute is true or not on each click of the other elements.
$("#address").click(function(){
if($(this).attr("data-clicked") == "true") {
$(this).attr("data-clicked","false")
} else {
$(this).attr("data-clicked","true")
}
});
$("#profession-1").click(function(){
if($("#address").attr("data-clicked") == "true") {
//Some action
}
});
$("#profession-2").click(function(){
if($("#address").attr("data-clicked") == "true") {
//Some action
}
});
None of this was tested, but it should point you in the right direction.

mouseleave/enter bind/unbind logic

I'm trying to build a simple script for a form. The script will show the form when the user hovers over the container div. Then I want to check to see if the user clicks on any form input, if not the form will hide. If an input or textarea are in focus I unbind mouseleave. If the user want's to close the form at this point he needs to click on a close button.
The problem I have right now is that after I have an input in focus and I close the form, on the next hover the form doesn't hide. I have to click the close button again. How do I 'reset' or disable the mouseleave unbind when the user clicks on close?
This is the relevant part of the script:
$(".close").on('click', function() {
$(".background").removeClass("green");
$(".q-form").hide();
$('.close').hide();
});
$(".container-background").on('mouseenter', function(){
$('.q-form').show();
$('.close').show();
$('.background').addClass("green");
});
$(".container-background").on('mouseleave', function() {
f ($('#contactForm input').is(':focus')) {
$(".container-background").off("mouseleave");
} else {
$('.q-form').hide();
$('.close').hide();
$('.background').removeClass("green");
}
});
First, a little offtopic: I recommend against checking for an input in :focus. A better approach for the scenario you described is to have:
$(document).on("focus", "#contactForm input", function() {
$(".container-background").off("mouseleave");
});
As for the problem you have with unbinding the event handler, you can just reattach it on form close:
$(".container-background").on("mouseleave", myFunction);
$(".close").on('click', function() {
$(".background").removeClass("green");
$(".q-form").hide();
$('.close').hide();
$(".container-background").off("mouseleave", myFunction)
.on("mouseleave", myFunction);
});
var myFunction = function() {
// You won't need this condition if you also do what's above
if (!$('#contactForm input').is(':focus')) {
$('.q-form').hide();
$('.close').hide();
$('.background').removeClass("green");
}
};
On second thought you can also just do this, and not have the .off() call at all:
if (!$('#contactForm input').is(':focus')) {
Personally, I don't like to use .hover or .on. I use .mouseenter and .mouseleave. Then, if you just create a .mouseenter, there would be no code to put it back into the unfocused state. Here is an example:
$("#something").mouseenter(function(){
$(this).animate({
//some css or whatever.
})
})
as long as you don't put a .mouseleave, it should not unfocus.

Fire an event only when an focused element looses focus

This is my Fiddle JsFiddle
$(function() {
$('.glyphicon-edit').click(function () {
$(this).parent().find('.form-control').removeAttr("readonly").focus();
});
$('.form-control:focus').blur(function() {
$(this).addAttr("readonly");
});
});
What I am trying to do?
I am trying to create a dynamically editable form.It should have
When someone click on edit icon, the corresponding Input field should get focussed and become editable. (I completed this part).
Next i want is when an element is in focus state and it looses focus then i want to add readonly attribute again to that element. This part in not working. can somebody explain me why. and give a solution for it
EDIT:
In the later part i was trying alert("some msg") to check whether the event is getting fired or not. while posting i just replaced it with addAttr. it was a typo
You could use instead:
--DEMO--
$(function () {
$('.glyphicon-edit').click(function () {
$(this).parent().find('.form-control').prop("readonly", false).focus().one('blur', function () {
$(this).prop('readonly', true);
});
});
});
There is no addAttr() function. The setter for attr looks like this:
$('.form-control').blur(function() {
$(this).attr("readonly", true);
});
Also, the :focus psuedo selector here is redundant, as to fire the blur event the element has to have focus in the first place.

Change Div Class on click takes multiple clicks before it works

I used the methods in this question:
change div class onclick on another div, and change back on body click
So here's my jQuery function:
jQuery('.checkbox_wrapper').on('click', function(e){
jQuery(this).parent()
.toggleClass('not_selected')
.toggleClass('selected');
});
However it doesn't seem to be working properly. It takes multiple clicks before the class changes.
See my jsfiddle:
http://jsfiddle.net/7A3vw/
I cut it down to the bare essentials thinking it might be conflicting javascript, but even with the single function it takes multiple clicks before the class actually changes. Because the production environment has 1 click toggle a hidden checkbox, multiple clicks is not reasonable.
Could someone help me figure out what's causing this issue?
The click function fires twice, once for the image, and once for the input, as both will bubble to the parent element, and firing twice reverts the classes again (proof).
Just target the image instead, as that is what you're really trying to click, not the parent :
jQuery('.deck_card img').on('click', function (e) {
jQuery(this).closest('div').parent().toggleClass('not_selected selected')
});
FIDDLE
i guest you need the checkbox checked together with the toggling of your div.
$(document).ready(function(e) {
$('.checkbox_wrapper').on('click', function(e){
var checked = $(this).find('input[type="checkbox"]').is(":checked");
if(checked){
jQuery(this).parent().addClass('selected').removeClass('not_selected');
}else{
jQuery(this).parent().addClass('not_selected').removeClass('selected');
}
});
});
Your code is triggering click event twice. So use .preventDefault()
This makes the default action of the event will not be triggered.
$('.checkbox_wrapper').on('click', function(e){
$(this).parent()
.toggleClass('not_selected')
.toggleClass('selected');
e.preventDefault(); // prevent the default action to be
}); // triggered for next time
Check this JSFiddle
try this
jQuery(document).on("click",'.checkbox_wrapper', function(e){
jQuery(this).parent()
.toggleClass('not_selected')
.toggleClass('selected');
});
Multiple Clicks are getting triggered because you are using class selector. You need to use not to exclude extra elements :
jQuery("div.checkbox_wrapper :not('div.checkboxdiv')").on('click', function(e){
jQuery(this).parent()
.toggleClass('not_selected selected')
});
Here is a FIDDLE.

Categories

Resources