jQuery Mobile 1.4 Upgrade Guide


link Introduction

This guide will assist you with upgrading from jQuery Mobile 1.3 to 1.4. It also prepares you for 1.5 by informing you about deprecated features. See the changelog for a list of all changes and new features.

link Supported platforms

(60aa05b) In previous versions A-grade support was based on whether a browser supports media queries and added Internet Explorer 7 and 8. As from 1.4 we also test for pseudo element support, because we use :after for icons. This means Internet Explorer 7 and Blackberry OS 5 are now C-grade.

link Theming

link Default theme

(8abb930) The default theme has been replaced and the new theme has two swatches, A (light) and B (dark). To keep using similar colors as the previous default theme you have to change the value you set for the theme option (data-theme="*").

link Light

To have a widget using a light swatch set theme A instead of C or D.

Old:

1
2
3
<ul data-role="listview" data-theme="d">
<li>List item</li>
</ul>

New:

1
2
3
<ul data-role="listview" data-theme="a">
<li>List item</li>
</ul>

link Dark

To have a widget using a dark swatch set theme B instead of A.

Old:

1
2
3
<ul data-role="listview" data-theme="a">
<li>List item</li>
</ul>

New:

1
2
3
<ul data-role="listview" data-theme="b">
<li>List item</li>
</ul>

Be aware of changes in the default values (see Option theme below) before upgrading your theme.

The blue and yellow swatches didn't return in the new default theme. You can use the ThemeRoller to create a complete custom theme or to add swatches to the default theme.

(abf1d0f) For convenience we updated the 1.3 default theme to 1.4 and added it as "classic" theme to the demos.

link Custom theme

When upgrading to 1.4 you have to replace your custom theme file. The easiest way to upgrade your 1.3 custom theme is by uploading it in the ThemeRoller and download it as 1.4 theme.

link Gradients

Because gradients are no longer part of the default theme, they can't be set with the ThemeRoller anymore either. You can still use gradients, but you have to manually copy the background-image settings from your current theme into your 1.4 theme CSS file.

Example:

1.3 custom theme:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.ui-body-a,
.ui-overlay-a {
border: 1px solid #111 /*{a-body-border}*/;
background: #333 /*{a-body-background-color}*/;
color: #fff /*{a-body-color}*/;
text-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ #111 /*{a-body-shadow-color}*/;
font-weight: normal;
background-image: -webkit-gradient(linear, left top, left bottom, from( #444 /*{a-body-background-start}*/), to( #222 /*{a-body-background-end}*/)); /* Saf4+, Chrome */
background-image: -webkit-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* Chrome 10+, Saf5.1+ */
background-image: -moz-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* FF3.6 */
background-image: -ms-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* IE10 */
background-image: -o-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* Opera 11.10+ */
background-image: linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/);
}

1.4 custom theme:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.ui-body-a,
.ui-page-theme-a .ui-body-inherit,
html .ui-bar-a .ui-body-inherit,
html .ui-body-a .ui-body-inherit,
html body .ui-group-theme-a .ui-body-inherit,
html .ui-panel-page-container-a {
background: #333 /*{a-body-background-color}*/;
border-color: #111 /*{a-body-border}*/;
color: #fff /*{a-body-color}*/;
text-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ #111 /*{a-body-shadow-color}*/;
/* Copied from 1.3 custom theme: */
background-image: -webkit-gradient(linear, left top, left bottom, from( #444 ), to( #222 )); /* Saf4+, Chrome */
background-image: -webkit-linear-gradient( #444, #222 ); /* Chrome 10+, Saf5.1+ */
background-image: -moz-linear-gradient( #444, #222 ); /* FF3.6 */
background-image: -ms-linear-gradient( #444, #222 ); /* IE10 */
background-image: -o-linear-gradient( #444, #222 ); /* Opera 11.10+ */
background-image: linear-gradient( #444, #222 );
}

link New styles

Compared to previous versions there are two new styles that you can specify in the theme CSS. You don't need to make any changes in your markup. The information in this section is just to make you aware of the possibility to use different styles.

link Page style

(7ae930a) Pages get theme class ui-page-theme-*, where * is the value (a-z) of the option theme. This used to be ui-body-*. When you use the ThemeRoller to upgrade your 1.3 custom theme, it will initially use the same color for the page style as the one you specified for the body style. You can customize the colors to create contrast between the page and body styled elements like read-only list items and collapsible content.

link Active and focus style for each swatch

(#3750, 3cc45ef) The active and focus state used to use one global style, but they are now themeable. When you use the ThemeRoller to upgrade your 1.3 custom theme, it will initially use the 1.3 global active and focus color for all swatches. You can customize this for each swatch.

link Override with custom CSS

When you are using custom CSS to override styles that are defined in the theme CSS you might have to change your selectors to take the following changes into account:

  • We now use pseudo classes for button hover (:hover) and down (:active) state
  • The level of specificity of many selectors has been increased due to a switch from JS to CSS for theme inheritance

Example custom button hover style:

Old:

1
2
3
4
5
6
7
8
9
/* Default: */
.ui-btn-hover-a {
/* Button hover style */
}
/* Override: */
.ui-mobile .ui-btn-hover-a {
/* Custom button hover style */
}

New:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* Default: */
.ui-page-theme-a .ui-btn:hover,
html .ui-bar-a .ui-btn:hover,
html .ui-body-a .ui-btn:hover,
html body .ui-group-theme-a .ui-btn:hover,
html head + body .ui-btn.ui-btn-a:hover {
/* Button hover style */
}
/* Override: */
.ui-mobile .ui-btn.ui-btn-a:hover {
/* Custom button hover style */
}

link Option theme

(98b90c3) We changed the default for option theme in some widgets. The general rule is now that all themeable components inherit the theme swatch from their container. This is done via CSS. If there is no container for which a theme has been specified, the page theme will be used. This now defaults to theme A. Because widgets don’t have a default theme specified anymore, you must set option theme if you use widgets outside a page.

Changes in the defaults:

  • Page: C → A
  • Loader: E → A
  • Header and Footer toolbars: A → inherit
  • Listview dividers: B → inherit
  • Listview count bubbles: C → inherit
  • Panels: C → inherit

For example, if you are using the default theme and don’t set a theme for the page and the header inside that page:

  • The page was using theme swatch C (light) and will now use theme swatch A (light) - No changes needed.
  • The header was using theme swatch A (dark) and will now inherit theme swatch A (light) from the page - You have to set the header to theme B (dark) to keep the same style.

link Buttons

(c747016) Button styled elements used to get enhanced by the buttonMarkup method, which generated the ui-btn-inner and ui-btn-text elements. In 1.4 those inner elements are no longer generated and there are no calls to buttonMarkup() from other widgets anymore.

Example:

1
<button>Button</button>

Old enhanced markup:

1
2
3
4
5
6
<div data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" data-theme="c" data-disabled="false" class="ui-btn ui-shadow ui-btn-corner-all ui-btn-up-c" aria-disabled="false">
<span class="ui-btn-inner">
<span class="ui-btn-text">Button</span>
</span>
<button class="ui-btn-hidden" data-disabled="false">Button</button>
</div>

New enhanced markup:

1
<button class="ui-btn ui-shadow ui-corner-all">Button</button>

To style anchor or button elements as jQuery Mobile buttons add the applicable classes to your markup, instead of data- attributes.

  • data-role="button" → class="ui-btn"
  • data-theme="a" → class="ui-btn-a" (replace "a" by the actual theme swatch letter that you want to use)
  • data-corners="true" → class="ui-corner-all"
  • data-shadow="true" → class="ui-shadow"
  • data-mini="true" → class="ui-mini"
  • data-icon="home" → class="ui-icon-home" (replace "home" by the actual name of the icon that you want to use)
  • data-iconpos="right" → class="ui-btn-icon-right" (replace "right" by the actual icon position that you want to use: right, left, top, or bottom)
  • data-iconshadow="true" → class="ui-shadow-icon"

Note that in cases where you didn't have to add the data- attribute because you used the default value, you do have to add the corresponding class.

Old:

1
<a href="#" data-role="button" data-theme="b" data-mini="true" data-icon="grid">Link button</a>

New:

1
<a href="#" class="ui-btn ui-corner-all ui-shadow ui-mini ui-btn-icon-right ui-icon-grid">Link button</a>

Only use the Button widget, and data- attributes, for input buttons. Input buttons don't have content so the widget generates a wrapper to make it possible to use the :after pseudo element for the icon.

link Icons

link Pseudo elements

(efc1f51) If you are using custom icons you have to change the selector in your icon background-image rules because we now use the :after pseudo element instead of generating a span with the icon class.

Old:

1
2
3
4
.ui-icon-myicon {
    background-image: url("path/to/your-icon.png");
    background-size: 18px 18px;
}

New:

1
2
3
4
.ui-icon-myicon:after {
    background-image: url("path/to/your-icon.png");
    background-size: 18px 18px;
}

link Alt and nodisc icons

(b180d3d) The alt (black instead of white) and nodisc (no background disc) icon classes have been renamed. Make the following changes in your markup:

  • class="ui-icon-alt"class="ui-alt-icon"
  • class="ui-icon-nodisc"class="ui-nodisc-icon"

Old:

1
2
3
<ul data-role="listview" class="ui-icon-alt ui-icon-nodisc">
<li>List item</li>
</ul>

New:

1
2
3
<ul data-role="listview" class="ui-alt-icon ui-nodisc-icon">
<li>List item</li>
</ul>

link Icon shadow

(4e864be) Icon shadow has been deprecated and in widgets that offer option iconShadow the default has been changed to false. If you want to keep using icon shadow (also in future versions) don’t set the option to true, but add class ui-shadow-icon to the button or its container.

Old:

1
<button data-icon="grid" data-iconshadow="true">Button</button>

New:

1
<button class="ui-btn ui-corner-all ui-shadow ui-btn-icon-left ui-icon-grid ui-shadow-icon">Button</button>

$.mobile.changePage and $.mobile.loadPage have been deprecated. Use the change and load methods of the new Pagecontainer widget instead.

Old:

1
$.mobile.changePage( "newpage.html", { transition: "slide" });

New:

1
$( "body" ).pagecontainer( "change", "newpage.html", { transition: "slide" });

$.mobile.activePage has been deprecated. Use the getActivePage method of the new Pagecontainer widget instead.

Old:

1
$.mobile.activePage();

New:

1
$( "body" ).pagecontainer( "getActivePage" );

The following page events have been deprecated. Use the corresponding event of the Page container widget instead.

  • pageshow
  • pagehide
  • pagebeforeload
  • pageload
  • pageloadfailed
  • pagechangefailed

Old:

1
2
3
$( document ).on( "pageshow", function( event, ui ) {
...
});

New:

1
2
3
$( document ).on( "pagecontainershow", function( event, ui ) {
...
});

The pageinit event has been deprecated as well. Bind to pagecreate instead.

Old:

1
2
3
$( document ).on( "pageinit", function() {
...
});

New:

1
2
3
$( document ).on( "pagecreate", function() {
...
});

link Widgets

link Initialization

link Standalone widgets

Many widgets (panel, popup, toolbar, etc.) can now be used outside/without a page (<div data-role="page">). However, when you use a widget outside a page you have to call the plugin yourself.

Example: If you use the same panel with a navmenu on all your pages you can put the markup outside the page and use $( ".myNavPanel" ).panel(); to call the plugin. There is no need to add the data-role="panel" attribute in your markup because that is used for auto initialization only.

link initSelector

(cbe643f) Option initSelector has been removed from widgets because you don’t need to set this for every instance of the widget, but you can still configure it.

Example: If you want to initialize the listview plugin for all unordered lists instead of only the ones with data-role="listview":

1
2
3
$( document ).on( "mobileinit", function() {
$.mobile.listview.prototype.initSelector = "ul";
});

Note: Always bind handlers to the mobileinit event before jQuery Mobile JS is loaded!

link enhanceWithin

(0e61e08) .trigger( "create" ) has been deprecated. You can use the new method .enhanceWithin() instead. For example, if you dynamically add a collapsible with an ul with data-role="listview" inside, you could use .enhanceWithin() to initialize the listview plugin.

1
2
3
4
5
6
<div id="mycollapsible">
<h1>Heading</h1>
<ul data-role="listview">
<li>List item</li>
</ul>
</div>

Old:

1
$( "#mycollapsible" ).collapsible().trigger( "create" );

New:

1
$( "#mycollapsible" ).collapsible().enhanceWithin();

However, for performance reasons we recommend to call each plugin directly.

1
2
3
4
5
6
<div id="mycollapsible">
<h1>Heading</h1>
<ul id="mylistview">
<li>List item</li>
</ul>
</div>
1
2
$( "#mycollapsible" ).collapsible();
$( "#mylistview" ).listview();

link Using defaults

(c56bc51) You can now add data-defaults="true to tell the widget to use the default values for all options. Retrieving option values from data- attributes will be skipped, which improves startup performance.

Example:

1
2
3
4
<div data-role="collapsible" data-defaults="true">
<h2>Header</h2>
<p>Content.</p>
</div>

link Added enhanced option

Most widgets now have an option enhanced. This allows you to write the markup yourself to improve performance. The default for the option is always false and like most options it is also exposed as data- attribute (data-enhanced). When you set it to true the widget won't do any DOM manipulation at all during enhancement, so you have to make sure all classes and DOM nodes are already present.

Widgets that don't have option enhanced (yet) are: Listview, Selectmenu, Panel, Toolbar, Navbar, and Slider.

Example of using option enhanced with the button widget:

Normal:

1
2
3
4
<form>
<label for="myinput">Button label:</label>
    <input type="button" id="myinput" data-icon="delete" value="Button text">
</form>

Enhanced:

1
2
3
4
5
6
7
<form>
<label for="myinput">Button label:</label>
    <div class="ui-input-btn ui-btn ui-icon-delete ui-btn-icon-left ui-corner-all ui-shadow">
        Button text
        <input type="button" id="myinput" data-enhanced="true" value="Button text">
    </div>
</form>

link Page and Dialog

link Deprecated Dialog widget, added page option dialog

(173a101) Instead of adding data-rel="dialog" to the page anchor link, set page option dialog to true. You can do this by adding data-dialog="true" to the page that you want to be styled as dialog.

To use a pop transition for the dialog, you have to explicitly set the transition. Otherwise the default page transition (fade) will be used.

Old:

1
2
3
<div data-role="page" id="my-dialog-page">
<h1>My dialog page</h1>
</div>
1
<a href="#my-dialog-page" data-rel="dialog">Opens dialog page with default pop transition</a>

New:

1
2
3
<div data-role="page" data-dialog="true" id="my-dialog-page">
<h1>My dialog page</h1>
</div>
1
<a href="#my-dialog-page" data-transition="pop">Opens dialog page with pop transition</a>

link Content

data-role="content" has been deprecated, add class ui-content and (if applicable) role="main" instead. Using data-theme for the content element has been deprecated as well. We don't recommend using a theme for the content, also not by adding a ui-body-* class, because there can be a gap between the bottom of the content and the bottom of the page.

Old:

1
2
<div data-role="content">
</div>

New:

1
2
<div class="ui-content" role="main">
</div>

link Toolbars

(c51fe84) Headers and footers are now using the new Toolbar widget. When you are using the "add back button" feature, all related data- attributes (data-add-back-btn, etc.) should be added to the header element, instead of the page.

Old:

1
2
3
4
5
6
7
8
9
<div data-role="page" data-add-back-btn="true" data-back-btn-text="Go back" data-back-btn-theme="b">
<div data-role="header">
<h1>Header</h1>
</div>
<div data-role="footer">
<h4>Footer</h4>
</div>
</div>

New:

1
2
3
4
5
6
7
8
9
<div data-role="page">
<div data-role="header" data-add-back-btn="true" data-back-btn-text="Go back" data-back-btn-theme="b">
<h1>Header</h1>
</div>
<div data-role="footer">
<h4>Footer</h4>
</div>
</div>

link Collapsible

(#5271, fe60da4) .trigger( "expand|collapse" ) no longer works. Use the new expand and collapse methods instead.

Old:

1
$( "#mycollapsible" ).trigger( "expand" );

New:

1
$( "#mycollapsible" ).collapsible( "expand" );

(63dd22f) The content of a collapsible now inherits the theme from a parent container by default. Set contentTheme to false (data-content-theme="false") to have a collapsible without content theme.

Old:

1
2
3
4
<div data-role="collapsible">
<h1>Heading</h1>
<div>Content without background and border</div>
</div>

New:

1
2
3
4
<div data-role="collapsible" data-content-theme="false">
<h1>Heading</h1>
<div>Content without background and border</div>
</div>

link Field containers

(3650c85) data-role="fieldcontain" has been deprecated. Add class ui-field-contain instead.

Old:

1
2
3
4
<div data-role="fieldcontain">
    <label for="mytextinput">Text input:</label>
    <input type="text" name="mytextinput" id="mytextinput" value="">
</div>

New:

1
2
3
4
<div class="ui-field-contain">
    <label for="mytextinput">Text input:</label>
    <input type="text" name="mytextinput" id="mytextinput" value="">
</div>

link Listview

(78cb933) When you are using custom CSS or JS with listviews you might have to update selectors that target list items or their contents. The widget no longer adds the classes ui-li, ui-li-heading, and ui-li-desc and there are no generated elements inside list items anymore.

Example:

1
2
3
4
5
6
7
8
<ul data-role="listview" data-theme="b">
<li>
<a href="#">
<h2>Title</h2>
<p>Description</p>
</a>
</li>
</ul>

Old enhanced markup:

1
2
3
4
5
6
7
8
9
10
11
12
13
<ul data-role="listview" data-theme="b" class="ui-listview">
<li data-corners="false" data-shadow="false" data-iconshadow="true" data-wrapperels="div" data-icon="arrow-r" data-iconpos="right" data-theme="b" class="ui-btn ui-btn-icon-right ui-li-has-arrow ui-li ui-first-child ui-last-child ui-btn-up-b">
<div class="ui-btn-inner ui-li">
<div class="ui-btn-text">
<a href="#" class="ui-link-inherit">
<h2 class="ui-li-heading">Title</h2>
<p class="ui-li-desc">Description</p>
</a>
</div>
<span class="ui-icon ui-icon-arrow-r ui-icon-shadow">&nbsp;</span>
</div>
</li>
</ul>

New enhanced markup:

1
2
3
4
5
6
7
8
<ul data-role="listview" data-theme="b" class="ui-listview ui-group-theme-b">
<li class="ui-first-child ui-last-child">
<a href="#" class="ui-btn ui-btn-icon-right ui-icon-carat-r">
<h2>Title</h2>
<p>Description</p>
</a>
</li>
</ul>

link Images

(ed89730, #6321, 0479daa) The auto-detection of images in list items has been deprecated to improve performance and small 16x16 images on the left (ui-li-icon) has been deprecated as feature.

  • When you use a thumbnail: Add class ui-li-has-thumb to the list item. Note: The framework no longer adds class ui-li-thumb to the img element.
  • When you want to use a smaller image: Do the same as described for thumbnails above and override the default width and height in your custom CSS.
  • When you want an element other than img (eg. a font icon) to be styled as thumbnail: Add class ui-li-has-thumb to the list item and class ui-li-thumb to the element.

Old:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul data-role="listview">
<li>
<img src="thumb.png">
List item with thumb on the left
</li>
<li>
<img src="smallimg.png" class="ui-li-icon">
List item with small image on the left
</li>
<li>
<div class="ui-li-thumb"></div>
List item with a div sized and positioned as thumb on the left
</li>
</ul>

New:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul data-role="listview">
<li class="ui-li-has-thumb">
<img src="thumb.png">
List item with thumb on the left
</li>
<li class="ui-li-has-thumb">
<img src="smallimg.png" style="max-width:16px; max-height:16px;">
List item with small image on the left
</li>
<li class="ui-li-has-thumb">
<div class="ui-li-thumb"></div>
List item with a div sized and positioned as thumb on the left
</li>
</ul>

link Filter

(b08bb6a) The filter extension has been deprecated in favor of the new Filterable widget. Add the filter input, wrapped in a form with class ui-filterable, to your markup and add the data-input attribute to the list to specify which input should be used to filter the list items.

Old:

1
2
3
4
5
<ul data-role="listview" data-filter="true">
    <li>List item 1</li>
    <li>List item 2</li>
    <li>List item 3</li>
</ul>

New:

1
2
3
4
5
6
7
8
<form class="ui-filterable">
    <input id="filter-input" data-type="search">
</form>
<ul data-role="listview" data-filter="true" data-input="#filter-input">
    <li>List item 1</li>
    <li>List item 2</li>
    <li>List item 3</li>
</ul>

link Panel

(4ebc70b) The properties and values of option classes have been changed. The CSS has been updated to use the new default values as classnames in the selectors.

  • pagePanel: "ui-page-panel" (class was added to the page) → pageContainer: "ui-panel-page-container" (class added to the page container)

  • pagePanelOpen: "ui-page-panel-open" → no longer used

  • contentWrap: "ui-panel-content-wrap"pageWrapper: "ui-panel-wrapper"

  • contentFixedToolbar: "ui-panel-content-fixed-toolbar"pageFixedToolbar: "ui-panel-fixed-toolbar"

  • contentWrapOpen: "ui-panel-content-wrap-open"pageContentPrefix: "ui-panel-page-content"

  • contentFixedToolbarOpen: "ui-panel-content-fixed-toolbar-open"pageContentPrefix: "ui-panel-page-content"

  • contentWrapClosed: "ui-panel-content-wrap-closed" → no longer used

  • contentFixedToolbarClosed: "ui-panel-content-fixed-toolbar-closed" → no longer used

Note: pageContentPrefix: "ui-panel-page-content" is also used as prefix for the display (reveal, overlay, push) and position (left, right) classes.

link Slider

(d4388f9) The Slider flip toggle switch has been deprecated. Use the new Flipswitch widget instead.

Old:

1
2
3
4
5
6
7
<form>
    <label for="switch">Switch:</label>
    <select id="switch" name="switch" data-role="slider">
        <option value="off">Off</option>
        <option value="on">On</option>
    </select>
</form>

New:

1
2
3
4
5
6
7
<form>
    <label for="switch">Switch:</label>
    <select id="switch" name="switch" data-role="flipswitch">
        <option>Off</option>
        <option>On</option>
    </select>
</form>

Note: You can also use a checkbox input with the new flipswitch widget.