ama2
ama2

Reputation: 2681

Checking element visibility using elementFromPoint() method

I'm trying to check to make sure an item is visible before I start working on it using the following function

isVisible: function (node, doc, x, y) {
    var el = doc.elementFromPoint(x, y);
    if (node === el) return true;
    else return false;
},

x and y are positions of the selected node and is calculated by

findPos: function (node) {
    var pos = new Object();
    pos.left = pos.top = 0;
    if (node.offsetParent) {
        do {
            pos.left += node.offsetLeft;
            pos.top += node.offsetTop;

        } while (node = node.offsetParent);
    }
    return pos;
}

Everything works fine. However, when I scroll the page down, the isVisible function is no longer returning the right value. This is caused by the position having changed but the find position function not returning the right value.

Is there a method to get the position of an element like the reverse of elementFromPoint? Or does anyone have another method?

Upvotes: 0

Views: 991

Answers (3)

Greg Franko
Greg Franko

Reputation: 1770

I just wrote an isVisible() method that uses the elementFromPoint() method and should work in IE9+ to detect if an element is visible.

var isVisible = function(elem) {
  var w = window, d = document, height, rects, on_top;
  if(!elem || (elem && elem.nodeType !== 1) || !elem.getClientRects || !d.elementFromPoint || !d.querySelector || !elem.contains) {
    return false;
  }
  if (elem.offsetWidth === 0 || elem.offsetHeight === 0) {
    return false;
  }
  height = w.innerHeight ? w.innerHeight: d.documentElement.clientHeight;
  rects = elem.getClientRects();
  on_top = function(r, elem) {
    var x = (r.left + r.right)/2,
      y = (r.top + r.bottom)/2,
      elemFromPoint = d.elementFromPoint(x, y);
      return (elemFromPoint === elem || elem.contains(elemFromPoint));
  };
  for (var i = 0, l = rects.length; i < l; i++) {
    var r = rects[i],
      in_viewport = r.top > 0 ? r.top <= height : (r.bottom > 0 && r.bottom <= height);
    if (in_viewport && on_top(r, elem)) {
      return true;
    }
  }
  return false;
};

You would call it like this: isVisible(document.getElementById('at-follow'));

Also, here is the gist of it.

Upvotes: 2

ama2
ama2

Reputation: 2681

I was able to fix this by adding window.scrollX and window.scrollY to the doc.elementFromPoint() input parameters x and y

    isVisible: function (node, doc, x, y) 
     {
      var el = doc.elementFromPoint(x-window.scrollX, y-window.scrollY);
        if (node === el) return true;
          else return false;
     },

this seems to work fine

Upvotes: 1

matt3141
matt3141

Reputation: 4423

This library should be what you're looking for: https://github.com/cpatik/within-viewport/blob/master/withinViewport.js

Upvotes: 0

Related Questions