Jquery click handler is stuck in infinite loop - javascript

I have an handler on clicking an element. It is getting stuck in an infinite loop. How can I turn off the listener for the 2nd click in this code... so that it doesn't keep repeating.
I'm trying to automatically close the toggle after 4.5 seconds. But the close click triggers another click... and so on...
$(document).ready(function(){
$(".navbar-toggle").click(function() {
setTimeout(function () {
$(".navbar-toggle").click();
}, 4500);
});
});

Add a 'flag' variable to your code
var has_clicked = false;
$(document).ready(function(){
$(".navbar-toggle").click(function() {
if(!has_clicked){
setTimeout(function () {
has_clicked = true;
$(".navbar-toggle").click();
}, 4500);
}
});
});

$(function(){
function callback2(){
$("#test").one("click", callback1);
}
function callback1(){
console.log('hi');
setTimeout(callback2, 4500);
}
$("#test").one("click", callback1);
});
jsFiddle Demo
Is this similar to what you want?
Attach the click event which execute only once, using .one(),
do whatever you want in the callback function, and attach it again after 4.5 seconds. If you cannot even modify your code to this, please let me know, I will try to think another work around

This is what I am going with for now though I believe I will use shole's approach when I get some more time... for now this is working well.
var is_open = false;
$(document).ready(function(){
$(".navbar-toggle").click(function() {
if(!is_open){
setTimeout(function () {
is_open = true;
$(".navbar-toggle").click();
is_open = false;
}, 3500);
}
});
});

Related

Is there a way to call jquery functions on another object after finishing the first?

I want to fade out object 1 and after fade out remove a class and add one. After that on another object the object 2 should fadein and then i assign it a class. The problem that i encountered is that if i fire my event faster than the fadein/fadeout the object stays active.
$('.menuA').on("click", function () {
$('.menuA').removeClass("blue accent-3 z-depth-2", 100);
let clicked = $(this);
$('.menuA').promise().done(function () {
clicked.addClass("blue accent-3 z-depth-2", 100);
})
animatePanes($(this).attr("con"));
})
function animatePanes(pane) {
let paneOld = $('.pane-active');
paneOld.fadeOut(250).removeClass("pane-active").addClass("pane-inactive").promise().done(function () {
$('.' + pane).fadeIn(250).removeClass("pane-inactive").addClass("pane-active");
});
};
Thats my event with the function. The problem is that if i click to fast and trigger the event on menuA the paneOld doesnt get the class pane-inactive.
I already tried to do a global variable that checks if the event is running but it didnt worked (probably because i thinked wrong).
Is there a way to disable the event listener until the event is completly finished?
Or is there a better way?
You can surely do it with a global variable - as you've already said. Maybe you just put in in the wrong place.
I'd recommend something like isAnimating=false and 'disable' the click event listener if it's value is true. This way you can reset isAnimating to false as soon as all your animations are completed.
var isAnimating = false;
$('.menuA').on("click", function() {
if (!isAnimating) {
$('.menuA').removeClass("blue accent-3 z-depth-2", 100);
let clicked = $(this);
$('.menuA').promise().done(function() {
clicked.addClass("blue accent-3 z-depth-2", 100);
})
animatePanes($(this).attr("con"));
isAnimating = true;
}
})
function animatePanes(pane) {
let paneOld = $('.pane-active');
paneOld.fadeOut(250).removeClass("pane-active").addClass("pane-inactive").promise().done(function() {
$('.' + pane).fadeIn(250).removeClass("pane-inactive").addClass("pane-active").promise().done(function() {
isAnimating = false;
});
});
}

avoid mouse detection before end animation

my animation blink () make an image (.stone) disappear very slowly, it is executed when the page is ready, and then onmouseout again. My problem is when during the animation the mouse is going above (.stone) then it will be executed several times in a row.
I think I have to use or clearqueued or preventdefault, to avoid that but no idea how. Can someone help?
<SCRIPT>
$(document).ready(function(){blink();});
function blink(){
$(".stone").animate({opacity:0},10000);
};
$(".stone").on('mouseover',function () {
$('.stone').animate({opacity:1},100);
$(".stone").clearQueue();
});
$(".stone").on('mouseout',function (){blink();});
</SCRIPT>
<body>
<div id='conteneur'class='responsiveeinstein'><div class='stone'class='responsiveeinstein'><a href='photos.html'><img src='image1/stone aloneintro.jpg'class='responsiveeinstein'/></a></div><div class='stone2'><img src='image1/stone9.jpg'class='responsiveeinstein'/></div><div><a href='photos.html'><h1 id='elementClignotant'>Einstein</h1></a></div></div>
</body>
I think that's what you are looking for:
fiddle link
$(document).ready(function(){
var isAnimationFinished = false;
blink();
function blink(){
isAnimationFinished = false;
$(".stone").animate({opacity:0},10000,function() {
isAnimationFinished = true;
});
};
$(".stone").on('mouseover',function () {
if(isAnimationFinished){
$(".stone").stop();
$('.stone').animate({opacity:1},100);
}
});
$(".stone").on('mouseout',function (){blink();});
});

OnClick propagation when generating divs with jQuery

I am not sure why the event StopPropagation technique is not working with this simple onClick example - the event seems to be bubbling up the DOM tree and is also iterating exponentially every time I click again.
I think this is because I generate html with a javascript function, and I'd be very eager to hear why you think this isn't working as expected.
EDIT: I have created a jsFiddle at http://jsfiddle.net/Guill84/GsLtN/22/. The issue becomes very clear. If I click on 'Text1' the first time, the alert pop-up comes up only once. If I click it again, it then comes up twice. If I click it again, it comes up three times, and so on. How can I amend the script so that it is run only once? This is driving me barmy.
HTML
<body>
<div id='container'>
<div id='1'>Text1</div>
<div id='2'>Text2</div>
</div>
</body>
Javascript
$(function notice_it(declim) {
if ($.isNumeric(declim)) {
//stuff
} else {
declim = 10;
}
$("#container").html("<div id='1'>Text1</div><div id='2'>Text2</div>");
alert(declim);
$('body').on('click', '#1', function (event) {
event.stopPropagation();
var declim = 10 - 1;
notice_it(declim);
});
$('body').on('click', '#2', function (event) {
event.stopPropagation();
var declim = 10 + 1;
notice_it(declim);
});
$('body').on('click', 'body', function (e) {
e.stopPropagation();
});
});
I have already added comment but then I thought this would explain in a better way.
Issue
$(function notice_it(declim) {
if ($.isNumeric(declim)) {
//stuff
} else {
declim = 10;
}
$("#container").html("<div id='1'>Text1</div><div id='2'>Text2</div>");
alert(declim);
$('body').on('click', '#1', function (event) {
event.stopPropagation();
var declim = 10 - 1;
notice_it(declim); // Issue
});
});
Here notice_it() is used to initialize events and it is called again in event handlers. Following is an updated JSFiddle - Issues showing different registered events.
Solution
A simple solution would be to migrate the code used to notify to a separate function, as done in following JSFiddle - Solution1.
A better way to implement though would be like this: JSFiddle - Solution2. It is somewhat Declarative Programming and makes it very easy for another person to understand.
Calling return false should work in your scenario.
$(function notice_it(declim) {
if ($.isNumeric(declim)) {
//stuff
} else {
declim = 10;
}
$("#container").html("<div id='1'>Text1</div><div id='2'>Text2</div>");
alert(declim);
$('body').on('click', '#1', function (event) {
return false;
var declim = 10 - 1;
notice_it(declim);
});
$('body').on('click', '#2', function (event) {
return false;
var declim = 10 + 1;
notice_it(declim);
});
$('body').on('click', 'body', function (e) {
e.stopPropagation();
});
});
Try to return false on click

How to close div when div loses focus?

I made a simple plunkr here http://plnkr.co/edit/zNb65ErYH5HXgAQPOSM0?p=preview
I created a little datepicker I would like this to close itself when you focus out of it (focusout of datepicker) if I put blur on input I'm unable to use the datepicker, if I put focusout event on datepicker it doesn't works
I also tried:
angular.element(theCalendar).bind('blur', function () {
$scope.hideCalendar();
});
but it doesn't work.
Any clue?
this is because you are removing the item before you get a chance to do anything, here is a working example:
http://plnkr.co/edit/mDfV9NLAQCP4l7wHdlfi?p=preview
just add a timeout:
thisInput.bind('blur', function () {
$timeout(function(){
$scope.hideCalendar();
}, 200);
});
have you considered using existing datepickers? like angularUI or angular-strap: http://mgcrea.github.io/angular-strap/##datepickers
Update:
Not a complete solution, but should get you quite closer:
angular.element($document[0].body).bind('click', function(e){
console.log(angular.element(e.target), e.target.nodeName)
var classNamed = angular.element(e.target).attr('class');
var inThing = (classNamed.indexOf('datepicker-calendar') > -1);
if (inThing || e.target.nodeName === "INPUT") {
console.log('in');
} else {
console.log('out');
$timeout(function(){
$scope.hideCalendar();
}, 200);
}
});
http://plnkr.co/edit/EbQl5xsCnG837rAEhBZh?p=preview
What you want to do then is to listen for a click on the page, and if the click is outside of the calendar, then close it, otherwise do nothing. The above only takes into account that you are clicking on something that has a class name which includes datepicker-calendar, you will need to adjust it so that clicking within the calendar doesn't close it as well.
How about closing on mouseout?
You need to cancel the close if you move to another div in the calendar though:
//get the calendar as element
theCalendar = element[0].children[1];
// hide the calendar on mouseout
var closeCalendarTimeout = null;
angular.element(theCalendar).bind('mouseout', function () {
if ( closeCalendarTimeout !== null )
$timeout.cancel(closeCalendarTimeout);
closeCalendarTimeout = $timeout(function () {
$scope.hideCalendar();
},250)
});
angular.element(theCalendar).bind('mouseover', function () {
if ( closeCalendarTimeout === null ) return
$timeout.cancel(closeCalendarTimeout);
closeCalendarTimeout = null;
});
EDIT
Adding a tabindex attribute to a div causes it to fire focus and blur events.
, htmlTemplate = '<div class="datepicker-calendar" tabindex="0">' +
angular.element(theCalendar).bind('blur', function () {
$scope.hideCalendar();
});
So, i know it probably is not the best practice or the best way to do this, but at the end i fixed and got what i need using this:
thisInput.bind('focus click', function bindingFunction() {
isMouseOnInput = true;
$scope.showCalendar();
angular.element(theCalendar).triggerHandler('focus');
});
thisInput.bind('blur focusout', function bindingFunction() {
isMouseOnInput = false;
});
angular.element(theCalendar).bind('mouseenter', function () {
isMouseOn = true;
});
angular.element(theCalendar).bind('mouseleave', function () {
isMouseOn = false;
});
angular.element($window).bind('click', function () {
if (!isMouseOn && !isMouseOnInput) {
$scope.hideCalendar();
}
});
I setted up some boolean vars to check where mouse is when you click the page and it works like a charm if you have some better solution that works , please let me know, but this actually fixed all.
I accept this as the answer but i thank all the guys on this page!

Registering jQuery click, first and second click

Is there a way to run two functions similar to this:
$('.myClass').click(
function() {
// First click
},
function() {
// Second click
}
);
I want to use a basic toggle event, but .toggle() has been deprecated.
Try this:
$('.myClass').click(function() {
var clicks = $(this).data('clicks');
if (clicks) {
// odd clicks
} else {
// even clicks
}
$(this).data("clicks", !clicks);
});
This is based on an already answered question: Alternative to jQuery's .toggle() method that supports eventData?
Or this :
var clicks = 0;
$('.myClass').click(function() {
if (clicks == 0){
// first click
} else{
// second click
}
++clicks;
});
this I worked for my menu
var SubMenuH = $('.subBoxHederMenu').height();
var clicks = 0;
$('.btn-menu').click(function(){
if(clicks == 0){
$('.headerMenu').animate({height:SubMenuH});
clicks++;
console.log("abierto");
}else{
$('.headerMenu').animate({height:"55px"});
clicks--;
console.log("cerrado");
}
console.log(clicks);
});
i don't know what you are tryin to do but we can get basic toggle by
$('.myClass').click({
var $this=$(this);
if($this.is(':hidden'))
{
$this.show('slow');
}else{
$this.hide('slow');
}
})
note: this works for endless click event for that element .. not just for two clicks (if that is what you want)
OR you can use css class to hide/show the div and use jquery.toggleClass()
In the method mentioned below We are passing an array of functions to our custom .toggleClick() function. And We are using data-* attribute of HTML5 to store index of the function that will be executed in next iteration of click event handling process. This value, stored in data-index property, is updated in each iteration so that we can track the index of function to be executed in next iteration.
All of these functions will be executed one by one in each iteration of click event. For example in first iteration function at index[0] will be executed, in 2nd iteration function stored at index[1] will be executed and so on.
You can pass only 2 functions to this array in your case. But this method is not limited to only 2 functions. You can pass 3, 4, 5 or more functions in this array and they will be executed without making any changes in code.
Example in the snippet below is handling four functions. You can pass functions according to your own needs.
$.fn.toggleClick = function(funcArray) {
return this.click(function() {
var elem = $(this);
var index = elem.data('index') || 0;
funcArray[index]();
elem.data('index', (index + 1) % funcArray.length);
});
};
$('.btn').toggleClick([
function() {
alert('From Function 1');
}, function() {
alert('From Function 2');
}, function() {
alert('From Function 3');
}, function() {
alert('From Function 4');
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button type="button" class="btn">Click Me</button>
<button type="button" class="btn">Click Me</button>
If you literally only want the first and second click:
$('.myClass').one( 'click', function() {
// First click
$('.myClass').one( 'click', function() {
// Second click
});
);
var click_s=0;
$('#show_pass').click(function(){
if(click_s % 2 == 0){
$('#pwd').attr('type','text');
$(this).html('Hide');
}
else{
$('#pwd').attr('type','password');
$(this).html('Show');
}
click_s++;
});
When You click the selector it automatically triggers second and waiting for another click event.
$(selector).click(function(e){
e.preventDefault(); // prevent from Posting or page loading
//do your stuff for first click;
$(this).click(function(e){
e.preventDefault();// prevent from Posting or page loading
// do your stuff for second click;
});
});
I hope this was helpful to you..
I reach here looking for some answers, and thanks to you guys I´ve solved this in great manner I would like to share mi solution.
I only use addClass, removeClass and hasClass JQuery commands.
This is how I´ve done it and it works great:
$('.toggle').click(function() {
if($('.categ').hasClass("open")){
$('.categ').removeClass('open');
}
else{
$('.categ').addClass('open');
}
});
This way a class .open is added to the Html when you first clikc.
Second click checks if the class exists. If exists it removes it.

Categories