Disclaimer:

This article can also be found as a part of my blog HERE.

Intro:

There are several ways of enhancing dynamically created content markup. It is just not enough to dynamically add new content to jQuery Mobile page, new content must be enhanced with classic jQuery Mobile styling. Because this is rather processing heavy task there need to be some priorities, if possible jQuery Mobile needs to do as less enhancing as possible. Don't enhance whole page if only one component need's to be styled.

What does this all means? When page plugin dispatches a pageInit event, which most widgets use to auto-initialize themselves. it will automatically enhance any instances of the widgets it finds on the page.

However, if you generate new markup client-side or load in content via Ajax and inject it into a page, you can trigger the create event to handle the auto-initialization for all the plugins contained within the new markup. This can be triggered on any element (even the page div itself), saving you the task of manually initializing each plugin (listview button, select, etc.).

With this in mind lets discuss enhancement levels. There are three of them and they are sorted from the less resource demanding to higher ones:

Enhance a single component/widget Enhance a page content Enhance a full page content (header, content, footer)

Enhance a single component/widget:

Important: The below enhancement methods are to be used only on current/active page. For dynamically inserted pages, those pages and their contents will be enhanced once inserted into DOM. Calling any method on dynamically created pages / other than the active page, will result an error.

Every jQuery Mobile widget can be enhanced dynamically:

Enhance a page content:

In case we are generating/rebuilding whole page content it is best to do it all at once and it can be done with this:

$('#index').trigger('create');

Enhancement example: http://jsfiddle.net/Gajotres/426NU/

Enhance a full page content (header, content, footer):

Unfortunately for us trigger('create') can not enhance header and footer markup. In that case we need big guns:

$('#index').trigger('pagecreate');

Enhancement example: http://jsfiddle.net/Gajotres/DGZcr/

This is almost a mystic method because I can't find it in official jQuery Mobile documentation. Still it is easily found in jQuery Mobile bug tracker with a warning not to use it unless it is really really necessary.

Note, .trigger('pagecreate'); can suppose be used only once per page refresh, I found it to be untrue:

http://jsfiddle.net/Gajotres/5rzxJ/

3rd party enhancement plugins

There are several 3rd party enhancement plugins. Some are made as an update to an existing method and some are made to fix broken jQM functionalities.

Button text change Unfortunately cant found the developer of this plugin. Original SO source: Change button text jquery mobile (function($) { /* * Changes the displayed text for a jquery mobile button. * Encapsulates the idiosyncracies of how jquery re-arranges the DOM * to display a button for either an <a> link or <input type="button"> */ $.fn.changeButtonText = function(newText) { return this.each(function() { $this = $(this); if( $this.is('a') ) { $('span.ui-btn-text',$this).text(newText); return; } if( $this.is('input') ) { $this.val(newText); // go up the tree var ctx = $this.closest('.ui-btn'); $('span.ui-btn-text',ctx).text(newText); return; } }); }; })(jQuery); Working example: http://jsfiddle.net/Gajotres/mwB22/

Get correct maximum content height

In case page header and footer has a constant height content div can be easily set to cover full available space with a little css trick:

#content { padding: 0; position : absolute !important; top : 40px !important; right : 0; bottom : 40px !important; left : 0 !important; }

And here's a working example with Google maps api3 demo: http://jsfiddle.net/Gajotres/7kGdE/

This method can be used to get correct maximum content height, and it must be used with a pageshow event.

function getRealContentHeight() { var header = $.mobile.activePage.find("div[data-role='header']:visible"); var footer = $.mobile.activePage.find("div[data-role='footer']:visible"); var content = $.mobile.activePage.find("div[data-role='content']:visible:visible"); var viewport_height = $(window).height(); var content_height = viewport_height - header.outerHeight() - footer.outerHeight(); if((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) { content_height -= (content.outerHeight() - content.height()); } return content_height; }

And here's a live jsFiddle example: http://jsfiddle.net/Gajotres/nVs9J/

There's one thing to remember. This function will correctly get you maximum available content height and at the same time it can be used to stretch that same content. Unfortunately it cant be used to stretch img to full content height, img tag has an overhead of 3px.

Methods of markup enhancement prevention:

This can be done in few ways, sometimes you will need to combine them to achieve a desired result.

Method 1: It can do it by adding this attribute: data-enhance="false" to the header, content, footer container. This also needs to be turned in the app loading phase: $(document).one("mobileinit", function () { $.mobile.ignoreContentEnabled=true; }); Initialize it before jquery-mobile.js is initialized (look at the example below). More about this can be found here: http://jquerymobile.com/test/docs/pages/page-scripting.html Example: http://jsfiddle.net/Gajotres/UZwpj/ To recreate a page again use this: $('#index').live('pagebeforeshow', function (event) { $.mobile.ignoreContentEnabled = false; $(this).attr('data-enhance','true'); $(this).trigger("pagecreate") });

Method 2: Second option is to do it manually with this line: data-role="none" Example: http://jsfiddle.net/Gajotres/LqDke/

Method 3: Certain HTML elements can be prevented from markup enhancement: $(document).bind('mobileinit',function(){ $.mobile.page.prototype.options.keepNative = "select, input"; }); Example: http://jsfiddle.net/Gajotres/gAGtS/ Again initialize it before jquery-mobile.js is initialized (look at the example below).

Markup enhancement problems:

Sometimes when creating a component from scratch (like listview) this error will occur:

cannot call methods on listview prior to initialization

It can be prevented with component initialization prior to markup enhancement, this is how you can fix this:

$('#mylist').listview().listview('refresh');

Markup overrding problems:

If for some reason default jQuery Mobile CSS needs to be changed it must be done with !important override. Without it default css styles can not be changed.

Example:

#navbar li { background: red !important; }

jsFiddle example: http://jsfiddle.net/Gajotres/vTBGa/

Changes: