" ).html( $this.clone() ).html(),
// In IE browsers, the type sometimes doesn't exist in the cloned markup, so we replace the closing tag instead
hasType = html.indexOf( " type=" ) > -1,
findstr = hasType ? /\s+type=["']?\w+['"]?/ : /\/?>/,
repstr = " type=\"" + optType + "\" data-" + $.mobile.ns + "type=\"" + type + "\"" + ( hasType ? "" : ">" );
$this.replaceWith( html.replace( findstr, repstr ) );
}
});
});
})( jQuery );
(function( $, window, undefined ) {
$.widget( "mobile.dialog", $.mobile.widget, {
options: {
closeBtn: "left",
closeBtnText: "Close",
overlayTheme: "a",
corners: true,
initSelector: ":jqmData(role='dialog')"
},
// Override the theme set by the page plugin on pageshow
_handlePageBeforeShow: function() {
this._isCloseable = true;
if ( this.options.overlayTheme ) {
this.element
.page( "removeContainerBackground" )
.page( "setContainerBackground", this.options.overlayTheme );
}
},
_handlePageBeforeHide: function() {
this._isCloseable = false;
},
_create: function() {
var self = this,
$el = this.element,
cornerClass = !!this.options.corners ? " ui-corner-all" : "",
dialogWrap = $( "
", {
"role" : "dialog",
"class" : "ui-dialog-contain ui-overlay-shadow" + cornerClass
});
$el.addClass( "ui-dialog ui-overlay-" + this.options.overlayTheme );
// Class the markup for dialog styling
// Set aria role
$el.wrapInner( dialogWrap );
/* bind events
- clicks and submits should use the closing transition that the dialog opened with
unless a data-transition is specified on the link/form
- if the click was on the close button, or the link has a data-rel="back" it'll go back in history naturally
*/
$el.bind( "vclick submit", function( event ) {
var $target = $( event.target ).closest( event.type === "vclick" ? "a" : "form" ),
active;
if ( $target.length && !$target.jqmData( "transition" ) ) {
active = $.mobile.urlHistory.getActive() || {};
$target.attr( "data-" + $.mobile.ns + "transition", ( active.transition || $.mobile.defaultDialogTransition ) )
.attr( "data-" + $.mobile.ns + "direction", "reverse" );
}
});
this._on( $el, {
pagebeforeshow: "_handlePageBeforeShow",
pagebeforehide: "_handlePageBeforeHide"
});
$.extend( this, {
_createComplete: false
});
this._setCloseBtn( this.options.closeBtn );
},
_setCloseBtn: function( value ) {
var self = this, btn, location;
if ( this._headerCloseButton ) {
this._headerCloseButton.remove();
this._headerCloseButton = null;
}
if ( value !== "none" ) {
// Sanitize value
location = ( value === "left" ? "left" : "right" );
btn = $( "
"+ this.options.closeBtnText + "" );
this.element.children().find( ":jqmData(role='header')" ).first().prepend( btn );
if ( this._createComplete && $.fn.buttonMarkup ) {
btn.buttonMarkup();
}
this._createComplete = true;
// this must be an anonymous function so that select menu dialogs can replace
// the close method. This is a change from previously just defining data-rel=back
// on the button and letting nav handle it
//
// Use click rather than vclick in order to prevent the possibility of unintentionally
// reopening the dialog if the dialog opening item was directly under the close button.
btn.bind( "click", function() {
self.close();
});
this._headerCloseButton = btn;
}
},
_setOption: function( key, value ) {
if ( key === "closeBtn" ) {
this._setCloseBtn( value );
}
this._super( key, value );
},
// Close method goes back in history
close: function() {
var idx, dst, hist = $.mobile.navigate.history;
if ( this._isCloseable ) {
this._isCloseable = false;
// If the hash listening is enabled and there is at least one preceding history
// entry it's ok to go back. Initial pages with the dialog hash state are an example
// where the stack check is necessary
if ( $.mobile.hashListeningEnabled && hist.activeIndex > 0 ) {
$.mobile.back();
} else {
idx = Math.max( 0, hist.activeIndex - 1 );
dst = hist.stack[ idx ].pageUrl || hist.stack[ idx ].url;
hist.previousIndex = hist.activeIndex;
hist.activeIndex = idx;
if ( !$.mobile.path.isPath( dst ) ) {
dst = $.mobile.path.makeUrlAbsolute( "#" + dst );
}
$.mobile.changePage( dst, { direction: "back", changeHash: false, fromHashChange: true } );
}
}
}
});
//auto self-init widgets
$.mobile.document.delegate( $.mobile.dialog.prototype.options.initSelector, "pagecreate", function() {
$.mobile.dialog.prototype.enhance( this );
});
})( jQuery, this );
(function( $, undefined ) {
$.mobile.page.prototype.options.backBtnText = "Back";
$.mobile.page.prototype.options.addBackBtn = false;
$.mobile.page.prototype.options.backBtnTheme = null;
$.mobile.page.prototype.options.headerTheme = "a";
$.mobile.page.prototype.options.footerTheme = "a";
$.mobile.page.prototype.options.contentTheme = null;
// NOTE bind used to force this binding to run before the buttonMarkup binding
// which expects .ui-footer top be applied in its gigantic selector
// TODO remove the buttonMarkup giant selector and move it to the various modules
// on which it depends
$.mobile.document.bind( "pagecreate", function( e ) {
var $page = $( e.target ),
o = $page.data( "mobile-page" ).options,
pageRole = $page.jqmData( "role" ),
pageTheme = o.theme;
$( ":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')", $page )
.jqmEnhanceable()
.each(function() {
var $this = $( this ),
role = $this.jqmData( "role" ),
theme = $this.jqmData( "theme" ),
contentTheme = theme || o.contentTheme || ( pageRole === "dialog" && pageTheme ),
$headeranchors,
leftbtn,
rightbtn,
backBtn;
$this.addClass( "ui-" + role );
//apply theming and markup modifications to page,header,content,footer
if ( role === "header" || role === "footer" ) {
var thisTheme = theme || ( role === "header" ? o.headerTheme : o.footerTheme ) || pageTheme;
$this
//add theme class
.addClass( "ui-bar-" + thisTheme )
// Add ARIA role
.attr( "role", role === "header" ? "banner" : "contentinfo" );
if ( role === "header") {
// Right,left buttons
$headeranchors = $this.children( "a, button" );
leftbtn = $headeranchors.hasClass( "ui-btn-left" );
rightbtn = $headeranchors.hasClass( "ui-btn-right" );
leftbtn = leftbtn || $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
rightbtn = rightbtn || $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
}
// Auto-add back btn on pages beyond first view
if ( o.addBackBtn &&
role === "header" &&
$( ".ui-page" ).length > 1 &&
$page.jqmData( "url" ) !== $.mobile.path.stripHash( location.hash ) &&
!leftbtn ) {
backBtn = $( "
"+ o.backBtnText +"" )
// If theme is provided, override default inheritance
.attr( "data-"+ $.mobile.ns +"theme", o.backBtnTheme || thisTheme )
.prependTo( $this );
}
// Page title
$this.children( "h1, h2, h3, h4, h5, h6" )
.addClass( "ui-title" )
// Regardless of h element number in src, it becomes h1 for the enhanced page
.attr({
"role": "heading",
"aria-level": "1"
});
} else if ( role === "content" ) {
if ( contentTheme ) {
$this.addClass( "ui-body-" + ( contentTheme ) );
}
// Add ARIA role
$this.attr( "role", "main" );
}
});
});
})( jQuery );
(function( $, undefined ) {
// This function calls getAttribute, which should be safe for data-* attributes
var getAttrFixed = function( e, key ) {
var value = e.getAttribute( key );
return value === "true" ? true :
value === "false" ? false :
value === null ? undefined : value;
};
$.fn.buttonMarkup = function( options ) {
var $workingSet = this,
nsKey = "data-" + $.mobile.ns,
key;
// Enforce options to be of type string
options = ( options && ( $.type( options ) === "object" ) )? options : {};
for ( var i = 0; i < $workingSet.length; i++ ) {
var el = $workingSet.eq( i ),
e = el[ 0 ],
o = $.extend( {}, $.fn.buttonMarkup.defaults, {
icon: options.icon !== undefined ? options.icon : getAttrFixed( e, nsKey + "icon" ),
iconpos: options.iconpos !== undefined ? options.iconpos : getAttrFixed( e, nsKey + "iconpos" ),
theme: options.theme !== undefined ? options.theme : getAttrFixed( e, nsKey + "theme" ) || $.mobile.getInheritedTheme( el, "c" ),
inline: options.inline !== undefined ? options.inline : getAttrFixed( e, nsKey + "inline" ),
shadow: options.shadow !== undefined ? options.shadow : getAttrFixed( e, nsKey + "shadow" ),
corners: options.corners !== undefined ? options.corners : getAttrFixed( e, nsKey + "corners" ),
iconshadow: options.iconshadow !== undefined ? options.iconshadow : getAttrFixed( e, nsKey + "iconshadow" ),
mini: options.mini !== undefined ? options.mini : getAttrFixed( e, nsKey + "mini" )
}, options ),
// Classes Defined
innerClass = "ui-btn-inner",
textClass = "ui-btn-text",
buttonClass, iconClass,
hover = false,
state = "up",
// Button inner markup
buttonInner,
buttonText,
buttonIcon,
buttonElements;
for ( key in o ) {
if ( o[ key ] === undefined || o[ key ] === null ) {
el.removeAttr( nsKey + key );
} else {
e.setAttribute( nsKey + key, o[ key ] );
}
}
// Check if this element is already enhanced
buttonElements = $.data( ( ( e.tagName === "INPUT" || e.tagName === "BUTTON" ) ? e.parentNode : e ), "buttonElements" );
if ( buttonElements ) {
e = buttonElements.outer;
el = $( e );
buttonInner = buttonElements.inner;
buttonText = buttonElements.text;
// We will recreate this icon below
$( buttonElements.icon ).remove();
buttonElements.icon = null;
hover = buttonElements.hover;
state = buttonElements.state;
}
else {
buttonInner = document.createElement( o.wrapperEls );
buttonText = document.createElement( o.wrapperEls );
}
buttonIcon = o.icon ? document.createElement( "span" ) : null;
if ( attachEvents && !buttonElements ) {
attachEvents();
}
// if not, try to find closest theme container
if ( !o.theme ) {
o.theme = $.mobile.getInheritedTheme( el, "c" );
}
buttonClass = "ui-btn ";
buttonClass += ( hover ? "ui-btn-hover-" + o.theme : "" );
buttonClass += ( state ? " ui-btn-" + state + "-" + o.theme : "" );
buttonClass += o.shadow ? " ui-shadow" : "";
buttonClass += o.corners ? " ui-btn-corner-all" : "";
if ( o.mini !== undefined ) {
// Used to control styling in headers/footers, where buttons default to `mini` style.
buttonClass += o.mini === true ? " ui-mini" : " ui-fullsize";
}
if ( o.inline !== undefined ) {
// Used to control styling in headers/footers, where buttons default to `inline` style.
buttonClass += o.inline === true ? " ui-btn-inline" : " ui-btn-block";
}
if ( o.icon ) {
o.icon = "ui-icon-" + o.icon;
o.iconpos = o.iconpos || "left";
iconClass = "ui-icon " + o.icon;
if ( o.iconshadow ) {
iconClass += " ui-icon-shadow";
}
}
if ( o.iconpos ) {
buttonClass += " ui-btn-icon-" + o.iconpos;
if ( o.iconpos === "notext" && !el.attr( "title" ) ) {
el.attr( "title", el.getEncodedText() );
}
}
if ( buttonElements ) {
el.removeClass( buttonElements.bcls || "" );
}
el.removeClass( "ui-link" ).addClass( buttonClass );
buttonInner.className = innerClass;
buttonText.className = textClass;
if ( !buttonElements ) {
buttonInner.appendChild( buttonText );
}
if ( buttonIcon ) {
buttonIcon.className = iconClass;
if ( !( buttonElements && buttonElements.icon ) ) {
buttonIcon.innerHTML = " ";
buttonInner.appendChild( buttonIcon );
}
}
while ( e.firstChild && !buttonElements ) {
buttonText.appendChild( e.firstChild );
}
if ( !buttonElements ) {
e.appendChild( buttonInner );
}
// Assign a structure containing the elements of this button to the elements of this button. This
// will allow us to recognize this as an already-enhanced button in future calls to buttonMarkup().
buttonElements = {
hover : hover,
state : state,
bcls : buttonClass,
outer : e,
inner : buttonInner,
text : buttonText,
icon : buttonIcon
};
$.data( e, 'buttonElements', buttonElements );
$.data( buttonInner, 'buttonElements', buttonElements );
$.data( buttonText, 'buttonElements', buttonElements );
if ( buttonIcon ) {
$.data( buttonIcon, 'buttonElements', buttonElements );
}
}
return this;
};
$.fn.buttonMarkup.defaults = {
corners: true,
shadow: true,
iconshadow: true,
wrapperEls: "span"
};
function closestEnabledButton( element ) {
var cname;
while ( element ) {
// Note that we check for typeof className below because the element we
// handed could be in an SVG DOM where className on SVG elements is defined to
// be of a different type (SVGAnimatedString). We only operate on HTML DOM
// elements, so we look for plain "string".
cname = ( typeof element.className === 'string' ) && ( element.className + ' ' );
if ( cname && cname.indexOf( "ui-btn " ) > -1 && cname.indexOf( "ui-disabled " ) < 0 ) {
break;
}
element = element.parentNode;
}
return element;
}
function updateButtonClass( $btn, classToRemove, classToAdd, hover, state ) {
var buttonElements = $.data( $btn[ 0 ], "buttonElements" );
$btn.removeClass( classToRemove ).addClass( classToAdd );
if ( buttonElements ) {
buttonElements.bcls = $( document.createElement( "div" ) )
.addClass( buttonElements.bcls + " " + classToAdd )
.removeClass( classToRemove )
.attr( "class" );
if ( hover !== undefined ) {
buttonElements.hover = hover;
}
buttonElements.state = state;
}
}
var attachEvents = function() {
var hoverDelay = $.mobile.buttonMarkup.hoverDelay, hov, foc;
$.mobile.document.bind( {
"vmousedown vmousecancel vmouseup vmouseover vmouseout focus blur scrollstart": function( event ) {
var theme,
$btn = $( closestEnabledButton( event.target ) ),
isTouchEvent = event.originalEvent && /^touch/.test( event.originalEvent.type ),
evt = event.type;
if ( $btn.length ) {
theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
if ( evt === "vmousedown" ) {
if ( isTouchEvent ) {
// Use a short delay to determine if the user is scrolling before highlighting
hov = setTimeout( function() {
updateButtonClass( $btn, "ui-btn-up-" + theme, "ui-btn-down-" + theme, undefined, "down" );
}, hoverDelay );
} else {
updateButtonClass( $btn, "ui-btn-up-" + theme, "ui-btn-down-" + theme, undefined, "down" );
}
} else if ( evt === "vmousecancel" || evt === "vmouseup" ) {
updateButtonClass( $btn, "ui-btn-down-" + theme, "ui-btn-up-" + theme, undefined, "up" );
} else if ( evt === "vmouseover" || evt === "focus" ) {
if ( isTouchEvent ) {
// Use a short delay to determine if the user is scrolling before highlighting
foc = setTimeout( function() {
updateButtonClass( $btn, "ui-btn-up-" + theme, "ui-btn-hover-" + theme, true, "" );
}, hoverDelay );
} else {
updateButtonClass( $btn, "ui-btn-up-" + theme, "ui-btn-hover-" + theme, true, "" );
}
} else if ( evt === "vmouseout" || evt === "blur" || evt === "scrollstart" ) {
updateButtonClass( $btn, "ui-btn-hover-" + theme + " ui-btn-down-" + theme, "ui-btn-up-" + theme, false, "up" );
if ( hov ) {
clearTimeout( hov );
}
if ( foc ) {
clearTimeout( foc );
}
}
}
},
"focusin focus": function( event ) {
$( closestEnabledButton( event.target ) ).addClass( $.mobile.focusClass );
},
"focusout blur": function( event ) {
$( closestEnabledButton( event.target ) ).removeClass( $.mobile.focusClass );
}
});
attachEvents = null;
};
//links in bars, or those with data-role become buttons
//auto self-init widgets
$.mobile.document.bind( "pagecreate create", function( e ) {
$( ":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a, .ui-bar > :jqmData(role='controlgroup') > a", e.target )
.jqmEnhanceable()
.not( "button, input, .ui-btn, :jqmData(role='none'), :jqmData(role='nojs')" )
.buttonMarkup();
});
})( jQuery );
(function( $, undefined ) {
$.widget( "mobile.collapsible", $.mobile.widget, {
options: {
expandCueText: " click to expand contents",
collapseCueText: " click to collapse contents",
collapsed: true,
heading: "h1,h2,h3,h4,h5,h6,legend",
collapsedIcon: "plus",
expandedIcon: "minus",
iconpos: "left",
theme: null,
contentTheme: null,
inset: true,
corners: true,
mini: false,
initSelector: ":jqmData(role='collapsible')"
},
_create: function() {
var $el = this.element,
o = this.options,
collapsible = $el.addClass( "ui-collapsible" ),
collapsibleHeading = $el.children( o.heading ).first(),
collapsibleContent = collapsible.wrapInner( "
" ).children( ".ui-collapsible-content" ),
collapsibleSet = $el.closest( ":jqmData(role='collapsible-set')" ).addClass( "ui-collapsible-set" ),
collapsibleClasses = "";
// Replace collapsibleHeading if it's a legend
if ( collapsibleHeading.is( "legend" ) ) {
collapsibleHeading = $( "
"+ collapsibleHeading.html() +"
" ).insertBefore( collapsibleHeading );
collapsibleHeading.next().remove();
}
// If we are in a collapsible set
if ( collapsibleSet.length ) {
// Inherit the theme from collapsible-set
if ( !o.theme ) {
o.theme = collapsibleSet.jqmData( "theme" ) || $.mobile.getInheritedTheme( collapsibleSet, "c" );
}
// Inherit the content-theme from collapsible-set
if ( !o.contentTheme ) {
o.contentTheme = collapsibleSet.jqmData( "content-theme" );
}
// Get the preference for collapsed icon in the set, but override with data- attribute on the individual collapsible
o.collapsedIcon = $el.jqmData( "collapsed-icon" ) || collapsibleSet.jqmData( "collapsed-icon" ) || o.collapsedIcon;
// Get the preference for expanded icon in the set, but override with data- attribute on the individual collapsible
o.expandedIcon = $el.jqmData( "expanded-icon" ) || collapsibleSet.jqmData( "expanded-icon" ) || o.expandedIcon;
// Gets the preference icon position in the set, but override with data- attribute on the individual collapsible
o.iconpos = $el.jqmData( "iconpos" ) || collapsibleSet.jqmData( "iconpos" ) || o.iconpos;
// Inherit the preference for inset from collapsible-set or set the default value to ensure equalty within a set
if ( collapsibleSet.jqmData( "inset" ) !== undefined ) {
o.inset = collapsibleSet.jqmData( "inset" );
} else {
o.inset = true;
}
// Set corners for individual collapsibles to false when in a collapsible-set
o.corners = false;
// Gets the preference for mini in the set
if ( !o.mini ) {
o.mini = collapsibleSet.jqmData( "mini" );
}
} else {
// get inherited theme if not a set and no theme has been set
if ( !o.theme ) {
o.theme = $.mobile.getInheritedTheme( $el, "c" );
}
}
if ( !!o.inset ) {
collapsibleClasses += " ui-collapsible-inset";
if ( !!o.corners ) {
collapsibleClasses += " ui-corner-all" ;
}
}
if ( o.contentTheme ) {
collapsibleClasses += " ui-collapsible-themed-content";
collapsibleContent.addClass( "ui-body-" + o.contentTheme );
}
if ( collapsibleClasses !== "" ) {
collapsible.addClass( collapsibleClasses );
}
collapsibleHeading
//drop heading in before content
.insertBefore( collapsibleContent )
//modify markup & attributes
.addClass( "ui-collapsible-heading" )
.append( "
" )
.wrapInner( "
" )
.find( "a" )
.first()
.buttonMarkup({
shadow: false,
corners: false,
iconpos: o.iconpos,
icon: o.collapsedIcon,
mini: o.mini,
theme: o.theme
});
//events
collapsible
.bind( "expand collapse", function( event ) {
if ( !event.isDefaultPrevented() ) {
var $this = $( this ),
isCollapse = ( event.type === "collapse" );
event.preventDefault();
collapsibleHeading
.toggleClass( "ui-collapsible-heading-collapsed", isCollapse )
.find( ".ui-collapsible-heading-status" )
.text( isCollapse ? o.expandCueText : o.collapseCueText )
.end()
.find( ".ui-icon" )
.toggleClass( "ui-icon-" + o.expandedIcon, !isCollapse )
// logic or cause same icon for expanded/collapsed state would remove the ui-icon-class
.toggleClass( "ui-icon-" + o.collapsedIcon, ( isCollapse || o.expandedIcon === o.collapsedIcon ) )
.end()
.find( "a" ).first().removeClass( $.mobile.activeBtnClass );
$this.toggleClass( "ui-collapsible-collapsed", isCollapse );
collapsibleContent.toggleClass( "ui-collapsible-content-collapsed", isCollapse ).attr( "aria-hidden", isCollapse );
collapsibleContent.trigger( "updatelayout" );
}
})
.trigger( o.collapsed ? "collapse" : "expand" );
collapsibleHeading
.bind( "tap", function( event ) {
collapsibleHeading.find( "a" ).first().addClass( $.mobile.activeBtnClass );
})
.bind( "click", function( event ) {
var type = collapsibleHeading.is( ".ui-collapsible-heading-collapsed" ) ? "expand" : "collapse";
collapsible.trigger( type );
event.preventDefault();
event.stopPropagation();
});
}
});
//auto self-init widgets
$.mobile.document.bind( "pagecreate create", function( e ) {
$.mobile.collapsible.prototype.enhanceWithin( e.target );
});
})( jQuery );
(function( $, undefined ) {
$.mobile.behaviors.addFirstLastClasses = {
_getVisibles: function( $els, create ) {
var visibles;
if ( create ) {
visibles = $els.not( ".ui-screen-hidden" );
} else {
visibles = $els.filter( ":visible" );
if ( visibles.length === 0 ) {
visibles = $els.not( ".ui-screen-hidden" );
}
}
return visibles;
},
_addFirstLastClasses: function( $els, $visibles, create ) {
$els.removeClass( "ui-first-child ui-last-child" );
$visibles.eq( 0 ).addClass( "ui-first-child" ).end().last().addClass( "ui-last-child" );
if ( !create ) {
this.element.trigger( "updatelayout" );
}
}
};
})( jQuery );
(function( $, undefined ) {
$.widget( "mobile.collapsibleset", $.mobile.widget, $.extend( {
options: {
initSelector: ":jqmData(role='collapsible-set')"
},
_create: function() {
var $el = this.element.addClass( "ui-collapsible-set" ),
o = this.options;
// Inherit the theme from collapsible-set
if ( !o.theme ) {
o.theme = $.mobile.getInheritedTheme( $el, "c" );
}
// Inherit the content-theme from collapsible-set
if ( !o.contentTheme ) {
o.contentTheme = $el.jqmData( "content-theme" );
}
// Inherit the corner styling from collapsible-set
if ( !o.corners ) {
o.corners = $el.jqmData( "corners" );
}
if ( $el.jqmData( "inset" ) !== undefined ) {
o.inset = $el.jqmData( "inset" );
}
o.inset = o.inset !== undefined ? o.inset : true;
o.corners = o.corners !== undefined ? o.corners : true;
if ( !!o.corners && !!o.inset ) {
$el.addClass( "ui-corner-all" );
}
// Initialize the collapsible set if it's not already initialized
if ( !$el.jqmData( "collapsiblebound" ) ) {
$el
.jqmData( "collapsiblebound", true )
.bind( "expand", function( event ) {
var closestCollapsible = $( event.target )
.closest( ".ui-collapsible" );
if ( closestCollapsible.parent().is( ":jqmData(role='collapsible-set')" ) ) {
closestCollapsible
.siblings( ".ui-collapsible" )
.trigger( "collapse" );
}
});
}
},
_init: function() {
var $el = this.element,
collapsiblesInSet = $el.children( ":jqmData(role='collapsible')" ),
expanded = collapsiblesInSet.filter( ":jqmData(collapsed='false')" );
this._refresh( "true" );
// Because the corners are handled by the collapsible itself and the default state is collapsed
// That was causing https://github.com/jquery/jquery-mobile/issues/4116
expanded.trigger( "expand" );
},
_refresh: function( create ) {
var collapsiblesInSet = this.element.children( ":jqmData(role='collapsible')" );
$.mobile.collapsible.prototype.enhance( collapsiblesInSet.not( ".ui-collapsible" ) );
this._addFirstLastClasses( collapsiblesInSet, this._getVisibles( collapsiblesInSet, create ), create );
},
refresh: function() {
this._refresh( false );
}
}, $.mobile.behaviors.addFirstLastClasses ) );
//auto self-init widgets
$.mobile.document.bind( "pagecreate create", function( e ) {
$.mobile.collapsibleset.prototype.enhanceWithin( e.target );
});
})( jQuery );
(function( $, undefined ) {
// filter function removes whitespace between label and form element so we can use inline-block (nodeType 3 = text)
$.fn.fieldcontain = function( options ) {
return this
.addClass( "ui-field-contain ui-body ui-br" )
.contents().filter( function() {
return ( this.nodeType === 3 && !/\S/.test( this.nodeValue ) );
}).remove();
};
//auto self-init widgets
$( document ).bind( "pagecreate create", function( e ) {
$( ":jqmData(role='fieldcontain')", e.target ).jqmEnhanceable().fieldcontain();
});
})( jQuery );
(function( $, undefined ) {
$.fn.grid = function( options ) {
return this.each(function() {
var $this = $( this ),
o = $.extend({
grid: null
}, options ),
$kids = $this.children(),
gridCols = { solo:1, a:2, b:3, c:4, d:5 },
grid = o.grid,
iterator;
if ( !grid ) {
if ( $kids.length <= 5 ) {
for ( var letter in gridCols ) {
if ( gridCols[ letter ] === $kids.length ) {
grid = letter;
}
}
} else {
grid = "a";
$this.addClass( "ui-grid-duo" );
}
}
iterator = gridCols[grid];
$this.addClass( "ui-grid-" + grid );
$kids.filter( ":nth-child(" + iterator + "n+1)" ).addClass( "ui-block-a" );
if ( iterator > 1 ) {
$kids.filter( ":nth-child(" + iterator + "n+2)" ).addClass( "ui-block-b" );
}
if ( iterator > 2 ) {
$kids.filter( ":nth-child(" + iterator + "n+3)" ).addClass( "ui-block-c" );
}
if ( iterator > 3 ) {
$kids.filter( ":nth-child(" + iterator + "n+4)" ).addClass( "ui-block-d" );
}
if ( iterator > 4 ) {
$kids.filter( ":nth-child(" + iterator + "n+5)" ).addClass( "ui-block-e" );
}
});
};
})( jQuery );
(function( $, undefined ) {
$.widget( "mobile.navbar", $.mobile.widget, {
options: {
iconpos: "top",
grid: null,
initSelector: ":jqmData(role='navbar')"
},
_create: function() {
var $navbar = this.element,
$navbtns = $navbar.find( "a" ),
iconpos = $navbtns.filter( ":jqmData(icon)" ).length ?
this.options.iconpos : undefined;
$navbar.addClass( "ui-navbar ui-mini" )
.attr( "role", "navigation" )
.find( "ul" )
.jqmEnhanceable()
.grid({ grid: this.options.grid });
$navbtns.buttonMarkup({
corners: false,
shadow: false,
inline: true,
iconpos: iconpos
});
$navbar.delegate( "a", "vclick", function( event ) {
// ui-btn-inner is returned as target
var target = $( event.target ).is( "a" ) ? $( this ) : $( this ).parent( "a" );
if ( !target.is( ".ui-disabled, .ui-btn-active" ) ) {
$navbtns.removeClass( $.mobile.activeBtnClass );
$( this ).addClass( $.mobile.activeBtnClass );
// The code below is a workaround to fix #1181
var activeBtn = $( this );
$( document ).one( "pagehide", function() {
activeBtn.removeClass( $.mobile.activeBtnClass );
});
}
});
// Buttons in the navbar with ui-state-persist class should regain their active state before page show
$navbar.closest( ".ui-page" ).bind( "pagebeforeshow", function() {
$navbtns.filter( ".ui-state-persist" ).addClass( $.mobile.activeBtnClass );
});
}
});
//auto self-init widgets
$.mobile.document.bind( "pagecreate create", function( e ) {
$.mobile.navbar.prototype.enhanceWithin( e.target );
});
})( jQuery );
(function( $, undefined ) {
//Keeps track of the number of lists per page UID
//This allows support for multiple nested list in the same page
//https://github.com/jquery/jquery-mobile/issues/1617
var listCountPerPage = {};
$.widget( "mobile.listview", $.mobile.widget, $.extend( {
options: {
theme: null,
countTheme: "c",
headerTheme: "b",
dividerTheme: "b",
icon: "arrow-r",
splitIcon: "arrow-r",
splitTheme: "b",
corners: true,
shadow: true,
inset: false,
initSelector: ":jqmData(role='listview')"
},
_create: function() {
var t = this,
listviewClasses = "";
listviewClasses += t.options.inset ? " ui-listview-inset" : "";
if ( !!t.options.inset ) {
listviewClasses += t.options.corners ? " ui-corner-all" : "";
listviewClasses += t.options.shadow ? " ui-shadow" : "";
}
// create listview markup
t.element.addClass(function( i, orig ) {
return orig + " ui-listview" + listviewClasses;
});
t.refresh( true );
},
// This is a generic utility method for finding the first
// node with a given nodeName. It uses basic DOM traversal
// to be fast and is meant to be a substitute for simple
// $.fn.closest() and $.fn.children() calls on a single
// element. Note that callers must pass both the lowerCase
// and upperCase version of the nodeName they are looking for.
// The main reason for this is that this function will be
// called many times and we want to avoid having to lowercase
// the nodeName from the element every time to ensure we have
// a match. Note that this function lives here for now, but may
// be moved into $.mobile if other components need a similar method.
_findFirstElementByTagName: function( ele, nextProp, lcName, ucName ) {
var dict = {};
dict[ lcName ] = dict[ ucName ] = true;
while ( ele ) {
if ( dict[ ele.nodeName ] ) {
return ele;
}
ele = ele[ nextProp ];
}
return null;
},
_getChildrenByTagName: function( ele, lcName, ucName ) {
var results = [],
dict = {};
dict[ lcName ] = dict[ ucName ] = true;
ele = ele.firstChild;
while ( ele ) {
if ( dict[ ele.nodeName ] ) {
results.push( ele );
}
ele = ele.nextSibling;
}
return $( results );
},
_addThumbClasses: function( containers ) {
var i, img, len = containers.length;
for ( i = 0; i < len; i++ ) {
img = $( this._findFirstElementByTagName( containers[ i ].firstChild, "nextSibling", "img", "IMG" ) );
if ( img.length ) {
img.addClass( "ui-li-thumb" );
$( this._findFirstElementByTagName( img[ 0 ].parentNode, "parentNode", "li", "LI" ) ).addClass( img.is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
}
}
},
refresh: function( create ) {
this.parentPage = this.element.closest( ".ui-page" );
this._createSubPages();
var o = this.options,
$list = this.element,
self = this,
dividertheme = $list.jqmData( "dividertheme" ) || o.dividerTheme,
listsplittheme = $list.jqmData( "splittheme" ),
listspliticon = $list.jqmData( "spliticon" ),
listicon = $list.jqmData( "icon" ),
li = this._getChildrenByTagName( $list[ 0 ], "li", "LI" ),
ol = !!$.nodeName( $list[ 0 ], "ol" ),
jsCount = !$.support.cssPseudoElement,
start = $list.attr( "start" ),
itemClassDict = {},
item, itemClass, itemTheme,
a, last, splittheme, counter, startCount, newStartCount, countParent, icon, imgParents, img, linkIcon;
if ( ol && jsCount ) {
$list.find( ".ui-li-dec" ).remove();
}
if ( ol ) {
// Check if a start attribute has been set while taking a value of 0 into account
if ( start || start === 0 ) {
if ( !jsCount ) {
startCount = parseInt( start , 10 ) - 1;
$list.css( "counter-reset", "listnumbering " + startCount );
} else {
counter = parseInt( start , 10 );
}
} else if ( jsCount ) {
counter = 1;
}
}
if ( !o.theme ) {
o.theme = $.mobile.getInheritedTheme( this.element, "c" );
}
for ( var pos = 0, numli = li.length; pos < numli; pos++ ) {
item = li.eq( pos );
itemClass = "ui-li";
// If we're creating the element, we update it regardless
if ( create || !item.hasClass( "ui-li" ) ) {
itemTheme = item.jqmData( "theme" ) || o.theme;
a = this._getChildrenByTagName( item[ 0 ], "a", "A" );
var isDivider = ( item.jqmData( "role" ) === "list-divider" );
if ( a.length && !isDivider ) {
icon = item.jqmData( "icon" );
item.buttonMarkup({
wrapperEls: "div",
shadow: false,
corners: false,
iconpos: "right",
icon: a.length > 1 || icon === false ? false : icon || listicon || o.icon,
theme: itemTheme
});
if ( ( icon !== false ) && ( a.length === 1 ) ) {
item.addClass( "ui-li-has-arrow" );
}
a.first().removeClass( "ui-link" ).addClass( "ui-link-inherit" );
if ( a.length > 1 ) {
itemClass += " ui-li-has-alt";
last = a.last();
splittheme = listsplittheme || last.jqmData( "theme" ) || o.splitTheme;
linkIcon = last.jqmData( "icon" );
last.appendTo( item )
.attr( "title", $.trim(last.getEncodedText()) )
.addClass( "ui-li-link-alt" )
.empty()
.buttonMarkup({
shadow: false,
corners: false,
theme: itemTheme,
icon: false,
iconpos: "notext"
})
.find( ".ui-btn-inner" )
.append(
$( document.createElement( "span" ) ).buttonMarkup({
shadow: true,
corners: true,
theme: splittheme,
iconpos: "notext",
// link icon overrides list item icon overrides ul element overrides options
icon: linkIcon || icon || listspliticon || o.splitIcon
})
);
}
} else if ( isDivider ) {
itemClass += " ui-li-divider ui-bar-" + ( item.jqmData( "theme" ) || dividertheme );
item.attr( "role", "heading" );
if ( ol ) {
//reset counter when a divider heading is encountered
if ( start || start === 0 ) {
if ( !jsCount ) {
newStartCount = parseInt( start , 10 ) - 1;
item.css( "counter-reset", "listnumbering " + newStartCount );
} else {
counter = parseInt( start , 10 );
}
} else if ( jsCount ) {
counter = 1;
}
}
} else {
itemClass += " ui-li-static ui-btn-up-" + itemTheme;
}
}
if ( ol && jsCount && itemClass.indexOf( "ui-li-divider" ) < 0 ) {
countParent = itemClass.indexOf( "ui-li-static" ) > 0 ? item : item.find( ".ui-link-inherit" );
countParent.addClass( "ui-li-jsnumbering" )
.prepend( "
" + ( counter++ ) + ". " );
}
// Instead of setting item class directly on the list item and its
// btn-inner at this point in time, push the item into a dictionary
// that tells us what class to set on it so we can do this after this
// processing loop is finished.
if ( !itemClassDict[ itemClass ] ) {
itemClassDict[ itemClass ] = [];
}
itemClassDict[ itemClass ].push( item[ 0 ] );
}
// Set the appropriate listview item classes on each list item
// and their btn-inner elements. The main reason we didn't do this
// in the for-loop above is because we can eliminate per-item function overhead
// by calling addClass() and children() once or twice afterwards. This
// can give us a significant boost on platforms like WP7.5.
for ( itemClass in itemClassDict ) {
$( itemClassDict[ itemClass ] ).addClass( itemClass ).children( ".ui-btn-inner" ).addClass( itemClass );
}
$list.find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" )
.end()
.find( "p, dl" ).addClass( "ui-li-desc" )
.end()
.find( ".ui-li-aside" ).each(function() {
var $this = $( this );
$this.prependTo( $this.parent() ); //shift aside to front for css float
})
.end()
.find( ".ui-li-count" ).each(function() {
$( this ).closest( "li" ).addClass( "ui-li-has-count" );
}).addClass( "ui-btn-up-" + ( $list.jqmData( "counttheme" ) || this.options.countTheme) + " ui-btn-corner-all" );
// The idea here is to look at the first image in the list item
// itself, and any .ui-link-inherit element it may contain, so we
// can place the appropriate classes on the image and list item.
// Note that we used to use something like:
//
// li.find(">img:eq(0), .ui-link-inherit>img:eq(0)").each( ... );
//
// But executing a find() like that on Windows Phone 7.5 took a
// really long time. Walking things manually with the code below
// allows the 400 listview item page to load in about 3 seconds as
// opposed to 30 seconds.
this._addThumbClasses( li );
this._addThumbClasses( $list.find( ".ui-link-inherit" ) );
this._addFirstLastClasses( li, this._getVisibles( li, create ), create );
// autodividers binds to this to redraw dividers after the listview refresh
this._trigger( "afterrefresh" );
},
//create a string for ID/subpage url creation
_idStringEscape: function( str ) {
return str.replace(/[^a-zA-Z0-9]/g, '-');
},
_createSubPages: function() {
var parentList = this.element,
parentPage = parentList.closest( ".ui-page" ),
parentUrl = parentPage.jqmData( "url" ),
parentId = parentUrl || parentPage[ 0 ][ $.expando ],
parentListId = parentList.attr( "id" ),
o = this.options,
dns = "data-" + $.mobile.ns,
self = this,
persistentFooterID = parentPage.find( ":jqmData(role='footer')" ).jqmData( "id" ),
hasSubPages;
if ( typeof listCountPerPage[ parentId ] === "undefined" ) {
listCountPerPage[ parentId ] = -1;
}
parentListId = parentListId || ++listCountPerPage[ parentId ];
$( parentList.find( "li>ul, li>ol" ).toArray().reverse() ).each(function( i ) {
var self = this,
list = $( this ),
listId = list.attr( "id" ) || parentListId + "-" + i,
parent = list.parent(),
nodeElsFull = $( list.prevAll().toArray().reverse() ),
nodeEls = nodeElsFull.length ? nodeElsFull : $( "
" + $.trim(parent.contents()[ 0 ].nodeValue) + "" ),
title = nodeEls.first().getEncodedText(),//url limits to first 30 chars of text
id = ( parentUrl || "" ) + "&" + $.mobile.subPageUrlKey + "=" + listId,
theme = list.jqmData( "theme" ) || o.theme,
countTheme = list.jqmData( "counttheme" ) || parentList.jqmData( "counttheme" ) || o.countTheme,
newPage, anchor;
//define hasSubPages for use in later removal
hasSubPages = true;
newPage = list.detach()
.wrap( "
" )
.parent()
.before( "
" )
.after( persistentFooterID ? $( "
" ) : "" )
.parent()
.appendTo( $.mobile.pageContainer );
newPage.page();
anchor = parent.find( 'a:first' );
if ( !anchor.length ) {
anchor = $( "
" ).html( nodeEls || title ).prependTo( parent.empty() );
}
anchor.attr( "href", "#" + id );
}).listview();
// on pagehide, remove any nested pages along with the parent page, as long as they aren't active
// and aren't embedded
if ( hasSubPages &&
parentPage.is( ":jqmData(external-page='true')" ) &&
parentPage.data( "mobile-page" ).options.domCache === false ) {
var newRemove = function( e, ui ) {
var nextPage = ui.nextPage, npURL,
prEvent = new $.Event( "pageremove" );
if ( ui.nextPage ) {
npURL = nextPage.jqmData( "url" );
if ( npURL.indexOf( parentUrl + "&" + $.mobile.subPageUrlKey ) !== 0 ) {
self.childPages().remove();
parentPage.trigger( prEvent );
if ( !prEvent.isDefaultPrevented() ) {
parentPage.removeWithDependents();
}
}
}
};
// unbind the original page remove and replace with our specialized version
parentPage
.unbind( "pagehide.remove" )
.bind( "pagehide.remove", newRemove);
}
},
// TODO sort out a better way to track sub pages of the listview this is brittle
childPages: function() {
var parentUrl = this.parentPage.jqmData( "url" );
return $( ":jqmData(url^='"+ parentUrl + "&" + $.mobile.subPageUrlKey + "')" );
}
}, $.mobile.behaviors.addFirstLastClasses ) );
//auto self-init widgets
$.mobile.document.bind( "pagecreate create", function( e ) {
$.mobile.listview.prototype.enhanceWithin( e.target );
});
})( jQuery );
(function( $ ) {
var meta = $( "meta[name=viewport]" ),
initialContent = meta.attr( "content" ),
disabledZoom = initialContent + ",maximum-scale=1, user-scalable=no",
enabledZoom = initialContent + ",maximum-scale=10, user-scalable=yes",
disabledInitially = /(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test( initialContent );
$.mobile.zoom = $.extend( {}, {
enabled: !disabledInitially,
locked: false,
disable: function( lock ) {
if ( !disabledInitially && !$.mobile.zoom.locked ) {
meta.attr( "content", disabledZoom );
$.mobile.zoom.enabled = false;
$.mobile.zoom.locked = lock || false;
}
},
enable: function( unlock ) {
if ( !disabledInitially && ( !$.mobile.zoom.locked || unlock === true ) ) {
meta.attr( "content", enabledZoom );
$.mobile.zoom.enabled = true;
$.mobile.zoom.locked = false;
}
},
restore: function() {
if ( !disabledInitially ) {
meta.attr( "content", initialContent );
$.mobile.zoom.enabled = true;
}
}
});
}( jQuery ));
(function( $, undefined ) {
$.widget( "mobile.textinput", $.mobile.widget, {
options: {
theme: null,
mini: false,
// This option defaults to true on iOS devices.
preventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1,
initSelector: "input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea, input[type='time'], input[type='date'], input[type='month'], input[type='week'], input[type='datetime'], input[type='datetime-local'], input[type='color'], input:not([type]), input[type='file']",
clearBtn: false,
clearSearchButtonText: null, //deprecating for 1.3...
clearBtnText: "clear text",
disabled: false
},
_create: function() {
var self = this,
input = this.element,
o = this.options,
theme = o.theme || $.mobile.getInheritedTheme( this.element, "c" ),
themeclass = " ui-body-" + theme,
miniclass = o.mini ? " ui-mini" : "",
isSearch = input.is( "[type='search'], :jqmData(type='search')" ),
focusedEl,
clearbtn,
clearBtnText = o.clearSearchButtonText || o.clearBtnText,
clearBtnBlacklist = input.is( "textarea, :jqmData(type='range')" ),
inputNeedsClearBtn = !!o.clearBtn && !clearBtnBlacklist,
inputNeedsWrap = input.is( "input" ) && !input.is( ":jqmData(type='range')" );
function toggleClear() {
setTimeout( function() {
clearbtn.toggleClass( "ui-input-clear-hidden", !input.val() );
}, 0 );
}
$( "label[for='" + input.attr( "id" ) + "']" ).addClass( "ui-input-text" );
focusedEl = input.addClass( "ui-input-text ui-body-"+ theme );
// XXX: Temporary workaround for issue 785 (Apple bug 8910589).
// Turn off autocorrect and autocomplete on non-iOS 5 devices
// since the popup they use can't be dismissed by the user. Note
// that we test for the presence of the feature by looking for
// the autocorrect property on the input element. We currently
// have no test for iOS 5 or newer so we're temporarily using
// the touchOverflow support flag for jQM 1.0. Yes, I feel dirty. - jblas
if ( typeof input[0].autocorrect !== "undefined" && !$.support.touchOverflow ) {
// Set the attribute instead of the property just in case there
// is code that attempts to make modifications via HTML.
input[0].setAttribute( "autocorrect", "off" );
input[0].setAttribute( "autocomplete", "off" );
}
//"search" and "text" input widgets
if ( isSearch ) {
focusedEl = input.wrap( "
" ).parent();
} else if ( inputNeedsWrap ) {
focusedEl = input.wrap( "
" ).parent();
}
if( inputNeedsClearBtn || isSearch ) {
clearbtn = $( "
" + clearBtnText + "" )
.bind( "click", function( event ) {
input
.val( "" )
.focus()
.trigger( "change" );
clearbtn.addClass( "ui-input-clear-hidden" );
event.preventDefault();
})
.appendTo( focusedEl )
.buttonMarkup({
icon: "delete",
iconpos: "notext",
corners: true,
shadow: true,
mini: o.mini
});
if ( !isSearch ) {
focusedEl.addClass( "ui-input-has-clear" );
}
toggleClear();
input.bind( "paste cut keyup input focus change blur", toggleClear );
}
else if ( !inputNeedsWrap && !isSearch ) {
input.addClass( "ui-corner-all ui-shadow-inset" + themeclass + miniclass );
}
input.focus(function() {
// In many situations, iOS will zoom into the input upon tap, this prevents that from happening
if ( o.preventFocusZoom ) {
$.mobile.zoom.disable( true );
}
focusedEl.addClass( $.mobile.focusClass );
})
.blur(function() {
focusedEl.removeClass( $.mobile.focusClass );
if ( o.preventFocusZoom ) {
$.mobile.zoom.enable( true );
}
});
// Autogrow
if ( input.is( "textarea" ) ) {
var extraLineHeight = 15,
keyupTimeoutBuffer = 100,
keyupTimeout;
this._keyup = function() {
var scrollHeight = input[ 0 ].scrollHeight,
clientHeight = input[ 0 ].clientHeight;
if ( clientHeight < scrollHeight ) {
var paddingTop = parseFloat( input.css( "padding-top" ) ),
paddingBottom = parseFloat( input.css( "padding-bottom" ) ),
paddingHeight = paddingTop + paddingBottom;
input.height( scrollHeight - paddingHeight + extraLineHeight );
}
};
input.on( "keyup change input paste", function() {
clearTimeout( keyupTimeout );
keyupTimeout = setTimeout( self._keyup, keyupTimeoutBuffer );
});
// binding to pagechange here ensures that for pages loaded via
// ajax the height is recalculated without user input
this._on( true, $.mobile.document, { "pagechange": "_keyup" });
// Issue 509: the browser is not providing scrollHeight properly until the styles load
if ( $.trim( input.val() ) ) {
// bind to the window load to make sure the height is calculated based on BOTH
// the DOM and CSS
this._on( true, $.mobile.window, {"load": "_keyup"});
}
}
if ( input.attr( "disabled" ) ) {
this.disable();
}
},
disable: function() {
var $el,
isSearch = this.element.is( "[type='search'], :jqmData(type='search')" ),
inputNeedsWrap = this.element.is( "input" ) && !this.element.is( ":jqmData(type='range')" ),
parentNeedsDisabled = this.element.attr( "disabled", true ) && ( inputNeedsWrap || isSearch );
if ( parentNeedsDisabled ) {
$el = this.element.parent();
} else {
$el = this.element;
}
$el.addClass( "ui-disabled" );
return this._setOption( "disabled", true );
},
enable: function() {
var $el,
isSearch = this.element.is( "[type='search'], :jqmData(type='search')" ),
inputNeedsWrap = this.element.is( "input" ) && !this.element.is( ":jqmData(type='range')" ),
parentNeedsEnabled = this.element.attr( "disabled", false ) && ( inputNeedsWrap || isSearch );
if ( parentNeedsEnabled ) {
$el = this.element.parent();
} else {
$el = this.element;
}
$el.removeClass( "ui-disabled" );
return this._setOption( "disabled", false );
}
});
//auto self-init widgets
$.mobile.document.bind( "pagecreate create", function( e ) {
$.mobile.textinput.prototype.enhanceWithin( e.target, true );
});
})( jQuery );
(function( $, undefined ) {
$.mobile.listview.prototype.options.filter = false;
$.mobile.listview.prototype.options.filterPlaceholder = "Filter items...";
$.mobile.listview.prototype.options.filterTheme = "c";
$.mobile.listview.prototype.options.filterReveal = false;
// TODO rename callback/deprecate and default to the item itself as the first argument
var defaultFilterCallback = function( text, searchValue, item ) {
return text.toString().toLowerCase().indexOf( searchValue ) === -1;
};
$.mobile.listview.prototype.options.filterCallback = defaultFilterCallback;
$.mobile.document.delegate( "ul, ol", "listviewcreate", function() {
var list = $( this ),
listview = list.data( "mobile-listview" );
if ( !listview || !listview.options.filter ) {
return;
}
if ( listview.options.filterReveal ) {
list.children().addClass( "ui-screen-hidden" );
}
var wrapper = $( "