views:

290

answers:

3

Is it possible to fire a specific javascript event when a certain DIV comes into view on the page?

Say, for example, I have a very large page, like 2500x2500 and I have a 40x40 div that sits at position 1980x1250. The div is not necessarily manually positioned, it could be there due to the content pushing it there. Now, is it possible to run a function when the user scrolls to a point where the div becomes visible?

+3  A: 

Not automatically. You would have to catch scroll events and check for it being in view each time by comparing the co-ordinates of the div rectangle with the visible page rectangle.

Here's a minimal example.

<div id="importantdiv">hello</div>

<script type="text/javascript">
    function VisibilityMonitor(element, showfn, hidefn) {
        var isshown= false;
        function check() {
            if (rectsIntersect(getPageRect(), getElementRect(element)) !== isshown) {
                isshown= !isshown;
                isshown? showfn() : hidefn();
            }
        };
        window.onscroll=window.onresize= check;
        check();
    }

    function getPageRect() {
        var isquirks= document.compatMode!=='BackCompat';
        var page= isquirks? document.documentElement : document.body;
        var x= page.scrollLeft;
        var y= page.scrollTop;
        var w= 'innerWidth' in window? window.innerWidth : page.clientWidth;
        var h= 'innerHeight' in window? window.innerHeight : page.clientHeight;
        return [x, y, x+w, y+h];
    }

    function getElementRect(element) {
        var x= 0, y= 0;
        var w= element.offsetWidth, h= element.offsetHeight;
        while (element.offsetParent!==null) {
            x+= element.offsetLeft;
            y+= element.offsetTop;
            element= element.offsetParent;
        }
        return [x, y, x+w, y+h];
    }

    function rectsIntersect(a, b) {
        return a[0]<b[2] && a[2]>b[0] && a[1]<b[3] && a[3]>b[1];
    }

    VisibilityMonitor(
        document.getElementById('importantdiv'),
        function() {
            alert('div in view!');
        },
        function() {
            alert('div gone away!');
        }
    );
</script>

You could improve this by:

  • making it catch onscroll on all ancestors that have overflow scroll or auto and adjusting the top/left co-ords for their scroll positions
  • detecting overflow scroll, auto and hidden cropping putting the div off-screen
  • using addEventListener/attachEvent to allow multiple VisibilityMonitors and other things using the resize/scroll events
  • some compatibility hacks to getElementRect to make the co-ords more accurate in some cases, and some event unbinding to avoid IE6-7 memory leaks, if you really need to.
bobince
A: 

Take a look at this website, I think it has what you need.

http://remysharp.com/2009/01/26/element-in-view-event-plugin/

Ken Penn
it seems this is for jQuery, in this case i am not using jQuery.
Russ Bradberry
A: 

Here's an starter example using jQuery:

<html>
<head><title>In View</title></head>
<body>
    <div style="text-align:center; font-size:larger" id="top"></div>
    <fieldset style="text-align:center; font-size:larger" id="middle">
        <legend id="msg"></legend>
        <div>&nbsp;</div>
        <div id="findme">Here I am!!!</div>
    </fieldset>
    <div style="text-align:center; font-size:larger" id="bottom"></div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" type="text/javascript"></script>

<script type="text/javascript">
    var $findme = $('#findme'),
        $msg = $('#msg');

    function Scrolled() {
        var findmeOffset = $findme.offset(),
            findmeTop = findmeOffset.top,
            scrollTop = $(document).scrollTop(),
            visibleBottom = window.innerHeight;

        if (findmeTop < scrollTop + visibleBottom) {
            $msg.text('findme is visible');
        }
        else {
            $msg.text('findme is NOT visible');
        }
    }

    function Setup() {
        var $top = $('#top'),
            $bottom = $('#bottom');

        $top.height(500);
        $bottom.height(500);

        $(window).scroll(function() {
            Scrolled();
        });
    }

    $(document).ready(function() {
        Setup();

    });
</script>
</body>
</html>

It only notifies once the div comes into view from the bottom. This example does not notify when the div scrolls out of the top.

slolife
again this is for jQuery, and while I am all for jQuery, in my situation I will not be able to use it.
Russ Bradberry
Then please note that in the question, so people posting will know your limitations. It also seems both people posted at almost exactly the same time, so they couldn't have known.
Cryophallion