{"id":1570,"date":"2012-03-15T07:55:05","date_gmt":"2012-03-15T12:55:05","guid":{"rendered":"http:\/\/www.wiredprairie.us\/blog\/?p=1570"},"modified":"2012-03-15T07:55:05","modified_gmt":"2012-03-15T12:55:05","slug":"javascript-isscrolledintoview","status":"publish","type":"post","link":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1570","title":{"rendered":"JavaScript: isScrolledIntoView"},"content":{"rendered":"

\"image\"<\/p>\n

I needed a simple way to detect when a placeholder DIV (that would contain an image) had scrolled into the current viewport of the browser. I\u2019ve seen a few solutions that worked, and a few that didn\u2019t (hello? test your code!). Here\u2019s my simple solution:<\/p>\n

function <\/span>isScrolledIntoView(elem) {\n    elem = $(elem);\n    var <\/span>win = $(window);\n    var <\/span>docViewTop = win.scrollTop();\n    var <\/span>docViewBottom = docViewTop + win.height();\n    var <\/span>elemTop = elem.offset().top;\n    var <\/span>elemBottom = elemTop + elem.height();\n\n    var <\/span>a = (elemTop > docViewBottom);\n    if <\/span>(a) { return false<\/span>; }\n    var <\/span>b = (elemBottom > docViewTop);\n    if <\/span>(!b) { return false<\/span>; }\n    return <\/span>!(a && b);\n}<\/pre>\n

Nothing fancy, except it does require jQuery.<\/p>\n

When one of the place holder DIVs scrolled into view, the code would trigger a queued load of the image.<\/p>\n

\"SmugMupBrowser-live\"<\/p>\n

As the SmugMug API is poorly designed in a few places, in particular as it relates to showing a thumbnail for a gallery\/album, when an album\/gallery is scrolled into view, the app loads a list of ALL of the images from the now visible album and selects one of them to show as the thumbnail. It\u2019s extremely inefficient unfortunately. <\/strong>Instead, if they could have included that extra piece of data in the gallery list (thumbnail image and thumbnail image key), boom! <\/p>\n

I\u2019ve also included a delay so that the auto loading only occurs after a 1 second pause (either the window being resized or scrolling occurring):<\/p>\n

function <\/span>delayLoadNewVisible() {\n    if <\/span>(visibilityDelayTimerId == 0) {\n        visibilityDelayTimerId = window.setTimeout(function <\/span>() {\n            visibilityDelayTimerId = 0;\n            loadNewVisible();\n        }, 1000);\n    }\n}<\/pre>\n

I\u2019m not going to post the code for the other useful aspect of this functionality, but I\u2019ll tell you about it, and leave coding it as an exercise for the reader. \"Smile\"<\/p>\n

When the user scrolls new albums into view, after the pause, they\u2019re added to a load queue. However, as it\u2019s just as likely that the user will scroll the album off the screen, my load code also can remove something from the load queue if it hasn\u2019t been loaded already. This way, visible albums are given precedence. By using the queue in this way, there are a manageable number of outstanding requests at any given time, and ideally only those that are relevant to what\u2019s on the user\u2019s screen. <\/p>\n","protected":false},"excerpt":{"rendered":"

I needed a simple way to detect when a placeholder DIV (that would contain an image) had scrolled into the current viewport of the browser. I\u2019ve seen a few solutions that worked, and a few that didn\u2019t (hello? test your code!). Here\u2019s my simple solution: function isScrolledIntoView(elem) { elem = $(elem); var win = $(window); […]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[4],"tags":[38,78,66],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pd5QIe-pk","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1559,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1559","url_meta":{"origin":1570,"position":0},"title":"Some code from SnugUp.Browser (an album browser for SmugMug)","date":"March 6, 2012","format":false,"excerpt":"I\u2019ve been doing some tinkering recently with SmugMug again. Through testing SnugUp for the past 4 years, I\u2019ve made quite the mess of my SmugMug account. Literally hundreds of poorly organized and often completely junk albums. I\u2019ve been wanting to clean it up, but SmugMug\u2019s UI for that is so\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"image","src":"https:\/\/i0.wp.com\/www.wiredprairie.us\/blog\/wp-content\/uploads\/2012\/03\/image_thumb.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1563,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1563","url_meta":{"origin":1570,"position":1},"title":"Knockout.JS: AsDictionary","date":"March 9, 2012","format":false,"excerpt":"I frequently find that I have an array of objects in JavaScript that I want to display in a particular order and also have the ability to quickly locate an object by an ID or a key (and not use the indexOf function). As my recent project is using Knockout.JS,\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.wiredprairie.us\/blog\/wp-content\/uploads\/2012\/03\/image3.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1565,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1565","url_meta":{"origin":1570,"position":2},"title":"Knockout.JS: Dictionary\/Index and ObservableArray, Part 2","date":"March 10, 2012","format":false,"excerpt":"Ryan suggested an alternative in a comment (and corresponding jsFiddle) to the technique that I\u2019d used in my previous Knockout.JS post. Following his suggestion, I made a few tweaks to my original function (and renamed it yet again): ko.observableArray.fn.withIndex = function (keyName) { var index = ko.computed(function () { var\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1820,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1820","url_meta":{"origin":1570,"position":3},"title":"Knockout binding for JavaScript route fixup","date":"January 25, 2013","format":false,"excerpt":"Part one. After the first round, I felt compelled to KnockOut the code a bit more. I\u2019d mentioned I wasn\u2019t pleased with the code exactly. It needed some refactoring. So, I\u2019ve created a new Knockout binding handler. This binding handler replaces\u00a0 named parameters with a model\u2019s properties in a path.\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1638,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1638","url_meta":{"origin":1570,"position":4},"title":"Spinning SVG Animation","date":"April 16, 2012","format":false,"excerpt":"Interested in learning a few capabilities of SVG animation this evening from JavaScript in a web page, I put together a simple demonstration. Click on the image to launch the demo. Animating SVG in a modern browser (including IE9) is generally easy enough. This example was slightly more interesting in\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.wiredprairie.us\/blog\/wp-content\/uploads\/2012\/04\/image23.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1836,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1836","url_meta":{"origin":1570,"position":5},"title":"Smarter queuing of files using jQuery deferred and when","date":"February 13, 2013","format":false,"excerpt":"I had a somewhat simple need \u2026a single web page style application using Backbone.JS had multiple template files it needed to download, if and only if the files hadn\u2019t already been downloaded before. While I suppose I could have relied on browser caching, I wanted to manage the requests in\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts\/1570"}],"collection":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/comments?post=1570"}],"version-history":[{"count":1,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts\/1570\/revisions"}],"predecessor-version":[{"id":1571,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts\/1570\/revisions\/1571"}],"wp:attachment":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/media?parent=1570"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/categories?post=1570"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/tags?post=1570"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}