diff --git a/Gemfile.lock b/Gemfile.lock
index 7ae11c4..041f144 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- jquery_mobile_rails (1.3.0)
+ jquery_mobile_rails (1.3.1)
railties (>= 3.1.0)
GEM
diff --git a/README.rdoc b/README.rdoc
index 3ffdaba..a7afd29 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -6,7 +6,7 @@ This gem adds the JQuery Mobile files to the rails assets pipeline.
==== Gem's JQuery Mobile Version
-1.3.0 (gem 1.3.0)
+1.3.1 (gem 1.3.1)
=== Instalation
diff --git a/lib/jquery_mobile_rails/version.rb b/lib/jquery_mobile_rails/version.rb
index 57f519f..568ceb9 100644
--- a/lib/jquery_mobile_rails/version.rb
+++ b/lib/jquery_mobile_rails/version.rb
@@ -1,3 +1,3 @@
module JqueryMobileRails
- VERSION = "1.3.0"
+ VERSION = "1.3.1"
end
diff --git a/vendor/assets/javascripts/jquery.mobile.js b/vendor/assets/javascripts/jquery.mobile.js
index bbe96bc..6708d34 100644
--- a/vendor/assets/javascripts/jquery.mobile.js
+++ b/vendor/assets/javascripts/jquery.mobile.js
@@ -1,5 +1,6 @@
/*
-* jQuery Mobile Git Build: SHA1: caa77b258660731d663844fe7867aa2c3a107ab1 <> Date: Wed Feb 20 15:03:27 2013 -0500
+* jQuery Mobile 1.3.1
+* Git HEAD hash: 74b4bec049fd93e4fe40205e6157de16eb64eb46 <> Date: Wed Apr 10 2013 21:57:23 UTC
* http://jquerymobile.com
*
* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors
@@ -25,14 +26,13 @@
$.mobile = {};
}( jQuery ));
(function( $, window, undefined ) {
-
var nsNormalizeDict = {};
// jQuery.mobile configurable options
$.mobile = $.extend($.mobile, {
// Version of the jQuery Mobile Framework
- version: "1.3.0",
+ version: "1.3.1",
// Namespace used framework-wide for data-attrs. Default is no namespace
ns: "",
@@ -323,7 +323,7 @@
};
// note that this helper doesn't attempt to handle the callback
- // or setting of an html elements text, its only purpose is
+ // or setting of an html element's text, its only purpose is
// to return the html encoded version of the text in all cases. (thus the name)
$.fn.getEncodedText = function() {
return $( "
" ).text( $( this ).text() ).html();
@@ -1746,6 +1746,8 @@ $.extend( $.support, {
// https://developers.google.com/chrome/mobile/docs/user-agent#chrome_for_ios_user-agent
pushState: "pushState" in history &&
"replaceState" in history &&
+ // When running inside a FF iframe, calling replaceState causes an error
+ !( window.navigator.userAgent.indexOf( "Firefox" ) >= 0 && window.top !== window ) &&
( window.navigator.userAgent.search(/CriOS/) === -1 ),
mediaquery: $.mobile.media( "only all" ),
@@ -2381,18 +2383,13 @@ if ( !$.support.boxShadow ) {
(function( $, undefined ) {
- var path = $.mobile.path;
+ var path = $.mobile.path,
+ initialHref = location.href;
$.mobile.Navigator = function( history ) {
this.history = history;
this.ignoreInitialHashChange = true;
- // This ensures that browsers which don't fire the initial popstate
- // like opera don't have further hash assignment popstates blocked
- setTimeout($.proxy(function() {
- this.ignoreInitialHashChange = false;
- }, this), 200);
-
$.mobile.window.bind({
"popstate.history": $.proxy( this.popstate, this ),
"hashchange.history": $.proxy( this.hashchange, this )
@@ -2555,13 +2552,18 @@ if ( !$.support.boxShadow ) {
// If there is no state, and the history stack length is one were
// probably getting the page load popstate fired by browsers like chrome
- // avoid it and set the one time flag to false
+ // avoid it and set the one time flag to false.
+ // TODO: Do we really need all these conditions? Comparing location hrefs
+ // should be sufficient.
if( !event.originalEvent.state &&
this.history.stack.length === 1 &&
this.ignoreInitialHashChange ) {
this.ignoreInitialHashChange = false;
- return;
+ if ( location.href === initialHref ) {
+ event.preventDefault();
+ return;
+ }
}
// account for direct manipulation of the hash. That is, we will receive a popstate
@@ -4209,6 +4211,7 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
.jqmData( "url", dataUrl );
}
+
// If we failed to find a page in the DOM, check the URL to see if it
// refers to the first page in the application. If it isn't a reference
// to the first page and refers to non-existent embedded page, error out.
@@ -4230,7 +4233,7 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
return deferred.promise();
}
}
-
+
// If the page we are interested in is already in the DOM,
// and the caller did not indicate that we should force a
// reload of the file, we are done. Otherwise, track the
@@ -4239,11 +4242,14 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
if ( !settings.reloadPage ) {
enhancePage( page, settings.role );
deferred.resolve( absUrl, options, page );
+ //if we are reloading the page make sure we update the base if its not a prefetch
+ if( base && !options.prefetch ){
+ base.set(url);
+ }
return deferred.promise();
}
dupCachedPage = page;
}
-
var mpc = settings.pageContainer,
pblEvent = new $.Event( "pagebeforeload" ),
triggerData = { url: url, absUrl: absUrl, dataUrl: dataUrl, deferred: deferred, options: settings };
@@ -4273,9 +4279,9 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
$.mobile.hidePageLoadingMsg();
};
}
-
// Reset base to the default document base.
- if ( base ) {
+ // only reset if we are not prefetching
+ if ( base && typeof options.prefetch === "undefined" ) {
base.reset();
}
@@ -4287,6 +4293,7 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
url: fileUrl,
type: settings.type,
data: settings.data,
+ contentType: settings.contentType,
dataType: "html",
success: function( html, textStatus, xhr ) {
//pre-parse html to check for a data-url,
@@ -4309,8 +4316,8 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
RegExp.$1 ) {
url = fileUrl = path.getFilePath( $( "
" + RegExp.$1 + "
" ).text() );
}
-
- if ( base ) {
+ //dont update the base tag if we are prefetching
+ if ( base && typeof options.prefetch === "undefined") {
base.set( fileUrl );
}
@@ -4521,7 +4528,6 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
$.mobile.changePage( newPage, options );
})
.fail(function( url, options ) {
- isPageTransitioning = false;
//clear out the active button state
removeActiveLinkClass( true );
@@ -4647,7 +4653,7 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
// if title element wasn't found, try the page div data attr too
// If this is a deep-link or a reload ( active === undefined ) then just use pageTitle
- var newPageTitle = ( !active )? pageTitle : toPage.jqmData( "title" ) || toPage.children( ":jqmData(role='header')" ).find( ".ui-title" ).getEncodedText();
+ var newPageTitle = ( !active )? pageTitle : toPage.jqmData( "title" ) || toPage.children( ":jqmData(role='header')" ).find( ".ui-title" ).text();
if ( !!newPageTitle && pageTitle === document.title ) {
pageTitle = newPageTitle;
}
@@ -4773,18 +4779,20 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
$.mobile.navreadyDeferred = $.Deferred();
$.mobile._registerInternalEvents = function() {
var getAjaxFormData = function( $form, calculateOnly ) {
- var type, target, url, ret = true, formData, vclickedName;
+ var url, ret = true, formData, vclickedName, method;
+
if ( !$.mobile.ajaxEnabled ||
// test that the form is, itself, ajax false
$form.is( ":jqmData(ajax='false')" ) ||
// test that $.mobile.ignoreContentEnabled is set and
// the form or one of it's parents is ajax=false
- !$form.jqmHijackable().length ) {
+ !$form.jqmHijackable().length ||
+ $form.attr( "target" ) ) {
return false;
}
- target = $form.attr( "target" );
url = $form.attr( "action" );
+ method = ( $form.attr( "method" ) || "get" ).toLowerCase();
// If no action is specified, browsers default to using the
// URL of the document containing the form. Since we dynamically
@@ -4794,6 +4802,13 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
if ( !url ) {
// Get the @data-url for the page containing the form.
url = getClosestBaseUrl( $form );
+
+ // NOTE: If the method is "get", we need to strip off the query string
+ // because it will get replaced with the new form data. See issue #5710.
+ if ( method === "get" ) {
+ url = path.parseUrl( url ).hrefNoSearch;
+ }
+
if ( url === documentBase.hrefNoHash ) {
// The url we got back matches the document base,
// which means the page must be an internal/embedded page,
@@ -4805,12 +4820,11 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
url = path.makeUrlAbsolute( url, getClosestBaseUrl( $form ) );
- if ( ( path.isExternal( url ) && !path.isPermittedCrossDomainRequest( documentUrl, url ) ) || target ) {
+ if ( ( path.isExternal( url ) && !path.isPermittedCrossDomainRequest( documentUrl, url ) ) ) {
return false;
}
if ( !calculateOnly ) {
- type = $form.attr( "method" );
formData = $form.serializeArray();
if ( $lastVClicked && $lastVClicked[ 0 ].form === $form[ 0 ] ) {
@@ -4833,7 +4847,7 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
ret = {
url: url,
options: {
- type: type && type.length && type.toLowerCase() || "get",
+ type: method,
data: $.param( formData ),
transition: $form.jqmData( "transition" ),
reverse: $form.jqmData( "direction" ) === "reverse",
@@ -5030,7 +5044,7 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
if ( url && $.inArray( url, urls ) === -1 ) {
urls.push( url );
- $.mobile.loadPage( url, { role: $link.attr( "data-" + $.mobile.ns + "rel" ) } );
+ $.mobile.loadPage( url, { role: $link.attr( "data-" + $.mobile.ns + "rel" ),prefetch: true } );
}
});
});
@@ -5113,7 +5127,13 @@ $.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defau
// TODO roll the logic here into the handleHashChange method
$window.bind( "navigate", function( e, data ) {
- var url = $.event.special.navigate.originalEventName.indexOf( "hashchange" ) > -1 ? data.state.hash : data.state.url;
+ var url;
+
+ if ( e.originalEvent && e.originalEvent.isDefaultPrevented() ) {
+ return;
+ }
+
+ url = $.event.special.navigate.originalEventName.indexOf( "hashchange" ) > -1 ? data.state.hash : data.state.url;
if( !url ) {
url = $.mobile.path.parseLocation().hash;
@@ -5365,9 +5385,8 @@ $.widget( "mobile.dialog", $.mobile.widget, {
_setOption: function( key, value ) {
if ( key === "closeBtn" ) {
this._setCloseBtn( value );
- this._super( key, value );
- this.element.attr( "data-" + ( $.mobile.ns || "" ) + "close-btn", value );
}
+ this._super( key, value );
},
// Close method goes back in history
@@ -5496,124 +5515,6 @@ $.mobile.document.bind( "pagecreate", function( e ) {
(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 ) {
-
-// 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 ) {
-
-$( document ).bind( "pagecreate create", function( e ) {
- $( ":jqmData(role='nojs')", e.target ).addClass( "ui-nojs" );
-
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.mobile.behaviors.formReset = {
- _handleFormReset: function() {
- this._on( this.element.closest( "form" ), {
- reset: function() {
- this._delay( "_reset" );
- }
- });
- }
-};
-
-})( jQuery );
-
-(function( $, undefined ) {
-
// This function calls getAttribute, which should be safe for data-* attributes
var getAttrFixed = function( e, key ) {
var value = e.getAttribute( key );
@@ -5657,7 +5558,11 @@ $.fn.buttonMarkup = function( options ) {
buttonElements;
for ( key in o ) {
- e.setAttribute( nsKey + key, o[ key ] );
+ if ( o[ key ] === undefined || o[ key ] === null ) {
+ el.removeAttr( nsKey + key );
+ } else {
+ e.setAttribute( nsKey + key, o[ key ] );
+ }
}
if ( getAttrFixed( e, nsKey + "rel" ) === "popup" && el.attr( "href" ) ) {
@@ -5729,10 +5634,6 @@ $.fn.buttonMarkup = function( options ) {
}
}
- if ( o.iconpos && o.iconpos === "notext" && !el.attr( "title" ) ) {
- el.attr( "title", el.getEncodedText() );
- }
-
if ( buttonElements ) {
el.removeClass( buttonElements.bcls || "" );
}
@@ -6050,7 +5951,36 @@ $.mobile.document.bind( "pagecreate create", function( e ) {
(function( $, undefined ) {
-$.widget( "mobile.collapsibleset", $.mobile.widget, {
+$.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')"
},
@@ -6119,9 +6049,7 @@ $.widget( "mobile.collapsibleset", $.mobile.widget, {
refresh: function() {
this._refresh( false );
}
-});
-
-$.widget( "mobile.collapsibleset", $.mobile.collapsibleset, $.mobile.behaviors.addFirstLastClasses );
+}, $.mobile.behaviors.addFirstLastClasses ) );
//auto self-init widgets
$.mobile.document.bind( "pagecreate create", function( e ) {
@@ -6132,6 +6060,72 @@ $.mobile.document.bind( "pagecreate create", function( e ) {
(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",
@@ -6160,13 +6154,18 @@ $.widget( "mobile.navbar", $.mobile.widget, {
});
$navbar.delegate( "a", "vclick", function( event ) {
- if ( !$(event.target).hasClass( "ui-disabled" ) ) {
+ // 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. We have to see why removeActiveLinkClass() doesn't take care of it.
- var activeNavbtn = $( this );
- $( document ).one( "pagechange", function( event ) {
- activeNavbtn.removeClass( $.mobile.activeBtnClass );
+
+ // The code below is a workaround to fix #1181
+ var activeBtn = $( this );
+
+ $( document ).one( "pagehide", function() {
+ activeBtn.removeClass( $.mobile.activeBtnClass );
});
}
});
@@ -6192,7 +6191,7 @@ $.mobile.document.bind( "pagecreate create", function( e ) {
//https://github.com/jquery/jquery-mobile/issues/1617
var listCountPerPage = {};
-$.widget( "mobile.listview", $.mobile.widget, {
+$.widget( "mobile.listview", $.mobile.widget, $.extend( {
options: {
theme: null,
@@ -6556,9 +6555,7 @@ $.widget( "mobile.listview", $.mobile.widget, {
return $( ":jqmData(url^='"+ parentUrl + "&" + $.mobile.subPageUrlKey + "')" );
}
-});
-
-$.widget( "mobile.listview", $.mobile.listview, $.mobile.behaviors.addFirstLastClasses );
+}, $.mobile.behaviors.addFirstLastClasses ) );
//auto self-init widgets
$.mobile.document.bind( "pagecreate create", function( e ) {
@@ -6567,4331 +6564,4433 @@ $.mobile.document.bind( "pagecreate create", function( e ) {
})( jQuery );
-(function( $, undefined ) {
+(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.listview.prototype.options.autodividers = false;
-$.mobile.listview.prototype.options.autodividersSelector = function( elt ) {
- // look for the text in the given element
- var text = $.trim( elt.text() ) || null;
-
- if ( !text ) {
- return null;
- }
-
- // create the text for the divider (first uppercased letter)
- text = text.slice( 0, 1 ).toUpperCase();
-
- return text;
-};
-
-$.mobile.document.delegate( "ul,ol", "listviewcreate", function() {
-
- var list = $( this ),
- listview = list.data( "mobile-listview" );
-
- if ( !listview || !listview.options.autodividers ) {
- return;
- }
-
- var replaceDividers = function () {
- list.find( "li:jqmData(role='list-divider')" ).remove();
-
- var lis = list.find( 'li' ),
- lastDividerText = null, li, dividerText;
-
- for ( var i = 0; i < lis.length ; i++ ) {
- li = lis[i];
- dividerText = listview.options.autodividersSelector( $( li ) );
-
- if ( dividerText && lastDividerText !== dividerText ) {
- var divider = document.createElement( 'li' );
- divider.appendChild( document.createTextNode( dividerText ) );
- divider.setAttribute( 'data-' + $.mobile.ns + 'role', 'list-divider' );
- li.parentNode.insertBefore( divider, li );
+ $.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;
}
-
- lastDividerText = dividerText;
}
- };
-
- var afterListviewRefresh = function () {
- list.unbind( 'listviewafterrefresh', afterListviewRefresh );
- replaceDividers();
- listview.refresh();
- list.bind( 'listviewafterrefresh', afterListviewRefresh );
- };
-
- afterListviewRefresh();
-});
-
-})( jQuery );
+ });
-/*
-* "checkboxradio" plugin
-*/
+}( jQuery ));
(function( $, undefined ) {
-$.widget( "mobile.checkboxradio", $.mobile.widget, {
+$.widget( "mobile.textinput", $.mobile.widget, {
options: {
theme: null,
mini: false,
- initSelector: "input[type='checkbox'],input[type='radio']"
+ // 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,
- inheritAttr = function( input, dataAttr ) {
- return input.jqmData( dataAttr ) || input.closest( "form, fieldset" ).jqmData( dataAttr );
- },
- // NOTE: Windows Phone could not find the label through a selector
- // filter works though.
- parentLabel = $( input ).closest( "label" ),
- label = parentLabel.length ? parentLabel : $( input ).closest( "form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')" ).find( "label" ).filter( "[for='" + input[0].id + "']" ).first(),
- inputtype = input[0].type,
- mini = inheritAttr( input, "mini" ) || o.mini,
- checkedState = inputtype + "-on",
- uncheckedState = inputtype + "-off",
- iconpos = inheritAttr( input, "iconpos" ),
- checkedClass = "ui-" + checkedState,
- uncheckedClass = "ui-" + uncheckedState;
+ 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')" );
- if ( inputtype !== "checkbox" && inputtype !== "radio" ) {
- return;
+ function toggleClear() {
+ setTimeout( function() {
+ clearbtn.toggleClass( "ui-input-clear-hidden", !input.val() );
+ }, 0 );
}
- // Expose for other methods
- $.extend( this, {
- label: label,
- inputtype: inputtype,
- checkedClass: checkedClass,
- uncheckedClass: uncheckedClass,
- checkedicon: checkedState,
- uncheckedicon: uncheckedState
- });
+ $( "label[for='" + input.attr( "id" ) + "']" ).addClass( "ui-input-text" );
- // If there's no selected theme check the data attr
- if ( !o.theme ) {
- o.theme = $.mobile.getInheritedTheme( this.element, "c" );
+ 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" );
}
- label.buttonMarkup({
- theme: o.theme,
- icon: uncheckedState,
- shadow: false,
- mini: mini,
- iconpos: iconpos
- });
+ //"search" and "text" input widgets
+ if ( isSearch ) {
+ focusedEl = input.wrap( "" ).parent();
+ } else if ( inputNeedsWrap ) {
+ focusedEl = input.wrap( "" ).parent();
+ }
- // Wrap the input + label in a div
- var wrapper = document.createElement('div');
- wrapper.className = 'ui-' + inputtype;
+ 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" );
+ }
- input.add( label ).wrapAll( wrapper );
+ toggleClear();
- label.bind({
- vmouseover: function( event ) {
- if ( $( this ).parent().is( ".ui-disabled" ) ) {
- event.stopPropagation();
- }
- },
+ input.bind( "paste cut keyup input focus change blur", toggleClear );
+ }
+ else if ( !inputNeedsWrap && !isSearch ) {
+ input.addClass( "ui-corner-all ui-shadow-inset" + themeclass + miniclass );
+ }
- vclick: function( event ) {
- if ( input.is( ":disabled" ) ) {
- event.preventDefault();
- return;
- }
+ 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 );
+ }
+ });
- self._cacheVals();
+ // Autogrow
+ if ( input.is( "textarea" ) ) {
+ var extraLineHeight = 15,
+ keyupTimeoutBuffer = 100,
+ keyupTimeout;
- input.prop( "checked", inputtype === "radio" && true || !input.prop( "checked" ) );
+ this._keyup = function() {
+ var scrollHeight = input[ 0 ].scrollHeight,
+ clientHeight = input[ 0 ].clientHeight;
- // trigger click handler's bound directly to the input as a substitute for
- // how label clicks behave normally in the browsers
- // TODO: it would be nice to let the browser's handle the clicks and pass them
- // through to the associate input. we can swallow that click at the parent
- // wrapper element level
- input.triggerHandler( 'click' );
+ 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 set for common radio buttons will contain all the radio
- // buttons, but will not for checkboxes. clearing the checked status
- // of other radios ensures the active button state is applied properly
- self._getInputSet().not( input ).prop( "checked", false );
+ input.on( "keyup change input paste", function() {
+ clearTimeout( keyupTimeout );
+ keyupTimeout = setTimeout( self._keyup, keyupTimeoutBuffer );
+ });
- self._updateAll();
- return false;
- }
- });
+ // 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" });
- input
- .bind({
- vmousedown: function() {
- self._cacheVals();
- },
-
- vclick: function() {
- var $this = $( this );
-
- // Adds checked attribute to checked input when keyboard is used
- if ( $this.is( ":checked" ) ) {
-
- $this.prop( "checked", true);
- self._getInputSet().not( $this ).prop( "checked", false );
- } else {
-
- $this.prop( "checked", false );
- }
-
- self._updateAll();
- },
-
- focus: function() {
- label.addClass( $.mobile.focusClass );
- },
-
- blur: function() {
- label.removeClass( $.mobile.focusClass );
- }
- });
-
- if ( this._handleFormReset ) {
- this._handleFormReset();
- }
- this.refresh();
- },
-
- _cacheVals: function() {
- this._getInputSet().each(function() {
- $( this ).jqmData( "cacheVal", this.checked );
- });
- },
-
- //returns either a set of radios with the same name attribute, or a single checkbox
- _getInputSet: function() {
- if ( this.inputtype === "checkbox" ) {
- return this.element;
- }
-
- return this.element.closest( "form, :jqmData(role='page'), :jqmData(role='dialog')" )
- .find( "input[name='" + this.element[0].name + "'][type='" + this.inputtype + "']" );
- },
-
- _updateAll: function() {
- var self = this;
-
- this._getInputSet().each(function() {
- var $this = $( this );
-
- if ( this.checked || self.inputtype === "checkbox" ) {
- $this.trigger( "change" );
+ // 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"});
}
- })
- .checkboxradio( "refresh" );
- },
-
- _reset: function() {
- this.refresh();
- },
-
- refresh: function() {
- var input = this.element[ 0 ],
- active = " " + $.mobile.activeBtnClass,
- checkedClass = this.checkedClass + ( this.element.parents( ".ui-controlgroup-horizontal" ).length ? active : "" ),
- label = this.label;
-
- if ( input.checked ) {
- label.removeClass( this.uncheckedClass + active ).addClass( checkedClass ).buttonMarkup( { icon: this.checkedicon } );
- } else {
- label.removeClass( checkedClass ).addClass( this.uncheckedClass ).buttonMarkup( { icon: this.uncheckedicon } );
}
-
- if ( input.disabled ) {
+ if ( input.attr( "disabled" ) ) {
this.disable();
- } else {
- this.enable();
}
},
disable: function() {
- this.element.prop( "disabled", true ).parent().addClass( "ui-disabled" );
+ 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() {
- this.element.prop( "disabled", false ).parent().removeClass( "ui-disabled" );
+ 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 );
}
});
-$.widget( "mobile.checkboxradio", $.mobile.checkboxradio, $.mobile.behaviors.formReset );
-
//auto self-init widgets
$.mobile.document.bind( "pagecreate create", function( e ) {
- $.mobile.checkboxradio.prototype.enhanceWithin( e.target, true );
+ $.mobile.textinput.prototype.enhanceWithin( e.target, true );
});
})( jQuery );
(function( $, undefined ) {
-$.widget( "mobile.button", $.mobile.widget, {
- options: {
- theme: null,
- icon: null,
- iconpos: null,
- corners: true,
- shadow: true,
- iconshadow: true,
- inline: null,
- mini: null,
- initSelector: "button, [type='button'], [type='submit'], [type='reset']"
- },
- _create: function() {
- var $el = this.element,
- $button,
- // create a copy of this.options we can pass to buttonMarkup
- o = ( function( tdo ) {
- var key, ret = {};
+$.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;
+ };
- for ( key in tdo ) {
- if ( tdo[ key ] !== null && key !== "initSelector" ) {
- ret[ key ] = tdo[ key ];
- }
- }
+$.mobile.listview.prototype.options.filterCallback = defaultFilterCallback;
- return ret;
- } )( this.options ),
- classes = "",
- $buttonPlaceholder;
+$.mobile.document.delegate( "ul, ol", "listviewcreate", function() {
+ var list = $( this ),
+ listview = list.data( "mobile-listview" );
- // if this is a link, check if it's been enhanced and, if not, use the right function
- if ( $el[ 0 ].tagName === "A" ) {
- if ( !$el.hasClass( "ui-btn" ) ) {
- $el.buttonMarkup();
- }
- return;
- }
+ if ( !listview || !listview.options.filter ) {
+ return;
+ }
- // get the inherited theme
- // TODO centralize for all widgets
- if ( !this.options.theme ) {
- this.options.theme = $.mobile.getInheritedTheme( this.element, "c" );
- }
+ if ( listview.options.filterReveal ) {
+ list.children().addClass( "ui-screen-hidden" );
+ }
- // TODO: Post 1.1--once we have time to test thoroughly--any classes manually applied to the original element should be carried over to the enhanced element, with an `-enhanced` suffix. See https://github.com/jquery/jquery-mobile/issues/3577
- /* if ( $el[0].className.length ) {
- classes = $el[0].className;
- } */
- if ( !!~$el[0].className.indexOf( "ui-btn-left" ) ) {
- classes = "ui-btn-left";
- }
+ var wrapper = $( "