Stop bind "blur" if click on a link - javascript

My bind function:
$searchInput.bind('blur', function() {
$searchResults.remove();
}
But this shouldn't happen if I click on a link inside of $searchResults. Now $searchResults is removed before I can click on a link.
How should I do that?

You may simply set a flag on mouse over $searchResults:
var isOver = false;
$searchInput.bind("blur", function(e) {
if (!isOver) {
$searchResults.remove();
}
});
$searchResults.hover(function() {
isOver = true;
}, function() {
isOver = false;
});
DEMO: http://jsfiddle.net/sUA4D/
You can do the same via element data, e.g. setting $searchResults.data("isOver", true).

One option that comes to mind is to delay the execution of the $.remove() call, like this:
$searchInput.bind('blur', function() {
setTimeout(function() {
$searchResults.remove();
}, 100);
}

$searchInput.find('a').on('click', function() {
$searchResults.remove();
});

Related

Can JavaScript help prevent duplicate click event handling?

I want the call function to run every 1.5 seconds.
However, if you are clicking continuously on a mobile machine
From the moment the call function is called in succession.
This is the code I am using:
$('#sendVideo').unbind('click');
$('#sendVideo').bind('click', function (event) {
$("#sendVideo").prop("disabled", true);
call();
setTimeout("$('#sendVideo').prop('disabled', false);", 1500);
});
Is there a solution for this?
You can use a clever hack:
var clickInProgress = false;
$('#sendVideo').bind('click', function (event) {
if(clickInProgress) return;
clickInProgress = true;
$("#sendVideo").prop("disabled", true);
call();
setTimeout("$('#sendVideo').prop('disabled', false); clickInProgress=false;", 1500);
});
You can set a flag on the element during the capture phase and delete it during bubble phase. I am not sure about jQuery but in simple java-script you can achieve it like this:
// set the flag on at capture
document.querySelector("#sendVideo").addEventListener('click', function(e) {
if (this.flagOn) {
e.preventDefault();
return false;
}
this.flagOn = true;
return true;
}, true);
// delete on bubble
document.querySelector("#sendVideo").addEventListener('click', function(e) {
delete this.flagOn;
}, false);
This should handle that for you without any modification in your own code.

Starting and ending functions in javascript

I am playing around with a short little code to see if I can get a function going while the user has their mouse down and then end it when they bring their mouse up. For this example I am trying to increment a number that I am displaying on the screen as the user moves their mouse while holding the button down. I want it to freeze and stop once they release the button, however the counter just resets and the count continues from 0 even though the button is not being pressed...
function dragInit(state, e) {
var i = 0;
$(document).on("mousemove", function() {
if (state) {
i+=1;
$('#debug').text(i); //Show the value in a div
}
});
}
$(document).ready(function() {
$(document).on(
{mousedown: function(e) {
var state = true;
dragInit(e, state);
},
mouseup: function(e) {
var state = false;
dragInit(e, state);
}
});
});
As an aside, is there a way I can display whether a variable is true or false onscreen? When I try it just says [object Object].
There are a lot of mistakes in your code. I suggest you to read more basic concepts before starting to use jQuery.
The order of the parameters passed to dragInit() is wrong on both mouseup and mousedown event bindings.
The reason your counter is restarting is because your variable i is local, so it exists only during the function context it is declared in.
You are making the same mistake with the state variable, but in this case it is completely unnecessary to declare it.
Consider making your counter a global (even though it is not a good practice).
I can't provide you code because I am answering from my phone. A solution would be create a mousemove event that checkes whether the mouse button is pressed before incrementing your counter.
Hope I helped
You could do something like this:
function dragInit() {
$(document).on("mousemove", function () {
if (eventState.state) {
eventState.count += 1;
$('#debug').text(eventState.count); //Show the value in a div
}
});
}
// Create an object to track event variables
var eventState = {
count:0, //replaces your previous 'i' variable
state: false //keeps track of mouseup or mousedown
};
$(document).ready(function () {
$(document).on({
mousedown: function (e) {
eventState.state = true;
dragInit(); //don't need to pass anything anymore
},
mouseup: function (e) {
eventState.state = false;
dragInit(); //don't need to pass anything anymore
}
});
});
jsFiddle
Or keep everything together as one object
var dragInit = function () {
var count = 0;
var state = false;
var action = function () {
$(document).on("mousemove", function () {
if (state) {
count += 1;
$('#debug').text(count); //Show the value in a div
}
})
};
$(document).on({
mousedown: function (e) {
state = true;
action(); //don't need to pass anything anymore
},
mouseup: function (e) {
state = false;
action(); //don't need to pass anything anymore
}
});
}
$(document).ready(function () {
var obj = new dragInit();
});
jsFiddle 2
Example in response to comment
jsFiddle: This shows why the following code snippets differ in execution.
// Works
$(document).on("mousemove", function () {
if (state) {
}
})
// Doesn't
if (state) {
$(document).on("mousemove", function () {
});
}
Less code, You just need this.
Use jquery on and Off to turn on and off mousemove event.
Counter Reset http://jsfiddle.net/kRtEk/
$(document).ready(function () {
var i = 0;
$(document).on({
mousedown: function (e) {
$(document).on("mousemove", function () {
$('#debug').text(i++); //Show the value in a div
});
},
mouseup: function (e) {
i = 0;
$('#debug').text(i);
$(document).off("mousemove");
}
});
});
W/O Reset http://jsfiddle.net/gumwj/
$(document).ready(function () {
var i = 0;
$(document).on({
mousedown: function (e) {
$(document).on("mousemove", function () {
$('#debug').text(i++); //Show the value in a div
});
},
mouseup: function (e) {
$(document).off("mousemove");
}
});
});
WithNoCounter http://jsfiddle.net/F3ESx/
$(document).ready(function () {
$(document).on({
mousedown: function (e) {
$(document).on("mousemove", function () {
$('#debug').data('idx',parseInt($('#debug').data('idx')|0)+1).text($('#debug').data('idx')); //Show the value in a div
});
},
mouseup: function (e) {
$(document).off("mousemove");
}
});
});
Assuming you are married to Jquery (nothing wrong with that) - check out and consider entirely re-thinking your approach leveraging the ".one()" (http://api.jquery.com/one/) method.
edit: and if that taste doesn't sit well - familiarize yourself with the "deferred" object (http://api.jquery.com/category/deferred-object/)
lots of ways to approach this via jquery - what you decide in the end depends on what you really intend to do with this.

jQuery - triggering a regular function call on mousedown

I want a function to be called regularly at a given interval whilst the left mouse button is being held down over a specific element. Is there a simple way of doing this in jQuery or should I use vanilla javascript and setInterval/setTimeout?
Thanks
Here's a jQuery plugin that provides a mousehold event.
http://remysharp.com/2006/12/15/jquery-mousehold-event/
If you go to the demo page and click on one of the arrows to the right of the last input box you'll see how it works.
This is how I would do it:
HTML:
<div id="box"></div>
JavaScript:
var box = $('#box'),
iv;
function foo() {
box.append('*');
}
box.bind('mousedown mouseup', function(e) {
$(this).toggleClass('hold', e.type === 'mousedown');
});
iv = setInterval(function() {
box.hasClass('hold') && foo();
}, 1000);
So you bind a handler to both the mousedown and mouseup events, and set the hold CSS class accordingly. Meanwhile, an independent timer iv will inspect whether or not the hold class is set, and call your function (foo) accordingly.
Live demo: http://jsfiddle.net/simevidas/7CUFE/
jQuery does not provide any function watching support as a result, you could use the vanilla setTimeout function as follows:
var timer;
function functionToRun() {
// Function code here...
functionToRun();
}
var inFunction = function() {
timer = window.setTimeout(functionToRun, intervalToRunFor);
}
var outFunction = function() {
window.clearTimeout(timer);
}
$('selector').hover(function() { inFunction, outFunction }
var mouseDown = false;
$('#yourID').bind('click', function() {
mouseDown = true;
});
$('#yourID').bind('mouseup', function() {
mouseDown = false;
});
setInterval('checkOut();',5000);
function checkOut() {
if(mouseDown) alert('mouse is down! Whatup!');
});

Stopping .click() listener until fadeIn() is finished in jQuery

$('#div1_button').click(function() {
$('#div0').fadeOut(function(){
$('#div1').fadeIn();
});
});
When a user clicks div1_button the previously selected div0 fades out and div1 fades in. If the user goes click crazy and clicks div2 before div1 is finished fading in then div2 begins to fade in and eventually div1 fades out, but they stack on top of each other until div1 is finished fading in then fades out. How can I stop the .click() event until the clicked div is finished fading in.
Something like
var div1_bclick_inprogress = false;
$('#div1_button').click(function() {
if (!div1_bclick_inprogress) {
div1_bclick_inprogress = true;
$('#div0').fadeOut(function(){
$('#div1').fadeIn(function(){
div1_bclick_inprogress = false;
});
});
}
});
but you may have to experiment a bit with the details
USE :animated ..
http://api.jquery.com/animated-selector/
Here: an example
$("#div1_button").click(function() {
if (!$(this).parent().children().is(':animated')) {
$('#div0').fadeOut(function(){
$('#div1').fadeIn();
});
}
return false;
});
You can stop animations by using the jQuery .stop() function.
http://api.jquery.com/stop/
$('#div1_button').click(function() {
$('#div0').stop(true, true).fadeOut(function(){
$('#div1').stop(true, true).fadeIn();
});
});
While this is not exactly what you requested, it's definitely what I would've done.
don't you think that is better to stop the fadeIn/fadeOut and change the direction as the user requested?
in this case:
$('#div1_button').click(function() {
var state = $(this).data("state");
$(this).data(state, !state);
var d0 = $("#div0").stop(),
d1 = $("#div1").stop();
if (state) {
d0.fadeOut(function() {
d1.fadeIn();
});
} else {
d0.fadeIn(function() {
d1.fadeOut();
});
}
});
or something like this
div1_click_handler = function()
{
$('#div1_button').unbind('click', div1_click_handler);
$('#div0').fadeOut('slow', function()
{
$('#div1').fadeIn('slow', function()
{
$('#div1_button').click(div1_click_handler);
});
});
});
$('#div1_button').click(div1_click_handler);
You could create an external boolean value that each click value checks before fading. i.e.
var noFading = true;
$('#div1_button').click(function() {
if (noFading) {
noFading = false;
$('#div0').fadeOut(function(){
$('#div1').fadeIn(function() { noFading = true; });
});
}
});
Use jQuery.data to store a flag. Set the flag after the first click, and ignore clicks until the flag is unset by the fade finishing:
$('#div1_button').click(function() {
if ($('#div1').data('disableClick') === true) return false;
$('#div1').data('disableClick', true);
$('#div0').fadeOut(function(){
$('#div1').fadeIn(function() {
$('#div1').data('disableClick', false);
});
});
});

jQuery .click function - prevent it from being called again until function completes

I've written my first bit of proper jQuery for an image slideshow, that allows users to scroll up and down through some images:
$(window).load(function(){
$('.scrollUp').click(function(){
$('.cardWrapper:visible:first').prevAll(':hidden:first').slideDown(function(){
$('.cardWrapper:visible:last').slideUp();
});
return false;
});
$('.scrollDown').click(function(){
if($('.cardWrapper:last').is(':hidden')){
$('.cardWrapper:visible:last').nextAll(':hidden:first').slideDown();
$('.cardWrapper:visible:first').slideUp();
}
else{
$('.cardWrapper:last').after('<div class="cardWrapper"></div>');
$('.cardWrapper:last').load('/followedTestSingle/?sequence={{gr.sequence_token}}', function(){
$('.cardWrapper:visible:first').slideUp();
});
}
return false;
});
});
The problem I have is that if you click very fast on the .scrollDown element link - it loses all the content as it hasn't had the time to add the extra ( i think) - and thus it starts to fail.
Is there a way to make jQuery not accept any new click on an element until its run all of this function?
Maybe something like
var scrollDownClickActive = false;
$('.scrollDown').click(function(){
if (scrollDownClickActive) return false;
scrollDownClickActive = true;
if($('.cardWrapper:last').is(':hidden')){
$('.cardWrapper:visible:last').nextAll(':hidden:first').slideDown();
$('.cardWrapper:visible:first').slideUp(200, function(){ scrollDownClickActive = false; } );
}
else
{
$('.cardWrapper:last').after('<div class="cardWrapper"></div>');
$('.cardWrapper:last').load('/followedTestSingle/?sequence={{gr.sequence_token}}', function(){
$('.cardWrapper:visible:first').slideUp(200, function(){ scrollDownClickActive = false; } );
});
}
return false;
});
Using a flag to determine if the function is active or not.
The use of binding and unbinding removes the use of flag variables =)
function scroller(obj){
$(obj).unbind('click');
if($('.cardWrapper:last').is(':hidden')){
$('.cardWrapper:visible:last').nextAll(':hidden:first').slideDown();
$('.cardWrapper:visible:first').slideUp();
scrollDownClickActive = false;
}
else
{
$('.cardWrapper:last').after('<div class="cardWrapper"></div>');
$('.cardWrapper:last').load('/followedTestSingle/?sequence={{gr.sequence_token}}', function(){
$('.cardWrapper:visible:first').slideUp();
scrollDownClickActive = false;
});
}
$(obj).click(function(){scroller(this);});
}
$('.scrollDown').click(function(){
scroller(this);
});
Hope this helps!
If it's clicking an button element, just have your function disable it and re-enable it in the completion callback function.
Otherwise just write your function to check for a variable value which prevents it from running. If the variable isn't set, have it set a the value (something like var busy = true;) in the handler and set it back to false in the completion callback.
You can use a flag to indicate that it is scrolling (as suggested by MiffTheFox), but you'll have to unset the flag in the slide callback because the slide happens asynchronously:
$(function(){
var scrolling = false;
function startScrolling() {
if(scrolling) return false;
return scrolling = true;
}
function scrollComplete() {
scrolling = false;
}
$('.scrollUp').click(function() {
if(startScrolling()) return false;
$('.cardWrapper:visible:first')
.prevAll(':hidden:first').slideDown(function() {
$('.cardWrapper:visible:last').slideUp(scrollComplete);
});
return false;
});
$('.scrollDown').click(function() {
if(startScrolling()) return false;
if($('.cardWrapper:last').is(':hidden')) {
$('.cardWrapper:visible:last').nextAll(':hidden:first').slideDown();
$('.cardWrapper:visible:first').slideUp(scrollComplete);
} else {
$('.cardWrapper:last').after('<div class="cardWrapper"></div>');
$('.cardWrapper:last').load('/followedTestSingle/?sequence={{gr.sequence_token}}', function() {
$('.cardWrapper:visible:first').slideUp(scrollComplete);
});
}
return false;
});
});
Disclaimer: I haven't checked your code to see how valid it is, I've just added the flag and the callbacks for you.

Categories