Development Update – Week of June 13, 2011

Posted on by

We slipped a bit on on our weekly updates so sorry for the lack of updates recently. We’ve been busy prepping for Beta 1 and fixing bugs so there is a lot of activity. Here’s what we’ve been up to on the jQuery Mobile project.

Over the last few weeks, we’ve been deeply re-factoring our Ajax navigation system to make it more extensible and robust. This week, we’re happy to announce that we just landed a batch of improvements to URL handling and base tag manipulation.

Improved URL handling

Supported URL types

At the outset of this process, we outlined the range of paths we needed to support out of the box:

Absolute

  • http://company.com/
  • http://company.com/dir1/dir2/
  • http://company.com/dir1/dir2/foo.html
  • http://company.com:8080/
  • http://company.com:8080/dir1/dir2/
  • http://company.com:8080/dir1/dir2/foo.html
  • file:///foo.html
  • file:///dir1/dir2/foo.html
  • file:///C:/foo.html
  • file:///C:/dir1/dir2/foo.html

Protocol Relative

  • //company.com/
  • //company.com/foo.html
  • //company.com/dir1/dir2/
  • //company.com/dir1/dir2/foo.html

Site Relative

  • /
  • /foo.html
  • /dir1/dir2/
  • /dir1/dir2/foo.html

Document Relative

  • foo.html
  • dir1/dir2/
  • dir1/dir2/foo.html
  • ../../
  • ../../foo.html
  • ../../dir1/dir2/foo.html

Query Relative Example

  • ?a=1&b=2&c=3

There are a number of factors involved in loading files in jQuery Mobile. The framework essentially listens for normal link clicks and form submissions and automates them through Ajax instead of regular HTTP, which allows us to support page transitions as the user navigates a site. Path handling within jQuery mobile is one of the most complex parts of the framework because it needs to handle the wide array of paths that a browser may encounter and seamlessly resolve the page and all it’s dependencies (images, stylesheets, scripts, etc) and also needs to work well with file:// URLs for installed applications.

This week’s re-factor now covers all these path types and includes robust unit test coverage to ensure we avoid regressions moving forward.

Base Tag fixes

The Ajax navigation system loads multiple “pages” into the DOM of the starting page. Each of these pages loaded in could live in completely different directories on the server so the paths of links, forms, images, scripts and styles of each page need to be dynamically set so everything “just works”.

To do this, when the initial jQuery Mobile document is loaded, the navigation code checks for an existing base tag, and if one does not exist, the framework injects one and sets its @href to path for the current document.

When the user clicks on a link to load a page, the framework uses Ajax to load the content, then sets the base tag’s @href attribute to the URL of the page it just loaded. It must do this prior to injecting the HTML source into the document so that any relative links or image paths get resolved relative to the new page’s directory path.

There is a twist to this though. The new page could have a @data-url attribute defined, and the value of that attribute should be used as the base for any content related @href and @src attributes. The path used for the base tag could be either the value of a data-url OR the URL used to load the page so we needed to seamlessly support both scenarios.

When upgrading to the forthcoming beta 1, there’s no changes needed to take advantage of these URL and base tag improvements. For developers who have more complex URL scenarios or are using tools like PhoneGap for installed apps, these will be welcome additions.

Please help us test these navigation changes! We’d appreciate getting feedback in the next few days on these important changes so please submit any issues you find into the GitHub tracker. See instructions at the end of this post for dropping in the latest builds from the CDN into your project for testing purposes.

Beta 1: Coming soon

We know many of you are eagerly awaiting the first beta release and we’re happy to announce that we’re very close to this important milestone. The team is targeting a release within the next week and are just waiting for the community to test the latest batch of navigation changes before releasing beta 1.

We are targeting second beta for July and 1.0 later in August. In beta 2, we will be tackling smoother page transitions, page caching and pre-loading and lots of bug and performance tweaks.

Nested lists: A note of caution

When we first created the list views in jQuery Mobile, we added support for nested lists that would automatically create “pages” for each level of the list and link them all together. It was one of those “wow” features that was both elegant semantically and an accelerator for developers.

However, we’ve been seeing some developers use nested lists as a mechanism for building major portions of their sites, including embedded forms and pages of content and we wanted to weigh in on how these can best be used. Over-using nested lists, especially for embedding forms or content views, has a number of drawbacks:

  • You have little control over styling, header bar, or other page content in nested lists because the child pages are generated dynamically. You can set the theme of the bar and the title is generated by the name of the node but there is no built-in way to add logos, navigation buttons or other features to the page. To support this, we’d need to include a templating system and that is too heavy for this simple feature. To have full control of each page, use separate pages and link them together.
  • Serving the full tree of list nodes results in heavier pages that include views that may never need to be displayed. It’s understandable that devs use nested lists to avoid seeing the Ajax loader on every click but bandwidth and memory are very limited on mobile devices. We recommend building separate HTML documents for each view and taking advantage of the Ajax navigation to pull in pages on demand. We’re planning on adding a feature that will allow you to preload pages which should help developers deliver the most lightweight page possible, then lazy-load commonly accessed pages from there.
  • Embedding forms or complex content formatting in a nested list node can result in a very confusing user experience for C-grade browsers or users with JavaScript disabled. Always view your nested listview in raw markup form on a mobile device to ensure that it is easy to navigate and logically organized.
  • Listviews with a lot of nodes or nested levels can be slow to render and use. In general, more than 100-200 listview nodes can result in slow performance on older or underpowered devices. Nested listviews are even more taxing on a device because the framework needs to parse the list levels and dynamically create pages for each level. We recommend breaking these into separate pages yourself to speed initialization time up considerably.
  • From a semantic perspective, nested lists are only appropriate for a limited number of situations. Specifically, presenting hierarchical, drillable lists. A list of email accounts followed by folders for each is a good use of nested lists, but placing richly formatted listviews for each the message lists is definitely overkill and won’t view cleanly in non-enhanced devices.

The nested list feature, although cool, is something we’d like to discourage using because of the drawbacks listed above. In general, we would like to encourage developers to use separate pages instead of nested lists and rely on the Ajax navigation system to pull in nodes as needed. This will always be the most lightweight approach because you’re only serving the minimal amount of markup needed at a given time.

We’ve discussed deprecating this feature at some point in the future because the same effect can be achieved with better performance and extensibility with our standard page model. We’re looking for feedback from the community on how to proceed so chime in below in the comments.

jQuery Mobile tutorials

Jorge Ramon has pulled together a nice Roundup of jQuery Mobile tutorials. Some good reads!

jQuery Mobile weekly team meeting

Join us at our new day and time: Thursdays at 2:00pm EST on #jquery-meeting on freenode.net to listen to the team meeting

Notable commits

Nested lists with same parent text resolve to the same sub-page (issue #1617) – Created a unique ID for each nested list to avoid naming collisions.

Fixed binding of orientationchange event – Fixed by switching to window and moving from bind to live. Thanks bestform!

Select menu options not visible in desktop Safari (issue 1717) – Fixed by setting the text-indent property on options to make Safari happy

Child grouped collapsibles close their parent (issue 1387) – Adjusted events to prevent collapsing from happening when interacting with child collapsibles

Form errors with Ajax disabled – Fixed cases where jqmData(ajax=’false’) might also match forms, which have neither of “src” or “href”. In that case, thisUrl is undefined, and the following replace results in an error. Thanks frietsch!

Get the latest builds on the jQuery CDN

To take advantage of the daily improvements happening in jQuery Mobile, be sure to check out out the new daily and latest builds that are now available on the jQuery CDN for hotlinking. This allows you to upgrade to the latest code without waiting for the next official release.

Here are the three files to include in the head of your page to always be viewing the latest in Git:

<link href="http://code.jquery.com/mobile/latest/jquery.mobile.min.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script src="http://code.jquery.com/mobile/latest/jquery.mobile.min.js"></script>

 

Please keep in mind that this the unstable, development version so we don’t recommend linking to the latest in a production site or app but it’s great for development and testing.

 

21 thoughts on “Development Update – Week of June 13, 2011

  1. Sindre Sorhus on said:

    Wow, must say, jQM is coming along nicely!

    Can’t wait for 1.0.

    About the nested list feature. I think it’s really handy for specifying additonal details quickly, without having to create separate pages. I don’t think noobproofing is the way to go here. The feature is clearly a useful shortcut if you know what you’re doing. Someone wil always find a way to misuse the code whatever you do to prevent it, just look at most jQuery code on StackOverflow. I’m not saying the feature should stay, only that you should not base your decision on whether it can be misused.

  2. Todd Parker on said:

    @Sindre – Thanks! And we agree that we want to give this a lot of thought before making and decisions on nested lists.

    @Johan – Since the pages all all built with real links that are hijacked for Ajax, they are already 100% crawlable without the need for the dreaded hashbang.

    Thanks for the comments!

  3. Dustin on said:

    For some reason when I switch to the new release the pages no longer load with a zoomed in viewport. But it loads fine with the 1.0a4 version

  4. Jay Rizzi on said:

    Call me noob if you want @sindre im trying to learn jqm, and currently am writing my app to dynamically create pages / nested lists onload from server script array query

    So, i would like to learn, For those of us who do want their jqm apps to be MVC type web solutions, and are using ajax+server side scripting to dynamically create content, whats the best way to approach this? Break the jqm site into many parts , and call scripts onClick rather than onLoad? I was doing that during my first iteration, and was having great difficulty due to the MVC framework and jqm conflicting on GET navigation

    Like i said , probably am a “noob” but i don’t care, any guidance on best practices would be much appreciated

    • Todd Parker on said:

      @Jay – You can use a multi-page document setup that contains as many pages in a singel HTML document as you like. The nested list script essentially just auto-creates these multiple pages for you and links them but if you’re creating complex page layouts within the nodes of your list, the multi-page system is a better way to go.
      http://jquerymobile.com/test/docs/pages/docs-pages.html

    • Sindre Sorhus on said:

      @Brent No, that’s a typo. The 1 should be unquoted.

      See the source of the demo to see how it should look like.

      • Brent on said:

        Yep, cool. That’s what I thought.

        meta name="viewport" content="width=device-width, initial-scale=1"

        Hey, are you thinking of integrating elements from Mobile Boilerplate by chance? Overkill, too much overlap? What are your thoughts on it?

        http://html5boilerplate.com/mobile/

        thx.

        • Sindre Sorhus on said:

          How exactly would it be integrated?

          jQM does not define any HTML by default. It’s up to you to define the structure of your page. You can use both jQM and mobile boilerplate together. The boilerplate is just a foundation to build upon. I would actually recommend using it since it will make your life easier by fixing inconsistencies and optimizing performance.

      • Todd Parker on said:

        Thanks for pointing out that issues with the blog post. I think that syntax may still be correct because the attributes were quoted within but the unquoted version is a lot simpler to understand so I changed it to match the demo pages.

  5. Mark Dalgleish on said:

    I agree with Sindre. Nested lists, like anything else, can be abused. However, I believe that deprecating them because of this fact would be a mistake. I find nested lists to be one of the most impressive parts of jQuery Mobile in day-to-day usage and I’d hate to see them go.

    More blog posts, like this one, and warnings in the documentation outlining best practices would be a better way forward. You’ll want to make sure beginners don’t use nested lists as a crutch too early, saving them from having to undo the damage later on. At the same time, you’ll want to allow seasoned jQuery Mobile developers to use nested lists appropriately, understanding the implications of their design choice.

    Keep up the great work with jQuery Mobile, I’m really looking forward to the beta release.

    • Todd Parker on said:

      @Mark – I think your comments pretty much summarize our thinking. Education and open discussions about the direction of the library are really important so you can bet that we’ll continue doing blog posts like this. Based on what I’ve heard so far, leaving nested lists as-is but beefing up the docs to explain the pros and cons is probably the way we’ll go.

  6. > In beta 2, we will be tackling smoother page transitions

    That’s good to hear! I hope this includes eliminating the jumping-to-the-top-of-the-page before the actual transition. Everybody to whom I showed the application that I’m working on pointed out that the page transitions look weird. They all expected the page to slide/fade/etc. right away without jumping to the top first, and when getting back in history the previous page needs to be at exactly the same position right away where they left it.
    Hope this is part of the tackling. 🙂

  7. btw: The same goes for dialogs (the page that opens a dialog needs to remain at the same scrolling position). 😉

  8. About the Back button being off by default now, I think you kinda forgot that alot of people add their favorite website to their Homescreen to have a better display/faster access. Then the native back button isnt avalaible anymore, so I hope you arent considering removing the Back button at some point later or stopping supporting it at all.

  9. We are using the list views to display a tree type structure for navgigation an instrument list (mobile trading app). So the initial page, loads the top 5 nodes, as the user clicks on an item, we dynamically generate a new page from data stored in a json object.

    Everything worked fine in 4a, now with the latest build I get an error:

    Uncaught TypeError: Cannot read property ‘jQuery1610060484680347144604’ of undefined

    from this line:


    _createSubPages: function() {
    var c = this.element, b = c.closest(".ui-page"), e = b.jqmData("url"), f = e || b[0][a.expando], g = c.attr("id"), j = this.options, h = "data-" + a.mobile.ns, m = b.find(":jqmData(role='footer')").jqmData("id");

  10. jersey shore season 1 episode 6 on said:

    Hi! Nice post. I learn something more challenging on different blogs everyday. It will always be stimulating to read content from other writers and practice a little something from their store. I’d prefer to use some with the content on my blog whether you don’t mind. Natually I’ll give you a link on your web blog. Thanks for sharing.

  11. James Scott on said:

    @gav – I was experiencing a similar problem. It was happening because the createSubPages function is looking for the nearest element with the class ‘ui-page’ to the element that I was creating and about to inject (in my case a list that I had called .listview() on). I got round it by appending the list to the page first and then calling .listview().