Skip to content
This repository
Browse code

This commit decouples all widgets from the page plugin so that they c…

…an be used ad-hoc.

- Internally, each plugin self-initializes by binding to the pagecreate event.

- Unit tests have been added and adjusted to support some internal changes involved in this commit.

- In the process, the portions of the page plugin that were used to enhance the header,content,and footer sections of a native-app style page layout are now located in jquery.mobile.page.sections.js.

- No public API options have changed, except that the page plugin no longer has options for keepNative, and degradeInputs, as plugins now handle these internally (keepNative was never documented, and degradeInputs only affected slider, so it lives there now. Page options related to the page sections are now located in the page.sections script, but they are still configurable via the page plugin's options api.

- Make, Ant, and index files are updated with a new load order for all JS files.
  • Loading branch information...
commit 2a6c7fc1b982c4308a0450a308f5a66a10e949cf 1 parent c7b6392
authored July 19, 2011
24  Makefile
@@ -46,21 +46,25 @@ JSFILES = 	  js/jquery.ui.widget.js \
46 46
 			  js/jquery.mobile.core.js \
47 47
 			  js/jquery.mobile.navigation.js \
48 48
 			  js/jquery.mobile.transition.js \
49  
-			  js/jquery.mobile.fixHeaderFooter.js \
  49
+			  js/jquery.mobile.dialog.js \
  50
+			  js/jquery.mobile.page.sections.js \
  51
+			  js/jquery.mobile.collapsible.js \
  52
+			  js/jquery.mobile.fieldContain.js \
  53
+			  js/jquery.mobile.grid.js \
  54
+			  js/jquery.mobile.navbar.js \
  55
+			  js/jquery.mobile.listview.js \
  56
+			  js/jquery.mobile.listview.filter.js \
  57
+			  js/jquery.mobile.nojs.js \
50 58
 			  js/jquery.mobile.forms.checkboxradio.js \
  59
+			  js/jquery.mobile.forms.button.js \
  60
+			  js/jquery.mobile.forms.slider.js \
51 61
 			  js/jquery.mobile.forms.textinput.js \
52 62
 			  js/jquery.mobile.forms.select.js \
53 63
 			  js/jquery.mobile.buttonMarkup.js \
54  
-			  js/jquery.mobile.forms.button.js \
55  
-			  js/jquery.mobile.forms.slider.js \
56  
-			  js/jquery.mobile.collapsible.js \
57 64
 			  js/jquery.mobile.controlGroup.js \
58  
-			  js/jquery.mobile.fieldContain.js \
59  
-			  js/jquery.mobile.listview.js \
60  
-			  js/jquery.mobile.listview.filter.js \
61  
-			  js/jquery.mobile.dialog.js \
62  
-			  js/jquery.mobile.navbar.js \
63  
-			  js/jquery.mobile.grid.js \
  65
+			  js/jquery.mobile.links.js \
  66
+			  js/jquery.mobile.fixHeaderFooter.js \
  67
+			  js/jquery.mobile.media.classes.js \
64 68
 			  js/jquery.mobile.init.js
65 69
 
66 70
 # The files to include when compiling the CSS files
58  build.xml
@@ -19,33 +19,37 @@
19 19
 	jquery.mobile.forms.textinput.css,
20 20
 	jquery.mobile.listview.css,
21 21
 	jquery.mobile.forms.slider.css"/>
22  
-	<property name="js-sources" value="jquery.ui.widget.js,
23  
-	jquery.mobile.widget.js,
24  
-	jquery.mobile.media.js,
25  
-	jquery.mobile.support.js,
26  
-	jquery.mobile.vmouse.js,
27  
-	jquery.mobile.event.js,
28  
-	jquery.mobile.hashchange.js,
29  
-	jquery.mobile.page.js,
30  
-	jquery.mobile.core.js,
31  
-	jquery.mobile.navigation.js,
32  
-	jquery.mobile.transition.js,
33  
-	jquery.mobile.fixHeaderFooter.js,
34  
-	jquery.mobile.forms.checkboxradio.js,
35  
-	jquery.mobile.forms.textinput.js,
36  
-	jquery.mobile.forms.select.js,
37  
-	jquery.mobile.buttonMarkup.js,
38  
-	jquery.mobile.forms.button.js,
39  
-	jquery.mobile.forms.slider.js,
40  
-	jquery.mobile.collapsible.js,
41  
-	jquery.mobile.controlGroup.js,
42  
-	jquery.mobile.fieldContain.js,
43  
-	jquery.mobile.listview.js,
44  
-	jquery.mobile.listview.filter.js,
45  
-	jquery.mobile.dialog.js,
46  
-	jquery.mobile.navbar.js,
47  
-	jquery.mobile.grid.js,
48  
-	jquery.mobile.init.js"/>
  22
+	<property name="js-sources" value="js/jquery.ui.widget.js,
  23
+		  js/jquery.mobile.widget.js,
  24
+		  js/jquery.mobile.media.js,
  25
+		  js/jquery.mobile.support.js,
  26
+		  js/jquery.mobile.vmouse.js,
  27
+		  js/jquery.mobile.event.js,
  28
+		  js/jquery.mobile.hashchange.js,
  29
+		  js/jquery.mobile.page.js,
  30
+		  js/jquery.mobile.core.js,
  31
+		  js/jquery.mobile.navigation.js,
  32
+		  js/jquery.mobile.transition.js,
  33
+		  js/jquery.mobile.dialog.js,
  34
+		  js/jquery.mobile.page.sections.js,
  35
+		  js/jquery.mobile.collapsible.js,
  36
+		  js/jquery.mobile.fieldContain.js,
  37
+		  js/jquery.mobile.grid.js,
  38
+		  js/jquery.mobile.navbar.js,
  39
+		  js/jquery.mobile.listview.js,
  40
+		  js/jquery.mobile.listview.filter.js,
  41
+		  js/jquery.mobile.nojs.js,
  42
+		  js/jquery.mobile.forms.checkboxradio.js,
  43
+		  js/jquery.mobile.forms.button.js,
  44
+		  js/jquery.mobile.forms.slider.js,
  45
+		  js/jquery.mobile.forms.textinput.js,
  46
+		  js/jquery.mobile.forms.select.js,
  47
+		  js/jquery.mobile.buttonMarkup.js,
  48
+		  js/jquery.mobile.controlGroup.js,
  49
+		  js/jquery.mobile.links.js,
  50
+		  js/jquery.mobile.fixHeaderFooter.js,
  51
+		  js/jquery.mobile.media.classes.js,
  52
+		  js/jquery.mobile.init.js"/>
49 53
 
50 54
 	<target name="merge">
51 55
 		<antcall target="merge_css" />
25  js/index.php
@@ -12,21 +12,26 @@
12 12
 	'jquery.mobile.core.js',
13 13
 	'jquery.mobile.navigation.js',
14 14
 	'jquery.mobile.transition.js',
15  
-	'jquery.mobile.fixHeaderFooter.js',
  15
+	
  16
+	'jquery.mobile.dialog.js',
  17
+	'jquery.mobile.page.sections.js',
  18
+	'jquery.mobile.collapsible.js',
  19
+	'jquery.mobile.fieldContain.js',
  20
+	'jquery.mobile.grid.js',
  21
+	'jquery.mobile.navbar.js',
  22
+	'jquery.mobile.listview.js',
  23
+	'jquery.mobile.listview.filter.js',
  24
+	'jquery.mobile.nojs.js',
16 25
 	'jquery.mobile.forms.checkboxradio.js',
  26
+	'jquery.mobile.forms.button.js',
  27
+	'jquery.mobile.forms.slider.js',
17 28
 	'jquery.mobile.forms.textinput.js',
18 29
 	'jquery.mobile.forms.select.js',
19 30
 	'jquery.mobile.buttonMarkup.js',
20  
-	'jquery.mobile.forms.button.js',
21  
-	'jquery.mobile.forms.slider.js',
22  
-	'jquery.mobile.collapsible.js',
23 31
 	'jquery.mobile.controlGroup.js',
24  
-	'jquery.mobile.fieldContain.js',
25  
-	'jquery.mobile.listview.js',
26  
-	'jquery.mobile.listview.filter.js',
27  
-	'jquery.mobile.dialog.js',
28  
-	'jquery.mobile.navbar.js',
29  
-	'jquery.mobile.grid.js',
  32
+	'jquery.mobile.links.js',
  33
+	'jquery.mobile.fixHeaderFooter.js',
  34
+	'jquery.mobile.media.classes.js',
30 35
 	'jquery.mobile.init.js'
31 36
 );
32 37
 
9  js/jquery.mobile.buttonMarkup.js
@@ -138,4 +138,13 @@ var attachEvents = function() {
138 138
 	attachEvents = null;
139 139
 };
140 140
 
  141
+//links in bars, or those with  data-role become buttons
  142
+//auto self-init widgets
  143
+$( document ).bind( "pagecreate", function( e ){
  144
+
  145
+	$( ":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a", e.target )
  146
+		.not( ".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')" )
  147
+		.buttonMarkup();
  148
+});
  149
+
141 150
 })( jQuery );
5  js/jquery.mobile.collapsible.js
@@ -6,6 +6,11 @@
6 6
 */
7 7
 (function( $, undefined ) {
8 8
 
  9
+//auto self-init widgets
  10
+$( document ).bind( "pagecreate", function( e ){
  11
+	$( ":jqmData(role='collapsible')", e.target ).collapsible();
  12
+});
  13
+
9 14
 $.widget( "mobile.collapsible", $.mobile.widget, {
10 15
 	options: {
11 16
 		expandCueText: " click to expand contents",
13  js/jquery.mobile.controlGroup.js
@@ -4,15 +4,22 @@
4 4
 * Dual licensed under the MIT or GPL Version 2 licenses.
5 5
 * http://jquery.org/license
6 6
 */
7  
-(function($, undefined ) {
  7
+(function( $, undefined ) {
  8
+
  9
+//auto self-init widgets
  10
+$( document ).bind( "pagecreate", function( e ){
  11
+	$( ":jqmData(role='controlgroup')", e.target ).controlgroup({ excludeInvisible: false });
  12
+});
8 13
 
9 14
 $.fn.controlgroup = function( options ) {
10 15
 
11 16
 	return this.each(function() {
  17
+
12 18
 		var $el = $( this ),
13 19
 			o = $.extend({
14 20
 						direction: $el.jqmData( "type" ) || "vertical",
15  
-						shadow: false
  21
+						shadow: false,
  22
+						excludeInvisible: true
16 23
 					}, options ),
17 24
 			groupheading = $el.find( ">legend" ),
18 25
 			flCorners = o.direction == "horizontal" ? [ "ui-corner-left", "ui-corner-right" ] : [ "ui-corner-top", "ui-corner-bottom" ],
@@ -36,7 +43,7 @@ $.fn.controlgroup = function( options ) {
36 43
 				.filter( ":last" ).addClass( flCorners[ 1 ] ).addClass( "ui-controlgroup-last" );
37 44
 		}
38 45
 
39  
-		flipClasses( $el.find( ".ui-btn" + ( o.dontFilterOutInvisible ? "" : ":visible" ) ) );
  46
+		flipClasses( $el.find( ".ui-btn" + ( o.excludeInvisible ? ":visible" : "" ) ) );
40 47
 		flipClasses( $el.find( ".ui-btn-inner" ) );
41 48
 
42 49
 		if ( o.shadow ) {
19  js/jquery.mobile.dialog.js
@@ -6,25 +6,30 @@
6 6
 
7 7
 (function( $, window, undefined ) {
8 8
 
  9
+//auto self-init widgets
  10
+$( ":jqmData(role='dialog')" ).live( "pagecreate", function(){
  11
+	$( this ).dialog();
  12
+});
  13
+
9 14
 $.widget( "mobile.dialog", $.mobile.widget, {
10 15
 	options: {
11  
-		closeBtnText: "Close"
  16
+		closeBtnText 	: "Close",
  17
+		theme			: "a"
12 18
 	},
13 19
 	_create: function() {
14 20
 		var $el = this.element;
  21
+		
  22
+		$el.jqmData( "theme", this.options.theme );
15 23
 
16 24
 		// Class the markup for dialog styling
17 25
 		// Set aria role
18 26
 		$el.attr( "role", "dialog" )
19  
-			.addClass( "ui-page ui-dialog ui-body-a" )
20  
-			.find( ":jqmData(role=header)" )
  27
+			.addClass( "ui-dialog" )
  28
+			.find( ":jqmData(role='header')" )
21 29
 			.addClass( "ui-corner-top ui-overlay-shadow" )
22 30
 				.prepend( "<a href='#' data-" + $.mobile.ns + "icon='delete' data-" + $.mobile.ns + "rel='back' data-" + $.mobile.ns + "iconpos='notext'>"+ this.options.closeBtnText + "</a>" )
23 31
 			.end()
24  
-			.find( ".ui-content:not([class*='ui-body-'])" )
25  
-				.addClass( 'ui-body-c' )
26  
-			.end()
27  
-			.find( ".ui-content,:jqmData(role='footer')" )
  32
+			.find( ":jqmData(role='content'),:jqmData(role='footer')" )
28 33
 				.last()
29 34
 				.addClass( "ui-corner-bottom ui-overlay-shadow" );
30 35
 
5  js/jquery.mobile.fieldContain.js
@@ -7,6 +7,11 @@
7 7
 
8 8
 (function( $, undefined ) {
9 9
 
  10
+//auto self-init widgets
  11
+$( document ).bind( "pagecreate", function( e ){
  12
+	$( ":jqmData(role='fieldcontain')", e.target ).fieldcontain();
  13
+});
  14
+
10 15
 $.fn.fieldcontain = function( options ) {
11 16
 	return this.addClass( "ui-field-contain ui-body ui-br" );
12 17
 };
29  js/jquery.mobile.fixHeaderFooter.js
@@ -6,6 +6,35 @@
6 6
 */
7 7
 
8 8
 (function( $, undefined ) {
  9
+	
  10
+//auto self-init widgets
  11
+$( document ).bind( "pagecreate", function( e ){
  12
+	
  13
+	if( $( ":jqmData(position='fixed')", e.target ).length ){
  14
+		$( e.target ).each(function(){
  15
+			
  16
+			if ( !$.support.scrollTop ) {
  17
+				return this;
  18
+			}
  19
+
  20
+			var $this = $( this );
  21
+
  22
+			if ( $this.jqmData( "fullscreen" ) ) {
  23
+				$this.addClass( "ui-page-fullscreen" );
  24
+			}
  25
+
  26
+			// Should be slidedown
  27
+			$this.find( ".ui-header:jqmData(position='fixed')" ).addClass( "ui-header-fixed ui-fixed-inline fade" );
  28
+
  29
+			// Should be slideup
  30
+			$this.find( ".ui-footer:jqmData(position='fixed')" ).addClass( "ui-footer-fixed ui-fixed-inline fade" );
  31
+			
  32
+		})
  33
+		
  34
+	}
  35
+});
  36
+
  37
+
9 38
 
10 39
 $.fn.fixHeaderFooter = function( options ) {
11 40
 
7  js/jquery.mobile.forms.button.js
@@ -7,6 +7,13 @@
7 7
 
8 8
 (function( $, undefined ) {
9 9
 
  10
+//auto self-init widgets
  11
+$( document ).bind( "pagecreate", function( e ){
  12
+	$( "button, [type='button'], [type='submit'], [type='reset'], [type='image']", e.target )
  13
+		.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
  14
+		.button();
  15
+});
  16
+
10 17
 $.widget( "mobile.button", $.mobile.widget, {
11 18
 	options: {
12 19
 		theme: null,
7  js/jquery.mobile.forms.checkboxradio.js
@@ -7,6 +7,13 @@
7 7
 
8 8
 (function( $, undefined ) {
9 9
 
  10
+//auto self-init widgets
  11
+$( document ).bind( "pagecreate", function( e ){
  12
+	$( "input[type='checkbox'],input[type='radio']", e.target )
  13
+		.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
  14
+		.checkboxradio();
  15
+});
  16
+
10 17
 $.widget( "mobile.checkboxradio", $.mobile.widget, {
11 18
 	options: {
12 19
 		theme: null
7  js/jquery.mobile.forms.select.js
@@ -7,6 +7,13 @@
7 7
 
8 8
 (function( $, undefined ) {
9 9
 
  10
+//auto self-init widgets
  11
+$( document ).bind( "pagecreate", function( e ){
  12
+	$( "select:not(:jqmData(role='slider'))", e.target )
  13
+		.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
  14
+		.selectmenu();
  15
+});
  16
+
10 17
 $.widget( "mobile.selectmenu", $.mobile.widget, {
11 18
 	options: {
12 19
 		theme: null,
17  js/jquery.mobile.forms.slider.js
@@ -7,6 +7,23 @@
7 7
 
8 8
 ( function( $, undefined ) {
9 9
 
  10
+//auto self-init widgets
  11
+$( document ).bind( "pagecreate", function( e ){
  12
+
  13
+	var nativeSel = ":jqmData(role='none'), :jqmData(role='nojs')";
  14
+
  15
+	//degrade range back to number type
  16
+	$( "input[type='range']:not("+ nativeSel +")", e.target ).each(function(){
  17
+		$(this).replaceWith(
  18
+			$( "<div>" ).html( $(this).clone() ).html()
  19
+				.replace( /\s+type=["']?\w+['"]?/, " type=\"number\" data-" + $.mobile.ns + "role=\"slider\" " ) );
  20
+	});				
  21
+
  22
+	//now self-init
  23
+	$( ":jqmData(role='slider'):not("+ nativeSel +")", e.target ).slider();
  24
+
  25
+});
  26
+
10 27
 $.widget( "mobile.slider", $.mobile.widget, {
11 28
 	options: {
12 29
 		theme: null,
7  js/jquery.mobile.forms.textinput.js
@@ -7,6 +7,13 @@
7 7
 
8 8
 (function( $, undefined ) {
9 9
 
  10
+//auto self-init widgets
  11
+$( document ).bind( "pagecreate", function( e ){
  12
+	$( "input[type='text'], input[type='search'], input[type='number'], input[type='password'], textarea", e.target )
  13
+		.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
  14
+		.textinput();
  15
+});
  16
+
10 17
 $.widget( "mobile.textinput", $.mobile.widget, {
11 18
 	options: {
12 19
 		theme: null
20  js/jquery.mobile.links.js
... ...
@@ -0,0 +1,20 @@
6  js/jquery.mobile.listview.js
@@ -6,6 +6,12 @@
6 6
 */
7 7
 
8 8
 (function( $, undefined ) {
  9
+
  10
+//auto self-init widgets
  11
+$( document ).bind( "pagecreate", function( e ){
  12
+	$( ":jqmData(role='listview')", e.target ).listview();
  13
+});
  14
+
9 15
 //Keeps track of the number of lists per page UID
10 16
 //This allows support for multiple nested list in the same page
11 17
 //https://github.com/jquery/jquery-mobile/issues/1617
102  js/jquery.mobile.media.classes.js
... ...
@@ -0,0 +1,102 @@
  1
+/*
  2
+* jQuery Mobile Framework : resolution and CSS media query related helpers and behavior
  3
+* Copyright (c) jQuery Project
  4
+* Dual licensed under the MIT or GPL Version 2 licenses.
  5
+* http://jquery.org/license
  6
+*/
  7
+(function( $, undefined ) {
  8
+
  9
+var $window = $( window ),
  10
+	$html = $( "html" ),
  11
+
  12
+	//media-query-like width breakpoints, which are translated to classes on the html element
  13
+	resolutionBreakpoints = [ 320, 480, 768, 1024 ];
  14
+
  15
+/*
  16
+	private function for adding/removing breakpoint classes to HTML element for faux media-query support
  17
+	It does not require media query support, instead using JS to detect screen width > cross-browser support
  18
+	This function is called on orientationchange, resize, and mobileinit, and is bound via the 'htmlclass' event namespace
  19
+*/
  20
+function detectResolutionBreakpoints() {
  21
+	var currWidth = $window.width(),
  22
+		minPrefix = "min-width-",
  23
+		maxPrefix = "max-width-",
  24
+		minBreakpoints = [],
  25
+		maxBreakpoints = [],
  26
+		unit = "px",
  27
+		breakpointClasses;
  28
+
  29
+	$html.removeClass( minPrefix + resolutionBreakpoints.join(unit + " " + minPrefix) + unit + " " +
  30
+		maxPrefix + resolutionBreakpoints.join( unit + " " + maxPrefix) + unit );
  31
+
  32
+	$.each( resolutionBreakpoints, function( i, breakPoint ) {
  33
+		if( currWidth >= breakPoint ) {
  34
+			minBreakpoints.push( minPrefix + breakPoint + unit );
  35
+		}
  36
+		if( currWidth <= breakPoint ) {
  37
+			maxBreakpoints.push( maxPrefix + breakPoint + unit );
  38
+		}
  39
+	});
  40
+
  41
+	if ( minBreakpoints.length ) {
  42
+		breakpointClasses = minBreakpoints.join(" ");
  43
+	}
  44
+	if ( maxBreakpoints.length ) {
  45
+		breakpointClasses += " " +  maxBreakpoints.join(" ");
  46
+	}
  47
+
  48
+	$html.addClass( breakpointClasses );
  49
+};
  50
+
  51
+/* $.mobile.addResolutionBreakpoints method:
  52
+	pass either a number or an array of numbers and they'll be added to the min/max breakpoint classes
  53
+	Examples:
  54
+		$.mobile.addResolutionBreakpoints( 500 );
  55
+		$.mobile.addResolutionBreakpoints( [500, 1200] );
  56
+*/
  57
+$.mobile.addResolutionBreakpoints = function( newbps ) {
  58
+	if( $.type( newbps ) === "array" ){
  59
+		resolutionBreakpoints = resolutionBreakpoints.concat( newbps );
  60
+	} else {
  61
+		resolutionBreakpoints.push( newbps );
  62
+	}
  63
+
  64
+	resolutionBreakpoints.sort(function( a, b ) {
  65
+		return a - b;
  66
+	});
  67
+
  68
+	detectResolutionBreakpoints();
  69
+};
  70
+
  71
+/* on mobileinit, add classes to HTML element
  72
+	and set handlers to update those on orientationchange and resize
  73
+*/
  74
+$( document ).bind( "mobileinit.htmlclass", function() {
  75
+	// bind to orientationchange and resize
  76
+	// to add classes to HTML element for min/max breakpoints and orientation
  77
+
  78
+	var ev = $.support.orientation;
  79
+
  80
+	$window.bind( "orientationchange.htmlclass throttledResize.htmlclass", function( event ) {
  81
+
  82
+		// add orientation class to HTML element on flip/resize.
  83
+		if ( event.orientation ) {
  84
+			$html.removeClass( "portrait landscape" ).addClass( event.orientation );
  85
+		}
  86
+
  87
+		// add classes to HTML element for min/max breakpoints
  88
+		detectResolutionBreakpoints();
  89
+	});
  90
+});
  91
+
  92
+/* Manually trigger an orientationchange event when the dom ready event fires.
  93
+	This will ensure that any viewport meta tag that may have been injected
  94
+	has taken effect already, allowing us to properly calculate the width of the
  95
+	document.
  96
+*/
  97
+$(function() {
  98
+	//trigger event manually
  99
+	$window.trigger( "orientationchange.htmlclass" );
  100
+});
  101
+
  102
+})(jQuery);
93  js/jquery.mobile.media.js
@@ -7,11 +7,7 @@
7 7
 (function( $, undefined ) {
8 8
 
9 9
 var $window = $( window ),
10  
-	$html = $( "html" ),
11  
-
12  
-	//media-query-like width breakpoints, which are translated to classes on the html element
13  
-	resolutionBreakpoints = [ 320, 480, 768, 1024 ];
14  
-
  10
+	$html = $( "html" );
15 11
 
16 12
 /* $.mobile.media method: pass a CSS media type or query and get a bool return
17 13
 	note: this feature relies on actual media query support for media queries, though types will work most anywhere
@@ -48,91 +44,4 @@ $.mobile.media = (function() {
48 44
 	};
49 45
 })();
50 46
 
51  
-/*
52  
-	private function for adding/removing breakpoint classes to HTML element for faux media-query support
53  
-	It does not require media query support, instead using JS to detect screen width > cross-browser support
54  
-	This function is called on orientationchange, resize, and mobileinit, and is bound via the 'htmlclass' event namespace
55  
-*/
56  
-function detectResolutionBreakpoints() {
57  
-	var currWidth = $window.width(),
58  
-		minPrefix = "min-width-",
59  
-		maxPrefix = "max-width-",
60  
-		minBreakpoints = [],
61  
-		maxBreakpoints = [],
62  
-		unit = "px",
63  
-		breakpointClasses;
64  
-
65  
-	$html.removeClass( minPrefix + resolutionBreakpoints.join(unit + " " + minPrefix) + unit + " " +
66  
-		maxPrefix + resolutionBreakpoints.join( unit + " " + maxPrefix) + unit );
67  
-
68  
-	$.each( resolutionBreakpoints, function( i, breakPoint ) {
69  
-		if( currWidth >= breakPoint ) {
70  
-			minBreakpoints.push( minPrefix + breakPoint + unit );
71  
-		}
72  
-		if( currWidth <= breakPoint ) {
73  
-			maxBreakpoints.push( maxPrefix + breakPoint + unit );
74  
-		}
75  
-	});
76  
-
77  
-	if ( minBreakpoints.length ) {
78  
-		breakpointClasses = minBreakpoints.join(" ");
79  
-	}
80  
-	if ( maxBreakpoints.length ) {
81  
-		breakpointClasses += " " +  maxBreakpoints.join(" ");
82  
-	}
83  
-
84  
-	$html.addClass( breakpointClasses );
85  
-};
86  
-
87  
-/* $.mobile.addResolutionBreakpoints method:
88  
-	pass either a number or an array of numbers and they'll be added to the min/max breakpoint classes
89  
-	Examples:
90  
-		$.mobile.addResolutionBreakpoints( 500 );
91  
-		$.mobile.addResolutionBreakpoints( [500, 1200] );
92  
-*/
93  
-$.mobile.addResolutionBreakpoints = function( newbps ) {
94  
-	if( $.type( newbps ) === "array" ){
95  
-		resolutionBreakpoints = resolutionBreakpoints.concat( newbps );
96  
-	} else {
97  
-		resolutionBreakpoints.push( newbps );
98  
-	}
99  
-
100  
-	resolutionBreakpoints.sort(function( a, b ) {
101  
-		return a - b;
102  
-	});
103  
-
104  
-	detectResolutionBreakpoints();
105  
-};
106  
-
107  
-/* on mobileinit, add classes to HTML element
108  
-	and set handlers to update those on orientationchange and resize
109  
-*/
110  
-$( document ).bind( "mobileinit.htmlclass", function() {
111  
-	// bind to orientationchange and resize
112  
-	// to add classes to HTML element for min/max breakpoints and orientation
113  
-
114  
-	var ev = $.support.orientation;
115  
-
116  
-	$window.bind( "orientationchange.htmlclass throttledResize.htmlclass", function( event ) {
117  
-
118  
-		// add orientation class to HTML element on flip/resize.
119  
-		if ( event.orientation ) {
120  
-			$html.removeClass( "portrait landscape" ).addClass( event.orientation );
121  
-		}
122  
-
123  
-		// add classes to HTML element for min/max breakpoints
124  
-		detectResolutionBreakpoints();
125  
-	});
126  
-});
127  
-
128  
-/* Manually trigger an orientationchange event when the dom ready event fires.
129  
-	This will ensure that any viewport meta tag that may have been injected
130  
-	has taken effect already, allowing us to properly calculate the width of the
131  
-	document.
132  
-*/
133  
-$(function() {
134  
-	//trigger event manually
135  
-	$window.trigger( "orientationchange.htmlclass" );
136  
-});
137  
-
138 47
 })(jQuery);
5  js/jquery.mobile.navbar.js
@@ -7,6 +7,11 @@
7 7
 
8 8
 (function( $, undefined ) {
9 9
 
  10
+//auto self-init widgets
  11
+$( document ).bind( "pagecreate", function( e ){
  12
+	$( ":jqmData(role='navbar')", e.target ).navbar();
  13
+});
  14
+
10 15
 $.widget( "mobile.navbar", $.mobile.widget, {
11 16
 	options: {
12 17
 		iconpos: "top",
15  js/jquery.mobile.nojs.js
... ...
@@ -0,0 +1,15 @@
  1
+/*
  2
+* jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
  3
+* Copyright (c) jQuery Project
  4
+* Dual licensed under the MIT or GPL Version 2 licenses.
  5
+* http://jquery.org/license
  6
+*/
  7
+
  8
+(function( $, undefined ) {
  9
+
  10
+$( document ).bind( "pagecreate", function( e ){
  11
+	$( ":jqmData(role='nojs')", e.target ).addClass( "ui-nojs" );
  12
+	
  13
+});
  14
+
  15
+})( jQuery );
208  js/jquery.mobile.page.js
@@ -9,220 +9,18 @@
9 9
 
10 10
 $.widget( "mobile.page", $.mobile.widget, {
11 11
 	options: {
12  
-		backBtnText: "Back",
13  
-		addBackBtn: false,
14  
-		backBtnTheme: null,
15  
-		degradeInputs: {
16  
-			color: false,
17  
-			date: false,
18  
-			datetime: false,
19  
-			"datetime-local": false,
20  
-			email: false,
21  
-			month: false,
22  
-			number: false,
23  
-			range: "number",
24  
-			search: true,
25  
-			tel: false,
26  
-			time: false,
27  
-			url: false,
28  
-			week: false
29  
-		},
30  
-		keepNative: null
  12
+		theme: "c"
31 13
 	},
32 14
 
33 15
 	_create: function() {
34 16
 		var $elem = this.element,
35 17
 			o = this.options;
36 18
 
37  
-		this.keepNative = ":jqmData(role='none'), :jqmData(role='nojs')" +
38  
-						( o.keepNative ? ", " + o.keepNative : "" );
39  
-
40 19
 		if ( this._trigger( "beforeCreate" ) === false ) {
41 20
 			return;
42 21
 		}
43  
-
44  
-		// Some of the form elements currently rely on the presence of ui-page and ui-content
45  
-		// classes so we'll handle page and content roles outside of the main role processing
46  
-		// loop below.
47  
-		$elem.find( ":jqmData(role='page'), :jqmData(role='content')" ).andSelf().each(function() {
48  
-			var $this = $( this );
49  
-
50  
-			$this.addClass( "ui-" + $this.jqmData( "role" ) );
51  
-		});
52  
-
53  
-		$elem.find( ":jqmData(role='nojs')" ).addClass( "ui-nojs" );
54  
-
55  
-		// Pre-find data els
56  
-		var $dataEls = $elem.find( ":jqmData(role)" ).andSelf().each(function() {
57  
-			var $this = $( this ),
58  
-				role = $this.jqmData( "role" ),
59  
-				theme = $this.jqmData( "theme" ),
60  
-				$headeranchors,
61  
-				leftbtn, rightbtn, backBtn;
62  
-
63  
-			//apply theming and markup modifications to page,header,content,footer
64  
-			if ( role === "header" || role === "footer" ) {
65  
-				$this.addClass( "ui-bar-" + (theme || $this.parent( ":jqmData(role='page')" ).jqmData( "theme" ) || "a") );
66  
-
67  
-				// Add ARIA role
68  
-				$this.attr( "role", role === "header" ? "banner" : "contentinfo" );
69  
-
70  
-				// Right,left buttons
71  
-				$headeranchors = $this.children( "a" );
72  
-				leftbtn = $headeranchors.hasClass( "ui-btn-left" );
73  
-				rightbtn = $headeranchors.hasClass( "ui-btn-right" );
74  
-
75  
-				if ( !leftbtn ) {
76  
-					leftbtn = $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
77  
-				}
78  
-
79  
-				if ( !rightbtn ) {
80  
-					rightbtn = $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
81  
-				}
82  
-
83  
-				// Auto-add back btn on pages beyond first view
84  
-				if ( o.addBackBtn && role === "header" &&
85  
-						$( ".ui-page" ).length > 1 &&
86  
-						$elem.jqmData( "url" ) !== $.mobile.path.stripHash( location.hash ) &&
87  
-						!leftbtn && $this.jqmData( "backbtn" ) !== false ) {
88  
-
89  
-					backBtn = $( "<a href='#' class='ui-btn-left' data-"+ $.mobile.ns +"rel='back' data-"+ $.mobile.ns +"icon='arrow-l'>"+ o.backBtnText +"</a>" ).prependTo( $this );
90  
-
91  
-					// If theme is provided, override default inheritance
92  
-					if ( o.backBtnTheme ) {
93  
-						backBtn.attr( "data-"+ $.mobile.ns +"theme", o.backBtnTheme );
94  
-					}
95  
-				}
96  
-
97  
-				// Page title
98  
-				$this.children( "h1, h2, h3, h4, h5, h6" )
99  
-					.addClass( "ui-title" )
100  
-					// Regardless of h element number in src, it becomes h1 for the enhanced page
101  
-					.attr({
102  
-						"tabindex": "0",
103  
-						"role": "heading",
104  
-						"aria-level": "1"
105  
-					});
106  
-
107  
-			} else if ( role === "content" ) {
108  
-
109  
-				if ( theme ) {
110  
-					$this.addClass( "ui-body-" + theme );
111  
-				}
112  
-
113  
-				// Add ARIA role
114  
-				$this.attr( "role", "main" );
115  
-
116  
-			} else if ( role === "page" ) {
117  
-				$this.addClass( "ui-body-" + (theme || "c") );
118  
-			}
119  
-
120  
-			switch ( role ) {
121  
-				case "header":
122  
-				case "footer":
123  
-				case "page":
124  
-				case "content":
125  
-					$this.addClass( "ui-" + role );
126  
-					break;
127  
-				case "collapsible":
128  
-				case "fieldcontain":
129  
-				case "navbar":
130  
-				case "listview":
131  
-				case "dialog":
132  
-					$this[ role ]();
133  
-					break;
134  
-			}
135  
-		});
136  
-
137  
-		//enhance form controls
138  
-  	this._enhanceControls();
139  
-
140  
-		//links in bars, or those with  data-role become buttons
141  
-		$elem.find( ":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a" )
142  
-			.not( ".ui-btn" )
143  
-			.not( this.keepNative )
144  
-			.buttonMarkup();
145  
-
146  
-		$elem.find( ":jqmData(role='controlgroup')" )
147  
-			.controlgroup({
148  
-				dontFilterOutInvisible: true
149  
-			});
150  
-
151  
-		// Links within content areas
152  
-		$elem.find( "a:not(.ui-btn):not(.ui-link-inherit)" )
153  
-			.not( this.keepNative )
154  
-			.addClass( "ui-link" );
155  
-
156  
-		// Fix toolbars
157  
-		$elem.fixHeaderFooter();
158  
-	},
159  
-
160  
-	_typeAttributeRegex: /\s+type=["']?\w+['"]?/,
161  
-
162  
-	_enhanceControls: function() {
163  
-		var o = this.options,
164  
-			self = this,
165  
-			allControls, nonNativeControls, textInputs;
166  
-
167  
-		// degrade inputs to avoid poorly implemented native functionality
168  
-		this.element.find( "input" ).not(this.keepNative).each(function() {
169  
-			var $this = $( this ),
170  
-				type = this.getAttribute( "type" ),
171  
-				optType = o.degradeInputs[ type ] || "text";
172  
-
173  
-			if ( o.degradeInputs[ type ] ) {
174  
-				$this.replaceWith(
175  
-					$( "<div>" ).html( $this.clone() ).html()
176  
-						.replace( self._typeAttributeRegex, " type=\"" + optType + "\" data-" + $.mobile.ns + "type=\"" + type + "\" " )
177  
-				);
178  
-			}
179  
-		});
180  
-
181  
-		// We re-find form elements since the degredation code above
182  
-		// may have injected new elements. We cache the non-native control
183  
-		// query to reduce the number of times we search through the entire page.
184  
-
185  
-		allControls = this.element.find("input, textarea, select, button");
186  
-		nonNativeControls = allControls.not(this.keepNative);
187  
-
188  
-		// XXX: Temporary workaround for issue 785. Turn off autocorrect and
189  
-		//      autocomplete since the popup they use can't be dismissed by
190  
-		//      the user. Note that we test for the presence of the feature
191  
-		//      by looking for the autocorrect property on the input element.
192  
-
193  
-		textInputs = allControls.filter( "input[type=text]" );
194  
-
195  
-		if ( textInputs.length && typeof textInputs[0].autocorrect !== "undefined" ) {
196  
-			textInputs.each(function() {
197  
-				// Set the attribute instead of the property just in case there
198  
-				// is code that attempts to make modifications via HTML.
199  
-				this.setAttribute( "autocorrect", "off" );
200  
-				this.setAttribute( "autocomplete", "off" );
201  
-			});
202  
-		}
203  
-
204  
-		// enchance form controls
205  
-		nonNativeControls
206  
-			.filter( "[type='radio'], [type='checkbox']" )
207  
-			.checkboxradio();
208  
-
209  
-		nonNativeControls
210  
-			.filter( "button, [type='button'], [type='submit'], [type='reset'], [type='image']" )
211  
-			.button();
212  
-
213  
-		nonNativeControls
214  
-			.filter( "input, textarea" )
215  
-			.not( "[type='radio'], [type='checkbox'], [type='button'], [type='submit'], [type='reset'], [type='image'], [type='hidden']" )
216  
-			.textinput();
217  
-
218  
-		nonNativeControls
219  
-			.filter( "input, select" )
220  
-			.filter( ":jqmData(role='slider'), :jqmData(type='range')" )
221  
-			.slider();
222  
-
223  
-		nonNativeControls
224  
-			.filter( "select:not(:jqmData(role='slider'))" )
225  
-			.selectmenu();
  22
+		
  23
+		$elem.addClass( "ui-page ui-body-" + o.theme );	
226 24
 	}
227 25
 });
228 26
 
91  js/jquery.mobile.page.sections.js
... ...
@@ -0,0 +1,91 @@
  1
+/*
  2
+* jQuery Mobile Framework : This plugin handles theming and layout of headers, footers, and content areas
  3
+* Copyright (c) jQuery Project
  4
+* Dual licensed under the MIT or GPL Version 2 licenses.
  5
+* http://jquery.org/license
  6
+*/
  7
+
  8
+(function( $, undefined ) {
  9
+
  10
+$.mobile.page.prototype.options.backBtnText		= "Back";
  11
+$.mobile.page.prototype.options.addBackBtn		= false;
  12
+$.mobile.page.prototype.options.backBtnTheme	= null;
  13
+$.mobile.page.prototype.options.headerTheme		= "a";
  14
+$.mobile.page.prototype.options.footerTheme		= "a";
  15
+$.mobile.page.prototype.options.contentTheme	= null;
  16
+
  17
+$( ":jqmData(role='page'), :jqmData(role='dialog')" ).live( "pagecreate", function( e ) {
  18
+	
  19
+	var $page		= $( this ),
  20
+		o			= $page.data( "page" ).options,
  21
+		pageTheme	= o.theme;
  22
+	
  23
+	$( ":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')", this ).each(function() {
  24
+		var $this	= $( this ),
  25
+			role	= $this.jqmData( "role" ),
  26
+			theme	= $this.jqmData( "theme" ),
  27
+			$headeranchors,
  28
+			leftbtn,
  29
+			rightbtn,
  30
+			backBtn;
  31
+			
  32
+		$this.addClass( "ui-" + role );	
  33
+
  34
+		//apply theming and markup modifications to page,header,content,footer
  35
+		if ( role === "header" || role === "footer" ) {
  36
+			
  37
+			var thisTheme = theme || pageTheme || ( role === "header" ? o.headerTheme : o.footerTheme );
  38
+
  39
+			//add theme class
  40
+			$this.addClass( "ui-bar-" + thisTheme );
  41
+
  42
+			// Add ARIA role
  43
+			$this.attr( "role", role === "header" ? "banner" : "contentinfo" );
  44
+
  45
+			// Right,left buttons
  46
+			$headeranchors	= $this.children( "a" );
  47
+			leftbtn			= $headeranchors.hasClass( "ui-btn-left" );
  48
+			rightbtn		= $headeranchors.hasClass( "ui-btn-right" );
  49
+
  50
+			if ( !leftbtn ) {
  51
+				leftbtn = $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
  52
+			}
  53
+
  54
+			if ( !rightbtn ) {
  55
+				rightbtn = $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
  56
+			}
  57
+
  58
+			// Auto-add back btn on pages beyond first view
  59
+			if ( o.addBackBtn && role === "header" &&
  60
+					$( ".ui-page" ).length > 1 &&
  61
+					$elem.jqmData( "url" ) !== $.mobile.path.stripHash( location.hash ) &&
  62
+					!leftbtn ) {
  63
+
  64
+				backBtn = $( "<a href='#' class='ui-btn-left' data-"+ $.mobile.ns +"rel='back' data-"+ $.mobile.ns +"icon='arrow-l'>"+ o.backBtnText +"</a>" ).prependTo( $this );
  65
+
  66
+				// If theme is provided, override default inheritance
  67
+				backBtn.attr( "data-"+ $.mobile.ns +"theme", o.backBtnTheme || thisTheme );
  68
+			}
  69
+
  70
+			// Page title
  71
+			$this.children( "h1, h2, h3, h4, h5, h6" )
  72
+				.addClass( "ui-title" )
  73
+				// Regardless of h element number in src, it becomes h1 for the enhanced page
  74
+				.attr({
  75
+					"tabindex": "0",
  76
+					"role": "heading",
  77
+					"aria-level": "1"
  78
+				});
  79
+
  80
+		} else if ( role === "content" ) {
  81
+
  82
+			$this.addClass( "ui-body-" + ( theme || pageTheme || o.contentTheme ) );
  83
+
  84
+			// Add ARIA role
  85
+			$this.attr( "role", "main" );
  86
+
  87
+		}
  88
+	});
  89
+});
  90
+
  91
+})( jQuery );
53  tests/unit/page-sections/index.html
... ...
@@ -0,0 +1,53 @@
  1
+<!DOCTYPE html>
  2
+<html lang="en">
  3
+<head>
  4
+	<meta charset="utf-8">
  5
+	<meta name="viewport" content="width=device-width, initial-scale=1">
  6
+	<title>jQuery Mobile Page Test Suite</title>
  7
+
  8
+	<script src="../../../js/jquery.js"></script>
  9
+	<script src="../jquery.setNameSpace.js"></script>
  10
+	<script src="../../../js/"></script>
  11
+	<script src="../../../tests/jquery.testHelper.js"></script>
  12
+
  13
+
  14
+	<link rel="stylesheet" href="../../../external/qunit.css"/>
  15
+	<script src="../../../external/qunit.js"></script>
  16
+
  17
+	<script src="page_core.js"></script>
  18
+</head>
  19
+<body>
  20
+
  21
+<h1 id="qunit-header">jQuery Mobile Page Test Suite</h1>
  22
+<h2 id="qunit-banner"></h2>
  23
+<h2 id="qunit-userAgent"></h2>
  24
+<ol id="qunit-tests">
  25
+</ol>
  26
+
  27
+<div id="qunit-fixture">
  28
+	<div  data-nstest-role="page">
  29
+		<div  data-nstest-role="header">
  30
+			<div>
  31
+				<a href="foo">foo</a>
  32
+			</div>
  33
+			<a href="foo">foo</a>
  34
+		</div><!-- /header -->
  35
+
  36
+		<div  data-nstest-role="footer">
  37
+			<div>
  38
+				<a href="foo">foo</a>
  39
+			</div>
  40
+
  41
+			<a href="foo">foo</a>
  42
+		</div><!-- /header -->
  43
+
  44
+		<div class="ui-bar">
  45
+			<div>
  46
+				<a href="foo">foo</a>
  47
+			</div>
  48
+
  49
+			<a href="foo">foo</a>
  50
+		</div>
  51
+	</div>
  52
+</body>
  53
+</html>
36  tests/unit/page-sections/page_core.js
... ...
@@ -0,0 +1,36 @@
  1
+/*
  2
+ * mobile page unit tests
  3
+ */
  4
+(function($){
  5
+	var libName = 'jquery.mobile.page.js';
  6
+
  7
+	module(libName);
  8
+
  9
+	test( "nested header anchors aren't altered", function(){
  10
+		ok(!$('.ui-header > div > a').hasClass('ui-btn'));
  11
+	});
  12
+
  13
+	test( "nested footer anchors aren't altered", function(){
  14
+		ok(!$('.ui-footer > div > a').hasClass('ui-btn'));
  15
+	});
  16
+
  17
+	test( "nested bar anchors aren't styled", function(){
  18
+		ok(!$('.ui-bar > div > a').hasClass('ui-btn'));
  19
+	});
  20
+
  21
+	test( "unnested footer anchors are styled", function(){
  22
+		ok($('.ui-footer > a').hasClass('ui-btn'));
  23
+	});
  24
+
  25
+	test( "unnested footer anchors are styled", function(){
  26
+		ok($('.ui-footer > a').hasClass('ui-btn'));
  27
+	});
  28
+
  29
+	test( "unnested bar anchors are styled", function(){
  30
+		ok($('.ui-bar > a').hasClass('ui-btn'));
  31
+	});
  32
+
  33
+	test( "no auto-generated back button exists on first page", function(){
  34
+		ok( !$(".ui-header > :jqmData(rel='back')").length );
  35
+	});
  36
+})(jQuery);
31  tests/unit/page/index.html
@@ -25,29 +25,12 @@ <h2 id="qunit-userAgent"></h2>
25 25
 </ol>
26 26
 
27 27
 <div id="qunit-fixture">
28  
-	<div  data-nstest-role="page">
29  
-		<div  data-nstest-role="header">
30  
-			<div>
31  
-				<a href="foo">foo</a>
32  
-			</div>
33  
-			<a href="foo">foo</a>
34  
-		</div><!-- /header -->
35  
-