jQuery how to constantly check if element is hidden/visible? - javascript

I have a couple of HTML5 videos on my website (within a slider), they automatically cycle every x seconds (or when user clicks "next slide").
I want to stop the videos that are actually invisible to user, any ideas how to achieve that?
I was tryng to do something like that, but I guess there's "each" missing and it works after click instead all the time (ok, in fact it doesn't work because "this" is used wrong here I guess, but you get the point, sorry, I'm not a JS-guy at all :():
document.on('click', ".videojs:hidden", function(){
alert('video hidden!');
jQuery(this).player.pause();
});

You might want to look into this:
http://www.west-wind.com/weblog/posts/2008/Sep/12/jQuery-CSS-Property-Monitoring-Plugin-updated
You can then do something like this:
jQuery(".videojs").watch("display,visibility", function() {
if(!jQuery(".videojs").is(':visible'))
{
alert('video hidden!');
jQuery(".videojs").player.pause();
}
});

I think you want to look into using setInterval(). Something like:
var videoInterval = setInterval(function() {
// video check logic here
}, 1000);
The above code will run your video check every second (1000 milliseconds). You can probably also use $( instead of jQuery(. The videoInterval variable will let you use clearInterval() if you need to stop the "loop" of checks for any reason. I believe this code will need to be inside of your $(document).ready(function() {...}) block.

Related

SetInterval loop relatively confusing to me

HTML
<div id="backspace" ng-click="deleteString(''); decrementCursor();">
JS
<script>
$scope.deleteString = function() {
if($scope.cursorPosVal > 0){
//$scope.name = $scope.name - letter;
$scope.name = [$scope.name.slice(0, $scope.cursorPosVal - 1) + $scope.name.slice($scope.cursorPosVal)].join('');
console.log($scope.name);
setTimeout(function(){ setCaretPosition("inputBox", $scope.cursorPosVal); }, 30);
} else {
$scope.cursorPosVal = 1;
}
};
</script>
I am designing an on screen touchscreen keyboard. This is my backspace button. I am going to make it so that when you click and hold the backspace button, it starts removing characters automatically. I don't know where to begin with creating a setInterval, and I know a setInterval is exactly what I need to use here.
If I'm not wrong, you want that while you're keeping your button pressed, a function repeats itself.
You're right with setInterval(). However, the way you manage the event is wrong.
Take a look at this fiddle (It's not your code, but a simple example is the best way to understand):
http://jsfiddle.net/daq9atdd/1/
$(function(){
var interval = null;
$('#myButton').mousedown(function(){
interval = setInterval(function(){
console.log('Hello !');
}, 250);
});
$('#myButton').mouseup(function(){
clearInterval(interval);
});
});
I start the interval when the button is pressed, store it, and clear it when the button is released.
You’re so sure about setInterval.
If browser briefly hangs for whatever reason (say some background task), setInterval would go on queueing your backspace calls until it has some CPU time. This means user may see no change and hold backspace longer than needed, and then see a whole bunch of characters suddenly vanish when browser is back to normal.
Thus by setting a timeout after every call you’re making sure user won’t remove more characters than needed. Might be important if the goal is to improve UX.
Example implementation with AngularJS directives and setTimeout
See also:
setTimeout or setInterval?
noKid’s fiddle updated with setTimeout in mind

Limiting click detection on the page [javascript]

I'm trying to limit the user's ability to click on an object to a certain time limit. I looked around and found that apparently, setTimeout() is the correct function to use for this type of thing. I've applied the function to my code, but its not working. I'm thinking/know now that the problem is that the setTimeout in my code isn't limiting the actual click event, which I need to do. Here is a snippet of my click code:
function clickRun(event) {
var $objectVersion = correspondingObject(event.target.id);
if (isAnyVisible() == false) { // none open
$objectVersion.makeVisible();
} else if (isAnyVisible() && $objectVersion.isVisible()) { //click already open div
$objectVersion.makeInvisible();
} else if (isAnyVisible() && $objectVersion.isVisible()==false) { //different div open
searchAndDestroy();
$objectVersion.delay(600).makeVisible();
};
};
$('.ChartLink').click(function(event) {
setTimeout(clickRun(event),5000);
});
I've also created a JSFiddle to represent what I'm talking about: http://jsfiddle.net/FHC7s/
Is there a way to achieve limiting the actual click detection on the page?
I think the easiest way to do it is to keep track of the time of the previous click and if the current click is too soon after that, then don't do anything:
onClick = function(){
if(new Date().getTime() - lastCheck < MIN_CLICK_SPACING) return;
}
Have a look at this JSFiddle, I've set it up so you can have the button disable itself for time duration after detecting a click. Just make sure to remember how your closures are operating with your setTimeouts.
Your code contains an error... your line should be
setTimeout(function(){clickRun(event)},5000);
but even then I don't think that's exactly what you're looking for; that code will "delay" the click by 5 seconds, not actually prevent more clicks. If your true intent is to ignore all clicks after a certain amount of time, then I would go with mowwalker's answer; there's no way to stop the clicks, but you can check to see if you should honor them or not.

force DOM redraw with javascript on demand

The title of the question expresses what I think is the ultimate question behind my particular case.
My case:
Inside a click handler, I want to make an image visible (a 'loading' animation) right before a busy function starts. Then I want to make it invisible again after the function has completed.
Instead of what I expected I realize that the image never becomes visible. I guess that this is due to the browser waiting for the handler to end, before it can do any redrawing (I am sure there are good performance reasons for that).
The code (also in this fiddle: http://jsfiddle.net/JLmh4/2/)
html:
<img id="kitty" src="http://placekitten.com/50/50" style="display:none">
<div>click to see the cat </div>
js:
$(document).ready(function(){
$('#enlace').click(function(){
var kitty = $('#kitty');
kitty.css('display','block');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec)
{
var endtime= new Date().getTime() + usec;
while (new Date().getTime() < endtime)
;
}
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.css('display','none');
});
});
I have added the alert call right after the sleepStupidly function to show that in that moment of rest, the browser does redraw, but not before. I innocently expected it to redraw right after setting the 'display' to 'block';
For the record, I have also tried appending html tags, or swapping css classes, instead of the image showing and hiding in this code. Same result.
After all my research I think that what I would need is the ability to force the browser to redraw and stop every other thing until then.
Is it possible? Is it possible in a crossbrowser way? Some plugin I wasn't able to find maybe...?
I thought that maybe something like 'jquery css callback' (as in this question: In JQuery, Is it possible to get callback function after setting new css rule?) would do the trick ... but that doesn't exist.
I have also tried to separte the showing, function call and hiding in different handlers for the same event ... but nothing. Also adding a setTimeout to delay the execution of the function (as recommended here: Force DOM refresh in JavaScript).
Thanks and I hope it also helps others.
javier
EDIT (after setting my preferred answer):
Just to further explain why I selected the window.setTimeout strategy.
In my real use case I have realized that in order to give the browser time enough to redraw the page, I had to give it about 1000 milliseconds (much more than the 50 for the fiddle example). This I believe is due to a deeper DOM tree (in fact, unnecessarily deep).
The setTimeout let approach lets you do that.
Use JQuery show and hide callbacks (or other way to display something like fadeIn/fadeOut).
http://jsfiddle.net/JLmh4/3/
$(document).ready(function () {
$('#enlace').click(function () {
var kitty = $('#kitty');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec) {
var endtime = new Date().getTime() + usec;
while (new Date().getTime() < endtime);
}
kitty.show(function () {
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.hide();
});
});
});
Use window.setTimeout() with some short unnoticeable delay to run slow function:
$(document).ready(function() {
$('#enlace').click(function() {
showImage();
window.setTimeout(function() {
sleepStupidly(4000);
alert('now you do see it');
hideImage();
}, 50);
});
});
Live demo
To force redraw, you can use offsetHeight or getComputedStyle().
var foo = window.getComputedStyle(el, null);
or
var bar = el.offsetHeight;
"el" being a DOM element
I do not know if this works in your case (as I have not tested it), but when manipulating CSS with JavaScript/jQuery it is sometimes necessary to force redrawing of a specific element to make changes take effect.
This is done by simply requesting a CSS property.
In your case, I would try putting a kitty.position().left; before the function call prior to messing with setTimeout.
What worked for me is setting the following:
$(element).css('display','none');
After that you can do whatever you want, and eventually you want to do:
$(element).css('display','block');

Starting, stopping & refreshing timer javascript

I have a little fiddle here where I'm starting/stopping/resetting a javascript timer.
The functionality needs to be a timer runs on a page. When the timer is up, it sends a message, then restarts. The stop button will stop the timer completely.
The fiddle above has the functionality I just described, however I feel like I'm not doing this correctly. Is setTimeout the correct way to create this timer? Should I use setInterval instead?
Secondly, my reset code looks like :
var onReset = function() {
clearTimeout(timerHandle);
onStart();
};
Is there a more elegant way to reset a timer in javascript?
Thanks.
The only improvement I can offer is for you to put it all in an encapsulated object, ask if you want an example. Or if you want to keep the structure you've got then change your onStart function to this to remove a bit of un-needed code.
var onStart = function() {
timerHandle = setInterval(function() {
$("#console").append("timer fired.. <br />");
}, 2000);
};
Fiddle here http://jsfiddle.net/qx6CM/

jQuery addClass removeClass with timer

I have an issue with a 'Latest News' module. Please have a look at http://www.proudfootsupermarkets.com/ to see an example of the module (it's the div close to the top of the page which has a large image in it).
At the moment I have it set up so that when a user clicks on a tab the main article shows. The jQuery for this is:
jQuery(document).ready(function() {
$(".moduletable.latestnews article:first-child").addClass("atfront")
$(".moduletable.latestnews article").click(function(){
$(".moduletable.latestnews article").css("zIndex",1).addClass("atback").removeClass("atfront");
$(this).css("zIndex",100).addClass("atfront").removeClass("atback");
});
});
This is all quite simple and straight forward. The problem that I am having is that I want the articles to change automatically after a few seconds. This would then go in an infinite loop starting with article 1 and then after a couple of seconds showing article 2 etc etc...
I am sure that this is fairly simple but I have just about exhausted my knowledge of JavaScript. Thank you for any help that you are able to give :)
I have created a jsfiddle http://jsfiddle.net/Bempv/
You can use setTimeout to change the article in front. If you select the article with the class ".atfront" and then use the .next() selector you should get the functionality you are looking for
$(function(){
var articleToggler = function articleToggler(){
var front = "atfront",
back = "atback";
return function(){
var selection = $(".moduletable.latestnews")
.find("article.atfront")
.addClass(back)
.removeClass(front);
next = selection.next("article");
next = next.length ? next : $(".moduletable.latestnews")
.find("article").first();
next.addClass(front)
.removeClass(back);
console.log(selection.length,next[0])
setTimeout(articleToggler(),1000); //changes every second
};
};
//start the rotation
(articleToggler())();
});
The setTimeout will call the function passed as the first argument once the timeout expires. The timeout argument is in miliseconds so the above code wait for 1 second before calling the function. Since the above function adds it self as the callback this will repeat indefinately

Categories