From 54a39cc8d80da03e1efbf50548218bda91194c81 Mon Sep 17 00:00:00 2001 From: Denise Draper Date: Sun, 8 Jun 2014 18:43:09 -0700 Subject: [PATCH 1/2] Rearrange and standardize headings --- README.md | 1856 +++++++++++++++++++++++++++-------------------------- 1 file changed, 930 insertions(+), 926 deletions(-) diff --git a/README.md b/README.md index 8395af2..a7d78e1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -watusi/jquery-mobile-iscrollview, Version 1.3.6 -=============================================== +# watusi/jquery-mobile-iscrollview, Version 1.3.6 + JQuery Mobile widget plug-in for easy use of the [iScroll](https://github.com/cubiq/iscroll) scroller in [JQuery Mobile](https://github.com/jquery/jquery-mobile) projects. @@ -16,12 +16,12 @@ widget. It follows the *widget-factory-mobile* --- -Release Notes -------------- +# Overview +## Release Notes +This is release Version 1.3.6. Please see releaseNotes.txt for information on changes in this and prior releases. -iScroll Version 4.2.5 ---------------------- +### iScroll Compatibility This widget is not yet compatible with iScroll version 4.2.1 through 4.2.5. Please stick with iScroll 4.2 for now. Some investigation and testing is needed due to changes in iScroll event code. @@ -30,31 +30,8 @@ when your finger leaves the wrapper. While this is a nice feature for small scro this is not always desirable. It is very odd on desktop browsers, as scroll continues when you drag with the mouse, even outside of the browser! It should be optional. (It will be in iScroll5). -Roadmap -------- -1.4 - Fully implement usejQueryEvents - -? - Option to un-enhance widget temporarily (and optionally hide headers/footers) during -virtual-keyboard input on select devices (iOS first), to eliminate all form input problems -when using a virtual keyboard. - -? iOS keyboard handing for inputs. Guess keyboard height based on device/orientation/fullscreen. -Resize wrapper to fit page in space above keyboard, center focused element. - - -? - Better support for collapsible content (scroll on expand if expanded content below window) - -Plug for jquery.mobile.simultaneous-transitions ------------------------------------------------ -This plugin works best when used with -[jquery.mobile.simultaneous-transitions](https://github.com/watusi/jquery.mobile.simultaneous-transitions) - -It puts back the old, simultaneous, non-scrolling transitions that everybody knew and loved -from jQuery Mobile 1.0. It's an ideal companion for jquery.mobile.iscrollview! Stop fighting the -goofy transitions in jQuery Mobile 1.1. If you're using iScroll, you probably don't need them. +## What This is For -What This is For ----------------- This widget is intended for use in any jQuery Mobile project, but it was designed to be especially useful for some specific uses. @@ -94,8 +71,8 @@ This widget is *not* well-tested on Android devices, and I very much appreciate ferreting-out Android issues. It is tested regularly in all three modes (Mobile Safari, full-screen, and UIWebView) on iPad 1(5.1), iPad 3(5.1), iPhone 4 (4.3.5) and iPhone 4S(5.1). -Usage ------ +## Usage + The most basic usage of this widget is simple: just add a `data-iscroll` attribute to a container. All content inside this container will be scrolled. @@ -140,8 +117,8 @@ to sidebars.) --- -Example -------- +## Example + ```html @@ -190,11 +167,81 @@ Example ``` +--- + +## Demo + +The demo contains a simple example with 5 pages. The demo can be found in `/demo/build`. It is built +using a static site generator (written in Ruby) called Middleman, but the demo has already been +built for you. If you do wish to build the demo yourself, you will need to install Middleman 3.0 or +higher. + +Just copy the contents of `/demo/build` to your web server, or open the index.html file directly +from `/demo/build`. + +You can switch between the pages using the tabbar at the bottom. The pages demonstrate: + +* a listview +* an inset listview (also has two expandible elements) +* a listview with pull-down and pull-up blocks +* a listview with a short list and pull-down/pull-up blocks +* a form + +To demo, simply open the `index.html` file in your browser. Note that the page transitions will +not work with some browsers when loading from a local file - for those browsers, you will have +to load the demo from a server. (It does work with local files for Safari and Firefox.) + +You can switch between jQuery Mobile 1.0.1 and 1.1 using the buttons in the headers. + +The demo illustrates the use of different-sized headers and footers for portrait and landscape +orientations. In landscape, the header and footer are shorter, and the header omits the buttons +for switching between jQuery Mobile versions. + +###Special Demo Borders + +The demo has headers and footer styled with a 1px red border at top and bottom. This facilitates +a quick visual indication of correct sizing of the page. You should not see any white +space above the header or below the footer. (Note that Retina devices will show a 2px border, +rather than 1px.) Use your OS's accessibility features to magnify and inspect. On mobile +devices, there is usually a way to capture the screen contents to an image file that you can +later examine. (iPhone: Home+On/Off) + +The iScroll wrapper is styled with a 1px green border at top and bottom. You should see no gap +or different color between the top of the wrapper and the bottom of the header, or between +the bottom of the wrapper and the top of the footer. + +###Demo Content + +As a convenience, the demo directory is self-contained (except for the widget, `iscroll-pull-js` +and pull icon files, which are expected to be found in the parent directory), and contains the +following additional components: + +* jQuery 1.6.4 +* jQuery 1.7.1 +* JQuery Mobile 1.0.1 +* jQuery Mobile 1.1.1 +* iscroll4, version 4.2 + + +Please obtain these components independently for your projects, so that +you can be sure of what version you are getting, and avail yourself +of any updates/improvements. --- -Fixed and persistent Toolbars (Headers/Footers) ------------------------------------------------ + +# Technical Details + +### Plug for jquery.mobile.simultaneous-transitions +This plugin works best when used with +[jquery.mobile.simultaneous-transitions](https://github.com/watusi/jquery.mobile.simultaneous-transitions) + +It puts back the old, simultaneous, non-scrolling transitions that everybody knew and loved +from jQuery Mobile 1.0. It's an ideal companion for jquery.mobile.iscrollview! Stop fighting the +goofy transitions in jQuery Mobile 1.1. If you're using iScroll, you probably don't need them. + +## Fixed and persistent Toolbars (Headers/Footers) + This plugin now works fairly well with both fixed and persistent toolbars, as long as you use jQuery Mobile 1.1.1 or later. @@ -245,8 +292,8 @@ transitions. If this is a problem in your environment, you can use an inline foo plugin will insure it always appears in the right place. However, you cannot implement a persistent toolbar in JQM 1.1 with an inline footer. -Dynamic Content ---------------- +## Dynamic Content + If you will be adding dynamic content that you want to have scrolled, you first need to understand the HTML structure that the plugin creates for you. @@ -312,8 +359,8 @@ collapsibles are expanded or collapsed. --- -Padding Issues --------------- +## Padding Issues + Previous versions of this widget had some issues involving the way jQuery Mobile standard CSS applies padding and margin to content divs and listviews. The widget now handles this for you in the most common use cases. @@ -331,8 +378,8 @@ and `addScrollerPadding`. --- -Pull-to-Refresh ---------------- +## Pull-to-Refresh + This widget supports "pull-to-refresh" functionality. You can have a block of HTML that is positioned above the top or below the bottom of the scroller that the user can pull down or pull up. These blocks can be revealed by scrolling, but the scroller will "snap back" after the user @@ -482,14 +529,14 @@ content. See the demo for an example. --- -Calling functions ------------------ +## Calling functions + The standard way of calling widget functions is by passing a sub-function name as a string parameter to the widget function. Any parameters to the function should follow. Note: This method works for all versions of jQuery Mobile from 1.0 to 1.4.x. See -below, though, for differences when using an alternative way of calling fucntions. +below, though, for differences when using an alternative way of calling functions. For example, to call the `refresh` function: @@ -569,1345 +616,1302 @@ iScroll's corresponding function and then calls the underlying widget function. --- +## Scroll Bars -Functions ---------- -###Standard Widget Functions +### Wrapper Positioning Requirement -These are functions that are typically implemented for ALL widgets: +iScroll requires that the wrapper be CSS-positioned either `absolute` or `relative`. If the +wrapper is positioned `static` (the default, if positioning is not specified), then the +scroll bars will (incorrectly) be created relative to the page, rather than the wrapper. The +symptom is that the scroll bar will be the full height of the window. (Though the widget +will hide the scrollbar under any header/footer.) -####option(key, [value_or_object]) +The standard CSS file for the widget sets relative positioning on the wrapper. -See "Options", below. +Either `absolute` or `relative` positioning of the wrapper will cause elements inside the +wrapper which themselves have `absolute` positioning to be positioned relative to the wrapper. +iScroll depends on this behaviour for positioning of the scrollbar. -####destroy() +### Customizing Scrollbar Position -Destroys the iScroll instance and removes page modifications. Also calls the -underlying widget `destroy()` code. +iScroll gives you the ability to customize scroll bars. See the iScroll4 documentation +for full details. You can customize the height, width, position, color, etc. etc. of +the scrollbar. To do so, you need to set the `scrollbarClass` option and then provide +CSS to customize the scrollbar. -###Custom Widget Functions +However, in many cases, all that is really desired is to set the position +of the scrollbar. In this case, you can add some very minimal CSS. -These are additional functions implemented in this widget which do -not have corresponding iScroll functions. +In this case, do NOT set the `scrollbarClass` option. Setting this option causes +iScroll to omit quite a bit of it's initialization of the scrollbar, and then you +are required to supply a considerable amount of CSS. -####resizeWrapper() +Instead, you can usually use a CSS rule similar to this: -This will resize the wrapper to use all available viewport space -after accounting for headers, footers, and other fixed-height elements -outside of the wrapper. This is normally done for you automatically, -but the automatic resize can be overriden with an option. Call this -if you have change the page structure and so need to resize the wrapper. -This is also normally called for you when page orientation or page -size changes. +```css -###iScroll Functions + div.my-iscroll-wrapper > div:last-child { + top: 46px !important; + bottom: 22px !important; + } -These are functions that exist in iScroll. They are available on -the widget as a convenience. See "calling functions" for information -on how to access any iScroll functions that are not implemented in -the widget. (For example, because you have updated iScroll to -a newer version, and this widget has not been updated yet.) +``` -Please see the iScroll documentation for details on using these -functions. +iScroll appends the scrollbar to the end of your wrapper. Unless you have appended something +else yourself, you can target the last child of the wrapper, and so you don't need the +`scrollbarClass` to identify the scrollbar. So, iScroll will still do all of it's usual +initialization. By using the `!important` modifier, your CSS will override the top and +bottom locations that iScroll itself sets. -####refresh(timeout, beforeCallback, afterCallback, noDefer) +--- -Note that this performs the proper timing for the iScroll `refresh()` -function using `setTimeout`. If you want to call the iScroll `refresh()` -function directly, please see "calling functions" above. +## Multiple Scrollers -If the timeout value is present, then the internal call of iScroll `refresh()` will be delayed -by this value. If the value is `null` or `undefined`, then the value of the `refreshDelay` -option will be used. +If you wish to have multiple scrollers, please note the following: -##### Refresh Callbacks +- The `resizeWrapper` option should be set to `true` for no more than one +of your scrollers. If you have multiple scrollers one above the other, +then at most one of them can be auto-sized. If you have multiple scrollers +side-by-side, then you will probably have to size all them yourself. +Since `resizeWrapper` is `true` by default, you will need to set the option +to `false` for all but (a maximum) of one of your scrollers. -If present, the optional `beforeCallback` function will be called just prior to refreshing iScroll. -This is useful if you have updated content inside the -scroller, and need to refresh widgets inside the scroller (such as a listview) prior to iScroll -refresh. While this is similar to the `iscroll_onbeforerefresh`, the callback is specific to -a particular call to `refresh()`. +- iScroll will not work correctly if scrollbars from multiple scrollers +overlap. It will fail to scroll in all but one of the scrollers that +have overlapping scrollbars. Please see the documentation on scrollbar +customization, above. -If your callback requires some context, you should use jQuery's $.proxy() function to provide a -`this` reference that will be available when the callback executes. +--- -If present, the optional `afterCallback` function will be called just after refreshing iScroll. -This is useful if you want to perform some action on -the scroller after updating content. For example, this might be used to scroll to a particular -position or element within the scroller after updating content. This is particularly useful -when adding content to the *end* of the scroller, when you might like to scroll the new content -into view. +## Listviews Containing Links -##### Deferred Refresh +*(Note: this discussion is somewhat obsoleted by changes in version 1.2 of this widget and +version 1.1 of jQuery Mobile. By default, the widget prevents this annoying list behaviour +when you are using it with jQuery Mobile 1.0 or 1.0.1 with the `preventTouchHover` option. jQuery +Mobile 1.1 prevents it inherently.)* -Calls made to `refresh()` for an iscrollview which is on a cached page that is not the active page -are normally (depending on the value of the `deferNonActiveRefresh` option) deferred until the -next `iscroll_onbeforepagerefresh` event for the page. This avoids unnecessary refreshes. Note -that if the `refreshOnPageBeforeChange` option is true, then the scroller will *always* be -refreshed on `iscroll_pagebeforefresh()`. +Listviews that have list items that are buttons (i.e. the items are clickable, +because they are wrapped in an `` tag) can be very slow on touchscreen devices. This is not an +iScroll or widget problem per-se - it is inherent to JQuery Mobile 1.0 and 1.0.1. -Each deferred call to `refresh()` overwrites the callback values from any previous -deferred `refresh()` call for the same iscrollview. This means that you should not use refresh -callbacks to modify content, because there is no guarantee that any particular callback will -be called - only that the callbacks for the *last* deferred `refresh()` will be called. +There is a discussion of this issue here: -Deferred calls only occur when the scroller being refreshed is *not* the active page. You -might do this if you are caching pages, and some data arrives that you want to update on -a page that is not currently the active page. + http://forum.jquery.com/topic/why-jqm-touchscreen-list-scrolling-performance-stinks-and-what-to-do-about-it -This is particularly useful in environments such -as PhoneGap, Titanium, or Rhodes, where a controller is able to update pages asynchronously. +The gist of it is that as you scroll a list, your finger slips from one list +item to the next, causing a "piano key" visual effect. The effect is both +distracting to the user and slow. -Deferring `refresh()` calls avoids a cascade of unnecessary refreshes when the document is -resized in a desktop environment, or when a mobile device's orientation is changed. The refreshes -for those pages that are cached in the DOM but not the active page are deferred until the next time -they become the active page, and then only a single refresh will be performed. +A work-around is to insure that up/down/hover states for your scrollable +listviews are identical, so that there is no *hover* effect and no *selected* +effect. If you're developing exclusively for a touch-screen mobile device, +there's little to no need for these effects. Users don't expect them: they +expect something to happen when they tap, but not a useless effect. -As well, if content is updated while a page is not the active page, then deferring `refresh()` -avoids unnecessary duplicate refreshes. If content were to be updated several times while the -page is not active, only a single refresh will be performed. +This is an *example* of CSS overrides that will remove the hover and selected effects. +You will need to modify this CSS to match your theme. The important thing is that +the up, down, and hover states must have identical CSS, so that there is no transition +between states. -##### NoDefer Argument -If you want to force a refresh to a scroller on a non-active page to be performed immediately, -you can set the `noDefer` parameter to `true`. Note that the `noDefer` parameter is intended -for the widget's internal use, and you should not normally set it to `true`. You should normally -just leave this parameter out of your call. +```css -You can disable deferred refreshes completely by setting the `deferNonActiveRefresh` widget -option to `false`. + /* + Sane overrides for buttons in lists -####scrollTo(x, y, time, relative) + JQM default styling has up/down/hover/select styles for buttons. This is nice for real + buttons, but slows list scrolling to a crawl. This can be avoided by styling the + up/down/hover states identically. + */ -Scroll to a particular `x`, `y` pixel position within the scroller. + ul.ui-listview *.ui-btn-up-c, + ul.ui-listview *.ui-btn-down-c, + ul.ui-listview *.ui-btn-hover-c + { + border-color: #ccc; + background: #eee; + font-weight: bold; + color: #444; + text-shadow: 0 1px 1px #f6f6f6; + background-image: -webkit-gradient(linear, left top, left bottom, from( #fdfdfd), to( #eee)); + } -The `time` parameter is the time in milliseconds over which to perform a smooth scroll. If omitted, -the scroll is immediate. - -The `relative` parameter is `true`, then the `x`, `y` position is relative to the current scroll -position. + ul.ui-listview *.ui-btn-up-c a.ui-link-inherit, + ul.ui-listview *.ui-btn-down-c a.ui-link-inherit, + ul.ui-listview *.ui-btn-hover-c a.ui-link-inherit + { color: #444; } -####scrollToElement(el, time) +``` -Scroll to a particular element within the scroller. The `el` parameter can be either a reference -to a DOM node object (*not* a jQuery object) or a CSS3 selector. jQuery selector extensions -cannot be used here. +--- -The `time` parameter is the time in milliseconds over which to perform a smooth scroll. If omitted, -the default iScroll `scrollToElement()` time value is used. This is based on larger of x and x -pixels scrolled, times 2. For example, if it will scroll 500px vertically (and less than 500px -horizontally), then the scroll will take place over a period of 1000mSec. +## Caching List Items -####scrollToPage(pageX, pageY, time) +Webkit-based browsers can exhibit a "flicker" effect wwhen scrolling +toward the bottom of the list, as well as exhibit slow and jerky movement until the first +time the user has reached the bottom of the list.. Once you have scrolled down to the bottom of +the list, the flicker will typically stop. This does not seem to be an issue with non-Webkit +browsers. -The default time value, if not specified, is 400mSec. (Default iScroll.js value) +This issue is discussed here: http://cubiq.org/you-shall-not-flicker -####disable() +A work-around for this issue to to force list items to be pre-cached. See +the above link for a discussion of why this works. Basically, the flicker occurs +when each element is first encountered and hardware acceleration is enabled for +the element. By pre-setting a null 3D transform (which triggers hardware accelation on WebKit +browsers) on each element, the flicker is avoided, and the content is added to the hardware cache. -Note that this function also calls the default widget `disable()` function. +This has been reported to cause bluring of text during transform on Android platforms. You will +need to decide which of two evils you want to live with. -Note: This has not been tested, and probably doesn't work correctly. Further, the iscroll-internal -`disable()` probably doesn't do what you wish it would do. You can't re-enable iScroll by calling -`enable()` after calling `disable()`. +If this *is* used, then the browser may be forced to cache the content in advance, resulting +in smoother scrolling, but with the side-effect of increasing initial rendering time. -If you do want to call the iScroll `disable()` function directly, please see "calling functions" above. +This can more than *double* initial rendering time if you are not careful with the selector. The +recommended CSS at the above link is NOT optimal. -####enable() +You need to apply this judiciously. For example, if you know your scroller content consists +of list items, use `li` not `*` to select. `*` as the right-most component of a select is +horribly expensive. A small additional performance gain can be made by selecting +iscroll-content instead of iscroll-scroller. You might get a +glitch on a pull-up if you have one, but it's a small price to pay for doubling speed. -Note that this function also calls the default widget `enable()` function. -If you want to call the iScroll `enable()` -function directly, please see "calling functions" above. +It is important NOT to apply this to `.iscroll-scroller` itself. This will result in a huge +performance loss. The rule below gives performance on iOS devices very close to not +using this at all. -####stop() +The demo uses this CSS: -####zoom(x, y, scale, time) +```css -The default time value, if not specified, is 200mSec (Default iScroll.js value) + .iscroll-content li { + -webkit-transform: translateZ(0); + } -### iScroll Getters +``` +--- -This widget provides getters for some iScroll internal variables that might be useful -to an application. These are all read-only. +## Mobile Safari Address Bar -For example, let's say you are adding elements to the end of a scrolled list. -You'd like to scroll up (using scrollToElement) if the new element would be -below the visible area. But if the list is intially empty, you'd want to avoid -this until the scrolling area is initially full. So you need to compare the -scroller height (scrollerH) to the wrapper height (wrapperH). +The Mobile Safari address bar is a 60px area at the top of the browser. The address bar is fixed +on iPad, but on iPhone and iPad, it can be made to scroll off-screen by scrolling content. +jQuery Mobile normally does this, but the address bar is always present at the time that a page +loads. jQuery Mobile then scrolls in order to push the address bar back up. -While wrapper and scroller height can be easily obtained using JQuery functions, -these functions can still be useful because they reflect the precise internal -state of the scroller. +jQuery Mobile 1.1 handles the address bar better than jQuery Mobile 1.0 or 1.0.1. With 1.1, the +address bar usually will not appear during a page transition. -####x() +It doesn't appear possible to consistently detect the real window height, though it is possible +to consistently detect the window height assuming that the address bar is present. So, this +widget adds 60px to page height in this situation. This addition is not applied for iPad, nor for +iPhone/iPod if running a native app in a UIWebView, or when running in "full screen" mode +(web page saved to home screen). -Current x origin (left) of the scroller. +If you are testing using desktop Safari's `Develop` `User Agent` option, please note that this +adaptation will fail. It depends on specific behaviour of the real Mobile Safari browser. If +you want to use desktop Safari to test pages designed to run on iPhone, either use the standard +Safari User Agent, or else use an "Other" User Agent: -####y() +First, set the User Agent to `Safari ... iPhone`. then, select `User Agent` `Other`. The user-agent +string will be pre-populated with the Mobile Safari user-agent string. Remove `Safari` from the +user agent. This will fool the widget into thinking you are running in "full screen" mode, without +the disappearing address bar which is not present on desktop Safari. -Current y origin top of the scroller. +--- -####wrapperW() +## Performance Logging -The width, in pixels, of the wrapper. This is the visible width of the scrolling area. +This widget can log events and performance data to the Javascript console when the `debug` option +is set to `true`. A number of additional options control what is logged. Setting `debug` false will +disable all logging. -####wrapperH() +These log entries are useful both to monitor performance and to understand the sequence of events +that occur as the widget is used. -The height, in pixels, of the wrapper. This is the visible height of the scrolling area. +There is a log entry at the start and end of each traced function, event, or callback. Each +entry shows the time, file name, function, event, or callback name, and (at end) elapsed mSec that +the operation took. -####scrollerW() +For some functions, a second set of elapsed mSec and start time are logged (in parenthesis). +This is for functions that were queued using a SetTimeout or that were initially triggered by +some event. So, you can see how long the function took to run, as well as the elapsed time from when +the function was queued. -The width, in pixels, of the scroller. This is the total width of the scroller, including -visible and non-visible portions. +The `debug` option must be `true` in order for any of the trace options to be enabled. -####scrollerH() +Performance logging can generate a large amount of data. You can use trace options to narrow +the logging to items of interest. -The height, in pixels, of the scroller. This is the total height of the scroller, including -visible and non-visible portions. +You can use `jsconsole.js` or other similar solutions to do remote logging from mobile devices. +It is important to narrow the focus of your logging when using such solutions. -###iScroll Getters/Setters +### traceCreateDestroy -This widget provides getters with options setter functionality for some iScroll internal -variables that might be useful to an application. If a value is provided, then the -functions act as setters. In any case, they return the value of the associated internal -variable. +If `true`, creation and destruction of the widget is traced. -####minScrollX(val) +### traceRefresh -The minimum X scroll position. This defines the left-most position of scroll. The user -can scroll past the minimum X, but then the scroller will snap-back to the mimimum X -position. +If this option option is `true`, calls to the widget's `refresh()` function are traced. -####minScrollY(val) +In the case of `refresh()` there is an initial log entry when the `refresh()` is queued, which +will also indicate the timeout value that was used. A second, separate, log entry shows the elapsed +time that `refresh()` ran as well as elapsed time from when it was queued. The time value shown +lets you match-up the first and second entries. This will help you evaluate the impact of +browser rendering time. (A 0mSec timeout will first allow all rendering to complete.) -The minimum Y scroll position. This defines the top-most position of the scroll. The -user can scroll past the minimum Y, but then the scroller will snap-back to the minimum -Y position. +If a refresh is occuring on an `iscroll_onpagebeforerefresh` event because a page is "dirty" +the log entry will indicate "(dirty)". "Dirty" pages are pages that have had `refresh()` called +while they were not the active page. Normally (depending on the `DeferNonActiveRefresh` option) +such pages have their `refresh()` deferred until the page is about to be shown. -####maxScrollX(val) +###traceResizeWrapper -The maximum X scroll position. This defines the right-most position of scroll. The user -can scroll past the maximum X, but then the scroller will snap-back to the maximum X -position. +If this option is `true`, calls to the widget's `resizeWrapper()` function +are traced. -####maxScrollY(val) +###traceIscrollEvents -The maximum Y scroll position. This defines the bottom-most position of the scroll. The -user can drag past the maximum Y, but then the scroller will snap-back to the maximum -Y position. +If this option is `true`, events handled by iScroll are traced. ---- +###tracedIscrollEvents -Public Members --------------- -The widget maintains several public data members that may be useful to you: +This is a list of iScroll events to trace. If the list is empty, all iScroll events will be +traced. List items are strings, example: `touchstart`. -###iscroll +###traceWidgetEvents -This is a reference the iScroll object. +If this option is `true` events handled by the widget (not by iScroll) are traced. -###$window +###tracedWidgetEvents -A jQuery collection object containing the window (viewport). +This is a list of widget events to trace. If the list is empty, all widget events will be +traced. List items are strings. Events that iScroll itself handles are *not* traced when this +option is `true`. As well, callbacks bound to `touchmove` only for the purpose of preventing +the page from scrolling are not traced, because they occur very frequently. -###$wrapper +###traceIscrollCallbacks -A jQuery collection object containing the iscrollview wrapper element. +If this option is `true`, callbacks issued by iScroll are traced. -###$scroller +###tracedIscrollCallbacks -A jQuery collection object containing the scroller element. +This is a list of iScroll callbacks to trace. If the list is empty, all iScroll callbacks will +be traced. List items are strings. Example: `onRefresh`. -###$scrollerContent +###traceWidgetCallbacks -a jQuery collection object containing the scroller content element. +If this option is `true`, callbacks issed by the widget are traced. This does not include +callbacks issued by iScroll itself (which application code may also bind to.) -###$pullDown +###tracedWidgetCallbacks -a jQuery collection object containing any pull-down element. If there is no pull-down element, then the -length of the collection will be zero. +This is a list of widget callbacks to trace. If the list is empty, all widget callbacks will +be traced. List items are strings. Do not include the `iscroll_` prefix. Example: `onpulldown`. -###$pullUp +--- -A jQuery collection object containing any pull-up element. If there is no pull-up element, then -the length of the collection will be zero. +## Variable names -###$page +The source code code follows the following conventions: -A jQuery collection object containing the page that the widget is contained in. +* Upper-case first letter: constant +* $ first letter: variable contains a JQuery object +* (underscore) first letter: Private funcion --- +# Reference -Options -------- +## Functions -### Overriding Option Defaults +###Standard Widget Functions -You can override the default options for new instances of this widget by setting the -prototype options in `$.mobile.iscrollview.prototype.options`. +These are functions that are typically implemented for ALL widgets: -Any options that you set programatically or using `data-` attributes will override the defaults. +####option(key, [value_or_object]) -Example: for all new instances of `$.mobile.iscrollview`, set the `refreshDelay` option to the -value `100`. +See "Options", below. - $.mobile.iscrollview.prototype.options.refreshDelay = 100; +####destroy() -If you want to override options for all instances of the widget, a good place to do that is -at the same time that you override any jQuery Mobile default options. `jquery.mobile.iscrollview` -triggers an `iscrollview_init` event that is triggered once it has loaded, and you may set any -global options here. +Destroys the iScroll instance and removes page modifications. Also calls the +underlying widget `destroy()` code. -Note that when `iscrollview_init` is triggered, this does *not* mean that any scroller(s) -have been initialized. It only means that the iscrollview library is loaded, and so you may -now set any global options. +###Custom Widget Functions -It's common to bind to `mobileinit` after jQuery is loaded, but before loading jQuery Mobile. -You can bind to `iscroll_init` in the same place. Alternately, you can make changes to -global options any time after `jquery.mobile.iscrollview` is loaded. +These are additional functions implemented in this widget which do +not have corresponding iScroll functions. -Note: `iscroll_init` is ONLY available as a jQuery Event. There is no corresponding -iscrollview callback function. +####resizeWrapper() -```html - -``` +###iScroll Functions -###Programatic access +These are functions that exist in iScroll. They are available on +the widget as a convenience. See "calling functions" for information +on how to access any iScroll functions that are not implemented in +the widget. (For example, because you have updated iScroll to +a newer version, and this widget has not been updated yet.) -This widget supports programmatic access to options using standard widget factory -syntax: +Please see the iScroll documentation for details on using these +functions. - .iscrollview("option"); Returns an object with all options - .iscrollview("option", "hScroll"); Returns value of option - .iscrollview("option", "hScroll", true); Sets option - .iscrollview("option", {hScroll: true}); Sets option, alternative syntax - .iscrollview("option", {hScroll: true, vScroll:true}; Set multiple options +####refresh(timeout, beforeCallback, afterCallback, noDefer) -The widget handles copying widget options to the iScroll object options and -vice-versa. +Note that this performs the proper timing for the iScroll `refresh()` +function using `setTimeout`. If you want to call the iScroll `refresh()` +function directly, please see "calling functions" above. -###Setting options in the data-iscroll attribute +If the timeout value is present, then the internal call of iScroll `refresh()` will be delayed +by this value. If the value is `null` or `undefined`, then the value of the `refreshDelay` +option will be used. -This widget also supports setting options directly in the `data-iscroll` -attribute. The options need to be in **strict** JSON format. This means that keys -and string values need to be enclosed in **double** quotes **only**. Numeric and -boolean values should **not** be enclosed in quotation marks. +##### Refresh Callbacks -####Example: +If present, the optional `beforeCallback` function will be called just prior to refreshing iScroll. +This is useful if you have updated content inside the +scroller, and need to refresh widgets inside the scroller (such as a listview) prior to iScroll +refresh. While this is similar to the `iscroll_onbeforerefresh`, the callback is specific to +a particular call to `refresh()`. -```html -
-``` +If your callback requires some context, you should use jQuery's $.proxy() function to provide a +`this` reference that will be available when the callback executes. -###Modifying options after instantiation +If present, the optional `afterCallback` function will be called just after refreshing iScroll. +This is useful if you want to perform some action on +the scroller after updating content. For example, this might be used to scroll to a particular +position or element within the scroller after updating content. This is particularly useful +when adding content to the *end* of the scroller, when you might like to scroll the new content +into view. -If you modify an iScroll option after a scroller has been instantiated, the underlying -iScroll object will be destroyed and re-created. This is because iScroll does -not currently support modifying options after the object has been created. +##### Deferred Refresh -However, unofficially, some options can be changed without destroying and -re-creating the object. It is unclear exactly which options these are, and -so this widget does not attempt it. There is skeletal code in the source -that is commented-out to do this if you wish to experiment. +Calls made to `refresh()` for an iscrollview which is on a cached page that is not the active page +are normally (depending on the value of the `deferNonActiveRefresh` option) deferred until the +next `iscroll_onbeforepagerefresh` event for the page. This avoids unnecessary refreshes. Note +that if the `refreshOnPageBeforeChange` option is true, then the scroller will *always* be +refreshed on `iscroll_pagebeforefresh()`. -If you modify a widget option (which is not also an iScroll option) after instantiation, -behaviour depends on the specific option. (Like iScroll) the widget does not currently -specifically support changing options after instantiation. Generally, if you change an -option after instantiation. If the option only has an effect at instantiation, then changing -the option after instantion will do nothing. (And might confuse the widget.) +Each deferred call to `refresh()` overwrites the callback values from any previous +deferred `refresh()` call for the same iscrollview. This means that you should not use refresh +callbacks to modify content, because there is no guarantee that any particular callback will +be called - only that the callbacks for the *last* deferred `refresh()` will be called. -###Emulated Options +Deferred calls only occur when the scroller being refreshed is *not* the active page. You +might do this if you are caching pages, and some data arrives that you want to update on +a page that is not currently the active page. -The following option is emulated by the widget: +This is particularly useful in environments such +as PhoneGap, Titanium, or Rhodes, where a controller is able to update pages asynchronously. -####bottomOffset +Deferring `refresh()` calls avoids a cascade of unnecessary refreshes when the document is +resized in a desktop environment, or when a mobile device's orientation is changed. The refreshes +for those pages that are cached in the DOM but not the active page are deferred until the next time +they become the active page, and then only a single refresh will be performed. -Offset at the bottom of the scroller. Complementary to the iScroll `topOffset` option. The number -of pixels specified by `bottomOffset` will apper below the bottom of the scroll range. You can -scroll into this area, but then the scroller will snap back. (This is needed to support the -pull-up funcitonality.) +As well, if content is updated while a page is not the active page, then deferring `refresh()` +avoids unnecessary duplicate refreshes. If content were to be updated several times while the +page is not active, only a single refresh will be performed. -Also, see the `emulateBottomOffset` option. +##### NoDefer Argument +If you want to force a refresh to a scroller on a non-active page to be performed immediately, +you can set the `noDefer` parameter to `true`. Note that the `noDefer` parameter is intended +for the widget's internal use, and you should not normally set it to `true`. You should normally +just leave this parameter out of your call. -Default: `0` +You can disable deferred refreshes completely by setting the `deferNonActiveRefresh` widget +option to `false`. -###Widget Options +####scrollTo(x, y, time, relative) -The following options are available which affect the widget itself. These are -not iScroll options. +Scroll to a particular `x`, `y` pixel position within the scroller. -####debug +The `time` parameter is the time in milliseconds over which to perform a smooth scroll. If omitted, +the scroll is immediate. -Enables performance logging. Please see the documentation section on performance logging. There -are a number of additional options which allow you to control what is logged. These are documented -in the section on performance logging. +The `relative` parameter is `true`, then the `x`, `y` position is relative to the current scroll +position. -Default: `false` +####scrollToElement(el, time) -####pageClass -A CSS class, or a space-separated list of classes, which will be added to the page -containing the wrapper. +Scroll to a particular element within the scroller. The `el` parameter can be either a reference +to a DOM node object (*not* a jQuery object) or a CSS3 selector. jQuery selector extensions +cannot be used here. -Default: `"iscroll-page"` +The `time` parameter is the time in milliseconds over which to perform a smooth scroll. If omitted, +the default iScroll `scrollToElement()` time value is used. This is based on larger of x and x +pixels scrolled, times 2. For example, if it will scroll 500px vertically (and less than 500px +horizontally), then the scroll will take place over a period of 1000mSec. -####wrapperClass +####scrollToPage(pageX, pageY, time) -A CSS class, or a space-separated list of classes, which will be added to the wrapper. +The default time value, if not specified, is 400mSec. (Default iScroll.js value) -Default: `"iscroll-wrapper"` +####disable() -####scrollerClass +Note that this function also calls the default widget `disable()` function. -A CSS class, or a space-separated list of classes, which will be added to the scroller. -(The scroller is the first child of the wrapper, and is the element that will -be scrolled.) +Note: This has not been tested, and probably doesn't work correctly. Further, the iscroll-internal +`disable()` probably doesn't do what you wish it would do. You can't re-enable iScroll by calling +`enable()` after calling `disable()`. -Default: `"iscroll-scroller"` +If you do want to call the iScroll `disable()` function directly, please see "calling functions" above. -####topSpacerClass +####enable() -A CSS class, or a space-separated list of classes, which will be added to the top spacer -`
`. +Note that this function also calls the default widget `enable()` function. +If you want to call the iScroll `enable()` +function directly, please see "calling functions" above. -####bottomSpacerClass +####stop() -A CSS class, or a space-separated list of classes, which will be added to the bottom spacer -`
`. +####zoom(x, y, scale, time) -####pullDownClass +The default time value, if not specified, is 200mSec (Default iScroll.js value) -If this class is found within the scroller, and the `topOffset` option value is not set or is zero, -then the `topOffset` will be set to the height of the pull-down element. As well, the widget makes -modifications to the pulldown element's CSS. +### iScroll Getters -Default: `"iscroll-pulldown"` +This widget provides getters for some iScroll internal variables that might be useful +to an application. These are all read-only. -####pullUpClass +For example, let's say you are adding elements to the end of a scrolled list. +You'd like to scroll up (using scrollToElement) if the new element would be +below the visible area. But if the list is intially empty, you'd want to avoid +this until the scrolling area is initially full. So you need to compare the +scroller height (scrollerH) to the wrapper height (wrapperH). -If this class is found within the scroller, and the `bottomOffset` option value is not set or is -zero, then the `bottomOffset` will be set to the height of the pull-up element. As well, the widget -makes modifications to the pullup element's CSS. +While wrapper and scroller height can be easily obtained using JQuery functions, +these functions can still be useful because they reflect the precise internal +state of the scroller. -Default: `"iscroll-pullup"` +####x() -####pullUpSpacerClass +Current x origin (left) of the scroller. -If you use a pull-up block, then the widget will create a special pull-up spacer, to insure -that the pull-up appears hidden below the bottom of the scroller window until manually scrolled, -even if the content is shorter than the height of the wrapper. +####y() -In case you need to apply some CSS to this spacer, it's assigned a class. +Current y origin top of the scroller. -Default: `"iscroll-pullup-spacer`" +####wrapperW() -####scrollerContentClass +The width, in pixels, of the wrapper. This is the visible width of the scrolling area. -Normally (unless override with `createScroller="false"`) the widget creates a protective `
` -around your scroller content. It also wraps the pull-down and/or pull-up blocks, if present. -This is so that you don't have to create this `
` in your HTML -if you are scrolling multiple elements. The widget adds a class to this `
`. +####wrapperH() -Default: `"iscroll-content"` +The height, in pixels, of the wrapper. This is the visible height of the scrolling area. -####fixedHeightSelector +####scrollerW() -A JQuery selector which selects the fixed-height elements on the page which are outside -of the scrolling area. The heights of these elements will be added-up, and subtracted -from the total viewport height to arrive at the wrapper height. +The width, in pixels, of the scroller. This is the total width of the scroller, including +visible and non-visible portions. -Note: these elements are ignored for purposes of determining scroller height when -they occur inside of a Popup or Panel. +####scrollerH() -Default: `":jqmData(role='header'), :jqmData(role='footer'), :jqmData(iscroll-fixed)"` +The height, in pixels, of the scroller. This is the total height of the scroller, including +visible and non-visible portions. -####fixedHeightClass +###iScroll Getters/Setters -The widget adds this class to elements that have the `data-iscroll-fixed` attribute. +This widget provides getters with options setter functionality for some iScroll internal +variables that might be useful to an application. If a value is provided, then the +functions act as setters. In any case, they return the value of the associated internal +variable. -Default: `"iscroll-fixed"` +####minScrollX(val) -####resizeWrapper +The minimum X scroll position. This defines the left-most position of scroll. The user +can scroll past the minimum X, but then the scroller will snap-back to the mimimum X +position. -If true, the wrapper will be resized to the height remaining after accounting for -fixed-height elements. You should only set this to "true" for one scroller on a page. +####minScrollY(val) -Default: `true` +The minimum Y scroll position. This defines the top-most position of the scroll. The +user can scroll past the minimum Y, but then the scroller will snap-back to the minimum +Y position. -####resizeEvents +####maxScrollX(val) -A space-separated list of events which will cause a resize of the wrapper. +The maximum X scroll position. This defines the right-most position of scroll. The user +can scroll past the maximum X, but then the scroller will snap-back to the maximum X +position. -Note that mobile devices are very inconsistent in regard to `orientationchange` and `resize` events. -There is no consistency as to whether just one or both event are fired, and multiple events -of each type are fired on some devices. They are also inconsistent as to which fired event -first reflects the new width and height values. +####maxScrollY(val) -Default: `"resize orientationchange"` if device supports orientation. Otherwise, `"resize"`. +The maximum Y scroll position. This defines the bottom-most position of the scroll. The +user can drag past the maximum Y, but then the scroller will snap-back to the maximum +Y position. -####refreshOnPageBeforeShow +--- -If true, the scroller will be refreshed on every JQuery Mobile `pagebeforeshow` event. -This should be set to true if scroller content might have changed asynchronously while -the page was loaded into the DOM but not shown, as might happen in some native -application environment. *This usage is obsoleted by the widget's deferred `refresh()` feature.* +## Public Members -Default: `false` +The widget maintains several public data members that may be useful to you: -####fixInput +###iscroll -If true, applies a fix to allow input elements to work within a scroller. This is optional -because there is an alternative fix that patches iScroll itself. You should disable this -option if you are using a patched verison of iScroll that has a input-element fix incorporated, -or in case it causes some sort of trouble. +This is a reference the iScroll object. -Default: `true` +###$window -####wrapperAdd +A jQuery collection object containing the window (viewport). -Number of additional pixels to add to the wrapper height. This can be a positive or -negative value. This is an "escape hatch" in case the calculation of wrapper height -is not correct for some particular scenario. +###$wrapper -Default: 0 +A jQuery collection object containing the iscrollview wrapper element. -####refreshDelay +###$scroller -Number of mSec to permit browser to render before performing `refresh()`. +A jQuery collection object containing the scroller element. -When you call `refresh()`, the call to iScroll's internal `refresh()` is delayed by this amount, -to allow the browser to complete any rendering, prior to refreshing the scroller. If this value -is 0, then a `setTimeout()` call is still used. This causes the script to relinquish control -to the renderer, and may be sufficient for many browsers. +###$scrollerContent -This value may need to be experimentally determined. +a jQuery collection object containing the scroller content element. -Alternately, you can specify a timeout value when calling `refresh()`. This is useful in case you -have done some update which you know will require a lengthy render. +###$pullDown -Default: `200` for Android, otherwise `0` +a jQuery collection object containing any pull-down element. If there is no pull-down element, then the +length of the collection will be zero. -####scrollShortContent +###$pullUp -If true, the widget will set the minimum height of the scroller so that it fills the wrapper -(exclusive of any pull-down/pull-up elements). +A jQuery collection object containing any pull-up element. If there is no pull-up element, then +the length of the collection will be zero. -Note that if you have a pull-down or pull-up, then this is done regardless of this setting, -since otherwise there would be no way to access the pull-down or pull-up if there is no -content. (If there were some content but it was shorter than the wrapper, then you wouldn't -be able to drag in the empty space.) +###$page -Set this to `false` if you want scrollers that do not have a pull-down or pull-up to not display -a scrollbar and not be draggable if they are shorter than the wrapper. Recommended setting is -`true` because it provides a more consistent UI experience. +A jQuery collection object containing the page that the widget is contained in. -Default: `true` +--- -####emulateBottomOffset -If true, the widget will emulate a `bottomOffset` iScroll option. This option needs to be set -`true` if you are using a pull-up block. +## Options -Default: `true` -####removeWrapperPadding +### Overriding Option Defaults -If true, the widget will remove any padding from the wrapper. Normally, there should be no -padding on the wrapper element. If there is padding, then it isn't possible to drag within the -padding, and pull-down/pull-up elements will not be 100% width. -` -Default `true` +You can override the default options for new instances of this widget by setting the +prototype options in `$.mobile.iscrollview.prototype.options`. -####addScrollerPadding +Any options that you set programatically or using `data-` attributes will override the defaults. -If true, the widget will add any padding removed from the wrapper to the protective `
` it -places around your scrolled content. +Example: for all new instances of `$.mobile.iscrollview`, set the `refreshDelay` option to the +value `100`. -Default: `true` + $.mobile.iscrollview.prototype.options.refreshDelay = 100; -####createScroller +If you want to override options for all instances of the widget, a good place to do that is +at the same time that you override any jQuery Mobile default options. `jquery.mobile.iscrollview` +triggers an `iscrollview_init` event that is triggered once it has loaded, and you may set any +global options here. -iScroll scrolls only the first child of the wrapper. So that you don't have to wrap multiple -content elements with a `
` the widget does this for you. This `
` is always needed if you -have a pull-up or pull-down block. +Note that when `iscrollview_init` is triggered, this does *not* mean that any scroller(s) +have been initialized. It only means that the iscrollview library is loaded, and so you may +now set any global options. -Default: `true` +It's common to bind to `mobileinit` after jQuery is loaded, but before loading jQuery Mobile. +You can bind to `iscroll_init` in the same place. Alternately, you can make changes to +global options any time after `jquery.mobile.iscrollview` is loaded. -####addSpacers +Note: `iscroll_init` is ONLY available as a jQuery Event. There is no corresponding +iscrollview callback function. -If true, spacer `
`s will be added before and after the `.iscroll-content` div. -The height of these spacer `
`s will default to 0. +```html + +``` -Default: `true` +###Programatic access -####scrollTopOnResize +This widget supports programmatic access to options using standard widget factory +syntax: -On some platforms (for example, iOS) when orientation is changed, the address bar pushes the -page down. jQuery Mobile scroll the pgae back up on hash changes, but doesn't do so for -orientation changes. So, the page is left scrolled-down. + .iscrollview("option"); Returns an object with all options + .iscrollview("option", "hScroll"); Returns value of option + .iscrollview("option", "hScroll", true); Sets option + .iscrollview("option", {hScroll: true}); Sets option, alternative syntax + .iscrollview("option", {hScroll: true, vScroll:true}; Set multiple options -Since `orientationchange` seems unreliable on iOS, the widget actually does this on resize. (Though -you can change the event(s) on which the widget resizes...) +The widget handles copying widget options to the iScroll object options and +vice-versa. -This will only be done if you also have `resizeWrapper` set to `true`. +###Setting options in the data-iscroll attribute -Default: `true` +This widget also supports setting options directly in the `data-iscroll` +attribute. The options need to be in **strict** JSON format. This means that keys +and string values need to be enclosed in **double** quotes **only**. Numeric and +boolean values should **not** be enclosed in quotation marks. -####deferNonActiveRefresh +####Example: -If this options is set to `true`, then calls to `refresh()` for pages that are not the -active page will be deferred to the next `pagebeforeshow` event for the page. This avoids -unnecessary refreshes when the browser window is resized or device orientation is changed. -As well, it avoids unnecessary refreshes when multiple updates are made to content in a scroller -on a non-active page. +```html +
+``` -Please see the discussion in the documentation on the `refresh()` function for further details. +###Modifying options after instantiation -Default: `true` +If you modify an iScroll option after a scroller has been instantiated, the underlying +iScroll object will be destroyed and re-created. This is because iScroll does +not currently support modifying options after the object has been created. -####deferNonActiveResize +However, unofficially, some options can be changed without destroying and +re-creating the object. It is unclear exactly which options these are, and +so this widget does not attempt it. There is skeletal code in the source +that is commented-out to do this if you wish to experiment. -If this option is set to `true`, then calls to `resizeWrapper()` for pages that are not the -active page will be deferred to the next `pagebeforeshow` event for the page. This avoids -unnecessary resizing when the browser window is resized or device orientation is changed. +If you modify a widget option (which is not also an iScroll option) after instantiation, +behaviour depends on the specific option. (Like iScroll) the widget does not currently +specifically support changing options after instantiation. Generally, if you change an +option after instantiation. If the option only has an effect at instantiation, then changing +the option after instantion will do nothing. (And might confuse the widget.) -Default: `true` +###Emulated Options -####preventTouchHover +The following option is emulated by the widget: -If `true`, prevent hover in scroller on touch devices. +####bottomOffset -If this is `false`, you will get "piano keyboard" effect if using jQuery Mobile 1.0 or 1.0.1 -when scrolling due to mouseover events, which is both time-consuming and distracting. If this -is `true`, the widget will prevent the piano-keyboard effect. +Offset at the bottom of the scroller. Complementary to the iScroll `topOffset` option. The number +of pixels specified by `bottomOffset` will apper below the bottom of the scroll range. You can +scroll into this area, but then the scroller will snap back. (This is needed to support the +pull-up funcitonality.) -This really is a jQuery Mobile problem with listviews, and is solved in jQuery Mobile 1.1. +Also, see the `emulateBottomOffset` option. -One negative is that with the current implementation, you will never get a "hover" visual -effect within a scroller on touch devices, even when not scrolling. But you still will on desktop -browser with mouse, and you will still get "down" effect when a link is selected. However, it -probably isn't desirable to get hover in a listview, because it is distracting. +Default: `0` -Default: `true` for touch devices if jQuery Mobile < 1.1, `false` for jQuery Mobile >= 1.1 +###Widget Options -####bindIscrollUsingJqueryEvents +The following options are available which affect the widget itself. These are +not iScroll options. -If `true`, iScroll will be bound using jQuery event binding, rather than using `addEventListener()`. -As well, iScroll will use jQuery `mouseleave` event instead of `mouseout`. +####debug -This is an experimental feature, and is not yet completely functional. The code is present to -permit further experimentation. +Enables performance logging. Please see the documentation section on performance logging. There +are a number of additional options which allow you to control what is logged. These are documented +in the section on performance logging. Default: `false` -###fastDestroy +####pageClass +A CSS class, or a space-separated list of classes, which will be added to the page +containing the wrapper. -If `true`, an assumption is made that you will not call the widget's `destroy()` function to -un-enhance the widget while retaining the page. The assumption is that `destroy()` will only -be called internally by the page plugin when the page is removed from the DOM. This saves -the overhead of un-enhancing the page. +Default: `"iscroll-page"` -Default: `false` +####wrapperClass -###preventPageScroll +A CSS class, or a space-separated list of classes, which will be added to the wrapper. -If `true` prevent scrolling the page by grabbing areas outside of the scroller. -Normally, this should be true. Set this false if you are NOT using a fixed-height page, -but instead are using iScroll to scroll an area within a scollable page. If you have -multiple scrollers on a scrollable page, then set this false for all of them. -Note that scrolling of the page by dragging inside the scroller is *always* prevented. +Default: `"iscroll-wrapper"` -Default: `true` +####scrollerClass -####pullDownResetText +A CSS class, or a space-separated list of classes, which will be added to the scroller. +(The scroller is the first child of the wrapper, and is the element that will +be scrolled.) -Default: `"Pull down to refresh..."` +Default: `"iscroll-scroller"` -####pullDownPulledText +####topSpacerClass -Default: `"Release to refresh..."` +A CSS class, or a space-separated list of classes, which will be added to the top spacer +`
`. -####pullDownLoadingText +####bottomSpacerClass + +A CSS class, or a space-separated list of classes, which will be added to the bottom spacer +`
`. + +####pullDownClass + +If this class is found within the scroller, and the `topOffset` option value is not set or is zero, +then the `topOffset` will be set to the height of the pull-down element. As well, the widget makes +modifications to the pulldown element's CSS. -Default: `"Loading..."` +Default: `"iscroll-pulldown"` -####pullUpResetText +####pullUpClass -Default: `"Pull up to refresh..."` +If this class is found within the scroller, and the `bottomOffset` option value is not set or is +zero, then the `bottomOffset` will be set to the height of the pull-up element. As well, the widget +makes modifications to the pullup element's CSS. -####pullUpPulledText +Default: `"iscroll-pullup"` -Default: `"Release to refresh..."` +####pullUpSpacerClass -####pullUpLoadingText +If you use a pull-up block, then the widget will create a special pull-up spacer, to insure +that the pull-up appears hidden below the bottom of the scroller window until manually scrolled, +even if the content is shorter than the height of the wrapper. -default: `"Loading..."` +In case you need to apply some CSS to this spacer, it's assigned a class. -####pullPulledClass +Default: `"iscroll-pullup-spacer`" -Default: `"iscroll-pull-pulled"` +####scrollerContentClass -####pullLoadingClass +Normally (unless override with `createScroller="false"`) the widget creates a protective `
` +around your scroller content. It also wraps the pull-down and/or pull-up blocks, if present. +This is so that you don't have to create this `
` in your HTML +if you are scrolling multiple elements. The widget adds a class to this `
`. -Default: `"iscroll-pull-loading"` +Default: `"iscroll-content"` ---- +####fixedHeightSelector -Events ------- -There are two ways to be notified when some event occurs in the widget: by binding/delegating -jQuery events, or by specifying a callback in the widget's `options` object. +A JQuery selector which selects the fixed-height elements on the page which are outside +of the scrolling area. The heights of these elements will be added-up, and subtracted +from the total viewport height to arrive at the wrapper height. -When an event is triggered it will call the callback if defined in options, and, as well, trigger -any bound events. +Note: these elements are ignored for purposes of determining scroller height when +they occur inside of a Popup or Panel. -###jQuery Event Callbacks +Default: `":jqmData(role='header'), :jqmData(role='footer'), :jqmData(iscroll-fixed)"` -The widget exposes jQuery events that can be bound like any other event. -The names are prepended with the string `iscroll_`. So, the `onrefresh` -event for this widget is actually `iscroll_onrefresh`. (Note also that widget event names -are different than iScroll event names. iScroll event names are in mixed case. Widget event -names are in all lower case - this is a limitation of jQuery widgets.) +####fixedHeightClass +The widget adds this class to elements that have the `data-iscroll-fixed` attribute. -###Option Callbacks +Default: `"iscroll-fixed"` -Alternately, you can add callback functions to the widget's `options` object. The key -of the option corresponds to the event name **without** the widget name -prefix. So, you can add a callback function for the refresh event -with the key `onrefresh`. +####resizeWrapper -I don't recommend using option callbacks. They are supported because they are required by -the jQuery Widget Factory. +If true, the wrapper will be resized to the height remaining after accounting for +fixed-height elements. You should only set this to "true" for one scroller on a page. -Note that the `iscrollview_init` event has no corresponding Widget Factory callback. +Default: `true` +####resizeEvents -###Bound Callback parameters +A space-separated list of events which will cause a resize of the wrapper. -Bound event callbacks receive two parameters: +Note that mobile devices are very inconsistent in regard to `orientationchange` and `resize` events. +There is no consistency as to whether just one or both event are fired, and multiple events +of each type are fired on some devices. They are also inconsistent as to which fired event +first reflects the new width and height values. -* `event` - The underlying DOM event (if any) associated with this event -* `data` - A map containing data passed to the event by this widget - * `:iscrollview` - a reference to the iscrollview object associated with this event +Default: `"resize orientationchange"` if device supports orientation. Otherwise, `"resize"`. -As well, when a bound event callback is called, `this` will be the DOM -object that triggered the event. (e.g. the wrapper). +####refreshOnPageBeforeShow +If true, the scroller will be refreshed on every JQuery Mobile `pagebeforeshow` event. +This should be set to true if scroller content might have changed asynchronously while +the page was loaded into the DOM but not shown, as might happen in some native +application environment. *This usage is obsoleted by the widget's deferred `refresh()` feature.* -###Binding to Events +Default: `false` -All events triggered by this widget trigger on the wrapper element. This includes events generated -by iScroll itself (and reflected to jQuery events) as well as those triggered by the widget. +####fixInput -It is most efficient, then, to bind directly to the wrapper element. If you bind from a script -within an HTML page, make sure that the script is at the *end* of the page, within the `` -element. +If true, applies a fix to allow input elements to work within a scroller. This is optional +because there is an alternative fix that patches iScroll itself. You should disable this +option if you are using a patched verison of iScroll that has a input-element fix incorporated, +or in case it causes some sort of trouble. -Do not put code to bind to events directly in `` on a particular page, because jQuery Mobile -ignores the content of `` on all but the first page encountered. (Thus the content of -`` should be identical for every page.) +Default: `true` -In this case, you can locate the wrapper element with: +####wrapperAdd -```javascript +Number of additional pixels to add to the wrapper height. This can be a positive or +negative value. This is an "escape hatch" in case the calculation of wrapper height +is not correct for some particular scenario. - $.mobile.activePage.find(".iscroll-wrapper") +Default: 0 -``` +####refreshDelay -or +Number of mSec to permit browser to render before performing `refresh()`. -```javascript +When you call `refresh()`, the call to iScroll's internal `refresh()` is delayed by this amount, +to allow the browser to complete any rendering, prior to refreshing the scroller. If this value +is 0, then a `setTimeout()` call is still used. This causes the script to relinquish control +to the renderer, and may be sufficient for many browsers. - (".iscroll-wrapper", $.mobile.activepage) +This value may need to be experimentally determined. -``` +Alternately, you can specify a timeout value when calling `refresh()`. This is useful in case you +have done some update which you know will require a lengthy render. -If you have multiple scrollers on a page, you will need to assign an ID or class to individual -wrappers so that you can locate them. +Default: `200` for Android, otherwise `0` -So, within a page, you can bind simply, such as: +####scrollShortContent -```javascript +If true, the widget will set the minimum height of the scroller so that it fills the wrapper +(exclusive of any pull-down/pull-up elements). - $.mobile.activePage.find(".iscroll-wrapper").bind("iscroll_onpulldown", function () { - alert("Pull-down gesture was completed"); - } ); +Note that if you have a pull-down or pull-up, then this is done regardless of this setting, +since otherwise there would be no way to access the pull-down or pull-up if there is no +content. (If there were some content but it was shorter than the wrapper, then you wouldn't +be able to drag in the empty space.) -``` +Set this to `false` if you want scrollers that do not have a pull-down or pull-up to not display +a scrollbar and not be draggable if they are shorter than the wrapper. Recommended setting is +`true` because it provides a more consistent UI experience. -To bind in common code called from ``, you will need to first delegate a function to the -`pageinit` event. This event is triggered whenever a page is first created. You can test (using -an ID or class) to see if that page has a scroller you want to bind to, and then bind from -within the delegated function. The file `pull-example.js` in the demo uses this technique. +Default: `true` -```javascript +####emulateBottomOffset - $(document).delegate("div.contacts-page", "pageinit", function () { - this.find(".iscroll-wrapper").bind("iscroll_onpulldown", function () { - alert("Pull-down gesture was completed"); - }); - }); +If true, the widget will emulate a `bottomOffset` iScroll option. This option needs to be set +`true` if you are using a pull-up block. -``` +Default: `true` -You can also use a delegation at the document level. This is shorter, but somewhat less efficient, -since events will bubble-up to the document: +####removeWrapperPadding -```javascript +If true, the widget will remove any padding from the wrapper. Normally, there should be no +padding on the wrapper element. If there is padding, then it isn't possible to drag within the +padding, and pull-down/pull-up elements will not be 100% width. +` +Default `true` - $(document).delegate("div.contacts-wrapper", "iscroll_onpulldown", function () { - alert("Pull-down gesture was completed"); - }); +####addScrollerPadding -``` +If true, the widget will add any padding removed from the wrapper to the protective `
` it +places around your scrolled content. -Finally, if you have a reference to an `iscrollview` object, you can use it's public `$wrapper` -member to bind: +Default: `true` -```javascript - // JQM < 1.3 - var view = $('.some-wrapper').jqmData('iscrollview'); - view.$wrapper.bind("iscroll_onpulldown", function () { - alert("Pull-down gesture was completed"); - }); -``` +####createScroller -```javascript - // JQM >= 1.3 - var view = $('.some-wrapper').data('mobileIscrollview'); - view.$wrapper.bind("iscroll_onpulldown", function () { - alert("Pull-down gesture was completed"); - }); -``` +iScroll scrolls only the first child of the wrapper. So that you don't have to wrap multiple +content elements with a `
` the widget does this for you. This `
` is always needed if you +have a pull-up or pull-down block. -###Supported Events +Default: `true` -#### iscroll_init +####addSpacers -This event is triggered when jquery.mobile.iscrollview has been loaded. This does *not* -mean that any iscrollview widgets have been initialized. The purpose of this event is to -allow you to set global options after the library is loaded, but before any widgets have -been initialized. +If true, spacer `
`s will be added before and after the `.iscroll-content` div. +The height of these spacer `
`s will default to 0. -This event does NOT have a corresponding Widget Factory callback option. +These spacers can be used as a substitute for top/bottom padding in situations where +top/bottom padding is ineffective, and collapses into the document. -####iscroll_onrefresh +Default: `true` -This event is triggered when iScroll's internal `refresh()` function is called. It is -called after iScroll has calculated the scroll range, but before it has updated the scroll -bar. +####scrollTopOnResize -*This event is of dubious value to applications. The widget uses this internally to -support pull-down/pull-up. (It seems it was put just where it is just for that purpose.)* +On some platforms (for example, iOS) when orientation is changed, the address bar pushes the +page down. jQuery Mobile scroll the pgae back up on hash changes, but doesn't do so for +orientation changes. So, the page is left scrolled-down. -If you want to do some refresh of jQuery Mobile structures (such as listview) contained within -the scroller prior to scroller refresh, see the `iscroll_onbeforerefresh` event and the optional -`callbackBefore` parameter to the `refresh()` function. +Since `orientationchange` seems unreliable on iOS, the widget actually does this on resize. (Though +you can change the event(s) on which the widget resizes...) -####iscroll_onbeforerefresh +This will only be done if you also have `resizeWrapper` set to `true`. -This event is triggered before the widget calls iScroll's `refresh()` function. It is useful -if you need to do some refresh of jQuery Mobile widgets (such as `listview`) contained within -the scroller. It is important to do this *before* iScroll's `refresh()` has been called. Do -not use `iscroll_onrefresh()` for this. +Default: `true` -You can also use the optional `callbackBefore` callback parameter to the widget's `refresh()` -function for this. +####deferNonActiveRefresh -####iscroll_onafterrefresh +If this options is set to `true`, then calls to `refresh()` for pages that are not the +active page will be deferred to the next `pagebeforeshow` event for the page. This avoids +unnecessary refreshes when the browser window is resized or device orientation is changed. +As well, it avoids unnecessary refreshes when multiple updates are made to content in a scroller +on a non-active page. -This event is triggered after the widget calls iScroll's `refresh()` function. It is useful -if you want to perform some action, such as scrolling, after changing content in the scroller. -This has to be done *after* the scroller is refreshed. +Please see the discussion in the documentation on the `refresh()` function for further details. -You can also use the optional `callbackAfter` callback parameter to the widget's `refresh()` -function for this. +Default: `true` -####iscroll_onbeforescrollstart +####deferNonActiveResize -Triggered by iScroll's `onBeforeScrollStart` event. +If this option is set to `true`, then calls to `resizeWrapper()` for pages that are not the +active page will be deferred to the next `pagebeforeshow` event for the page. This avoids +unnecessary resizing when the browser window is resized or device orientation is changed. -####iscroll_onscrollstart +Default: `true` -Triggered by iScroll's `onScrollStart` event. +####preventTouchHover -####iscroll_onbeforescrollmove +If `true`, prevent hover in scroller on touch devices. -Triggered by iScroll's `onBeforeScrollMove` event. +If this is `false`, you will get "piano keyboard" effect if using jQuery Mobile 1.0 or 1.0.1 +when scrolling due to mouseover events, which is both time-consuming and distracting. If this +is `true`, the widget will prevent the piano-keyboard effect. -####iscroll_onscrollmove +This really is a jQuery Mobile problem with listviews, and is solved in jQuery Mobile 1.1. -Triggered by iScroll's `onScrollMove` event. +One negative is that with the current implementation, you will never get a "hover" visual +effect within a scroller on touch devices, even when not scrolling. But you still will on desktop +browser with mouse, and you will still get "down" effect when a link is selected. However, it +probably isn't desirable to get hover in a listview, because it is distracting. -####iscroll_onbeforescrollend +Default: `true` for touch devices if jQuery Mobile < 1.1, `false` for jQuery Mobile >= 1.1 -Triggered by iScroll's onBeforeScrollEnd event. +####bindIscrollUsingJqueryEvents -####iscroll_ontouchend +If `true`, iScroll will be bound using jQuery event binding, rather than using `addEventListener()`. +As well, iScroll will use jQuery `mouseleave` event instead of `mouseout`. -Triggered by iScroll's `onTouchEnd` event. +This is an experimental feature, and is not yet completely functional. The code is present to +permit further experimentation. -####iscroll_ondestroy +Default: `false` -Triggered by iScroll's `onDestroy` event. +###fastDestroy -####iscroll_onzoomstart +If `true`, an assumption is made that you will not call the widget's `destroy()` function to +un-enhance the widget while retaining the page. The assumption is that `destroy()` will only +be called internally by the page plugin when the page is removed from the DOM. This saves +the overhead of un-enhancing the page. -Triggered by iScroll's `onZoomStart` event. +Default: `false` -####iscroll_onzoom +###preventPageScroll -Triggered by iScroll's `onZoom` event. +If `true` prevent scrolling the page by grabbing areas outside of the scroller. +Normally, this should be true. Set this false if you are NOT using a fixed-height page, +but instead are using iScroll to scroll an area within a scollable page. If you have +multiple scrollers on a scrollable page, then set this false for all of them. +Note that scrolling of the page by dragging inside the scroller is *always* prevented. -####iscroll_onzoomend +Default: `true` -Triggered by iScroll's `onZoomEnd` event. +####pullDownResetText -####iscroll_onpulldown +Default: `"Pull down to refresh..."` -This event is triggered when the user has completed a pull-down gesture. Your event callback -should perform the pull-down action. (For example, getting data from a server in order to refresh -text shown within the scroller.) +####pullDownPulledText -You can also use this event for complex customization of pull-down feedback to the user. The -UI should indicate that the pull-down action is being performed. +Default: `"Release to refresh..."` -####iscroll_onpulldownreset +####pullDownLoadingText -This event is triggered when the user has aborted a pull-down gesture by scrolling back up, or -after completion of the pull-down action and `refresh()`. You can use this event for complex -customization of pull-down feedback to the user. The UI should indicate that the user may -initiate a pull-down sequence. +Default: `"Loading..."` -####iscroll_onpulldownpulled +####pullUpResetText -This event is triggered when the user has completed the first half of a pull-down gesture. -i.e. they have pulled-down, but not yet released. You can use this event for complex -customization of pull-down feedback to the user. The UI should indicate that the user may -complete a pull-down sequence by releasing. +Default: `"Pull up to refresh..."` -####iscroll_onpullup +####pullUpPulledText -This event is triggered when the user has completed a pull-up gesture. Your event callback -should perform the pull-up action. (For example, getting data from a server in order to refresh -text shown within the scroller.) +Default: `"Release to refresh..."` -You can also use this event for complex customization of pull-up feedback to the user. The -UI should indicate that the pull-up action is being performed. +####pullUpLoadingText -####iscroll_onpullupreset +default: `"Loading..."` -This event is triggered when the user has aborted a pull-up gesture by scrolling back down, or -after completion of the pull-up action and `refresh()`. You can use this event for complex -customization of pull-up feedback to the user. The UI should indicate that the user may -initiate a pull-up sequence. +####pullPulledClass -####iscroll_onpulluppulled +Default: `"iscroll-pull-pulled"` -This event is triggered when the user has completed the first half of a pull-up gesture. -i.e. they have pulled-up, but not yet released. You can use this event for complex -customization of pull-up feedback to the user. The UI should indicate that the user may -complete a pull-up sequence by releasing. +####pullLoadingClass +Default: `"iscroll-pull-loading"` --- -Scroll Bars ------------ +## Events -### Wrapper Positioning Requirement - -iScroll requires that the wrapper be CSS-positioned either `absolute` or `relative`. If the -wrapper is positioned `static` (the default, if positioning is not specified), then the -scroll bars will (incorrectly) be created relative to the page, rather than the wrapper. The -symptom is that the scroll bar will be the full height of the window. (Though the widget -will hide the scrollbar under any header/footer.) +There are two ways to be notified when some event occurs in the widget: by binding/delegating +jQuery events, or by specifying a callback in the widget's `options` object. -The standard CSS file for the widget sets relative positioning on the wrapper. +When an event is triggered it will call the callback if defined in options, and, as well, trigger +any bound events. -Either `absolute` or `relative` positioning of the wrapper will cause elements inside the -wrapper which themselves have `absolute` positioning to be positioned relative to the wrapper. -iScroll depends on this behaviour for positioning of the scrollbar. +###jQuery Event Callbacks -### Customizing Scrollbar Position +The widget exposes jQuery events that can be bound like any other event. +The names are prepended with the string `iscroll_`. So, the `onrefresh` +event for this widget is actually `iscroll_onrefresh`. (Note also that widget event names +are different than iScroll event names. iScroll event names are in mixed case. Widget event +names are in all lower case - this is a limitation of jQuery widgets.) -iScroll gives you the ability to customize scroll bars. See the iScroll4 documentation -for full details. You can customize the height, width, position, color, etc. etc. of -the scrollbar. To do so, you need to set the `scrollbarClass` option and then provide -CSS to customize the scrollbar. -However, in many cases, all that is really desired is to set the position -of the scrollbar. In this case, you can add some very minimal CSS. +###Option Callbacks -In this case, do NOT set the `scrollbarClass` option. Setting this option causes -iScroll to omit quite a bit of it's initialization of the scrollbar, and then you -are required to supply a considerable amount of CSS. +Alternately, you can add callback functions to the widget's `options` object. The key +of the option corresponds to the event name **without** the widget name +prefix. So, you can add a callback function for the refresh event +with the key `onrefresh`. -Instead, you can usually use a CSS rule similar to this: +I don't recommend using option callbacks. They are supported because they are required by +the jQuery Widget Factory. -```css +Note that the `iscrollview_init` event has no corresponding Widget Factory callback. - div.my-iscroll-wrapper > div:last-child { - top: 46px !important; - bottom: 22px !important; - } -``` +###Bound Callback parameters -iScroll appends the scrollbar to the end of your wrapper. Unless you have appended something -else yourself, you can target the last child of the wrapper, and so you don't need the -`scrollbarClass` to identify the scrollbar. So, iScroll will still do all of it's usual -initialization. By using the `!important` modifier, your CSS will override the top and -bottom locations that iScroll itself sets. +Bound event callbacks receive two parameters: ---- +* `event` - The underlying DOM event (if any) associated with this event +* `data` - A map containing data passed to the event by this widget + * `:iscrollview` - a reference to the iscrollview object associated with this event -Multiple Scrollers ------------------- -If you wish to have multiple scrollers, please note the following: +As well, when a bound event callback is called, `this` will be the DOM +object that triggered the event. (e.g. the wrapper). -- The `resizeWrapper` option should be set to `true` for no more than one -of your scrollers. If you have multiple scrollers one above the other, -then at most one of them can be auto-sized. If you have multiple scrollers -side-by-side, then you will probably have to size all them yourself. -Since `resizeWrapper` is `true` by default, you will need to set the option -to `false` for all but (a maximum) of one of your scrollers. -- iScroll will not work correctly if scrollbars from multiple scrollers -overlap. It will fail to scroll in all but one of the scrollers that -have overlapping scrollbars. Please see the documentation on scrollbar -customization, above. +###Binding to Events ---- +All events triggered by this widget trigger on the wrapper element. This includes events generated +by iScroll itself (and reflected to jQuery events) as well as those triggered by the widget. -Listviews Containing Links --------------------------- -*(Note: this discussion is somewhat obsoleted by changes in version 1.2 of this widget and -version 1.1 of jQuery Mobile. By default, the widget prevents this annoying list behaviour -when you are using it with jQuery Mobile 1.0 or 1.0.1 with the `preventTouchHover` option. jQuery -Mobile 1.1 prevents it inherently.)* +It is most efficient, then, to bind directly to the wrapper element. If you bind from a script +within an HTML page, make sure that the script is at the *end* of the page, within the `` +element. -Listviews that have list items that are buttons (i.e. the items are clickable, -because they are wrapped in an `` tag) can be very slow on touchscreen devices. This is not an -iScroll or widget problem per-se - it is inherent to JQuery Mobile 1.0 and 1.0.1. +Do not put code to bind to events directly in `` on a particular page, because jQuery Mobile +ignores the content of `` on all but the first page encountered. (Thus the content of +`` should be identical for every page.) -There is a discussion of this issue here: +In this case, you can locate the wrapper element with: - http://forum.jquery.com/topic/why-jqm-touchscreen-list-scrolling-performance-stinks-and-what-to-do-about-it +```javascript -The gist of it is that as you scroll a list, your finger slips from one list -item to the next, causing a "piano key" visual effect. The effect is both -distracting to the user and slow. + $.mobile.activePage.find(".iscroll-wrapper") -A work-around is to insure that up/down/hover states for your scrollable -listviews are identical, so that there is no *hover* effect and no *selected* -effect. If you're developing exclusively for a touch-screen mobile device, -there's little to no need for these effects. Users don't expect them: they -expect something to happen when they tap, but not a useless effect. +``` -This is an *example* of CSS overrides that will remove the hover and selected effects. -You will need to modify this CSS to match your theme. The important thing is that -the up, down, and hover states must have identical CSS, so that there is no transition -between states. +or -```css +```javascript - /* - Sane overrides for buttons in lists + (".iscroll-wrapper", $.mobile.activepage) - JQM default styling has up/down/hover/select styles for buttons. This is nice for real - buttons, but slows list scrolling to a crawl. This can be avoided by styling the - up/down/hover states identically. - */ +``` - ul.ui-listview *.ui-btn-up-c, - ul.ui-listview *.ui-btn-down-c, - ul.ui-listview *.ui-btn-hover-c - { - border-color: #ccc; - background: #eee; - font-weight: bold; - color: #444; - text-shadow: 0 1px 1px #f6f6f6; - background-image: -webkit-gradient(linear, left top, left bottom, from( #fdfdfd), to( #eee)); - } +If you have multiple scrollers on a page, you will need to assign an ID or class to individual +wrappers so that you can locate them. - ul.ui-listview *.ui-btn-up-c a.ui-link-inherit, - ul.ui-listview *.ui-btn-down-c a.ui-link-inherit, - ul.ui-listview *.ui-btn-hover-c a.ui-link-inherit - { color: #444; } +So, within a page, you can bind simply, such as: -``` +```javascript ---- + $.mobile.activePage.find(".iscroll-wrapper").bind("iscroll_onpulldown", function () { + alert("Pull-down gesture was completed"); + } ); -Caching List Items ------------------- -Webkit-based browsers can exhibit a "flicker" effect wwhen scrolling -toward the bottom of the list, as well as exhibit slow and jerky movement until the first -time the user has reached the bottom of the list.. Once you have scrolled down to the bottom of -the list, the flicker will typically stop. This does not seem to be an issue with non-Webkit -browsers. +``` -This issue is discussed here: http://cubiq.org/you-shall-not-flicker +To bind in common code called from ``, you will need to first delegate a function to the +`pageinit` event. This event is triggered whenever a page is first created. You can test (using +an ID or class) to see if that page has a scroller you want to bind to, and then bind from +within the delegated function. The file `pull-example.js` in the demo uses this technique. -A work-around for this issue to to force list items to be pre-cached. See -the above link for a discussion of why this works. Basically, the flicker occurs -when each element is first encountered and hardware acceleration is enabled for -the element. By pre-setting a null 3D transform (which triggers hardware accelation on WebKit -browsers) on each element, the flicker is avoided, and the content is added to the hardware cache. +```javascript -This has been reported to cause bluring of text during transform on Android platforms. You will -need to decide which of two evils you want to live with. + $(document).delegate("div.contacts-page", "pageinit", function () { + this.find(".iscroll-wrapper").bind("iscroll_onpulldown", function () { + alert("Pull-down gesture was completed"); + }); + }); -If this *is* used, then the browser may be forced to cache the content in advance, resulting -in smoother scrolling, but with the side-effect of increasing initial rendering time. +``` -This can more than *double* initial rendering time if you are not careful with the selector. The -recommended CSS at the above link is NOT optimal. +You can also use a delegation at the document level. This is shorter, but somewhat less efficient, +since events will bubble-up to the document: -You need to apply this judiciously. For example, if you know your scroller content consists -of list items, use `li` not `*` to select. `*` as the right-most component of a select is -horribly expensive. A small additional performance gain can be made by selecting -iscroll-content instead of iscroll-scroller. You might get a -glitch on a pull-up if you have one, but it's a small price to pay for doubling speed. +```javascript -It is important NOT to apply this to `.iscroll-scroller` itself. This will result in a huge -performance loss. The rule below gives performance on iOS devices very close to not -using this at all. + $(document).delegate("div.contacts-wrapper", "iscroll_onpulldown", function () { + alert("Pull-down gesture was completed"); + }); -The demo uses this CSS: +``` -```css +Finally, if you have a reference to an `iscrollview` object, you can use it's public `$wrapper` +member to bind: - .iscroll-content li { - -webkit-transform: translateZ(0); - } +```javascript + // JQM < 1.3 + var view = $('.some-wrapper').jqmData('iscrollview'); + view.$wrapper.bind("iscroll_onpulldown", function () { + alert("Pull-down gesture was completed"); + }); +``` +```javascript + // JQM >= 1.3 + var view = $('.some-wrapper').data('mobileIscrollview'); + view.$wrapper.bind("iscroll_onpulldown", function () { + alert("Pull-down gesture was completed"); + }); ``` ---- -Mobile Safari Address Bar -------------------------- -The Mobile Safari address bar is a 60px area at the top of the browser. The address bar is fixed -on iPad, but on iPhone and iPad, it can be made to scroll off-screen by scrolling content. -jQuery Mobile normally does this, but the address bar is always present at the time that a page -loads. jQuery Mobile then scrolls in order to push the address bar back up. +###Supported Events -jQuery Mobile 1.1 handles the address bar better than jQuery Mobile 1.0 or 1.0.1. With 1.1, the -address bar usually will not appear during a page transition. +#### iscroll_init -It doesn't appear possible to consistently detect the real window height, though it is possible -to consistently detect the window height assuming that the address bar is present. So, this -widget adds 60px to page height in this situation. This addition is not applied for iPad, nor for -iPhone/iPod if running a native app in a UIWebView, or when running in "full screen" mode -(web page saved to home screen). +This event is triggered when jquery.mobile.iscrollview has been loaded. This does *not* +mean that any iscrollview widgets have been initialized. The purpose of this event is to +allow you to set global options after the library is loaded, but before any widgets have +been initialized. -If you are testing using desktop Safari's `Develop` `User Agent` option, please note that this -adaptation will fail. It depends on specific behaviour of the real Mobile Safari browser. If -you want to use desktop Safari to test pages designed to run on iPhone, either use the standard -Safari User Agent, or else use an "Other" User Agent: +This event does NOT have a corresponding Widget Factory callback option. -First, set the User Agent to `Safari ... iPhone`. then, select `User Agent` `Other`. The user-agent -string will be pre-populated with the Mobile Safari user-agent string. Remove `Safari` from the -user agent. This will fool the widget into thinking you are running in "full screen" mode, without -the disappearing address bar which is not present on desktop Safari. +####iscroll_onrefresh ---- +This event is triggered when iScroll's internal `refresh()` function is called. It is +called after iScroll has calculated the scroll range, but before it has updated the scroll +bar. -Demo ----- -The demo contains a simple example with 5 pages. The demo can be found in `/demo/build`. It is built -using a static site generator (written in Ruby) called Middleman, but the demo has already been -built for you. If you do wish to build the demo yourself, you will need to install Middleman 3.0 or -higher. +*This event is of dubious value to applications. The widget uses this internally to +support pull-down/pull-up. (It seems it was put just where it is just for that purpose.)* -Just copy the contents of `/demo/build` to your web server, or open the index.html file directly -from `/demo/build`. +If you want to do some refresh of jQuery Mobile structures (such as listview) contained within +the scroller prior to scroller refresh, see the `iscroll_onbeforerefresh` event and the optional +`callbackBefore` parameter to the `refresh()` function. -You can switch between the pages using the tabbar at the bottom. The pages demonstrate: +####iscroll_onbeforerefresh -* a listview -* an inset listview (also has two expandible elements) -* a listview with pull-down and pull-up blocks -* a listview with a short list and pull-down/pull-up blocks -* a form +This event is triggered before the widget calls iScroll's `refresh()` function. It is useful +if you need to do some refresh of jQuery Mobile widgets (such as `listview`) contained within +the scroller. It is important to do this *before* iScroll's `refresh()` has been called. Do +not use `iscroll_onrefresh()` for this. -To demo, simply open the `index.html` file in your browser. Note that the page transitions will -not work with some browsers when loading from a local file - for those browsers, you will have -to load the demo from a server. (It does work with local files for Safari and Firefox.) +You can also use the optional `callbackBefore` callback parameter to the widget's `refresh()` +function for this. -You can switch between jQuery Mobile 1.0.1 and 1.1 using the buttons in the headers. +####iscroll_onafterrefresh -The demo illustrates the use of different-sized headers and footers for portrait and landscape -orientations. In landscape, the header and footer are shorter, and the header omits the buttons -for switching between jQuery Mobile versions. +This event is triggered after the widget calls iScroll's `refresh()` function. It is useful +if you want to perform some action, such as scrolling, after changing content in the scroller. +This has to be done *after* the scroller is refreshed. -###Special Demo Borders +You can also use the optional `callbackAfter` callback parameter to the widget's `refresh()` +function for this. -The demo has headers and footer styled with a 1px red border at top and bottom. This facilitates -a quick visual indication of correct sizing of the page. You should not see any white -space above the header or below the footer. (Note that Retina devices will show a 2px border, -rather than 1px.) Use your OS's accessibility features to magnify and inspect. On mobile -devices, there is usually a way to capture the screen contents to an image file that you can -later examine. (iPhone: Home+On/Off) +####iscroll_onbeforescrollstart -The iScroll wrapper is styled with a 1px green border at top and bottom. You should see no gap -or different color between the top of the wrapper and the bottom of the header, or between -the bottom of the wrapper and the top of the footer. +Triggered by iScroll's `onBeforeScrollStart` event. -###Demo Content +####iscroll_onscrollstart -As a convenience, the demo directory is self-contained (except for the widget, `iscroll-pull-js` -and pull icon files, which are expected to be found in the parent directory), and contains the -following additional components: +Triggered by iScroll's `onScrollStart` event. -* jQuery 1.6.4 -* jQuery 1.7.1 -* JQuery Mobile 1.0.1 -* jQuery Mobile 1.1.1 -* iscroll4, version 4.2 +####iscroll_onbeforescrollmove +Triggered by iScroll's `onBeforeScrollMove` event. -Please obtain these components independently for your projects, so that -you can be sure of what version you are getting, and avail yourself -of any updates/improvements. +####iscroll_onscrollmove ---- +Triggered by iScroll's `onScrollMove` event. -Performance Logging -------------------- -This widget can log events and performance data to the Javascript console when the `debug` option -is set to `true`. A number of additional options control what is logged. Setting `debug` false will -disable all logging. +####iscroll_onbeforescrollend -These log entries are useful both to monitor performance and to understand the sequence of events -that occur as the widget is used. +Triggered by iScroll's onBeforeScrollEnd event. -There is a log entry at the start and end of each traced function, event, or callback. Each -entry shows the time, file name, function, event, or callback name, and (at end) elapsed mSec that -the operation took. +####iscroll_ontouchend -For some functions, a second set of elapsed mSec and start time are logged (in parenthesis). -This is for functions that were queued using a SetTimeout or that were initially triggered by -some event. So, you can see how long the function took to run, as well as the elapsed time from when -the function was queued. +Triggered by iScroll's `onTouchEnd` event. -The `debug` option must be `true` in order for any of the trace options to be enabled. +####iscroll_ondestroy -Performance logging can generate a large amount of data. You can use trace options to narrow -the logging to items of interest. +Triggered by iScroll's `onDestroy` event. -You can use `jsconsole.js` or other similar solutions to do remote logging from mobile devices. -It is important to narrow the focus of your logging when using such solutions. +####iscroll_onzoomstart -### traceCreateDestroy +Triggered by iScroll's `onZoomStart` event. -If `true`, creation and destruction of the widget is traced. +####iscroll_onzoom -### traceRefresh +Triggered by iScroll's `onZoom` event. -If this option option is `true`, calls to the widget's `refresh()` function are traced. +####iscroll_onzoomend -In the case of `refresh()` there is an initial log entry when the `refresh()` is queued, which -will also indicate the timeout value that was used. A second, separate, log entry shows the elapsed -time that `refresh()` ran as well as elapsed time from when it was queued. The time value shown -lets you match-up the first and second entries. This will help you evaluate the impact of -browser rendering time. (A 0mSec timeout will first allow all rendering to complete.) +Triggered by iScroll's `onZoomEnd` event. -If a refresh is occuring on an `iscroll_onpagebeforerefresh` event because a page is "dirty" -the log entry will indicate "(dirty)". "Dirty" pages are pages that have had `refresh()` called -while they were not the active page. Normally (depending on the `DeferNonActiveRefresh` option) -such pages have their `refresh()` deferred until the page is about to be shown. +####iscroll_onpulldown -###traceResizeWrapper +This event is triggered when the user has completed a pull-down gesture. Your event callback +should perform the pull-down action. (For example, getting data from a server in order to refresh +text shown within the scroller.) -If this option is `true`, calls to the widget's `resizeWrapper()` function -are traced. +You can also use this event for complex customization of pull-down feedback to the user. The +UI should indicate that the pull-down action is being performed. -###traceIscrollEvents +####iscroll_onpulldownreset -If this option is `true`, events handled by iScroll are traced. +This event is triggered when the user has aborted a pull-down gesture by scrolling back up, or +after completion of the pull-down action and `refresh()`. You can use this event for complex +customization of pull-down feedback to the user. The UI should indicate that the user may +initiate a pull-down sequence. -###tracedIscrollEvents +####iscroll_onpulldownpulled -This is a list of iScroll events to trace. If the list is empty, all iScroll events will be -traced. List items are strings, example: `touchstart`. +This event is triggered when the user has completed the first half of a pull-down gesture. +i.e. they have pulled-down, but not yet released. You can use this event for complex +customization of pull-down feedback to the user. The UI should indicate that the user may +complete a pull-down sequence by releasing. -###traceWidgetEvents +####iscroll_onpullup -If this option is `true` events handled by the widget (not by iScroll) are traced. +This event is triggered when the user has completed a pull-up gesture. Your event callback +should perform the pull-up action. (For example, getting data from a server in order to refresh +text shown within the scroller.) -###tracedWidgetEvents +You can also use this event for complex customization of pull-up feedback to the user. The +UI should indicate that the pull-up action is being performed. -This is a list of widget events to trace. If the list is empty, all widget events will be -traced. List items are strings. Events that iScroll itself handles are *not* traced when this -option is `true`. As well, callbacks bound to `touchmove` only for the purpose of preventing -the page from scrolling are not traced, because they occur very frequently. +####iscroll_onpullupreset -###traceIscrollCallbacks +This event is triggered when the user has aborted a pull-up gesture by scrolling back down, or +after completion of the pull-up action and `refresh()`. You can use this event for complex +customization of pull-up feedback to the user. The UI should indicate that the user may +initiate a pull-up sequence. -If this option is `true`, callbacks issued by iScroll are traced. +####iscroll_onpulluppulled -###tracedIscrollCallbacks +This event is triggered when the user has completed the first half of a pull-up gesture. +i.e. they have pulled-up, but not yet released. You can use this event for complex +customization of pull-up feedback to the user. The UI should indicate that the user may +complete a pull-up sequence by releasing. -This is a list of iScroll callbacks to trace. If the list is empty, all iScroll callbacks will -be traced. List items are strings. Example: `onRefresh`. -###traceWidgetCallbacks +--- +# End Notes -If this option is `true`, callbacks issed by the widget are traced. This does not include -callbacks issued by iScroll itself (which application code may also bind to.) -###tracedWidgetCallbacks +## Roadmap -This is a list of widget callbacks to trace. If the list is empty, all widget callbacks will -be traced. List items are strings. Do not include the `iscroll_` prefix. Example: `onpulldown`. +1.4 - Fully implement usejQueryEvents ---- +? - Option to un-enhance widget temporarily (and optionally hide headers/footers) during +virtual-keyboard input on select devices (iOS first), to eliminate all form input problems +when using a virtual keyboard. -Variable names --------------- -The source code code follows the following conventions: +? iOS keyboard handing for inputs. Guess keyboard height based on device/orientation/fullscreen. +Resize wrapper to fit page in space above keyboard, center focused element. -* Upper-case first letter: constant -* $ first letter: variable contains a JQuery object -* (underscore) first letter: Private funcion + +? - Better support for collapsible content (scroll on expand if expanded content below window) --- +## Minified Version -Minified Version ----------------- As a convenience, I have added YUI and Google Closure-compressed versions of the JS file. You will find these in the /lib directory along with the uncompressed version. You should evaluate your own needs for compression, and use the compressor and options that are appropriate for your own site. -Bugs and Enhancements ---------------------- +## Bugs and Enhancements + Please submit bug and enhancement requests via [jquery.mobile.iscrollview gitHub Issues](https://github.com/watusi/jquery-mobile-iscrollview/issues) If you have developed code that you would like to have incorporated in a future release of this widget, please submit it for consideration via a gitHub pull request. --- -License -------- +## License + Copyright (c), 2012 Watusiware Corporation Distributed under the MIT License From 62491678f25d38038d9655aa98c9daf2471b6775 Mon Sep 17 00:00:00 2001 From: Denise Draper Date: Sun, 8 Jun 2014 19:01:10 -0700 Subject: [PATCH 2/2] Added TOC --- README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/README.md b/README.md index a7d78e1..4a59b62 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,40 @@ It is an implementation of a JQuery [Widget Factory](https://github.com/scottgon widget. It follows the *widget-factory-mobile* [Widget Factory Pattern](https://github.com/addyosmani/jquery-plugin-patterns). +--- +**Table of Contents** *(generated with [DocToc](http://doctoc.herokuapp.com/))* + +- [Overview](#user-content-overview) + - [Release Notes](#user-content-release-notes) + - [What This is For](#user-content-what-this-is-for) + - [Usage](#user-content-usage) + - [Example](#user-content-example) + - [Demo](#user-content-demo) +- [Technical Details](#user-content-technical-details) + - [Plug for jquery.mobile.simultaneous-transitions](#user-content-plug-for-jquerymobilesimultaneous-transitions) + - [Fixed and persistent Toolbars (Headers/Footers)](#user-content-fixed-and-persistent-toolbars-headersfooters) + - [Dynamic Content](#user-content-dynamic-content) + - [Padding Issues](#user-content-padding-issues) + - [Pull-to-Refresh](#user-content-pull-to-refresh) + - [Calling functions](#user-content-calling-functions) + - [Scroll Bars](#user-content-scroll-bars) + - [Multiple Scrollers](#user-content-multiple-scrollers) + - [Listviews Containing Links](#user-content-listviews-containing-links) + - [Caching List Items](#user-content-caching-list-items) + - [Mobile Safari Address Bar](#user-content-mobile-safari-address-bar) + - [Performance Logging](#user-content-performance-logging) + - [Variable names](#user-content-variable-names) +- [Reference](#user-content-reference) + - [Functions](#user-content-functions) + - [Public Members](#user-content-public-members) + - [Options](#user-content-options) + - [Events](#user-content-events) +- [End Notes](#user-content-end-notes) + - [Roadmap](#user-content-roadmap) + - [Minified Version](#user-content-minified-version) + - [Bugs and Enhancements](#user-content-bugs-and-enhancements) + - [License](#user-content-license) + --- # Overview