Wait until div is not visible to process next line - javascript

I need to write some code which is supposed to wait until a predefined div is no longer visible in order to process the next line. I plan on using jQuery( ":visible" ) for this, and was thinking I could have some type of while loop. Does anyone have a good suggestion on how to accomplish this task?
$( document ).ready(function() {
$(".scroller-right" ).mouseup(function( event ) {
alert('right');
pollVisibility();
});
});
function pollVisibility() {
if ($(".mstrWaitBox").attr("visibility")!== 'undefined') || $(".mstrWaitBox").attr("visibility") !== false) {
alert('inside else');
microstrategy.getViewerBone().commands.exec('refresh');
} else {
setTimeout(pollVisibility, 100);
}
}
$( document ).ready(function() {
$(".scroller-right" ).mouseup(function( event ) {
alert('right');
pollVisibility();
});
});
function pollVisibility() {
if (!$(".mstrWaitBox").is(":visible")) {
alert('inside if');
microstrategy.getViewerBone().commands.exec('refresh');
} else {
setTimeout(pollVisibility, 100);
}
}
div when not visible:
<div class=​"mstrWaitBox" id=​"divWaitBox" scriptclass=​"mstrDialogImpl" dg=​"1" ty=​"edt">​
</div>​
div when visible:
<div class=​"mstrWaitBox" id=​"divWaitBox" scriptclass=​"mstrDialogImpl" dg=​"1" ty=​"edt" visibility="visible">​
</div>​

You can use the setTimeout function to poll the display status of the div. This implementation checks to see if the div is invisible every 1/2 second, once the div is no longer visible, execute some code. In my example we show another div, but you could easily call a function or do whatever.
http://jsfiddle.net/vHmq6/1/
Script
$(function() {
setTimeout(function() {
$("#hideThis").hide();
}, 3000);
pollVisibility();
function pollVisibility() {
if (!$("#hideThis").is(":visible")) {
// call a function here, or do whatever now that the div is not visible
$("#thenShowThis").show();
} else {
setTimeout(pollVisibility, 500);
}
}
}
Html
<div id='hideThis' style="display:block">
The other thing happens when this is no longer visible in about 3s</div>
<div id='thenShowThis' style="display:none">Hi There</div>

If your code is running in a modern browser you could always use the MutationObserver object and fallback on polling with setInterval or setTimeout when it's not supported.
There seems to be a polyfill as well, however I have never tried it and it's the first time I have a look at the project.
FIDDLE
var div = document.getElementById('test'),
divDisplay = div.style.display,
observer = new MutationObserver(function () {
var currentDisplay = div.style.display;
if (divDisplay !== currentDisplay) {
console.log('new display is ' + (divDisplay = currentDisplay));
}
});
//observe changes
observer.observe(div, { attributes: true });
div.style.display = 'none';
setTimeout(function () {
div.style.display = 'block';
}, 500);
However an even better alternative in my opinion would be to add an interceptor to third-party function that's hiding the div, if possible.
E.g
var hideImportantElement = function () {
//hide logic
};
//intercept
hideImportantElement = (function (fn) {
return function () {
fn.apply(this, arguments);
console.log('element was hidden');
};
})(hideImportantElement);

I used this approach to wait for an element to disappear so I can execute the other functions after that.
Let's say doTheRestOfTheStuff(parameters) function should only be called after the element with ID the_Element_ID disappears, we can use,
var existCondition = setInterval(function() {
if ($('#the_Element_ID').length <= 0) {
console.log("Exists!");
clearInterval(existCondition);
doTheRestOfTheStuff(parameters);
}
}, 100); // check every 100ms

Related

On / Off function after a certain period of time

Wondering how you can make .off() only happen for a specific period of time. I have a div which once clicked i want to disable the click event for 2 seconds, and then be allowed to click again. At the moment all I have is the div can be clicked, then once clicked it is off.
Here is a brief example of what I am asking:
$('.test').on('click', function() {
// *do stuff*
$('.test').off('click'); *for a certain perdiod of time*
});
It's a much simpler task to use a boolean variable as a flag to state whether the click handler should be executed, instead of attaching/detaching events from multiple elements. Try this:
var clickEnabled = true;
$('div').click(function() {
clickEnabled = false;
setTimeout(function() {
clickEnabled = true;
}, 2000);
});
$('.test').on('click', function(e) {
if (!clickEnabled) {
e.preventDefault();
} else {
// do stuff...
}
});
Note that you should also make the fact that .test is disabled visible in the UI, otherwise you'll just confuse and annoy your visitors when they click an element expecting an action, but nothing happens.
What about activate on after a certain period of time?
function myFunction() {
...do stuff
$('.test').off('click'); for a certain perdiod of time
setTimeout(function(){ $('.test').on('click', myFunction)}, 2000);
}
Using the setTimeout you may do something like:
var enabled = true;
var timeoutSeconds = 2;
$(function () {
$('.test').on('click', function(e) {
if (enabled) {
// *do stuff*
enabled = false;
window.setTimeout(function() {
enabled = true;
}, timeoutSeconds * 1000);
} else {
e.preventDefault();
}
});
});
You could do it like this.
function onClick() {
// do stuff here
$('.test').off('click');
setTimeout(function(){
$('.test').on('click', onClick);
}, 2000)
}
$('.test').on('click', onClick);
Or you can do it with css and toggleClass
// css
.disabled {
pointer-events: none;
}
// js
$('.test').on('click', function(){
// do stuff here
$('.test').addClass('disabled');
setTimeout(function(){
$('.test').removeClass('disabled');
}, 2000);
});

JQuery prototype not working when traversing

I am using the following (http://jsfiddle.net/mkmurray/drv5w/27/) code to allow me to override the .show() function of a DIV.
<script>
(function ($) {
var _oldShow = $.fn.show;
$.fn.show = function (/*speed, easing, callback*/) {
var argsArray = Array.prototype.slice.call(arguments),
duration = argsArray[0],
easing,
callback,
callbackArgIndex;
// jQuery recursively calls show sometimes; we shouldn't
// handle such situations. Pass it to original show method.
if (!this.selector) {
_oldShow.apply(this, argsArray);
return this;
}
if (argsArray.length === 2) {
if ($.isFunction(argsArray[1])) {
callback = argsArray[1];
callbackArgIndex = 1;
} else {
easing = argsArray[1];
}
} else if (argsArray.length === 3) {
easing = argsArray[1];
callback = argsArray[2];
callbackArgIndex = 2;
}
return $(this).each(function () {
var obj = $(this),
oldCallback = callback,
newCallback = function () {
if ($.isFunction(oldCallback)) {
oldCallback.apply(obj);
}
obj.trigger('afterShow');
};
if (callback) {
argsArray[callbackArgIndex] = newCallback;
} else {
argsArray.push(newCallback);
}
obj.trigger('beforeShow');
_oldShow.apply(obj, argsArray);
});
};
})(jQuery);
</script>
I have the following HTML code
<div id="divBeforeHiddenDiv">
foo
</div>
<div id="hiddenDiv" style="display:none">
bar
</div>
And then:
<script>
$('#hiddendiv').bind("beforeShow", function () {
alert("show event successfully overridden");
});
</script>
It works great when I call $('#hiddenDiv').show() but not if I call $('#divBeforeHiddenDiv').next().show() the hidden div containing 'bar' shows but the alert is not displayed.
So why?
UPDATE
This appears to be a jQuery issue as per Bergi's comment. If I use this JSFiddle on jQuery 1.7.1 it works but using jQuery 1.10.1 or any higher version it does not: JSFiddle. Is there a better solution than simply downgrading?
You need to bind the events to the proper elements.
From the example you've given, and what I've interpreted, this piece of code
$('#beforeShow').bind("beforeShow", function () {
alert("show event successfully overridden");
});
Should be
$('#hiddenDiv').bind("beforeShow", function () {
alert("show event successfully overridden");
});
As you want the events to be bound to the hidden div. (or as described in the question, the div right after "#divBeforeHiddenDiv"
You also should change this piece
$('divBeforeHiddenDiv').next().show()
to this
$('#divBeforeHiddenDiv').next().show()
divBeforeHiddenDiv is an ID and in the first code snippet there is no id in the jQuery object.
JSFiddle

After setTimeout() check if still mouse out

I have a piece of code that hides an element on mouseout.
The code looks like this:
var myMouseOutFunction = function (event) {
setTimeout(function () {
$(".classToHide").hide();
$(".classToShow").show();
}, 200);
};
This produces a result very close to what I want to do. However, I want to wait the time on the timeout (in this case 200 ms) then check to see if my mouse is still "out" of the element. If it is, I want to do .hide() and .show() on the desired elements.
I want to do this because if a user slightly mouses out then quickly mouses back in, I don't want the elements to flicker (meaning: hide then show real quick) when the user just wants to see the element.
Assign the timeout's return value to a variable, then use clearTimeout in the onmouseover event.
Detailing Kolink answer
DEMO: http://jsfiddle.net/EpMQ2/1/
var timer = null;
element.onmouseout = function () {
timer = setTimeout(function () {
$(".classToHide").hide();
$(".classToShow").show();
}, 200);
}
element.onmouseover = function () {
clearTimeout(timer);
}
You should use mouseenter and mouseleave of jquery. mouseenter and mouseleave will get called only once.and use a flag if to check if mouseenter again called.
var isMouseEnter ;
var mouseLeaveFunction = function (event) {
isMouseEnter = false;
setTimeout(function () {
if(isMouseEnter ){ return;}
$(".classToHide").hide();
$(".classToShow").show();
}, 200);
};
var mouseEnterFunction = function(){
isMouseEnter = true;
}
Use a boolean flag:
var mustWait = true;
var myMouseOutFunction = function (event) {
setTimeout(function () {
if(mustWait){
mustWait = false;
}
else{
$(".classToHide").hide();
$(".classToShow").show();
mustWait = true;
}
}, 200);
};

make 'each' cycles occur consecutively

I have two actions I need to apply to a set of DIV's, but I need one cycle to happen before the other is finished.
Here is my code:
$("div").each(function(){
//do stuff first
}).each(function(){
//do stuff next
});
but at present, do stuff next happens before do stuff first finishes. Anything I can do to stop this?
Full Script
$("div").each(function(){
if($(this).html() === "yes"){
$(this).fadeOut(time,function(){
$(this).parent().height(0);
});
}
}).each(function(){
if($(this).html() !== "yes"){
$(this).parent().height(25);
$(this).fadeIn(time);
}
});
Knowing that you want to fadeIn and then set height, will this do what you require?
var divs = $('div');
divs.fadeIn(function () {
divs.height('200');
});
Using each to allow different settings for different divs:
$('div').each(function () {
var div = $(this), toggle = true;
div.fadeIn(function () {
if (toggle = !toggle) {
div.height('200');
} else {
div.width('200');
}
});
});
Seeing your code snippet I believe I got it now:
var yesDivs = $('div').filter(function () {
return $(this).html() === 'yes';
});
yesDivs.fadeOut(time, function () {
yesDivs.parent().height(0);
$('div').filter(function () {
return $(this).html() !== 'yes';
}).fadeIn(time).parent().height(25);
});

How do I make a function to run only when the mouse is NOT hovering a specified div?

what I got now is:
function()
{
setInterval("getSearch()",10000);
getSearch();
}
);
But I want this interval to pause if the mouse cursor is placed inside a div on my website. How do I attack this problem? Surely I need to give the div an ID.. But some input on how to make the javascript/jquery part is much appreciated.
EDIT: More of my code.. I'm not quite sure where to insert the code in the answers inside this:
$(
function()
{
setInterval("getSearch()",10000);
getSearch();
}
);
TwitterCache = {};
function getSearch()
{
var url = "http://search.twitter.com/search.json?q=test&refresh=6000&callback=?"; // Change your query here
$.getJSON
(
url,
function(data)
{
if( data.results ) // Checks to see if you have any new tweets
{
var i = -1, result, HTML='', HTML2='';
while( (result = data.results[++i]) && !TwitterCache[result.id] )
{
insert html.. blabla}
setInterval returns a "reference" to that interval you set up, allowing you to stop it with window.clearInterval(), and that's what you have to do:
var myInterval;
function startMyInterval() {
if (!myInterval) {
// It's better to call setInterval width a function reference, than a string,
// also always use "window", in case you are not in its scope.
myInterval = window.setInterval(getSearch, 10000);
}
}
function stopMyInterval() {
if (myInterval) {
window.clearInterval(myInterval);
}
}
startMyInterval(); // Start the interval
jQuery("#myDiv").hover(stopMyInterval, startMyInterval);
Set a global variable
var intID;
Assign setInterval to this variable
intID = setInterval("getSearch()",10000);
Set an id for the div
$("#divid").hover(function(){
clearInterval(intID);
},
function(){
// set the interval again
});
I think this should work:
$("#divID").hover(
function () {
PauseTheInterValThing()
},
function()
{
setInterval("getSearch()",10000);
getSearch();
}
);
The simplest way, and the shortest
Simplest method would be:
<div id="yourDiv">
EXAMPLE TEXT
</div>
<script language="Javascript">
var interval = setInterval("getSearch()",1000);
document.getElementById("yourDiv").addEventListener('mouseover', function()
{
clearInterval(interval);
},false);
document.getElementById("yourDiv").addEventListener('mouseout', function()
{
interval = setInterval("getSearch()",1000);
},false);
</script>
insert this in your dom-ready function:
var inv = setInterval("getSearch",1000);
$('#yourdiv').mouseover(function(){
clearInterval(inv);
}).mouseout(function(){
inv = setInterval("getSearch",1000);
})

Categories

Resources