Now most browsers support getBoundingClientRect method, which has become the best practice. Using an old answer is very slow, not accurate and has several bugs.
The solution selected as correct is almost never precise.
This solution was tested on Internet Explorer 7 (and later), iOS 5 (and later) Safari, Android 2.0 (Eclair) and later, BlackBerry, Opera Mobile, and Internet Explorer Mobile 9.
function isElementInViewport (el) {
// Special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /* or $(window).height() */
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */
);
}
How to use:
You can be sure that the function given above returns correct answer at the moment of time when it is called, but what about tracking element's visibility as an event?
Place the following code at the bottom of your <body>
tag:
function onVisibilityChange(el, callback) {
var old_visible;
return function () {
var visible = isElementInViewport(el);
if (visible != old_visible) {
old_visible = visible;
if (typeof callback == 'function') {
callback();
}
}
}
}
var handler = onVisibilityChange(el, function() {
/* Your code go here */
});
// jQuery
$(window).on('DOMContentLoaded load resize scroll', handler);
/* // Non-jQuery
if (window.addEventListener) {
addEventListener('DOMContentLoaded', handler, false);
addEventListener('load', handler, false);
addEventListener('scroll', handler, false);
addEventListener('resize', handler, false);
} else if (window.attachEvent) {
attachEvent('onDOMContentLoaded', handler); // Internet Explorer 9+ :(
attachEvent('onload', handler);
attachEvent('onscroll', handler);
attachEvent('onresize', handler);
}
*/
If you do any DOM modifications, they can change your element's visibility of course.
Guidelines and common pitfalls:
Maybe you need to track page zoom / mobile device pinch? jQuery should handle zoom/pinch cross browser, otherwise first or second link should help you.
If you modify DOM, it can affect the element's visibility. You should take control over that and call handler()
manually. Unfortunately, we don't have any cross browser onrepaint
event. On the other hand that allows us to make optimizations and perform re-check only on DOM modifications that can change an element's visibility.
Never Ever use it inside jQuery $(document).ready() only, because there is no warranty CSS has been applied in this moment. Your code can work locally with your CSS on a hard drive, but once put on a remote server it will fail.
After DOMContentLoaded
is fired, styles are applied, but the images are not loaded yet. So, we should add window.onload
event listener.
We can't catch zoom/pinch event yet.
The last resort could be the following code:
/* TODO: this looks like a very bad code */
setInterval(handler, 600);
You can use the awesome feature pageVisibiliy of the HTML5 API if you care if the tab with your web page is active and visible.
TODO: this method does not handle two situations:
Using
$("a").attr("href", "http://www.google.com/")
will modify the href of all hyperlinks to point to Google. You probably want a somewhat more refined selector though. For instance, if you have a mix of link source (hyperlink) and link target (a.k.a. "anchor") anchor tags:
<a name="MyLinks"></a>
<a href="http://www.codeproject.com/">The CodeProject</a>
...Then you probably don't want to accidentally add href
attributes to them. For safety then, we can specify that our selector will only match <a>
tags with an existing href
attribute:
$("a[href]") //...
Of course, you'll probably have something more interesting in mind. If you want to match an anchor with a specific existing href
, you might use something like this:
$("a[href='http://www.google.com/']").attr('href', 'http://www.live.com/')
This will find links where the href
exactly matches the string http://www.google.com/
. A more involved task might be matching, then updating only part of the href
:
$("a[href^='http://stackoverflow.com']")
.each(function()
{
this.href = this.href.replace(/^http:\/\/beta\.stackoverflow\.com/,
"http://stackoverflow.com");
});
The first part selects only links where the href starts with http://stackoverflow.com
. Then, a function is defined that uses a simple regular expression to replace this part of the URL with a new one. Note the flexibility this gives you - any sort of modification to the link could be done here.
Best Answer
I am also looking for an answer to this question, (to clarify, I want to be able to draw an image with user defined opacity such as how you can draw shapes with opacity) if you draw with primitive shapes you can set fill and stroke color with alpha to define the transparency. As far as I have concluded right now, this does not seem to affect image drawing.
I have concluded that setting the
globalCompositeOperation
works with images.I wonder if there is some kind third way of setting color so that we can tint images and make them transparent easily.
EDIT:
After further digging I have concluded that you can set the transparency of an image by setting the
globalAlpha
parameter BEFORE you draw the image:If you want to achieve a fading effect over time you need some kind of loop that changes the alpha value, this is fairly easy, one way to achieve it is the
setTimeout
function, look that up to create a loop from which you alter the alpha over time.