Skip to content

Updating to iScroll 5

iScroll, the number one widget for managing scrollable panels, has been available in version 5 since October. This post documents my pain updating to iScroll 5.0.9.

We've been using iScroll for ages. We've been using it long before we moved to package managers (npm and bower) and it so happened that the library got stuck at version 4.2.5. A patched version. A patched version of a patched version. A dark and ugly corner of our app infrastructure.

I considered the update important because of 3 things:

  1. I don't like stale (as in untracked) dependencies
  2. I don't like patched dependencies
  3. Version 5 comes with PointerEvents support, interactive scrollbars, and quite a number of enhancements

I've looked at the source and it made a good impression. It's clean, well structured, moderately simple and easy to understand. From a coding perspective a job very well done. That said, I spent most of the afternoon cursing. Good code is one thing, completely missing documentation, changelog and upgrade guide paint a different picture.

Anyway, Matteo is working on it. As many of the smaller open source tools are side projects, they have to be dealt with in the author's personal time. Matteo is spending his Christmas holiday on writing the docs for iScroll 5. The official documentation (including tutorials) should be available early 2014. Until then I hope this post can help ease your upgrade pains.


Back to updating iScroll…

Changed API

The first breaking change is its name — it used to be window.iScroll, it now is window.IScroll. I'm just going to leave this here, without debating naming conventions.

iScroll 4 would accept a string as the element to scroll in new iScroll("id-of-wrapper");, version 5 uses querySelector() and thus needs a hash new IScroll("#id-of-wrapper");

No AMD support

Version 5 still only supports CommonJS modules, so AMD style systems like RequireJS have to be shimmed:

require.config({
  paths: {
    "iscroll": "path/to/iscroll"
  },
  shim: {
    "iscroll": {
      "exports": "IScroll"
    }
  }
});

Changed Styling

The scrollable content bled through the boundary. iScroll 4 used to add overflow: hidden to the wrapping element - iScroll 5 does not. Add overflow:hidden (or overflow-x:hidden) to whatever element you initialize iScroll for.

Option Properties

A lot, if not most, of the option properties known to iScroll 4 have been renamed in iScroll 5. What used to be called hScroll is now known as scrollX — still a boolean advising if the horizontal axis can be scrolled or not. Here's an incomplete map of changed names:

iScroll 4 propertyiScroll 5 propertydescription
hScrollscrollX(boolean) allow horizontal scrolling
vScrollscrollY(boolean) allow vertical scrolling
vScrollbar-render vertical scrollbar
hScrollbar-render horizontal scrollbar
hideScrollbarscrollbars(boolean) render scrollbars or not - inverted meaning
draggableScrollbarsinteractiveScrollbars(boolean) make scrollbars tangible
lockDirectionfreeScroll(boolean) if scrolling one direction, lock the other - inverted meaning
wheelActionmouseWheel(string "scroll"|"zoom") controlling the reaction to the mouse wheel
handleClicktap, click(boolean) issue click/tap events

Without spending too much time on reading the source, I can't say I fully understand what each and every option's side effects are. For example some kind of "custom styling" is triggered for scrollbar not being a string. But if it's a string, besides not triggering the default style I can't see what should happen with that string… We're not using custom styles, so I had to quit investigating at some point — sorry.

Note: The option useTransition used to default to false in iScroll 4, version 5 enables this by default.

Have a look at the demos to quickly figure out what options you need to pass. The way we use iScroll most is rather simple:

var scroller = new IScroll(scrollableElement, {
  // scroll only vertically
  scrollX: false,
  scrollY: true,
  // paint scrollbars
  scrollbars: true,
  // make scrollbars draggable
  interactiveScrollbars: true,
  // allow scrolling by wheel
  mouseWheel: true
});

Callbacks vs. Events

In iScroll 4 we would register a function to be triggered after a scroll operation had finished, like so:

var scroller = new iScroll(element, {
  // ... options ...
  onScrollEnd: function() {
    console.log("scolled!");
  }
});

in iScroll 5 there all the callbacks have been replaced by events:

var scroller = new IScroll(element, {
  // ... options ...
});
scroller.on("scrollEnd", function() {
  console.log("scolled!");
});

The same is true for scrollEnd, scrollCancel, scrollStart, beforeScrollStart, refresh and destroy. Also a new event called flick was added.

The built file build/iscroll-zoom.js additionally knows the events zoomStart and zoomEnd.

Since I couldn't find anything in the source, I fear the following callbacks have been removed entirely: onBeforeScrollMove, onScrollMove, onBeforeScrollEnd, onTouchEnd, onZoom

Preventing Default

In case that never bit you, iScroll 4 called event.preventDefault() for pretty much every event, essentially making it impossible to focus form elements. We got around that by doing things like the following, to allow a <textarea> to be focused, even if they were inside an iScroll container:

var scroller = new iScroll(element, {
  // ... options ...
  onBeforeScrollStart: function (event) {
    // do not preventDefault() for <textarea>s, as that makes them unfocusable
    if (event.target.nodeName.toLowerCase() !== "textarea") {
      event.preventDefault();
    }
  }
});

iScroll 5 deals with this differently. It has an option preventDefaultException that comes with a default value of { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ }. With this you can run any (string) property of HTMLElement through a filter, preventing the preventDefault():

var scroller = new IScroll(element, {
  // ... options ...
  preventDefaultException: {
    // default config, all form elements,
    // extended with a WebComponents Custom Element from the future
    tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|X-WIDGET)$/,
    // and allow any element that has an accessKey (because we can)
    accessKey: /.+/
  }
});

Conclusion

iScroll 5 is a solid improvement over iScroll 4. It's currently lacking the docs to upgrade easily, but that stuff is coming. Until then I hope the pointers in this post can get you started updating today.

Now go read iScroll, a small moan and do something about it. Ask your employer to give you some time to help with the project, or better yet, ask them to support the project financially. God knows your product has benefited from Matteo's work.

Comments

Display comments as Linear | Threaded

No comments

The author does not allow comments to this entry