I found this OP when I was googling as part of finding solutions for a project I'm working on. Those solutions have now been found and implemented. I'll post here what we were trying to do and how we did it. I *think" that may be of some use to the OP. The solution code does not belong to me, it belongs to the company who hired me to write it, and I don't have permission to post it. However, I do have permission to describe the solution. (If you have a problem with that, please don't bother whining to me about it. If it were up to me I'd post it.)
We wanted the following behavior,
1. When we placed focus on a form field via a call to focus(), we didn't want the browser to auto-scroll to the field by default if it was not currently completely in the viewport - we wanted to be able to specify whether the field should be scrolled to or not.
2. When we did want to scroll to a field with focus, we wanted (i) the scroll to be animated (so as to be smooth rather than the browser's default abrupt scroll-to behavior), and (ii) we wanted to control precisely how far into the viewport the field would be scrolled.
3. When fields partially or completely out of view are navigated to via TAB and SHIFT-TAB, we again wanted to control the scrolling behavior for the same reasons already cited in #2 above.
To make all this happen, we leveraged off four jQuery additions/plugins (three of which we already had) and one jQuery override/plugin (all 5 of which are instance methods),
1. $.getScrollPosition(), returns {scrollLeft: valuex, scrollTop: valuey}. This method is called on a scroll parent.
2. $.scrollTo(options), where the options includes scrollLeft, scrollTop, duration, callback. If duration is specified, the scrolling is animated; if duration is not specified, the scrolling is not animated. This method is called on a scroll parent.
3. $.scrollIntoView(options), where options includes duration, callback, marginH, marginV. Again, if duration is specified, the scrolling is animated, and vice-versa. This method is called on an element with a scroll parent. If the element is already fully within the scroll parent's viewport, the method does nothing. Otherwise, this method scrolls the scroll parent such that the element is fully within the scroll parent's viewport - taking into account options.marginX and options.marginY. The margins specify how far away the element must end up from its two closest viewport edges.
4. $.focus(params) - We overrode the default jQuery.focus() method. This method is called on the element to receive focus and only operates on the first matched element - self = this.first() (i) The override calls originalPosition = self.scrollParent().getScrollPosition() (ii) If, within arguments, we detect an object that represents our scrollOptions, it is removed from the arguments and a call to the original focus method is made - original.apply(this, arguments). If scrollOptions are not specified, the method exits; if scrollOptions are specified, they contain the same options accepted by $.scrollIntoView() (iii) To counter any browser auto-scrolling related to applying the focus, the following call is made - self.scrollParent().scrollTo(originalPosition) (iv) A call to self.scrollIntoView(scrollOptions) is made.
5. $.tabkey(listener) - This method listens for TAB key usage. When detected, the event default and propogation are prevented, and the registered listener/s are notified. When our application is notified, it then takes on the responsibility of placing focus on the next/previous field and specifies our smooth, precise scrollIntoView functionality to scroll the new focus element into view if it is not yet fully in view.
The bottom line is that it is possible to combat the following: (i) the browser's default scroll-to-on-focus behavior, and (ii) the browser's default show-into-view-on-tab behavior. This post describes one possible way of replacing these default behaviors with something that logically the same, but a nicer physical outcome.