admin管理员组文章数量:1278985
When using Google Reader and browsing RSS entries in the "Expanded" view, entries will automatically be marked as 'read' once a certain percentage of the div is visible on the screen (difficult to tell what percentage has to be visible in the case of Google Reader). So, as I scroll down line-by-line, the javascript code can determine that a) the entry is being rendered in the visible window and b) a certain amount is visible and when those conditions are met, the state is toggled to read.
Does anyone have any idea how that feature is implemented? Specifically, does anyone here know how to tell if a div has scrolled into view an how much of the div is visible?
As an aside, I'm using jQuery, so if anyone has any jQuery-specific examples, they would be much appreciated.
When using Google Reader and browsing RSS entries in the "Expanded" view, entries will automatically be marked as 'read' once a certain percentage of the div is visible on the screen (difficult to tell what percentage has to be visible in the case of Google Reader). So, as I scroll down line-by-line, the javascript code can determine that a) the entry is being rendered in the visible window and b) a certain amount is visible and when those conditions are met, the state is toggled to read.
Does anyone have any idea how that feature is implemented? Specifically, does anyone here know how to tell if a div has scrolled into view an how much of the div is visible?
As an aside, I'm using jQuery, so if anyone has any jQuery-specific examples, they would be much appreciated.
Share Improve this question edited Jul 19, 2012 at 3:36 Linger 15.1k23 gold badges54 silver badges79 bronze badges asked Dec 9, 2008 at 20:33 smoodysmoody 1235 bronze badges6 Answers
Reset to default 4The real trick is to keep track of where the scrollbar is in the element containing your items. Here's some code I once whipped up to do it: http://pastebin./f4a329cd9
You can see that as you scroll it changes focus. You just need to add more handler code to the function that handles each focus change. It works scrolling in both direction, and also by clicking right on the scrollbar, which simple mouse tracking won't give you (though in this case since the example elements are all the same size, with the same text, it's hard to tell that it has indeed scrolled). The other issue is what to do when the container bottoms out. The solution I have right now only works in FF. If you want to have it look nice in IE, you'll have to use a dummy element that blends into the background, like the one I have mented out in the code.
I just came across this as I need the same thing, and it looks super useful:
http://www.appelsiini/projects/viewport
In my experience, Reader has only ever marked something as read if I have moused-over or clicked on it. Assuming that as you scroll your mouse is over the div (I tend to put my mouse to the right edge of the screen when I scroll) that might explain the appearance that it only gets marked off when a certain % has been shown.
I could be (and likely am) wrong, though. I just know that the act of just scrolling through my items in reader does not mark them off. I have to make sure the mouse mouses over them as it scrolls to do it.
The dom and javascript let you calculate an element offset from its parent. To calculate the offset from the window you need to use recursion and climb your way to the top window, and also pare that against the window's size. It gets more plicated because of cross-browser issues and iframes.
To the best of my knowledge, prototype offers a simple viewportOffset
method that does most of the work for you. You can also check the source for getOffsetParent
and scrollTo
. I don't know about jquery, but I expect it to offer similar methods.
My guess is that the script in google reader simply runs on a timeout, probably a few times a second, or perhaps in response to a scroll event. In both cases, I am sure that it is adaptive (timeout changes based on how fast the user scrolls, etc.), and that it is smart enough not to be a resource hog (i.e., don't just check all the divs in the document)
In order to calculate whether an element is visible, you can create such a function (credit is due here https://stackoverflow./a/22480938/825240):
function isScrolledIntoView(element) {
var elementTop = element.getBoundingRect().top;
var elementBottom = element.getBoundingRect().bottom;
var isVisible = (elementTop <= window.innerHeight) && (elementBottom >= 0);
return isVisible;
}
You can customize that function to your situation by calculating if an element has been read:
function isRead(element) {
var elementTop = element.getBoundingRect().top;
var elementBottom = element.getBoundingRect().bottom;
var elementHeight = elementBottom - elementTop;
// if 75% of the document has been scrolled, we'll assume it's been read
var readIfPercentage = 0.75;
// an element has been read if the top has been scrolled up out of view
// and at least 75% of the element is no longer visible
var isRead = (elementTop < 0 && Math.abs(elementTop) / elementHeight >= readIfPercentage);
return isRead;
}
You can then call the functions above, passing in a DOM node as the element:
isScrolledIntoView(document.getElementById('targetDiv');
//or
isRead(document.getElementById('targetDiv');
You can tie it all together by creating a scroll listener (jQuery makes this pretty easy):
function setScrollListener() {
var scrollEventHandler = function() {
if (isRead(document.getElementById('article'))) {
// set article to 'read'
}
}
// on scroll, fire the event handler
$(document).scroll(scrollEventHandler);
}
It's worth noting that if you want to unbind the scroll listener, say if all of the articles have been read and you no longer need to listen to the scroll, you can call the unbind function within the scrollEventHandler. It is as simple as:
function unbindScrollEventHandler() {
$(document).unbind('scroll', scrollEventHandler);
}
You can try this one, the key point is the element must visible to inner body more and meet the visible ratio (in this case 0.85).
isRead(element) {
let rect = element.getBoundingClientRect();
const visibleRatio = 0.85;
let elementRatio = (window.innerHeight - Math.abs(rect.top))/rect.height;
let isRead = (rect.top >= 0) && (elementRatio >= visibleRatio);
return isRead;
}
本文标签:
版权声明:本文标题:javascript - Detecting divs as rendered in the window to implement Google-Reader-like auto-mark-as-read? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741299440a2371006.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论