Giter Club home page Giter Club logo

jquery-scrollintoview's Introduction

jQuery .scrollintoview() plugin
with additional :scrollable selector filter

This plugin makes it easy to scroll any element on your page into view. It scrolls in a user friendly way using animation (speed can be configured) so users never loose track where they moved within the current page. Default browser functionality simply jumps to some element which may confuse users greatly. This kind of behaviour is considered bad user experience, since pages look different above and below the fold. This means that users may as well think they were redirected to a different site (since it looks different) or at least page within the same site.

How to use this plugin

Usage is very simple and straightforward:

$("some_selector").scrollintoview();

And that's it really. This is of course if we use defaults. It also supports some configuration possibilities that should be provided as an options object along with the call:

  • duration (default: "fast") - specified the same as with jQuery animate function; it can be provided as a string (slow, normal, fast) or a number of milliseconds that specifies animation duration
  • direction (default: "both") - scrolling can be performed in three different directions:
    • x or horizontal
    • y or vertical
    • both - scrolling will perform in both directions; since scrolling is performed only when element is actually out of view this simply means that scrolling may only perform in one direction even though you set it to scroll in both directions; both is therefore the most reliable scrolling option that will make sure your element will be visible
  • complete function - this is the complete handler function that will get called when scrolling completes; it runs in context of scrollable element; this function will be called regardless whether scrolling will perform or not (when element already in view); but it won't get called when there's no scrollable element (context can't be determined)
$("some_selector").scrollintoview({
    duration: 2500,
    direction: "vertical",
    complete: function() {
        // highlight the element so user's focus gets where it needs to be
    }
});

How does this plugin solve the user experience issue

This plugin scrolls a particular element into view similar to browser built-in functionality (DOM's scrollIntoView() function), but works differently (and arguably more user friendly):

  • it only scrolls to element when element is actually out of view; if element is in view (anywhere in visible document area), no scrolling will be performed;
  • it scrolls using animation effects; when scrolling is performed users know exactly they're not redirected anywhere, but actually see that they're simply moved somewhere else within the same page (as well as in which direction they moved);
  • there's always the smallest amount of scrolling being applied; when element is above the visible document area it will be scrolled to the top of visible area; when element is below the visible are it will be scrolled to the bottom of visible area; this is the most consistent way of scrolling - when scrolling would always be to top it sometimes couldn't scroll an element to top when it was close to the bottom of scrollable container (thus scrolling would be unpredictable);
  • when element's size exceeds the size of visible document area its top-left corner is the one that will be scrolled to;

What about :scrollable selector filter

The good thing about this plugin is that you don't have to provide two elements: scrollable ancestor and element that will be scrolled into view. This plugin rather searches for the closest scrollable ancestor. By scrollable it means that its content exceeds its view area and that is also displays scrollbars (using overflow:hidden won't select element as scrollable). This checking is therefore implemented as a :scrollable selector filter that anyone can use.

var scrollableDivs = $("div:scrollable");

This code would select all DIV elements that have scroll bars (at least one) and their content exceeds their visible area (at least in direction that can be scrolled using scroll bar).

See blog post for details.

jquery-scrollintoview's People

Contributors

litera avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jquery-scrollintoview's Issues

broken with jQuery 1.8

Uncaught TypeError: Cannot read property '3' of undefined
jquery.scrollintoview.min.js:174

This is the part that breaks:

var direction = converter[typeof (meta[3]) === "string" && meta[3].toLowerCase()]

Does not work if element is scrollable.

If the element you call $.scrollintoview() on is itself scrollable, then it doesn't work because inside the function you use el.closest(":selectable") instead of el.parent().closest(":selectable"). Thus the element is always selected rather than it's closest scrollable parent.

Does not work with scrollable DIV on iPad

I am using v1.7, which works perfectly on all desktop browsers I have tested with. I discovered today that it doesn't work with the iPad. After some digging around in the code, I discovered the :scrollable selector is the problem. Since the iPad does not have scrollbars, the this.height.actual > this.height.client test will always fail at line 201 in the code.

scrollableX: function () {
    return (this.height.actual > this.height.client || overflow.isRoot) && this.width.scroll > this.width.client;
},
scrollableY: function () {
    return (this.width.actual > this.width.client || overflow.isRoot) && this.height.scroll > this.height.client;
}

That is a clever trick for determining if a scrollbar is robbing the client space, but is it really necessary for determining if the area is scrollable? It works very well, except for when the device doesn't actually have scrollbars, which many mobile devices choose to omit. It seems that the second test this.width.scroll > this.width.client is more than sufficient.

Removing the first conditional (before the &&) works in all browsers, including the iPad for me. Could that be fixed in the next release?

Patch

Replace Lines 200-205 with:

scrollableX: function () {
    return this.width.scroll > this.width.client;
},
scrollableY: function () {
    return this.height.scroll > this.height.client;
}

Bower compatible

Is it possible to add this plugin into the bower repository ?

Thanks.

Complete event is not fired no scrollbar

It'd be nice if the complete event fired even if there is no scroll bar on the page. This would allow the calling code not to have to be concerned about checking such a detail to make sure their event handler gets called.

Feature request: outline as an option to the function

It would be nice if one could pass an outline parameter to the function, containing minimum distance between the element and its scrollable parent border.

// If possible, $target will be scrolled so,
//   that there will be at least 10px around it's border visible for a user
$target.scrollintoview({
    outline : 10
});

// Different values for different sides
$target.scrollintoview({
    outline : {top: 10, right: 15, bottom: 5, left: 15}
});

Feature Request: Add padding to scroll parent (Implemented Already)

I wanted to be able to pretend like the "visible client area" of the scroll parent was smaller than what was actually visible, effectively adding a sort of "padding" so that the item you're scrolling to can be placed away from the edges of the screen/scroll parent.

To enable this, I added another parameter that is passed in the "options" object called "padding". It is a JSON object having 4 parameters that represent pixel values for padding. They are named "T, B, L, R" for top, bottom, left, right. All params are set to 0 by default, which would not change the default behavior.

Usage:

\\ this would cause the item to be scrolled to 200 pixels below the top of the scroll 
\\ parent's visible area, or 300 pixels above the bottom edge of the visible area:
$("#element_id").scrollintoview( {padding:{T:200, B:300}} );

In my case, I needed this because I was using the YUI AutoComplete widget on a dynamically-generated "spreadsheet" type form, and the autocomplete suggestions were displaying off the bottom of the screen for the lower rows. Using this "padding" modification with a bottom padding of 200 (pixels), I am able to ensure that the item is always scrolled up at least 200 pixels from the bottom of the screen so that I can effectively use the autocomplete suggestions without any manual scrolling.

Hopefully this may be of use to others. Thanks so much for this useful plugin!

Old Line 21:

var settings = {
    duration: "fast",
    direction: "both",
    padding: {L:0, R:0, T:0, B:0}
};

Old Line 103 - subtract "options.padding.T" etc... from each dimension:

var rel = {
    top: dim.e.rect.top - (dim.s.rect.top + dim.s.border.top) - options.padding.T,
    bottom: dim.s.rect.bottom - dim.s.border.bottom - dim.s.scrollbar.bottom - dim.e.rect.bottom - options.padding.B,
    left: dim.e.rect.left - (dim.s.rect.left + dim.s.border.left) - options.padding.L,
    right: dim.s.rect.right - dim.s.border.right - dim.s.scrollbar.right - dim.e.rect.right - options.padding.R
};

Issues with Google Chrome

While doing some cross-browser testing, I ran into an issue where Google's Chrome wouldn't scroll anything into view using your plugin. After much sleuthing through the code and fiddling, I found the following changes to the code made it work with Chrome without breaking it from working with other browsers.

In the $.fn.extend() definition, when defining the "rel" variable, I found that Chrome was reporting back an object for the "dim.s.scrollbar.bottom" and "dim.s.scrollbar.right" used in the calculations. This was causing it to calculate rel.bottom and rel.right as undefined, causing problems down the line. By enclosing the calculations in parseInt() (see below), it fixed that for me.

var rel = {
    top: parseInt(dim.e.rect.top - (dim.s.rect.top + dim.s.border.top)),
    bottom: parseInt(dim.s.rect.bottom - dim.s.border.bottom - dim.s.scrollbar.bottom - dim.e.rect.bottom),
    left: parseInt(dim.e.rect.left - (dim.s.rect.left + dim.s.border.left)),
    right: parseInt(dim.s.rect.right - dim.s.border.right - dim.s.scrollbar.right - dim.e.rect.right)
};

One other thing that I ran into is that if you're trying to scroll a jQuery dialog UI element into view, if the contents of the dialog have a scrollbar, your extension doesn't scroll anything at all because rel.top and rel.bottom both come out positive, even though the element I want to scroll into view is well out of sight. The workaround I found was to ensure that the dialog was large enough to show all the elements without a scrollbar appearing (an adjustment of about 10 pixels in my case).

Scroll Parent is inside another Parent

I have three DIV's. Scrollintoview is used to scroll to DIV 3, that is inside DIV 2. This works. However, DIV 2 is inside DIV 1, and the part where DIV 3 is visible is not into view from the viewpoint of DIV 1. So I have to scroll down DIV 1 (which is the actually the body of my document) to get DIV 3 visible. Is there a way to also scroll the DIV 1 automatically so DIV 3 becomes visible?

Decouple code from JQuery and support NPM / Browserify / Webpack

Thanks for this plugin. I've tried many alternatives like native version and jquery scrollTop but only this one give me the good UX to be able to design a very simple thing: a scrollable dropdown with a highlighted element that must remain in the view.
It works fine for me with Chrome and Firefox.

However nowadays we use modern tools like React and AngularJS. It would be nice to have all the features of this plugin extracted from JQuery and usable without JQuery, or at least published to NPM and usable with tools like Browserify or Webpack

Ability to manually specify the scroll parent

It's nice that the library automatically looks up the DOM for the first scrollable parent, but I have a bit of a corner case where the automatic detection doesn't work.

I have a div (A) whose scrollLeft is manually synchronized with the scrollLeft of another div (B). The element I want to scroll into view is contained in A, but it doesn't appear to be scrollable, even though it really is (A has overflow: hidden).

Would you consider allowing the scroll parent to be manually passed to jquery-scrollintoview to support this corner case?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.