Thursday, August 25, 2016

Listviews with scrollbars in jQuery Mobile

Abstract: on a smartphone scrollbars are not an issue, header and footer are fixed, the content is scrolled on the right. But for browser applications like upload files by developers, scrollbars are needed for different listviews. Various tools where checked without success, the jQuery Mobile roadmap is not sufficient, so I went back to the roots of HTML - and it works in the browser very well and easy together with grid-layout and listview of jQuery Mobile
August, 23, 2016 Rolf Eckertz

There are several overviews in the internet like  http://ourcodeworld.com/articles/read/179/top-7-best-custom-browser-scrollbar-javascript-and-jquery-plugins

I tested iscroolview, tinyscrollbar, nicescroll, iscrolljs, the documentation was not always the best for beginners and I like robust and easy solutions.

At this time iscrolljs is the favorite - there are a pdf and a lot of examples. iscrolljs is on github and has a special website.

The harmonization with jQuery Mobile was not that easy, no examples and no detailled instructions. So I had to find out with a step by step approach of putting things together:
  • the documentation says it's easy, just do:
    • var myScroll = new IScroll('#wrapper');
  • but that is not sufficient, you need style sheet directives too
  • I derived these from one of the examples
  • then I made the styplesheets more abstract, not dedicated to id's but to the classes wrapper and scroller
    • wrapper is the class of the outer div 
    • scroller is the class of the inner div in the wrapper
    • ul then starts the listview within the scroller
That gives code like:

<div id="X" class="wrapper">
<div id="Y" class="scroller">
<ul id=liste data-role="listview" data-inset="true">
<li>Pretty row 1</li>
</ul>
</div>
</div>

The next problems came when li-elements were added dynamically. Step by step:
  • when new IScroll('#X'); is executed, the li-Elements that are already assigned are shown
  • if you add more elements, they are not shown
  • in the documentation a setTimeout-Wrapper around new IScroll is recommended, but that is not enough, because listview("refresh") also has to be done. So far my solution is after dynamic adding li-elements:
setTimeout(function () {
myScroll.destroy();
myScroll = new IScroll('#X', { 
scrollbars: true,
mouseWheel: true,
interactiveScrollbars: true,
shrinkScrollbars: 'scale',
fadeScrollbars: true
});
$("#liste").listview("refresh");
    }, 10);

I did not manage a refresh on IScroll. The solution worked in a clean test-environment, but not in the complete solution environment. I found out: resizing the browser window somehow activated the scrollbars and the scrollwheel? The solution following the documentation: increased the waiting time in setTimeout to 100 and everything worked fine. With 100 the $("#liste").listview("refresh"); statement can be put before the setTimeout-statement.

BUT: this approach only works for one listview on a page so far, so I have to restart to build a multi-listview solution bottom up. After some experiments the result seems to me: it's not possible to have multiple listviews with their own scrollbars on one page, jQuery Mobile always tries to supply one scrollbar on the page-content level. The roadmap for jQuery Mobile points to release 1.7 for "Make panels scroll independently from page" and as we see 1.4.5 at the moment and little progress it will surely take a while for that feature.

On the other hand, the roadmap shows that there is a real problem with multiple scrollbars in jQuery Mobile.

Back to the roots in HTML scrollbars are easy:
  • you need a div as wrapper
  • the wrapper must have a fixed height
  • the scrollbar must be allowed
<div id="" style="overflow:scroll; height:400px;">


Sometimes decisions have to be made, here: back to the roots of HTML:
  • for smartphone and touchscreen jQuery Mobile is ok
  • for desktop there are restrictions and roadmap-points that are too far in the future
  • so: for desktop other solutions are necessary - or a special restriction to a subset of jQuery Mobile.

The screenshot shows: two listviews, two scrollbars - and just html:

<body style="overflow:hidden;">
...
<div class="list ui-block-a" style="overflow:auto; max-height:100vh;">
...
<div class="list ui-block-b" style="background-color:yellow; overflow:auto; max-height:100vh;">

So sometimes back to the roots is not the worst choice. On the long run the ui-code for my apps will be generated from declarative scripts, that way it's rather easy to do responsive design on the fly.

The solution finally has the following points:

  • pagecontainer - the beforechange-event is no longer used, instead transition is used
  • with transition there are no problems to calculate a fixed height for the block-elements that get the scrollbars
  • the 100vh-parameter did not work fine, because a lot of data is in an invisible area, with the calculated height between the form and the footer everything works fine
  • transition requires that the target page is already defined, otherwise it is not fired, but dynamic loading of the target page is possible
November 21, 2016
The understanding of screen, window, page, header, content and footer is deeper now, scrolling programatically to a special element can be done rather easily.



No comments:

Post a Comment