mouseleave/enter bind/unbind logic - javascript

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.

Related

Checking button click event and doing something and removing them if user clicks elsewhere

I am attaching a onclick function to the button#1 and according to this function i am changing other buttons' opacity and disabling user to click on them.
But I want to undo what has been changed onclick event, making other buttons as normal.
My javascript and jquery code as below;
btnLink.onclick = function(e) {
var divToShow = document.getElementById('linkNewDiv');
console.log('clicked');
divToShow.style.display = 'inherit';
$(btnVideo).prop('disabled',true);
$(btnVideo).addClass('opacityReducing');
$(btnPicture).addClass('opacityReducing');
$(btnPublish).addClass('opacityReducing');
$(btnPicture).prop('disabled',true);
$(btnPublish).prop('disabled',true);
$(btnCheck).addClass('opacityReducing');
}
I couldnt manage to figure it. I found a one way if user clicks outside of the elements I am changing elements style and disable property by writing all these codes again. Any better solutions ? Thanks :)
You can achieve this with stopPropagation(). I made some changes to your code to make it more readable, check this:
$(document).on('click', function(e) {
console.log('clicked');
$('#linkNewDiv').css("display", "inherit");
$(btnVideo, btnPicture, btnPublish).removeClass('opacityReducing').prop('disabled', false);
$(btnCheck).removeClass('opacityReducing');
});
$('#bnLink').on('click', function(e) {
e.stopPropagation();
console.log('clicked');
$('#linkNewDiv').css("display", "inherit");
$(btnVideo, btnPicture, btnPublish).addClass('opacityReducing').prop('disabled', true);
$(btnCheck).addClass('opacityReducing');
});

automatic close function for selection

I have a button which creates a pulldown in which you can select several categories.
Now i want this to close automatically when i click outside the pulldown.
Something like a lightbox or modal popup which closes if you click anywhere else on the page.
Now i have to click the button again to close it. If i dont and go elsewhere on the page, the dropdown stays visible (until i click it)
This is the code of the button:
$(function(){
$('#browse-btn').click(function(){
$('#browse-content').toggle('1000');
$(this).toggleClass('active');
if ($(this).hasClass('active')) $(this).find('span').html('▲')
else $(this).find('span').html('▼')
});
$(".scroll-top").scrollToTop();
$("#category_id").selectbox();
});
Is this possible?
thanks
Using jquery this is the code I used for a similar case scenario sometime ago:
$(document).click(function(event) {
if(!$(event.target).closest('.pulldown').length) {
if($('.pulldown').is(":visible")) {
$('.pulldown').slideUp()
}
}
})
You can read more about this in the original post How to detect a click outside an element? submitted by Art.
I'm not exactly sure of the elements you want to hide as you don't have a demo, so I cannot provide a fully working code, however you should do something like this:
$("body").click(function(event) {
if (event.target.id != "browse-btn") {
// Do something when there's a click outside of #browse-btn
// and the element you want to hide is currently visible
}
});
You can attach a click event to all chidren of the body tag that removes that active class, but you would want to make sure to unbind that event so it doesn't run every time a click takes place that doesn't have some sort of prevent default on it. Something like this:
$(function(){
var hidePulldown = function(){
$('#browse-btn').removeClass('active');
$('body *').unbind("click", hidePulldown);
}
$('#browse-btn').click(function(){
$('#browse-content').toggle('1000');
$(this).toggleClass('active');
if ($(this).hasClass('active')) $(this).find('span').html('▲')
else {
$(this).find('span').html('▼');
$(document).on('click', 'body *', hidePulldown);
}
});
$(".scroll-top").scrollToTop();
$("#category_id").selectbox();
});
Also, the
$(document).on('click', element, function(){function body})
is the preferred way to attach click events i believe: $(document).on('click', '#id', function() {}) vs $('#id').on('click', function(){})
This is what worked flawlessly for me after reading some of the answers here:
$(document).click(function(event) {
if(!$(event.target).closest('#menucontainer').length &&
!$(event.target).is('#menucontainer')) {
if($('#menucontainer').is(":visible")) {
$('#menucontainer').hide();
}
}
})
Thanks for pointing me in the right way!

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

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
});

Jquery using focusout & on click together doesn't work

I am trying to achieve the result when i am typing inside input the list will drop down.
if the list is clicked then will give out an alert.
in the same time if the input is focus out , it will hide the list.
But the problem is when on click , it doesn't work.
$("input").on("keyup",function(){
$(".abc li").show();
});
$(".abc li").on("click",function(){
alert("123");
});
$("input").focusout(function(){
$(".abc").find("li").hide();
});
Reference to my code
http://jsfiddle.net/8t7erade/
Your click event is never getting called because the li is hidden by your focusout event before it can be triggered.
You could set a timeout to allow for the click to be registered:
$("input").focusout(function () {
setTimeout(function () {
$(".abc").find("li").hide()
}, 100)
});
demo
How about setting (short) time out on blur (focus out)?
Like this:
$("input").on("keyup",function(){
$(".abc li").show();
});
$(".abc li").on("click",function(){
alert("123");
});
$("input").focusout(function(){
setTimeout(function(){$(".abc").find("li").hide();}, 150);//i set 150 just as example
});
Problem is that blur occurs first, and at that time elements got hidden and mouse event is passed to other (visible) element.

Prevent click on another button jquery

How to prevent click another button if first is clicked...
Example
http://jsfiddle.net/C5AVH/3/
$(function(){
$('.vote_like').one('click',function(){
$('.vote_dislike').removeClass('vote_dislike');
alert('Done!')
});
$('.vote_dislike').one('click',function(){
$('.vote_like').removeClass('vote_like');
alert('Done!');
});
});
Like -
Dislike
When you click Like button i want disable click on Dislike button and inversely...
im try with removing class but seems that not working...
$('.vote_like').removeClass('vote_like');
You can remove the click handler
$(function () {
$('.vote_like').one('click.like', function () {
$('.vote_dislike').off('click.like');
console.log('like!')
});
$('.vote_dislike').one('click.like', function () {
$('.vote_like').off('click.like');
console.log('dislike!');
});
});
Demo: Fiddle
Because you've attached the .one handler to each button, it will still be executed at most one time according to the jquery docs. To prevent the click you must remove the handler after one is clicked.
$('.vote_like').one('click',function(){
$('.vote_dislike').off();
alert('Done!')
});
$('.vote_dislike').one('click',function(){
$('.vote_like').off();
alert('Done!');
});
});
Like -
Dislike
But better yet, why not just attach the one handler to both elements and check which was clicked:
$(function(){
$('.vote_like,.vote_dislike').one('click',function(){
if($(this).is('.vote_like')){
//set data for like
}
else{
//set data for dislike
}
//make ajax call
});
Anchors don't have a way to disable them, so you'd either need to remove the anchor or set a boolean in your javascript to track if it's been clicked.
Or, you can convert them into actual button elements, play with the disabled state.
Or you can use jquery to add custom data attributes to the anchor to track if it's "disabled"
Demo
$(function(){
$('.vote_like, .vote_dislike').on('click',function(){
$(this).siblings('.vote_like, .vote_dislike').add($(this)).prop('disabled',true);
if ($(this).hasClass('vote_like')) {
/* Do like things */ alert('like');
}else{
/* Do dislike things */ alert('dislike');
}
});
});
Can use one handler for both buttons and remove click handler within it for both
var btns=$('.vote_like, .vote_dislike').on('click',function(e){
e.preventDefault();
var isLikeBtn=$(this).is('.vote_like');
/* remove click handler for both, remove class from other button */
btns.off('click').not(this).removeClass( isLikeBtn ? 'vote_dislike' : 'vote_like');
});
Since using off on both would be equivalent of using one

Categories

Resources