|
|
@ -172,13 +172,10 @@ function watchScroll(viewAreaElement, callback) { |
|
|
|
|
|
|
|
|
|
|
|
var currentY = viewAreaElement.scrollTop; |
|
|
|
var currentY = viewAreaElement.scrollTop; |
|
|
|
var lastY = state.lastY; |
|
|
|
var lastY = state.lastY; |
|
|
|
if (currentY > lastY) { |
|
|
|
if (currentY !== lastY) { |
|
|
|
state.down = true; |
|
|
|
state.down = currentY > lastY; |
|
|
|
} else if (currentY < lastY) { |
|
|
|
|
|
|
|
state.down = false; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
state.lastY = currentY; |
|
|
|
state.lastY = currentY; |
|
|
|
// else do nothing and use previous value
|
|
|
|
|
|
|
|
callback(state); |
|
|
|
callback(state); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
}; |
|
|
@ -194,6 +191,38 @@ function watchScroll(viewAreaElement, callback) { |
|
|
|
return state; |
|
|
|
return state; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Use binary search to find the index of the first item in a given array which |
|
|
|
|
|
|
|
* passes a given condition. The items are expected to be sorted in the sense |
|
|
|
|
|
|
|
* that if the condition is true for one item in the array, then it is also true |
|
|
|
|
|
|
|
* for all following items. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @returns {Number} Index of the first array element to pass the test, |
|
|
|
|
|
|
|
* or |items.length| if no such element exists. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
function binarySearchFirstItem(items, condition) { |
|
|
|
|
|
|
|
var minIndex = 0; |
|
|
|
|
|
|
|
var maxIndex = items.length - 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (items.length === 0 || !condition(items[maxIndex])) { |
|
|
|
|
|
|
|
return items.length; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (condition(items[minIndex])) { |
|
|
|
|
|
|
|
return minIndex; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (minIndex < maxIndex) { |
|
|
|
|
|
|
|
var currentIndex = (minIndex + maxIndex) >> 1; |
|
|
|
|
|
|
|
var currentItem = items[currentIndex]; |
|
|
|
|
|
|
|
if (condition(currentItem)) { |
|
|
|
|
|
|
|
maxIndex = currentIndex; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
minIndex = currentIndex + 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return minIndex; /* === maxIndex */ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Generic helper to find out what elements are visible within a scroll pane. |
|
|
|
* Generic helper to find out what elements are visible within a scroll pane. |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -201,30 +230,45 @@ function getVisibleElements(scrollEl, views, sortByVisibility) { |
|
|
|
var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight; |
|
|
|
var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight; |
|
|
|
var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth; |
|
|
|
var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth; |
|
|
|
|
|
|
|
|
|
|
|
var visible = [], view; |
|
|
|
function isElementBottomBelowViewTop(view) { |
|
|
|
|
|
|
|
var element = view.div; |
|
|
|
|
|
|
|
var elementBottom = |
|
|
|
|
|
|
|
element.offsetTop + element.clientTop + element.clientHeight; |
|
|
|
|
|
|
|
return elementBottom > top; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var visible = [], view, element; |
|
|
|
var currentHeight, viewHeight, hiddenHeight, percentHeight; |
|
|
|
var currentHeight, viewHeight, hiddenHeight, percentHeight; |
|
|
|
var currentWidth, viewWidth; |
|
|
|
var currentWidth, viewWidth; |
|
|
|
for (var i = 0, ii = views.length; i < ii; ++i) { |
|
|
|
var firstVisibleElementInd = (views.length === 0) ? 0 : |
|
|
|
|
|
|
|
binarySearchFirstItem(views, isElementBottomBelowViewTop); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = firstVisibleElementInd, ii = views.length; i < ii; i++) { |
|
|
|
view = views[i]; |
|
|
|
view = views[i]; |
|
|
|
currentHeight = view.div.offsetTop + view.div.clientTop; |
|
|
|
element = view.div; |
|
|
|
viewHeight = view.div.clientHeight; |
|
|
|
currentHeight = element.offsetTop + element.clientTop; |
|
|
|
if ((currentHeight + viewHeight) < top) { |
|
|
|
viewHeight = element.clientHeight; |
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (currentHeight > bottom) { |
|
|
|
if (currentHeight > bottom) { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
currentWidth = view.div.offsetLeft + view.div.clientLeft; |
|
|
|
|
|
|
|
viewWidth = view.div.clientWidth; |
|
|
|
currentWidth = element.offsetLeft + element.clientLeft; |
|
|
|
if ((currentWidth + viewWidth) < left || currentWidth > right) { |
|
|
|
viewWidth = element.clientWidth; |
|
|
|
|
|
|
|
if (currentWidth + viewWidth < left || currentWidth > right) { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
hiddenHeight = Math.max(0, top - currentHeight) + |
|
|
|
hiddenHeight = Math.max(0, top - currentHeight) + |
|
|
|
Math.max(0, currentHeight + viewHeight - bottom); |
|
|
|
Math.max(0, currentHeight + viewHeight - bottom); |
|
|
|
percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0; |
|
|
|
percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0; |
|
|
|
|
|
|
|
|
|
|
|
visible.push({ id: view.id, x: currentWidth, y: currentHeight, |
|
|
|
visible.push({ |
|
|
|
view: view, percent: percentHeight }); |
|
|
|
id: view.id, |
|
|
|
|
|
|
|
x: currentWidth, |
|
|
|
|
|
|
|
y: currentHeight, |
|
|
|
|
|
|
|
view: view, |
|
|
|
|
|
|
|
percent: percentHeight |
|
|
|
|
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var first = visible[0]; |
|
|
|
var first = visible[0]; |
|
|
|