jQuery Mobile is a jQuery project framework that encourages the design of ubiquitous web applications that work both on popular mobile devices and platforms and on the desktop. Rather than writing unique applications for each device or OS, we simply write the code once, and it should ideally run on many of the A-, B- and C-grade browsers out there at the moment.
The fundamentals behind jQuery Mobile can also be applied to plug-in and widget development.
Whatâs interesting in this next pattern is that although there are small, subtle differences in writing a âmobileâ-optimized widget, those familiar with using the jQuery UI Widget Factory pattern from earlier should be able to grasp this in next to no time.
The mobile-optimized widget below has a number of interesting differences than the standard UI widget pattern we saw earlier:
$.mobile.widget
is referenced as an existing widget prototype from which to inherit. For standard widgets, passing through any such prototype is unnecessary for basic development, but using this jQuery-mobile specific widget prototype provides internal access to further âoptionsâ formatting.In
_create()
, a guide is provided on how the official jQuery Mobile widgets handle element selection, opting for a role-based approach that better fits the jQM mark-up. This isnât at all to say that standard selection isnât recommended, only that this approach might make more sense given the structure of jQuery Mobile pages.Guidelines are also provided in comment form for applying our plug-in methods on
pagecreate
as well as for selecting the plug-in application via data roles and data attributes.
/*!
* (jQuery mobile) jQuery UI Widget-factory plugin boilerplate (for 1.8/9+)
* Author: @scottjehl
* Further changes: @addyosmani
* Licensed under the MIT license
*/
;(
function
(
$
,
window
,
document
,
undefined
)
{
// define a widget under a namespace of our choice
// here "mobile" has been used in the first argument
$
.
widget
(
"mobile.widgetName"
,
$
.
mobile
.
widget
,
{
// Options to be used as defaults
options
:
{
foo
:
true
,
bar
:
false
},
_create
:
function
()
{
// _create will automatically run the first time this
// widget is called. Put the initial widget set-up code
// here, then we can access the element on which
// the widget was called via this.element
// The options defined above can be accessed via
// this.options
// var m = this.element,
// p = m.parents( ":jqmData(role="page")" ),
// c = p.find( ":jqmData(role="content")" )
},
// Private methods/props start with underscores
_dosomething
:
function
(){
...
},
// Public methods like these below can can be called
// externally:
// $("#myelem").foo( "enable", arguments );
enable
:
function
()
{
...
},
// Destroy an instantiated plug-in and clean up modifications
// the widget has made to the DOM
destroy
:
function
()
{
// this.element.removeStuff();
// For UI 1.8, destroy must be invoked from the
// base widget
$
.
Widget
.
prototype
.
destroy
.
call
(
this
);
// For UI 1.9, define _destroy instead and don't
// worry about calling the base widget
},
methodB
:
function
(
event
)
{
//_trigger dispatches callbacks the plug-in user can
// subscribe to
// signature: _trigger( "callbackName" , [eventObject],
// [uiObject] )
// e.g. this._trigger( "hover", e /*where e.type ==
// "mouseenter"*/, { hovered: $(e.target)});
this
.
_trigger
(
"methodA"
,
event
,
{
key
:
value
});
},
methodA
:
function
(
event
)
{
this
.
_trigger
(
"dataChanged"
,
event
,
{
key
:
value
});
},
// Respond to any changes the user makes to the option method
_setOption
:
function
(
key
,
value
)
{
switch
(
key
)
{
case
"someValue"
:
// this.options.someValue = doSomethingWith( value );
break
;
default
:
// this.options[ key ] = value;
break
;
}
// For UI 1.8, _setOption must be manually invoked from
// the base widget
$
.
Widget
.
prototype
.
_setOption
.
apply
(
this
,
arguments
);
// For UI 1.9 the _super method can be used instead
// this._super( "_setOption", key, value );
}
});
})(
jQuery
,
window
,
document
);
Usage:
var
instance
=
$
(
"#foo"
).
widgetName
({
foo
:
false
});
instance
.
widgetName
(
"methodB"
);
We can also self-initialize this widget whenever a new page in
jQuery Mobile is created. jQuery Mobileâs page
plug-in dispatches a create
event when a jQuery Mobile
page (found via the data-role="page"
attribute) is first initialized. We can listen for that event (called
pagecreate
) and run our plug-in automatically whenever
a new page is created.
$
(
document
).
on
(
"pagecreate"
,
function
(
e
)
{
// In here, e.target refers to the page that was created
// (it's the target of the pagecreate event)
// So, we can simply find elements on this page that match a
// selector of our choosing, and call our plug-in on them.
// Here's how we'd call our "foo" plug-in on any element with a
// data-role attribute of "foo":
$
(
e
.
target
).
find
(
"[data-role="
foo
"]"
).
foo
(
options
);
// Or, better yet, let's write the selector accounting for the configurable
// data-attribute namespace
$
(
e
.
target
).
find
(
":jqmData(role="
foo
")"
).
foo
(
options
);
});
We can now simply reference the script containing our widget and
pagecreate
binding in a page running
the jQuery Mobile site, and it will automatically run like any other
jQuery Mobile plug-in.
Get Learning JavaScript Design Patterns now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.