Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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
scottjehl authored
Showing with 577 additions and 407 deletions.
  1. +14 −10 Makefile
  2. +31 −27 build.xml
  3. +15 −10 js/index.php
  4. +9 −0 js/jquery.mobile.buttonMarkup.js
  5. +5 −0 js/jquery.mobile.collapsible.js
  6. +10 −3 js/jquery.mobile.controlGroup.js
  7. +12 −7 js/jquery.mobile.dialog.js
  8. +5 −0 js/jquery.mobile.fieldContain.js
  9. +29 −0 js/jquery.mobile.fixHeaderFooter.js
  10. +7 −0 js/jquery.mobile.forms.button.js
  11. +7 −0 js/jquery.mobile.forms.checkboxradio.js
  12. +7 −0 js/jquery.mobile.forms.select.js
  13. +17 −0 js/jquery.mobile.forms.slider.js
  14. +7 −0 js/jquery.mobile.forms.textinput.js
  15. +20 −0 js/jquery.mobile.links.js
  16. +6 −0 js/jquery.mobile.listview.js
  17. +102 −0 js/jquery.mobile.media.classes.js
  18. +1 −92 js/jquery.mobile.media.js
  19. +5 −0 js/jquery.mobile.navbar.js
  20. +15 −0 js/jquery.mobile.nojs.js
  21. +3 −205 js/jquery.mobile.page.js
  22. +91 −0 js/jquery.mobile.page.sections.js
  23. +53 −0 tests/unit/page-sections/index.html
  24. +36 −0 tests/unit/page-sections/page_core.js
  25. +7 −24 tests/unit/page/index.html
  26. +59 −29 tests/unit/page/page_core.js
  27. +4 −0 tests/unit/slider/slider_events.js
24 Makefile
View
@@ -46,21 +46,25 @@ JSFILES = js/jquery.ui.widget.js \
js/jquery.mobile.core.js \
js/jquery.mobile.navigation.js \
js/jquery.mobile.transition.js \
- js/jquery.mobile.fixHeaderFooter.js \
+ js/jquery.mobile.dialog.js \
+ js/jquery.mobile.page.sections.js \
+ js/jquery.mobile.collapsible.js \
+ js/jquery.mobile.fieldContain.js \
+ js/jquery.mobile.grid.js \
+ js/jquery.mobile.navbar.js \
+ js/jquery.mobile.listview.js \
+ js/jquery.mobile.listview.filter.js \
+ js/jquery.mobile.nojs.js \
js/jquery.mobile.forms.checkboxradio.js \
+ js/jquery.mobile.forms.button.js \
+ js/jquery.mobile.forms.slider.js \
js/jquery.mobile.forms.textinput.js \
js/jquery.mobile.forms.select.js \
js/jquery.mobile.buttonMarkup.js \
- js/jquery.mobile.forms.button.js \
- js/jquery.mobile.forms.slider.js \
- js/jquery.mobile.collapsible.js \
js/jquery.mobile.controlGroup.js \
- js/jquery.mobile.fieldContain.js \
- js/jquery.mobile.listview.js \
- js/jquery.mobile.listview.filter.js \
- js/jquery.mobile.dialog.js \
- js/jquery.mobile.navbar.js \
- js/jquery.mobile.grid.js \
+ js/jquery.mobile.links.js \
+ js/jquery.mobile.fixHeaderFooter.js \
+ js/jquery.mobile.media.classes.js \
js/jquery.mobile.init.js
# The files to include when compiling the CSS files
58 build.xml
View
@@ -19,33 +19,37 @@
jquery.mobile.forms.textinput.css,
jquery.mobile.listview.css,
jquery.mobile.forms.slider.css"/>
- <property name="js-sources" value="jquery.ui.widget.js,
- jquery.mobile.widget.js,
- jquery.mobile.media.js,
- jquery.mobile.support.js,
- jquery.mobile.vmouse.js,
- jquery.mobile.event.js,
- jquery.mobile.hashchange.js,
- jquery.mobile.page.js,
- jquery.mobile.core.js,
- jquery.mobile.navigation.js,
- jquery.mobile.transition.js,
- jquery.mobile.fixHeaderFooter.js,
- jquery.mobile.forms.checkboxradio.js,
- jquery.mobile.forms.textinput.js,
- jquery.mobile.forms.select.js,
- jquery.mobile.buttonMarkup.js,
- jquery.mobile.forms.button.js,
- jquery.mobile.forms.slider.js,
- jquery.mobile.collapsible.js,
- jquery.mobile.controlGroup.js,
- jquery.mobile.fieldContain.js,
- jquery.mobile.listview.js,
- jquery.mobile.listview.filter.js,
- jquery.mobile.dialog.js,
- jquery.mobile.navbar.js,
- jquery.mobile.grid.js,
- jquery.mobile.init.js"/>
+ <property name="js-sources" value="js/jquery.ui.widget.js,
+ js/jquery.mobile.widget.js,
+ js/jquery.mobile.media.js,
+ js/jquery.mobile.support.js,
+ js/jquery.mobile.vmouse.js,
+ js/jquery.mobile.event.js,
+ js/jquery.mobile.hashchange.js,
+ js/jquery.mobile.page.js,
+ js/jquery.mobile.core.js,
+ js/jquery.mobile.navigation.js,
+ js/jquery.mobile.transition.js,
+ js/jquery.mobile.dialog.js,
+ js/jquery.mobile.page.sections.js,
+ js/jquery.mobile.collapsible.js,
+ js/jquery.mobile.fieldContain.js,
+ js/jquery.mobile.grid.js,
+ js/jquery.mobile.navbar.js,
+ js/jquery.mobile.listview.js,
+ js/jquery.mobile.listview.filter.js,
+ js/jquery.mobile.nojs.js,
+ js/jquery.mobile.forms.checkboxradio.js,
+ js/jquery.mobile.forms.button.js,
+ js/jquery.mobile.forms.slider.js,
+ js/jquery.mobile.forms.textinput.js,
+ js/jquery.mobile.forms.select.js,
+ js/jquery.mobile.buttonMarkup.js,
+ js/jquery.mobile.controlGroup.js,
+ js/jquery.mobile.links.js,
+ js/jquery.mobile.fixHeaderFooter.js,
+ js/jquery.mobile.media.classes.js,
+ js/jquery.mobile.init.js"/>
<target name="merge">
<antcall target="merge_css" />
25 js/index.php
View
@@ -12,21 +12,26 @@
'jquery.mobile.core.js',
'jquery.mobile.navigation.js',
'jquery.mobile.transition.js',
- 'jquery.mobile.fixHeaderFooter.js',
+
+ 'jquery.mobile.dialog.js',
+ 'jquery.mobile.page.sections.js',
+ 'jquery.mobile.collapsible.js',
+ 'jquery.mobile.fieldContain.js',
+ 'jquery.mobile.grid.js',
+ 'jquery.mobile.navbar.js',
+ 'jquery.mobile.listview.js',
+ 'jquery.mobile.listview.filter.js',
+ 'jquery.mobile.nojs.js',
'jquery.mobile.forms.checkboxradio.js',
+ 'jquery.mobile.forms.button.js',
+ 'jquery.mobile.forms.slider.js',
'jquery.mobile.forms.textinput.js',
'jquery.mobile.forms.select.js',
'jquery.mobile.buttonMarkup.js',
- 'jquery.mobile.forms.button.js',
- 'jquery.mobile.forms.slider.js',
- 'jquery.mobile.collapsible.js',
'jquery.mobile.controlGroup.js',
- 'jquery.mobile.fieldContain.js',
- 'jquery.mobile.listview.js',
- 'jquery.mobile.listview.filter.js',
- 'jquery.mobile.dialog.js',
- 'jquery.mobile.navbar.js',
- 'jquery.mobile.grid.js',
+ 'jquery.mobile.links.js',
+ 'jquery.mobile.fixHeaderFooter.js',
+ 'jquery.mobile.media.classes.js',
'jquery.mobile.init.js'
);
9 js/jquery.mobile.buttonMarkup.js
View
@@ -138,4 +138,13 @@ var attachEvents = function() {
attachEvents = null;
};
+//links in bars, or those with data-role become buttons
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+
+ $( ":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a", e.target )
+ .not( ".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')" )
+ .buttonMarkup();
+});
+
})( jQuery );
5 js/jquery.mobile.collapsible.js
View
@@ -6,6 +6,11 @@
*/
(function( $, undefined ) {
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+ $( ":jqmData(role='collapsible')", e.target ).collapsible();
+});
+
$.widget( "mobile.collapsible", $.mobile.widget, {
options: {
expandCueText: " click to expand contents",
13 js/jquery.mobile.controlGroup.js
View
@@ -4,15 +4,22 @@
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
-(function($, undefined ) {
+(function( $, undefined ) {
+
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+ $( ":jqmData(role='controlgroup')", e.target ).controlgroup({ excludeInvisible: false });
+});
$.fn.controlgroup = function( options ) {
return this.each(function() {
+
var $el = $( this ),
o = $.extend({
direction: $el.jqmData( "type" ) || "vertical",
- shadow: false
+ shadow: false,
+ excludeInvisible: true
}, options ),
groupheading = $el.find( ">legend" ),
flCorners = o.direction == "horizontal" ? [ "ui-corner-left", "ui-corner-right" ] : [ "ui-corner-top", "ui-corner-bottom" ],
@@ -36,7 +43,7 @@ $.fn.controlgroup = function( options ) {
.filter( ":last" ).addClass( flCorners[ 1 ] ).addClass( "ui-controlgroup-last" );
}
- flipClasses( $el.find( ".ui-btn" + ( o.dontFilterOutInvisible ? "" : ":visible" ) ) );
+ flipClasses( $el.find( ".ui-btn" + ( o.excludeInvisible ? ":visible" : "" ) ) );
flipClasses( $el.find( ".ui-btn-inner" ) );
if ( o.shadow ) {
19 js/jquery.mobile.dialog.js
View
@@ -6,25 +6,30 @@
(function( $, window, undefined ) {
+//auto self-init widgets
+$( ":jqmData(role='dialog')" ).live( "pagecreate", function(){
+ $( this ).dialog();
+});
+
$.widget( "mobile.dialog", $.mobile.widget, {
options: {
- closeBtnText: "Close"
+ closeBtnText : "Close",
+ theme : "a"
},
_create: function() {
var $el = this.element;
+
+ $el.jqmData( "theme", this.options.theme );
// Class the markup for dialog styling
// Set aria role
$el.attr( "role", "dialog" )
- .addClass( "ui-page ui-dialog ui-body-a" )
- .find( ":jqmData(role=header)" )
+ .addClass( "ui-dialog" )
+ .find( ":jqmData(role='header')" )
.addClass( "ui-corner-top ui-overlay-shadow" )
.prepend( "<a href='#' data-" + $.mobile.ns + "icon='delete' data-" + $.mobile.ns + "rel='back' data-" + $.mobile.ns + "iconpos='notext'>"+ this.options.closeBtnText + "</a>" )
.end()
- .find( ".ui-content:not([class*='ui-body-'])" )
- .addClass( 'ui-body-c' )
- .end()
- .find( ".ui-content,:jqmData(role='footer')" )
+ .find( ":jqmData(role='content'),:jqmData(role='footer')" )
.last()
.addClass( "ui-corner-bottom ui-overlay-shadow" );
5 js/jquery.mobile.fieldContain.js
View
@@ -7,6 +7,11 @@
(function( $, undefined ) {
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+ $( ":jqmData(role='fieldcontain')", e.target ).fieldcontain();
+});
+
$.fn.fieldcontain = function( options ) {
return this.addClass( "ui-field-contain ui-body ui-br" );
};
29 js/jquery.mobile.fixHeaderFooter.js
View
@@ -6,6 +6,35 @@
*/
(function( $, undefined ) {
+
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+
+ if( $( ":jqmData(position='fixed')", e.target ).length ){
+ $( e.target ).each(function(){
+
+ if ( !$.support.scrollTop ) {
+ return this;
+ }
+
+ var $this = $( this );
+
+ if ( $this.jqmData( "fullscreen" ) ) {
+ $this.addClass( "ui-page-fullscreen" );
+ }
+
+ // Should be slidedown
+ $this.find( ".ui-header:jqmData(position='fixed')" ).addClass( "ui-header-fixed ui-fixed-inline fade" );
+
+ // Should be slideup
+ $this.find( ".ui-footer:jqmData(position='fixed')" ).addClass( "ui-footer-fixed ui-fixed-inline fade" );
+
+ })
+
+ }
+});
+
+
$.fn.fixHeaderFooter = function( options ) {
7 js/jquery.mobile.forms.button.js
View
@@ -7,6 +7,13 @@
(function( $, undefined ) {
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+ $( "button, [type='button'], [type='submit'], [type='reset'], [type='image']", e.target )
+ .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
+ .button();
+});
+
$.widget( "mobile.button", $.mobile.widget, {
options: {
theme: null,
7 js/jquery.mobile.forms.checkboxradio.js
View
@@ -7,6 +7,13 @@
(function( $, undefined ) {
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+ $( "input[type='checkbox'],input[type='radio']", e.target )
+ .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
+ .checkboxradio();
+});
+
$.widget( "mobile.checkboxradio", $.mobile.widget, {
options: {
theme: null
7 js/jquery.mobile.forms.select.js
View
@@ -7,6 +7,13 @@
(function( $, undefined ) {
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+ $( "select:not(:jqmData(role='slider'))", e.target )
+ .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
+ .selectmenu();
+});
+
$.widget( "mobile.selectmenu", $.mobile.widget, {
options: {
theme: null,
17 js/jquery.mobile.forms.slider.js
View
@@ -7,6 +7,23 @@
( function( $, undefined ) {
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+
+ var nativeSel = ":jqmData(role='none'), :jqmData(role='nojs')";
+
+ //degrade range back to number type
+ $( "input[type='range']:not("+ nativeSel +")", e.target ).each(function(){
+ $(this).replaceWith(
+ $( "<div>" ).html( $(this).clone() ).html()
+ .replace( /\s+type=["']?\w+['"]?/, " type=\"number\" data-" + $.mobile.ns + "role=\"slider\" " ) );
+ });
+
+ //now self-init
+ $( ":jqmData(role='slider'):not("+ nativeSel +")", e.target ).slider();
+
+});
+
$.widget( "mobile.slider", $.mobile.widget, {
options: {
theme: null,
7 js/jquery.mobile.forms.textinput.js
View
@@ -7,6 +7,13 @@
(function( $, undefined ) {
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+ $( "input[type='text'], input[type='search'], input[type='number'], input[type='password'], textarea", e.target )
+ .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
+ .textinput();
+});
+
$.widget( "mobile.textinput", $.mobile.widget, {
options: {
theme: null
20 js/jquery.mobile.links.js
View
@@ -0,0 +1,20 @@
+/*
+* jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+
+(function( $, undefined ) {
+
+$( document ).bind( "pagecreate", function( e ){
+
+ //links within content areas
+ $( e.target )
+ .find( "a" )
+ .not( ".ui-btn, .ui-link-inherit, :jqmData(role='none'), :jqmData(role='nojs')" )
+ .addClass( "ui-link" );
+
+});
+
+})( jQuery );
6 js/jquery.mobile.listview.js
View
@@ -6,6 +6,12 @@
*/
(function( $, undefined ) {
+
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+ $( ":jqmData(role='listview')", e.target ).listview();
+});
+
//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
102 js/jquery.mobile.media.classes.js
View
@@ -0,0 +1,102 @@
+/*
+* jQuery Mobile Framework : resolution and CSS media query related helpers and behavior
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+(function( $, undefined ) {
+
+var $window = $( window ),
+ $html = $( "html" ),
+
+ //media-query-like width breakpoints, which are translated to classes on the html element
+ resolutionBreakpoints = [ 320, 480, 768, 1024 ];
+
+/*
+ private function for adding/removing breakpoint classes to HTML element for faux media-query support
+ It does not require media query support, instead using JS to detect screen width > cross-browser support
+ This function is called on orientationchange, resize, and mobileinit, and is bound via the 'htmlclass' event namespace
+*/
+function detectResolutionBreakpoints() {
+ var currWidth = $window.width(),
+ minPrefix = "min-width-",
+ maxPrefix = "max-width-",
+ minBreakpoints = [],
+ maxBreakpoints = [],
+ unit = "px",
+ breakpointClasses;
+
+ $html.removeClass( minPrefix + resolutionBreakpoints.join(unit + " " + minPrefix) + unit + " " +
+ maxPrefix + resolutionBreakpoints.join( unit + " " + maxPrefix) + unit );
+
+ $.each( resolutionBreakpoints, function( i, breakPoint ) {
+ if( currWidth >= breakPoint ) {
+ minBreakpoints.push( minPrefix + breakPoint + unit );
+ }
+ if( currWidth <= breakPoint ) {
+ maxBreakpoints.push( maxPrefix + breakPoint + unit );
+ }
+ });
+
+ if ( minBreakpoints.length ) {
+ breakpointClasses = minBreakpoints.join(" ");
+ }
+ if ( maxBreakpoints.length ) {
+ breakpointClasses += " " + maxBreakpoints.join(" ");
+ }
+
+ $html.addClass( breakpointClasses );
+};
+
+/* $.mobile.addResolutionBreakpoints method:
+ pass either a number or an array of numbers and they'll be added to the min/max breakpoint classes
+ Examples:
+ $.mobile.addResolutionBreakpoints( 500 );
+ $.mobile.addResolutionBreakpoints( [500, 1200] );
+*/
+$.mobile.addResolutionBreakpoints = function( newbps ) {
+ if( $.type( newbps ) === "array" ){
+ resolutionBreakpoints = resolutionBreakpoints.concat( newbps );
+ } else {
+ resolutionBreakpoints.push( newbps );
+ }
+
+ resolutionBreakpoints.sort(function( a, b ) {
+ return a - b;
+ });
+
+ detectResolutionBreakpoints();
+};
+
+/* on mobileinit, add classes to HTML element
+ and set handlers to update those on orientationchange and resize
+*/
+$( document ).bind( "mobileinit.htmlclass", function() {
+ // bind to orientationchange and resize
+ // to add classes to HTML element for min/max breakpoints and orientation
+
+ var ev = $.support.orientation;
+
+ $window.bind( "orientationchange.htmlclass throttledResize.htmlclass", function( event ) {
+
+ // add orientation class to HTML element on flip/resize.
+ if ( event.orientation ) {
+ $html.removeClass( "portrait landscape" ).addClass( event.orientation );
+ }
+
+ // add classes to HTML element for min/max breakpoints
+ detectResolutionBreakpoints();
+ });
+});
+
+/* Manually trigger an orientationchange event when the dom ready event fires.
+ This will ensure that any viewport meta tag that may have been injected
+ has taken effect already, allowing us to properly calculate the width of the
+ document.
+*/
+$(function() {
+ //trigger event manually
+ $window.trigger( "orientationchange.htmlclass" );
+});
+
+})(jQuery);
93 js/jquery.mobile.media.js
View
@@ -7,11 +7,7 @@
(function( $, undefined ) {
var $window = $( window ),
- $html = $( "html" ),
-
- //media-query-like width breakpoints, which are translated to classes on the html element
- resolutionBreakpoints = [ 320, 480, 768, 1024 ];
-
+ $html = $( "html" );
/* $.mobile.media method: pass a CSS media type or query and get a bool return
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() {
};
})();
-/*
- private function for adding/removing breakpoint classes to HTML element for faux media-query support
- It does not require media query support, instead using JS to detect screen width > cross-browser support
- This function is called on orientationchange, resize, and mobileinit, and is bound via the 'htmlclass' event namespace
-*/
-function detectResolutionBreakpoints() {
- var currWidth = $window.width(),
- minPrefix = "min-width-",
- maxPrefix = "max-width-",
- minBreakpoints = [],
- maxBreakpoints = [],
- unit = "px",
- breakpointClasses;
-
- $html.removeClass( minPrefix + resolutionBreakpoints.join(unit + " " + minPrefix) + unit + " " +
- maxPrefix + resolutionBreakpoints.join( unit + " " + maxPrefix) + unit );
-
- $.each( resolutionBreakpoints, function( i, breakPoint ) {
- if( currWidth >= breakPoint ) {
- minBreakpoints.push( minPrefix + breakPoint + unit );
- }
- if( currWidth <= breakPoint ) {
- maxBreakpoints.push( maxPrefix + breakPoint + unit );
- }
- });
-
- if ( minBreakpoints.length ) {
- breakpointClasses = minBreakpoints.join(" ");
- }
- if ( maxBreakpoints.length ) {
- breakpointClasses += " " + maxBreakpoints.join(" ");
- }
-
- $html.addClass( breakpointClasses );
-};
-
-/* $.mobile.addResolutionBreakpoints method:
- pass either a number or an array of numbers and they'll be added to the min/max breakpoint classes
- Examples:
- $.mobile.addResolutionBreakpoints( 500 );
- $.mobile.addResolutionBreakpoints( [500, 1200] );
-*/
-$.mobile.addResolutionBreakpoints = function( newbps ) {
- if( $.type( newbps ) === "array" ){
- resolutionBreakpoints = resolutionBreakpoints.concat( newbps );
- } else {
- resolutionBreakpoints.push( newbps );
- }
-
- resolutionBreakpoints.sort(function( a, b ) {
- return a - b;
- });
-
- detectResolutionBreakpoints();
-};
-
-/* on mobileinit, add classes to HTML element
- and set handlers to update those on orientationchange and resize
-*/
-$( document ).bind( "mobileinit.htmlclass", function() {
- // bind to orientationchange and resize
- // to add classes to HTML element for min/max breakpoints and orientation
-
- var ev = $.support.orientation;
-
- $window.bind( "orientationchange.htmlclass throttledResize.htmlclass", function( event ) {
-
- // add orientation class to HTML element on flip/resize.
- if ( event.orientation ) {
- $html.removeClass( "portrait landscape" ).addClass( event.orientation );
- }
-
- // add classes to HTML element for min/max breakpoints
- detectResolutionBreakpoints();
- });
-});
-
-/* Manually trigger an orientationchange event when the dom ready event fires.
- This will ensure that any viewport meta tag that may have been injected
- has taken effect already, allowing us to properly calculate the width of the
- document.
-*/
-$(function() {
- //trigger event manually
- $window.trigger( "orientationchange.htmlclass" );
-});
-
})(jQuery);
5 js/jquery.mobile.navbar.js
View
@@ -7,6 +7,11 @@
(function( $, undefined ) {
+//auto self-init widgets
+$( document ).bind( "pagecreate", function( e ){
+ $( ":jqmData(role='navbar')", e.target ).navbar();
+});
+
$.widget( "mobile.navbar", $.mobile.widget, {
options: {
iconpos: "top",
15 js/jquery.mobile.nojs.js
View
@@ -0,0 +1,15 @@
+/*
+* jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+
+(function( $, undefined ) {
+
+$( document ).bind( "pagecreate", function( e ){
+ $( ":jqmData(role='nojs')", e.target ).addClass( "ui-nojs" );
+
+});
+
+})( jQuery );
208 js/jquery.mobile.page.js
View
@@ -9,220 +9,18 @@
$.widget( "mobile.page", $.mobile.widget, {
options: {
- backBtnText: "Back",
- addBackBtn: false,
- backBtnTheme: null,
- degradeInputs: {
- color: false,
- date: false,
- datetime: false,
- "datetime-local": false,
- email: false,
- month: false,
- number: false,
- range: "number",
- search: true,
- tel: false,
- time: false,
- url: false,
- week: false
- },
- keepNative: null
+ theme: "c"
},
_create: function() {
var $elem = this.element,
o = this.options;
- this.keepNative = ":jqmData(role='none'), :jqmData(role='nojs')" +
- ( o.keepNative ? ", " + o.keepNative : "" );
-
if ( this._trigger( "beforeCreate" ) === false ) {
return;
}
-
- // Some of the form elements currently rely on the presence of ui-page and ui-content
- // classes so we'll handle page and content roles outside of the main role processing
- // loop below.
- $elem.find( ":jqmData(role='page'), :jqmData(role='content')" ).andSelf().each(function() {
- var $this = $( this );
-
- $this.addClass( "ui-" + $this.jqmData( "role" ) );
- });
-
- $elem.find( ":jqmData(role='nojs')" ).addClass( "ui-nojs" );
-
- // Pre-find data els
- var $dataEls = $elem.find( ":jqmData(role)" ).andSelf().each(function() {
- var $this = $( this ),
- role = $this.jqmData( "role" ),
- theme = $this.jqmData( "theme" ),
- $headeranchors,
- leftbtn, rightbtn, backBtn;
-
- //apply theming and markup modifications to page,header,content,footer
- if ( role === "header" || role === "footer" ) {
- $this.addClass( "ui-bar-" + (theme || $this.parent( ":jqmData(role='page')" ).jqmData( "theme" ) || "a") );
-
- // Add ARIA role
- $this.attr( "role", role === "header" ? "banner" : "contentinfo" );
-
- // Right,left buttons
- $headeranchors = $this.children( "a" );
- leftbtn = $headeranchors.hasClass( "ui-btn-left" );
- rightbtn = $headeranchors.hasClass( "ui-btn-right" );
-
- if ( !leftbtn ) {
- leftbtn = $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
- }
-
- if ( !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 &&
- $elem.jqmData( "url" ) !== $.mobile.path.stripHash( location.hash ) &&
- !leftbtn && $this.jqmData( "backbtn" ) !== false ) {
-
- backBtn = $( "<a href='#' class='ui-btn-left' data-"+ $.mobile.ns +"rel='back' data-"+ $.mobile.ns +"icon='arrow-l'>"+ o.backBtnText +"</a>" ).prependTo( $this );
-
- // If theme is provided, override default inheritance
- if ( o.backBtnTheme ) {
- backBtn.attr( "data-"+ $.mobile.ns +"theme", o.backBtnTheme );
- }
- }
-
- // 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({
- "tabindex": "0",
- "role": "heading",
- "aria-level": "1"
- });
-
- } else if ( role === "content" ) {
-
- if ( theme ) {
- $this.addClass( "ui-body-" + theme );
- }
-
- // Add ARIA role
- $this.attr( "role", "main" );
-
- } else if ( role === "page" ) {
- $this.addClass( "ui-body-" + (theme || "c") );
- }
-
- switch ( role ) {
- case "header":
- case "footer":
- case "page":
- case "content":
- $this.addClass( "ui-" + role );
- break;
- case "collapsible":
- case "fieldcontain":
- case "navbar":
- case "listview":
- case "dialog":
- $this[ role ]();
- break;
- }
- });
-
- //enhance form controls
- this._enhanceControls();
-
- //links in bars, or those with data-role become buttons
- $elem.find( ":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a" )
- .not( ".ui-btn" )
- .not( this.keepNative )
- .buttonMarkup();
-
- $elem.find( ":jqmData(role='controlgroup')" )
- .controlgroup({
- dontFilterOutInvisible: true
- });
-
- // Links within content areas
- $elem.find( "a:not(.ui-btn):not(.ui-link-inherit)" )
- .not( this.keepNative )
- .addClass( "ui-link" );
-
- // Fix toolbars
- $elem.fixHeaderFooter();
- },
-
- _typeAttributeRegex: /\s+type=["']?\w+['"]?/,
-
- _enhanceControls: function() {
- var o = this.options,
- self = this,
- allControls, nonNativeControls, textInputs;
-
- // degrade inputs to avoid poorly implemented native functionality
- this.element.find( "input" ).not(this.keepNative).each(function() {
- var $this = $( this ),
- type = this.getAttribute( "type" ),
- optType = o.degradeInputs[ type ] || "text";
-
- if ( o.degradeInputs[ type ] ) {
- $this.replaceWith(
- $( "<div>" ).html( $this.clone() ).html()
- .replace( self._typeAttributeRegex, " type=\"" + optType + "\" data-" + $.mobile.ns + "type=\"" + type + "\" " )
- );
- }
- });
-
- // We re-find form elements since the degredation code above
- // may have injected new elements. We cache the non-native control
- // query to reduce the number of times we search through the entire page.
-
- allControls = this.element.find("input, textarea, select, button");
- nonNativeControls = allControls.not(this.keepNative);
-
- // XXX: Temporary workaround for issue 785. Turn off autocorrect and
- // autocomplete 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.
-
- textInputs = allControls.filter( "input[type=text]" );
-
- if ( textInputs.length && typeof textInputs[0].autocorrect !== "undefined" ) {
- textInputs.each(function() {
- // Set the attribute instead of the property just in case there
- // is code that attempts to make modifications via HTML.
- this.setAttribute( "autocorrect", "off" );
- this.setAttribute( "autocomplete", "off" );
- });
- }
-
- // enchance form controls
- nonNativeControls
- .filter( "[type='radio'], [type='checkbox']" )
- .checkboxradio();
-
- nonNativeControls
- .filter( "button, [type='button'], [type='submit'], [type='reset'], [type='image']" )
- .button();
-
- nonNativeControls
- .filter( "input, textarea" )
- .not( "[type='radio'], [type='checkbox'], [type='button'], [type='submit'], [type='reset'], [type='image'], [type='hidden']" )
- .textinput();
-
- nonNativeControls
- .filter( "input, select" )
- .filter( ":jqmData(role='slider'), :jqmData(type='range')" )
- .slider();
-
- nonNativeControls
- .filter( "select:not(:jqmData(role='slider'))" )
- .selectmenu();
+
+ $elem.addClass( "ui-page ui-body-" + o.theme );
}
});
91 js/jquery.mobile.page.sections.js
View
@@ -0,0 +1,91 @@
+/*
+* jQuery Mobile Framework : This plugin handles theming and layout of headers, footers, and content areas
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+
+(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;
+
+$( ":jqmData(role='page'), :jqmData(role='dialog')" ).live( "pagecreate", function( e ) {
+
+ var $page = $( this ),
+ o = $page.data( "page" ).options,
+ pageTheme = o.theme;
+
+ $( ":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')", this ).each(function() {
+ var $this = $( this ),
+ role = $this.jqmData( "role" ),
+ theme = $this.jqmData( "theme" ),
+ $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 || pageTheme || ( role === "header" ? o.headerTheme : o.footerTheme );
+
+ //add theme class
+ $this.addClass( "ui-bar-" + thisTheme );
+
+ // Add ARIA role
+ $this.attr( "role", role === "header" ? "banner" : "contentinfo" );
+
+ // Right,left buttons
+ $headeranchors = $this.children( "a" );
+ leftbtn = $headeranchors.hasClass( "ui-btn-left" );
+ rightbtn = $headeranchors.hasClass( "ui-btn-right" );
+
+ if ( !leftbtn ) {
+ leftbtn = $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
+ }
+
+ if ( !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 &&
+ $elem.jqmData( "url" ) !== $.mobile.path.stripHash( location.hash ) &&
Jacob Gable
jgable added a note

There is no $elem defined here, and it causes an error when the addBackBtn option is set for the page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ !leftbtn ) {
+
+ backBtn = $( "<a href='#' class='ui-btn-left' data-"+ $.mobile.ns +"rel='back' data-"+ $.mobile.ns +"icon='arrow-l'>"+ o.backBtnText +"</a>" ).prependTo( $this );
+
+ // If theme is provided, override default inheritance
+ backBtn.attr( "data-"+ $.mobile.ns +"theme", o.backBtnTheme || thisTheme );
+ }
+
+ // 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({
+ "tabindex": "0",
+ "role": "heading",
+ "aria-level": "1"
+ });
+
+ } else if ( role === "content" ) {
+
+ $this.addClass( "ui-body-" + ( theme || pageTheme || o.contentTheme ) );
+
+ // Add ARIA role
+ $this.attr( "role", "main" );
+
+ }
+ });
+});
+
+})( jQuery );
53 tests/unit/page-sections/index.html
View
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>jQuery Mobile Page Test Suite</title>
+
+ <script src="../../../js/jquery.js"></script>
+ <script src="../jquery.setNameSpace.js"></script>
+ <script src="../../../js/"></script>
+ <script src="../../../tests/jquery.testHelper.js"></script>
+
+
+ <link rel="stylesheet" href="../../../external/qunit.css"/>
+ <script src="../../../external/qunit.js"></script>
+
+ <script src="page_core.js"></script>
+</head>
+<body>
+
+<h1 id="qunit-header">jQuery Mobile Page Test Suite</h1>
+<h2 id="qunit-banner"></h2>
+<h2 id="qunit-userAgent"></h2>
+<ol id="qunit-tests">
+</ol>
+
+<div id="qunit-fixture">
+ <div data-nstest-role="page">
+ <div data-nstest-role="header">
+ <div>
+ <a href="foo">foo</a>
+ </div>
+ <a href="foo">foo</a>
+ </div><!-- /header -->
+
+ <div data-nstest-role="footer">
+ <div>
+ <a href="foo">foo</a>
+ </div>
+
+ <a href="foo">foo</a>
+ </div><!-- /header -->
+
+ <div class="ui-bar">
+ <div>
+ <a href="foo">foo</a>
+ </div>
+
+ <a href="foo">foo</a>
+ </div>
+ </div>
+</body>
+</html>
36 tests/unit/page-sections/page_core.js
View
@@ -0,0 +1,36 @@
+/*
+ * mobile page unit tests
+ */
+(function($){
+ var libName = 'jquery.mobile.page.js';
+
+ module(libName);
+
+ test( "nested header anchors aren't altered", function(){
+ ok(!$('.ui-header > div > a').hasClass('ui-btn'));
+ });
+
+ test( "nested footer anchors aren't altered", function(){
+ ok(!$('.ui-footer > div > a').hasClass('ui-btn'));
+ });
+
+ test( "nested bar anchors aren't styled", function(){
+ ok(!$('.ui-bar > div > a').hasClass('ui-btn'));
+ });
+
+ test( "unnested footer anchors are styled", function(){
+ ok($('.ui-footer > a').hasClass('ui-btn'));
+ });
+
+ test( "unnested footer anchors are styled", function(){
+ ok($('.ui-footer > a').hasClass('ui-btn'));
+ });
+
+ test( "unnested bar anchors are styled", function(){
+ ok($('.ui-bar > a').hasClass('ui-btn'));
+ });
+
+ test( "no auto-generated back button exists on first page", function(){
+ ok( !$(".ui-header > :jqmData(rel='back')").length );
+ });
+})(jQuery);
31 tests/unit/page/index.html
View
@@ -25,29 +25,12 @@ <h2 id="qunit-userAgent"></h2>
</ol>
<div id="qunit-fixture">
- <div data-nstest-role="page">
- <div data-nstest-role="header">
- <div>
- <a href="foo">foo</a>
- </div>
- <a href="foo">foo</a>
- </div><!-- /header -->
-
- <div data-nstest-role="footer">
- <div>
- <a href="foo">foo</a>
- </div>
-
- <a href="foo">foo</a>
- </div><!-- /header -->
-
- <div class="ui-bar">
- <div>
- <a href="foo">foo</a>
- </div>
-
- <a href="foo">foo</a>
- </div>
- </div>
+ <div id="a" data-nstest-role="page"></div>
+
+
+ <div id="b" data-nstest-role="page" data-nstest-theme="e"></div>
+
+ <div id="c" data-nstest-role="page"></div>
+</div>
</body>
</html>
88 tests/unit/page/page_core.js
View
@@ -2,47 +2,77 @@
* mobile page unit tests
*/
(function($){
- var libName = 'jquery.mobile.page.js',
- typeAttributeRegex = $.mobile.page.prototype._typeAttributeRegex;
+ var libName = 'jquery.mobile.page.sections.js',
+ themedefault = $.mobile.page.prototype.options.theme;
module(libName);
+
+
+ var eventStack = [],
+ etargets = [],
+ cEvents=[],
+ cTargets=[];
- test( "nested header anchors aren't altered", function(){
- ok(!$('.ui-header > div > a').hasClass('ui-btn'));
+
+ $( document ).bind( "pagebeforecreate pagecreate", function( e ){
+ eventStack.push( e.type );
+ etargets.push( e.target );
});
-
- test( "nested footer anchors aren't altered", function(){
- ok(!$('.ui-footer > div > a').hasClass('ui-btn'));
+
+ $("#c").live( "pagebeforecreate", function( e ){
+
+ cEvents.push( e.type );
+ cTargets.push( e.target );
+ return false;
});
- test( "nested bar anchors aren't styled", function(){
- ok(!$('.ui-bar > div > a').hasClass('ui-btn'));
+ test( "pagecreate event fires when page is created", function(){
+ ok( eventStack[0] === "pagecreate" || eventStack[1] === "pagecreate" );
});
-
- test( "unnested footer anchors are styled", function(){
- ok($('.ui-footer > a').hasClass('ui-btn'));
+
+ test( "pagebeforecreate event fires when page is created", function(){
+ ok( eventStack[0] === "pagebeforecreate" || eventStack[1] === "pagebeforecreate" );
});
-
- test( "unnested footer anchors are styled", function(){
- ok($('.ui-footer > a').hasClass('ui-btn'));
+
+ test( "pagebeforecreate fires before pagecreate", function(){
+ ok( eventStack[0] === "pagebeforecreate" );
});
-
- test( "unnested bar anchors are styled", function(){
- ok($('.ui-bar > a').hasClass('ui-btn'));
+
+ test( "target of pagebeforecreate event was div #a", function(){
+ ok( $( etargets[0] ).is("#a") );
});
-
- test( "no auto-generated back button exists on first page", function(){
- ok( !$(".ui-header > :jqmData(rel='back')").length );
+
+ test( "target of pagecreate event was div #a" , function(){
+ ok( $( etargets[0] ).is("#a") );
+ });
+
+ test( "page element has ui-page class" , function(){
+ ok( $( "#a" ).hasClass( "ui-page" ) );
});
+
+ test( "page element has default body theme when not overidden" , function(){
+ ok( $( "#a" ).hasClass( "ui-body-" + themedefault ) );
+ });
+
+ test( "B page has non-default theme matching its data-theme attr" , function(){
+ $( "#b" ).page();
+ var btheme = $( "#b" ).jqmData( "theme" );
+ ok( $( "#b" ).hasClass( "ui-body-" + btheme ) );
+ });
+
- test( "input type replacement regex works properly", function(){
- ok(typeAttributeRegex.test( "<input type=range" ), "test no quotes" );
- ok(typeAttributeRegex.test( "<input type='range'" ), "test single quotes" );
- ok(typeAttributeRegex.test( "<input type=\"range\"" ), "test double quotes" );
- ok(typeAttributeRegex.test( "<input type=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_"), "test \w" );
- ok(typeAttributeRegex.test( "<input type=\"range\"" ), "test many preceding spaces" );
- ok(typeAttributeRegex.test( "<input type='range'>" ), "test final attribute (FF)" );
+ test( "Binding to pagebeforecreate and returning false prevents pagecreate event from firing" , function(){
+ $("#c").page();
- ok(!typeAttributeRegex.test( "<inputtype=\"range\"" ), "requires preceding space" );
+ ok( cEvents[0] === "pagebeforecreate" );
+ ok( !cTargets[1] );
});
+
+ test( "Binding to pagebeforecreate and returning false prevents classes from being applied to page" , function(){
+ ok( !$( "#b" ).hasClass( "ui-body-" + themedefault ) );
+ ok( !$( "#b" ).hasClass( "ui-page" ) );
+ });
+
+
+
})(jQuery);
4 tests/unit/slider/slider_events.js
View
@@ -99,6 +99,10 @@
slider.keyup();
same(slider.val(), "200");
});
+
+ test( "input type should degrade to number when slider is created", function(){
+ same($("#range-slider-up").attr( "type" ), "number");
+ });
// generic switch test function
var sliderSwitchTest = function(opts){
Jacob Gable

There is no $elem defined here, and it causes an error when the addBackBtn option is set for the page.

Please sign in to comment.
Something went wrong with that request. Please try again.