Created
February 4, 2015 21:52
-
-
Save nkcmr/c2a468750588ef5c4d14 to your computer and use it in GitHub Desktop.
$.fn.scrollIntoView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([], function() { | |
function stripWrapper(ele) { | |
return (ele instanceof jQuery || ele instanceof angular.element) ? ele[0] : ele; | |
} | |
function getRect(el) { | |
el = stripWrapper(el); | |
return _.pick(el.getBoundingClientRect(), 'top', 'left', 'bottom', 'right', 'width', 'height'); | |
} | |
$.fn.doesScroll = function doesScroll() { | |
var _this = stripWrapper(this); | |
return ((_this.scrollTop != ((_this.scrollTop += 1) === null || | |
_this.scrollTop) && (_this.scrollTop -= 1) !== null) || | |
(_this.scrollTop != ((_this.scrollTop -= 1) === null || | |
_this.scrollTop) && (_this.scrollTop += 1) !== null)); | |
}; | |
function findNearestScrollingParent(ele) { | |
var parents = $(ele).parents(); | |
parents = [].slice.call(parents); | |
// find the nearest | |
return _.find(parents, function(p) { | |
return $(p).doesScroll(); | |
}); | |
} | |
function upmostScroller() { | |
/* | |
quirkiness: | |
in chrome the upmost scroller is the `body`. according to W3C, this is wrong. | |
the upmost scroller is supposed to be the `documentElement` | |
here, we resolve that quirkiness | |
*/ | |
if ((/chrome/i).test(navigator.userAgent)) { | |
return document.body; | |
} else { | |
return document.documentElement; | |
} | |
} | |
$.fn.scrollIntoView = function scrollIntoView(opts) { | |
opts = opts || {}; | |
var parent, | |
parentOffset, | |
view, | |
eleRect, | |
ele = this, | |
scrollX, | |
scrollY, | |
duration = (_.isNumber(opts.duration) ? opts.duration : 100), | |
padding = opts.padding || 10; | |
parent = findNearestScrollingParent(this); | |
// nothing in this hierarchy scrolls | |
if (!parent) { | |
return; | |
} | |
parentOffset = $(parent).offset(); | |
eleRect = getRect(ele); | |
if (parent.tagName == 'BODY' || parent.tagName == 'HTML') { | |
view = {}; | |
view.top = 0; | |
view.left = 0; | |
view.bottom = window.innerHeight; | |
view.right = window.innerWidth; | |
view.width = window.innerWidth; | |
view.height = window.innerHeight; | |
parent = upmostScroller(); | |
scrollY = window.pageYOffset; | |
scrollX = window.pageXOffset; | |
} else { | |
view = {}; | |
view.top = parentOffset.top; | |
view.left = parentOffset.left; | |
view.right = view.left + parent.clientWidth; | |
view.bottom = view.top + parent.clientHeight; | |
view.width = parent.clientWidth; | |
view.height = parent.clientHeight; | |
scrollY = parent.scrollTop; | |
scrollX = parent.scrollLeft; | |
eleRect.left = window.pageXOffset + eleRect.left; | |
eleRect.right = window.pageXOffset + eleRect.right; | |
eleRect.top = window.pageYOffset + eleRect.top; | |
eleRect.bottom = window.pageYOffset + eleRect.bottom; | |
} | |
if (eleRect.left < view.left) { | |
scrollX += eleRect.left - (view.left + padding); | |
} else if (eleRect.right > view.right) { | |
scrollX += eleRect.right - (view.right - padding); | |
} | |
if (eleRect.top < view.top) { | |
scrollY += eleRect.top - (view.top + padding); | |
} else if (eleRect.bottom > view.bottom) { | |
scrollY += eleRect.bottom - (view.bottom - padding); | |
} | |
if (duration === 0) { | |
parent.scrollTop = scrollY; | |
parent.scrollLeft = scrollX; | |
} else { | |
$(parent).animate({ | |
scrollTop: scrollY, | |
scrollLeft: scrollX | |
}, duration); | |
} | |
}; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment