diff --git a/frontend/src/ketr-photos/ketr-photos.html b/frontend/src/ketr-photos/ketr-photos.html index 1895232..fbd389c 100755 --- a/frontend/src/ketr-photos/ketr-photos.html +++ b/frontend/src/ketr-photos/ketr-photos.html @@ -217,6 +217,10 @@ path: { type: String, value: "" + }, + visibleThumbs: { + type: Array, + value: [] } }, @@ -317,16 +321,90 @@ this.triggerVisibilityChecks(); }, + checkPosition: function(thumbIndex) { + var rect = this.thumbnails[thumbIndex].getBoundingClientRect(); + + if (rect.top > window.innerHeight) { + return +1; + } + + if (rect.top + rect.height < 0) { + return -1; + } + + return 0; + }, triggerVisibilityChecks: function() { this.debounce("hide-or-show", function() { - var thumbs = this.querySelectorAll("photo-thumbnail"), visible; - thumbs.forEach(function(thumb) { - visible = this.isThumbInView(thumb); - if (thumb.visible != visible) { - thumb.visible = visible; + if (!this.thumbnails) { + return; + } + + var index, length = this.thumbnails.length; + + if (this.visibleThumbs.length) { + index = this.visibleThumbs[this.visibleThumbs.length >> 1]; + } else { + index = length >> 1; + } + + var pos = this.checkPosition(index), last = -1; + while (pos != 0 && last != pos) { + if (pos == +1) { /* Checked item was too low on the page, so look closer to start */ + index = index >> 1; + } else { /* Checked item was too high on the page, so look farther */ + index += (length - index) >> 1; + } + + last = index; /* safety escape in case the DOM changed and nothing matches */ + pos = this.checkPosition(index); + } + + if (pos == last) { + console.log("DOM changed or viewport changed and search would never exit; re-scheduling check") + //this.triggerVisibilityChecks(); + return; + } + + /* 'index' now points to a thumbnail that is in the viewport; scan + * above and below until a non-in-viewport item is found in each + * direction. That creates the new 'visible' array. */ + var visible = []; + visible.push(index); + /* Scan above... */ + var tmp = index - 1; + while (tmp >= 0 && this.checkPosition(tmp) == 0) { + visible.push(tmp--); + } + tmp = index + 1; + while (tmp < length && this.checkPosition(tmp) == 0) { + visible.push(tmp++); + } + + var i; + /* Remove 'visible' attribute from any thumbnail + * that was visible and is not in the new set of + * visible thumbs. */ + this.visibleThumbs.forEach(function(index) { + for (i = 0; i < visible.length; i++) { + if (visible[i] == index) { + break; + } + } + if (i == visible.length) { + this.thumbnails[index].visible = false; + } + }); + + /* Turn on visibility for any item that is now visible */ + visible.forEach(function(index) { + if (this.thumbnails[index].visible != true) { + this.thumbnails[index].visible = true; } }.bind(this)); + + this.visibleThumbs = visible; }, 250); }, @@ -507,6 +585,8 @@ Polymer.dom(thumbnails).appendChild(thumbnail); } + this.thumbnails = this.querySelectorAll("photo-thumbnail"); + this.triggerVisibilityChecks(); },