jquery_mobile_rails 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/README.rdoc +1 -1
  2. data/lib/jquery_mobile_rails/version.rb +1 -1
  3. data/test/dummy/db/development.sqlite3 +0 -0
  4. data/test/dummy/log/development.log +470 -0
  5. data/test/dummy/tmp/cache/assets/C8E/8B0/sprockets%2F52156458f704751589bb6d29ec84a52e +0 -0
  6. data/test/dummy/tmp/cache/assets/CB1/D10/sprockets%2F5827a2184097ddeeb4158ef641f00085 +0 -0
  7. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  8. data/test/dummy/tmp/cache/assets/CDE/910/sprockets%2F8af59305547610b5be0e9e038bb58f21 +0 -0
  9. data/test/dummy/tmp/cache/assets/D20/330/sprockets%2Fe76bd3b1395773eefc19cb17743e5846 +0 -0
  10. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  11. data/test/dummy/tmp/cache/assets/D38/BD0/sprockets%2Ffe52d2d1bcf248d028108d0c513e6d79 +0 -0
  12. data/test/dummy/tmp/cache/assets/D40/4D0/sprockets%2F20f705b59cf5abf8a0a7938b887b11f1 +0 -0
  13. data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  14. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  15. data/test/dummy/tmp/cache/assets/D5F/7B0/sprockets%2F1792255ae34105be22fabed9ba5e4d15 +0 -0
  16. data/test/dummy/tmp/cache/assets/D6C/7A0/sprockets%2Ff25aa7e262f1ff93154f29dc914afc20 +0 -0
  17. data/test/dummy/tmp/cache/assets/D9B/360/sprockets%2Fbb7052d2ba9883c28d4db137e1fb9b6c +0 -0
  18. data/test/dummy/tmp/cache/assets/DB7/390/sprockets%2Ff800b3c4a4a306067fea026fc7b2bbde +0 -0
  19. data/test/dummy/tmp/cache/assets/DDC/0B0/sprockets%2F63d8cfc5e184b372b7ec77cca69d4db7 +0 -0
  20. data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  21. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  22. data/test/dummy/tmp/cache/assets/E08/030/sprockets%2F21255d26ce8eda2e2e0e69dfbea8cf99 +0 -0
  23. data/test/dummy/tmp/cache/assets/E1F/BB0/sprockets%2F222d4a2c95dbe3c58acdb1df2a04bff9 +0 -0
  24. data/test/dummy/tmp/cache/assets/E9D/620/sprockets%2Fcbde7d2f6466ed4a7dddefc773f63eae +0 -0
  25. data/vendor/assets/images/jquery-mobile/icons-18-black.png +0 -0
  26. data/vendor/assets/images/jquery-mobile/icons-36-black.png +0 -0
  27. data/vendor/assets/javascripts/jquery.mobile.js +245 -77
  28. data/vendor/assets/javascripts/jquery.mobile.min.js +123 -117
  29. data/vendor/assets/stylesheets/jquery.mobile.css.scss +42 -42
  30. data/vendor/assets/stylesheets/jquery.mobile.min.css.scss +1 -1
  31. data/vendor/assets/stylesheets/jquery.mobile.structure.css +33 -11
  32. data/vendor/assets/stylesheets/jquery.mobile.structure.min.css +2 -2
  33. metadata +52 -8
@@ -1,8 +1,8 @@
1
1
  /*
2
- * jQuery Mobile Framework 1.0
2
+ * jQuery Mobile Framework 1.0.1
3
3
  * http://jquerymobile.com
4
4
  *
5
- * Copyright 2011 (c) jQuery Project
5
+ * Copyright 2011-2012 (c) jQuery Project
6
6
  * Dual licensed under the MIT or GPL Version 2 licenses.
7
7
  * http://jquery.org/license
8
8
  *
@@ -311,7 +311,7 @@ $.widget( "mobile.widget", {
311
311
  // TODO remove dependency on the page widget for the keepNative.
312
312
  // Currently the keepNative value is defined on the page prototype so
313
313
  // the method is as well
314
- var page = $(target).closest(":jqmData(role='page')").data( "page" ),
314
+ var page = $.mobile.closestPageData( $(target) ),
315
315
  keepNative = (page && page.keepNativeSelector()) || "";
316
316
 
317
317
  $( this.options.initSelector, target ).not( keepNative )[ this.widgetName ]();
@@ -422,7 +422,9 @@ $.mobile.browser.ie = (function() {
422
422
  div = document.createElement( "div" ),
423
423
  a = div.all || [];
424
424
 
425
- while ( div.innerHTML = "<!--[if gt IE " + ( ++v ) + "]><br><![endif]-->", a[ 0 ] );
425
+ // added {} to silence closure compiler warnings. registering my dislike of all things
426
+ // overly clever here for future reference
427
+ while ( div.innerHTML = "<!--[if gt IE " + ( ++v ) + "]><br><![endif]-->", a[ 0 ] ){};
426
428
 
427
429
  return v > 4 ? v : !v;
428
430
  })();
@@ -1161,7 +1163,37 @@ $.event.special.swipe = {
1161
1163
  var win = $( window ),
1162
1164
  special_event,
1163
1165
  get_orientation,
1164
- last_orientation;
1166
+ last_orientation,
1167
+ initial_orientation_is_landscape,
1168
+ initial_orientation_is_default,
1169
+ portrait_map = { "0": true, "180": true };
1170
+
1171
+ // It seems that some device/browser vendors use window.orientation values 0 and 180 to
1172
+ // denote the "default" orientation. For iOS devices, and most other smart-phones tested,
1173
+ // the default orientation is always "portrait", but in some Android and RIM based tablets,
1174
+ // the default orientation is "landscape". The following code injects a landscape orientation
1175
+ // media query into the document to figure out what the current orientation is, and then
1176
+ // makes adjustments to the portrait_map if necessary, so that we can properly
1177
+ // decode the window.orientation value whenever get_orientation() is called.
1178
+ if ( $.support.orientation ) {
1179
+
1180
+ // Use a media query to figure out the true orientation of the device at this moment.
1181
+ // Note that we've initialized the portrait map values to 0 and 180, *AND* we purposely
1182
+ // use a landscape media query so that if the device/browser does not support this particular
1183
+ // media query, we default to the assumption that portrait is the default orientation.
1184
+ initial_orientation_is_landscape = $.mobile.media("all and (orientation: landscape)");
1185
+
1186
+ // Now check to see if the current window.orientation is 0 or 180.
1187
+ initial_orientation_is_default = portrait_map[ window.orientation ];
1188
+
1189
+ // If the initial orientation is landscape, but window.orientation reports 0 or 180, *OR*
1190
+ // if the initial orientation is portrait, but window.orientation reports 90 or -90, we
1191
+ // need to flip our portrait_map values because landscape is the default orientation for
1192
+ // this device/browser.
1193
+ if ( ( initial_orientation_is_landscape && initial_orientation_is_default ) || ( !initial_orientation_is_landscape && !initial_orientation_is_default ) ) {
1194
+ portrait_map = { "-90": true, "90": true };
1195
+ }
1196
+ }
1165
1197
 
1166
1198
  $.event.special.orientationchange = special_event = {
1167
1199
  setup: function() {
@@ -1230,7 +1262,7 @@ $.event.special.swipe = {
1230
1262
  if ( $.support.orientation ) {
1231
1263
  // if the window orientation registers as 0 or 180 degrees report
1232
1264
  // portrait, otherwise landscape
1233
- isPortrait = window.orientation % 180 == 0;
1265
+ isPortrait = portrait_map[ window.orientation ];
1234
1266
  } else {
1235
1267
  isPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1;
1236
1268
  }
@@ -1374,8 +1406,6 @@ $.each({
1374
1406
  // part of jQuery BBQ, but also be available separately.
1375
1407
 
1376
1408
  (function($,window,undefined){
1377
- '$:nomunge'; // Used by YUI compressor.
1378
-
1379
1409
  // Reused string.
1380
1410
  var str_hashchange = 'hashchange',
1381
1411
 
@@ -1710,7 +1740,7 @@ $.widget( "mobile.page", $.mobile.widget, {
1710
1740
  }
1711
1741
  });
1712
1742
  })( jQuery );
1713
- /*
1743
+ /*
1714
1744
  * "core" - The base file for jQm
1715
1745
  */
1716
1746
 
@@ -1864,11 +1894,24 @@ $.widget( "mobile.page", $.mobile.widget, {
1864
1894
  }
1865
1895
  e = e.parentNode;
1866
1896
  }
1867
-
1897
+
1868
1898
  // Return the theme letter we found, if none, return the
1869
1899
  // specified default.
1870
1900
 
1871
1901
  return ltr || defaultTheme || "a";
1902
+ },
1903
+
1904
+ // TODO the following $ and $.fn extensions can/probably should be moved into jquery.mobile.core.helpers
1905
+ //
1906
+ // Find the closest javascript page element to gather settings data jsperf test
1907
+ // http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit
1908
+ // possibly naive, but it shows that the parsing overhead for *just* the page selector vs
1909
+ // the page and dialog selector is negligable. This could probably be speed up by
1910
+ // doing a similar parent node traversal to the one found in the inherited theme code above
1911
+ closestPageData: function( $target ) {
1912
+ return $target
1913
+ .closest(':jqmData(role="page"), :jqmData(role="dialog")')
1914
+ .data("page");
1872
1915
  }
1873
1916
  });
1874
1917
 
@@ -2194,6 +2237,19 @@ $.widget( "mobile.page", $.mobile.widget, {
2194
2237
  return ( u.hash && ( u.hrefNoHash === documentUrl.hrefNoHash || ( documentBaseDiffers && u.hrefNoHash === documentBase.hrefNoHash ) ) );
2195
2238
  }
2196
2239
  return (/^#/).test( u.href );
2240
+ },
2241
+
2242
+
2243
+ // Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR
2244
+ // requests if the document doing the request was loaded via the file:// protocol.
2245
+ // This is usually to allow the application to "phone home" and fetch app specific
2246
+ // data. We normally let the browser handle external/cross-domain urls, but if the
2247
+ // allowCrossDomainPages option is true, we will allow cross-domain http/https
2248
+ // requests to go through our page loading logic.
2249
+ isPermittedCrossDomainRequest: function( docUrl, reqUrl ) {
2250
+ return $.mobile.allowCrossDomainPages
2251
+ && docUrl.protocol === "file:"
2252
+ && reqUrl.search( /^https?:/ ) != -1;
2197
2253
  }
2198
2254
  },
2199
2255
 
@@ -3043,7 +3099,7 @@ $.widget( "mobile.page", $.mobile.widget, {
3043
3099
 
3044
3100
  // Kill the keyboard.
3045
3101
  // XXX_jblas: We need to stop crawling the entire document to kill focus. Instead,
3046
- // we should be tracking focus with a live() handler so we already have
3102
+ // we should be tracking focus with a delegate() handler so we already have
3047
3103
  // the element in hand at this point.
3048
3104
  // Wrap this in a try/catch block since IE9 throw "Unspecified error" if document.activeElement
3049
3105
  // is undefined when we are in an IFrame.
@@ -3169,13 +3225,12 @@ $.widget( "mobile.page", $.mobile.widget, {
3169
3225
  return path.makeUrlAbsolute( url, base);
3170
3226
  }
3171
3227
 
3172
-
3173
3228
  //The following event bindings should be bound after mobileinit has been triggered
3174
3229
  //the following function is called in the init file
3175
3230
  $.mobile._registerInternalEvents = function(){
3176
3231
 
3177
3232
  //bind to form submit events, handle with Ajax
3178
- $( "form" ).live('submit', function( event ) {
3233
+ $( document ).delegate( "form", "submit", function( event ) {
3179
3234
  var $this = $( this );
3180
3235
  if( !$.mobile.ajaxEnabled ||
3181
3236
  $this.is( ":jqmData(ajax='false')" ) ) {
@@ -3205,8 +3260,7 @@ $.widget( "mobile.page", $.mobile.widget, {
3205
3260
 
3206
3261
  url = path.makeUrlAbsolute( url, getClosestBaseUrl($this) );
3207
3262
 
3208
- //external submits use regular HTTP
3209
- if( path.isExternal( url ) || target ) {
3263
+ if(( path.isExternal( url ) && !path.isPermittedCrossDomainRequest(documentUrl, url)) || target ) {
3210
3264
  return;
3211
3265
  }
3212
3266
 
@@ -3314,12 +3368,11 @@ $.widget( "mobile.page", $.mobile.widget, {
3314
3368
  // data. We normally let the browser handle external/cross-domain urls, but if the
3315
3369
  // allowCrossDomainPages option is true, we will allow cross-domain http/https
3316
3370
  // requests to go through our page loading logic.
3317
- isCrossDomainPageLoad = ( $.mobile.allowCrossDomainPages && documentUrl.protocol === "file:" && href.search( /^https?:/ ) != -1 ),
3318
3371
 
3319
3372
  //check for protocol or rel and its not an embedded page
3320
3373
  //TODO overlap in logic from isExternal, rel=external check should be
3321
3374
  // moved into more comprehensive isExternalLink
3322
- isExternal = useDefaultUrlHandling || ( path.isExternal( href ) && !isCrossDomainPageLoad );
3375
+ isExternal = useDefaultUrlHandling || ( path.isExternal( href ) && !path.isPermittedCrossDomainRequest(documentUrl, href) );
3323
3376
 
3324
3377
  if( isExternal ) {
3325
3378
  httpCleanup();
@@ -3342,7 +3395,7 @@ $.widget( "mobile.page", $.mobile.widget, {
3342
3395
  });
3343
3396
 
3344
3397
  //prefetch pages when anchors with data-prefetch are encountered
3345
- $( ".ui-page" ).live( "pageshow.prefetch", function() {
3398
+ $( document ).delegate( ".ui-page", "pageshow.prefetch", function() {
3346
3399
  var urls = [];
3347
3400
  $( this ).find( "a:jqmData(prefetch)" ).each(function(){
3348
3401
  var $link = $(this),
@@ -3649,7 +3702,7 @@ $.mobile.page.prototype.options.degradeInputs = {
3649
3702
  //auto self-init widgets
3650
3703
  $( document ).bind( "pagecreate create", function( e ){
3651
3704
 
3652
- var page = $(e.target).closest(':jqmData(role="page")').data("page"), options;
3705
+ var page = $.mobile.closestPageData( $(e.target) );
3653
3706
 
3654
3707
  if( !page ) {
3655
3708
  return;
@@ -3711,7 +3764,10 @@ $.widget( "mobile.dialog", $.mobile.widget, {
3711
3764
  // this must be an anonymous function so that select menu dialogs can replace
3712
3765
  // the close method. This is a change from previously just defining data-rel=back
3713
3766
  // on the button and letting nav handle it
3714
- headerCloseButton.bind( "vclick", function() {
3767
+ //
3768
+ // Use click rather than vclick in order to prevent the possibility of unintentionally
3769
+ // reopening the dialog if the dialog opening item was directly under the close button.
3770
+ headerCloseButton.bind( "click", function() {
3715
3771
  self.close();
3716
3772
  });
3717
3773
 
@@ -3744,7 +3800,7 @@ $.widget( "mobile.dialog", $.mobile.widget, {
3744
3800
  });
3745
3801
 
3746
3802
  //auto self-init widgets
3747
- $( $.mobile.dialog.prototype.options.initSelector ).live( "pagecreate", function(){
3803
+ $( document ).delegate( $.mobile.dialog.prototype.options.initSelector, "pagecreate", function(){
3748
3804
  $( this ).dialog();
3749
3805
  });
3750
3806
 
@@ -3762,7 +3818,7 @@ $.mobile.page.prototype.options.headerTheme = "a";
3762
3818
  $.mobile.page.prototype.options.footerTheme = "a";
3763
3819
  $.mobile.page.prototype.options.contentTheme = null;
3764
3820
 
3765
- $( ":jqmData(role='page'), :jqmData(role='dialog')" ).live( "pagecreate", function( e ) {
3821
+ $( document ).delegate( ":jqmData(role='page'), :jqmData(role='dialog')", "pagecreate", function( e ) {
3766
3822
 
3767
3823
  var $page = $( this ),
3768
3824
  o = $page.data( "page" ).options,
@@ -3952,6 +4008,88 @@ $( document ).bind( "pagecreate create", function( e ){
3952
4008
  $( $.mobile.collapsible.prototype.options.initSelector, e.target ).collapsible();
3953
4009
  });
3954
4010
 
4011
+ })( jQuery );
4012
+ /*
4013
+ * "collapsibleset" plugin
4014
+ */
4015
+
4016
+ (function( $, undefined ) {
4017
+
4018
+ $.widget( "mobile.collapsibleset", $.mobile.widget, {
4019
+ options: {
4020
+ initSelector: ":jqmData(role='collapsible-set')"
4021
+ },
4022
+ _create: function() {
4023
+ var $el = this.element.addClass( "ui-collapsible-set" ),
4024
+ o = this.options,
4025
+ collapsiblesInSet = $el.children( ":jqmData(role='collapsible')" );
4026
+
4027
+ // Inherit the theme from collapsible-set
4028
+ if ( !o.theme ) {
4029
+ o.theme = $el.jqmData( "theme" );
4030
+ }
4031
+ // Inherit the content-theme from collapsible-set
4032
+ if ( !o.contentTheme ) {
4033
+ o.contentTheme = $el.jqmData( "content-theme" );
4034
+ }
4035
+
4036
+ // Initialize the collapsible set if it's not already initialized
4037
+ if ( !$el.jqmData( "collapsiblebound" ) ) {
4038
+
4039
+ $el
4040
+ .jqmData( "collapsiblebound", true )
4041
+ .bind( "expand collapse", function( event ) {
4042
+ var isCollapse = ( event.type === "collapse" ),
4043
+ collapsible = $( event.target ).closest( ".ui-collapsible" ),
4044
+ widget = collapsible.data( "collapsible" ),
4045
+ contentTheme = widget.options.contentTheme;
4046
+ if ( contentTheme && collapsible.jqmData( "collapsible-last" ) ) {
4047
+ collapsible.find( widget.options.heading ).first()
4048
+ .find( "a" ).first()
4049
+ .add( ".ui-btn-inner" )
4050
+ .toggleClass( "ui-corner-bottom", isCollapse );
4051
+ collapsible.find( ".ui-collapsible-content" ).toggleClass( "ui-corner-bottom", !isCollapse );
4052
+ }
4053
+ })
4054
+ .bind( "expand", function( event ) {
4055
+ $( event.target )
4056
+ .closest( ".ui-collapsible" )
4057
+ .siblings( ".ui-collapsible" )
4058
+ .trigger( "collapse" );
4059
+
4060
+ });
4061
+
4062
+ // clean up borders
4063
+ collapsiblesInSet.each( function() {
4064
+ $( this ).find( $.mobile.collapsible.prototype.options.heading )
4065
+ .find( "a" ).first()
4066
+ .add( ".ui-btn-inner" )
4067
+ .removeClass( "ui-corner-top ui-corner-bottom" );
4068
+ });
4069
+
4070
+ collapsiblesInSet.first()
4071
+ .find( "a" )
4072
+ .first()
4073
+ .addClass( "ui-corner-top" )
4074
+ .find( ".ui-btn-inner" )
4075
+ .addClass( "ui-corner-top" );
4076
+
4077
+ collapsiblesInSet.last()
4078
+ .jqmData( "collapsible-last", true )
4079
+ .find( "a" )
4080
+ .first()
4081
+ .addClass( "ui-corner-bottom" )
4082
+ .find( ".ui-btn-inner" )
4083
+ .addClass( "ui-corner-bottom" );
4084
+ }
4085
+ }
4086
+ });
4087
+
4088
+ //auto self-init widgets
4089
+ $( document ).bind( "pagecreate create", function( e ){
4090
+ $( $.mobile.collapsibleset.prototype.options.initSelector, e.target ).collapsibleset();
4091
+ });
4092
+
3955
4093
  })( jQuery );
3956
4094
  /*
3957
4095
  * "fieldcontain" plugin - simple class additions to make form row separators
@@ -4053,8 +4191,10 @@ $.widget( "mobile.navbar", $.mobile.widget, {
4053
4191
  });
4054
4192
 
4055
4193
  $navbar.delegate( "a", "vclick", function( event ) {
4056
- $navbtns.not( ".ui-state-persist" ).removeClass( $.mobile.activeBtnClass );
4057
- $( this ).addClass( $.mobile.activeBtnClass );
4194
+ if( !$(event.target).hasClass("ui-disabled") ) {
4195
+ $navbtns.not( ".ui-state-persist" ).removeClass( $.mobile.activeBtnClass );
4196
+ $( this ).addClass( $.mobile.activeBtnClass );
4197
+ }
4058
4198
  });
4059
4199
  }
4060
4200
  });
@@ -4477,7 +4617,7 @@ $.mobile.listview.prototype.options.filterCallback = function( text, searchValue
4477
4617
  return text.toLowerCase().indexOf( searchValue ) === -1;
4478
4618
  };
4479
4619
 
4480
- $( ":jqmData(role='listview')" ).live( "listviewcreate", function() {
4620
+ $( document ).delegate( ":jqmData(role='listview')", "listviewcreate", function() {
4481
4621
 
4482
4622
  var list = $( this ),
4483
4623
  listview = list.data( "listview" );
@@ -4503,13 +4643,11 @@ $( ":jqmData(role='listview')" ).live( "listviewcreate", function() {
4503
4643
  lastval = $this.jqmData( "lastval" ) + "",
4504
4644
  childItems = false,
4505
4645
  itemtext = "",
4506
- item, change;
4646
+ item;
4507
4647
 
4508
4648
  // Change val as lastval for next execution
4509
4649
  $this.jqmData( "lastval" , val );
4510
- change = val.substr( 0 , lastval.length - 1 ).replace( lastval , "" );
4511
-
4512
- if ( val.length < lastval.length || change.length != ( val.length - lastval.length ) ) {
4650
+ if ( val.length < lastval.length || val.indexOf(lastval) !== 0 ) {
4513
4651
 
4514
4652
  // Removed chars or pasted something totally different, check all items
4515
4653
  listItems = list.children();
@@ -4604,7 +4742,7 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
4604
4742
  input = this.element,
4605
4743
  // NOTE: Windows Phone could not find the label through a selector
4606
4744
  // filter works though.
4607
- label = input.closest( "form,fieldset,:jqmData(role='page')" ).find( "label[for='" + input[ 0 ].id + "']"),
4745
+ label = input.closest( "form,fieldset,:jqmData(role='page')" ).find( "label" ).filter( "[for='" + input[ 0 ].id + "']" ),
4608
4746
  inputtype = input.attr( "type" ),
4609
4747
  checkedState = inputtype + "-on",
4610
4748
  uncheckedState = inputtype + "-off",
@@ -4808,6 +4946,12 @@ $.widget( "mobile.button", $.mobile.widget, {
4808
4946
  name,
4809
4947
  $buttonPlaceholder;
4810
4948
 
4949
+ // if this is a link, check if it's been enhanced and, if not, use the right function
4950
+ if( $el[ 0 ].tagName === "A" ) {
4951
+ if ( !$el.hasClass( "ui-btn" ) ) $el.buttonMarkup();
4952
+ return;
4953
+ }
4954
+
4811
4955
  // Add ARIA role
4812
4956
  this.button = $( "<div></div>" )
4813
4957
  .text( $el.text() || $el.val() )
@@ -4960,7 +5104,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
4960
5104
  if ( cType == "select" ) {
4961
5105
 
4962
5106
  slider.wrapInner( "<div class='ui-slider-inneroffset'></div>" );
4963
-
5107
+
4964
5108
  // make the handle move with a smooth transition
4965
5109
  handle.addClass( "ui-slider-handle-snapping" );
4966
5110
 
@@ -5003,14 +5147,14 @@ $.widget( "mobile.slider", $.mobile.widget, {
5003
5147
  if ( self.dragging ) {
5004
5148
  // self.mouseMoved must be updated before refresh() because it will be used in the control "change" event
5005
5149
  self.mouseMoved = true;
5006
-
5150
+
5007
5151
  if ( cType === "select" ) {
5008
5152
  // make the handle move in sync with the mouse
5009
5153
  handle.removeClass( "ui-slider-handle-snapping" );
5010
5154
  }
5011
-
5155
+
5012
5156
  self.refresh( event );
5013
-
5157
+
5014
5158
  // only after refresh() you can calculate self.userModified
5015
5159
  self.userModified = self.beforeStart !== control[0].selectedIndex;
5016
5160
  return false;
@@ -5025,7 +5169,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
5025
5169
  if ( cType === "select" ) {
5026
5170
  self.beforeStart = control[0].selectedIndex;
5027
5171
  }
5028
-
5172
+
5029
5173
  self.refresh( event );
5030
5174
  return false;
5031
5175
  });
@@ -5037,12 +5181,12 @@ $.widget( "mobile.slider", $.mobile.widget, {
5037
5181
  self.dragging = false;
5038
5182
 
5039
5183
  if ( cType === "select") {
5040
-
5184
+
5041
5185
  // make the handle move with a smooth transition
5042
5186
  handle.addClass( "ui-slider-handle-snapping" );
5043
-
5187
+
5044
5188
  if ( self.mouseMoved ) {
5045
-
5189
+
5046
5190
  // this is a drag, change the value only if user dragged enough
5047
5191
  if ( self.userModified ) {
5048
5192
  self.refresh( self.beforeStart == 0 ? 1 : 0 );
@@ -5050,17 +5194,17 @@ $.widget( "mobile.slider", $.mobile.widget, {
5050
5194
  else {
5051
5195
  self.refresh( self.beforeStart );
5052
5196
  }
5053
-
5197
+
5054
5198
  }
5055
5199
  else {
5056
5200
  // this is just a click, change the value
5057
5201
  self.refresh( self.beforeStart == 0 ? 1 : 0 );
5058
5202
  }
5059
-
5203
+
5060
5204
  }
5061
-
5205
+
5062
5206
  self.mouseMoved = false;
5063
-
5207
+
5064
5208
  return false;
5065
5209
  }
5066
5210
  });
@@ -5133,14 +5277,15 @@ $.widget( "mobile.slider", $.mobile.widget, {
5133
5277
 
5134
5278
  refresh: function( val, isfromControl, preventInputUpdate ) {
5135
5279
 
5136
- if ( this.options.disabled || this.element.attr('disabled')) {
5280
+ if ( this.options.disabled || this.element.attr('disabled')) {
5137
5281
  this.disable();
5138
5282
  }
5139
5283
 
5140
5284
  var control = this.element, percent,
5141
5285
  cType = control[0].nodeName.toLowerCase(),
5142
5286
  min = cType === "input" ? parseFloat( control.attr( "min" ) ) : 0,
5143
- max = cType === "input" ? parseFloat( control.attr( "max" ) ) : control.find( "option" ).length - 1;
5287
+ max = cType === "input" ? parseFloat( control.attr( "max" ) ) : control.find( "option" ).length - 1,
5288
+ step = (cType === "input" && parseFloat( control.attr( "step" ) ) > 0) ? parseFloat(control.attr("step")) : 1;
5144
5289
 
5145
5290
  if ( typeof val === "object" ) {
5146
5291
  var data = val,
@@ -5154,7 +5299,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
5154
5299
  percent = Math.round( ( ( data.pageX - this.slider.offset().left ) / this.slider.width() ) * 100 );
5155
5300
  } else {
5156
5301
  if ( val == null ) {
5157
- val = cType === "input" ? parseFloat( control.val() ) : control[0].selectedIndex;
5302
+ val = cType === "input" ? parseFloat( control.val() || 0 ) : control[0].selectedIndex;
5158
5303
  }
5159
5304
  percent = ( parseFloat( val ) - min ) / ( max - min ) * 100;
5160
5305
  }
@@ -5171,7 +5316,18 @@ $.widget( "mobile.slider", $.mobile.widget, {
5171
5316
  percent = 100;
5172
5317
  }
5173
5318
 
5174
- var newval = Math.round( ( percent / 100 ) * ( max - min ) ) + min;
5319
+ var newval = ( percent / 100 ) * ( max - min ) + min;
5320
+
5321
+ //from jQuery UI slider, the following source will round to the nearest step
5322
+ var valModStep = ( newval - min ) % step;
5323
+ var alignValue = newval - valModStep;
5324
+
5325
+ if ( Math.abs( valModStep ) * 2 >= step ) {
5326
+ alignValue += ( valModStep > 0 ) ? step : ( -step );
5327
+ }
5328
+ // Since JavaScript has problems with large floats, round
5329
+ // the final value to 5 digits after the decimal point (see jQueryUI: #4124)
5330
+ newval = parseFloat( alignValue.toFixed(5) );
5175
5331
 
5176
5332
  if ( newval < min ) {
5177
5333
  newval = min;
@@ -5181,15 +5337,11 @@ $.widget( "mobile.slider", $.mobile.widget, {
5181
5337
  newval = max;
5182
5338
  }
5183
5339
 
5184
- // Flip the stack of the bg colors
5185
- if ( percent > 60 && cType === "select" ) {
5186
- // TODO: Dead path?
5187
- }
5188
5340
  this.handle.css( "left", percent + "%" );
5189
5341
  this.handle.attr( {
5190
5342
  "aria-valuenow": cType === "input" ? newval : control.find( "option" ).eq( newval ).attr( "value" ),
5191
5343
  "aria-valuetext": cType === "input" ? newval : control.find( "option" ).eq( newval ).getEncodedText(),
5192
- title: newval
5344
+ title: cType === "input" ? newval : control.find( "option" ).eq( newval ).getEncodedText()
5193
5345
  });
5194
5346
 
5195
5347
  // add/remove classes for flip toggle switch
@@ -5338,15 +5490,15 @@ $.widget( "mobile.textinput", $.mobile.widget, {
5338
5490
  keyupTimeout = setTimeout( keyup, keyupTimeoutBuffer );
5339
5491
  });
5340
5492
 
5493
+ // binding to pagechange here ensures that for pages loaded via
5494
+ // ajax the height is recalculated without user input
5495
+ $( document ).one( "pagechange", keyup );
5496
+
5341
5497
  // Issue 509: the browser is not providing scrollHeight properly until the styles load
5342
5498
  if ( $.trim( input.val() ) ) {
5343
5499
  // bind to the window load to make sure the height is calculated based on BOTH
5344
5500
  // the DOM and CSS
5345
5501
  $( window ).load( keyup );
5346
-
5347
- // binding to pagechange here ensures that for pages loaded via
5348
- // ajax the height is recalculated without user input
5349
- $( document ).one( "pagechange", keyup );
5350
5502
  }
5351
5503
  }
5352
5504
  },
@@ -5667,11 +5819,11 @@ $( document ).bind( "pagecreate create", function( e ){
5667
5819
  menuWidth = self.list.parent().outerWidth(),
5668
5820
  activePage = $( ".ui-page-active" ),
5669
5821
  tOverflow = $.support.touchOverflow && $.mobile.touchOverflowEnabled,
5670
- tScrollElem = activePage.is( ".ui-native-fixed" ) ? activePage.find( ".ui-content" ) : activePage;
5822
+ tScrollElem = activePage.is( ".ui-native-fixed" ) ? activePage.find( ".ui-content" ) : activePage,
5671
5823
  scrollTop = tOverflow ? tScrollElem.scrollTop() : $( window ).scrollTop(),
5672
5824
  btnOffset = self.button.offset().top,
5673
- screenHeight = window.innerHeight,
5674
- screenWidth = window.innerWidth;
5825
+ screenHeight = $(window).height(),
5826
+ screenWidth = $(window).width();
5675
5827
 
5676
5828
  //add active class to button
5677
5829
  self.button.addClass( $.mobile.activeBtnClass );
@@ -5853,7 +6005,7 @@ $( document ).bind( "pagecreate create", function( e ){
5853
6005
  });
5854
6006
  };
5855
6007
 
5856
- $( "select" ).live( "selectmenubeforecreate", function(){
6008
+ $( document ).delegate( "select", "selectmenubeforecreate", function(){
5857
6009
  var selectmenuWidget = $( this ).data( "selectmenu" );
5858
6010
 
5859
6011
  if( !selectmenuWidget.options.nativeMenu ){
@@ -6074,7 +6226,6 @@ $( document ).bind( "pagecreate create", function( e ){
6074
6226
 
6075
6227
  $.fn.buttonMarkup = function( options ) {
6076
6228
  options = options || {};
6077
-
6078
6229
  for ( var i = 0; i < this.length; i++ ) {
6079
6230
  var el = this.eq( i ),
6080
6231
  e = el[ 0 ],
@@ -6098,6 +6249,15 @@ $.fn.buttonMarkup = function( options ) {
6098
6249
  buttonText = document.createElement( o.wrapperEls ),
6099
6250
  buttonIcon = o.icon ? document.createElement( "span" ) : null;
6100
6251
 
6252
+ // if so, prevent double enhancement, and continue with rest of the elements.
6253
+ if( e.tagName === "INPUT" && el.jqmData('role') === "button" ) continue;
6254
+
6255
+ // if this is a button, check if it's been enhanced and, if not, use the right function
6256
+ if( e.tagName === "BUTTON" ) {
6257
+ if ( !$( e.parentNode ).hasClass( "ui-btn" ) ) $( e ).button();
6258
+ continue;
6259
+ }
6260
+
6101
6261
  if ( attachEvents ) {
6102
6262
  attachEvents();
6103
6263
  }
@@ -6145,7 +6305,6 @@ $.fn.buttonMarkup = function( options ) {
6145
6305
  el.addClass( buttonClass );
6146
6306
 
6147
6307
  buttonInner.className = innerClass;
6148
- buttonInner.setAttribute("aria-hidden", "true");
6149
6308
 
6150
6309
  buttonText.className = textClass;
6151
6310
  buttonInner.appendChild( buttonText );
@@ -6160,7 +6319,7 @@ $.fn.buttonMarkup = function( options ) {
6160
6319
  }
6161
6320
 
6162
6321
  e.appendChild( buttonInner );
6163
-
6322
+
6164
6323
  // TODO obviously it would be nice to pull this element out instead of
6165
6324
  // retrieving it from the DOM again, but this change is much less obtrusive
6166
6325
  // and 1.0 draws nigh
@@ -6186,12 +6345,11 @@ function closestEnabledButton( element ) {
6186
6345
  // handed could be in an SVG DOM where className on SVG elements is defined to
6187
6346
  // be of a different type (SVGAnimatedString). We only operate on HTML DOM
6188
6347
  // elements, so we look for plain "string".
6189
-
6190
- cname = ( typeof element.className === 'string' ) && element.className.split(' ');
6191
-
6192
- if ( cname && $.inArray( "ui-btn", cname ) > -1 && $.inArray( "ui-disabled", cname ) < 0 ) {
6348
+ cname = ( typeof element.className === 'string' ) && (element.className + ' ');
6349
+ if ( cname && cname.indexOf("ui-btn ") > -1 && cname.indexOf("ui-disabled ") < 0 ) {
6193
6350
  break;
6194
6351
  }
6352
+
6195
6353
  element = element.parentNode;
6196
6354
  }
6197
6355
 
@@ -6475,9 +6633,7 @@ $.mobile.fixedToolbars = (function() {
6475
6633
 
6476
6634
  // 1. Before page is shown, check for duplicate footer
6477
6635
  // 2. After page is shown, append footer to new page
6478
- $( ".ui-page" )
6479
- .live( "pagebeforeshow", function( event, ui ) {
6480
-
6636
+ $( document ).delegate( ".ui-page", "pagebeforeshow", function( event, ui ) {
6481
6637
  var page = $( event.target ),
6482
6638
  footer = page.find( ":jqmData(role='footer')" ),
6483
6639
  id = footer.data( "id" ),
@@ -6490,12 +6646,10 @@ $.mobile.fixedToolbars = (function() {
6490
6646
  setTop( stickyFooter.removeClass( "fade in out" ).appendTo( $.mobile.pageContainer ) );
6491
6647
  }
6492
6648
  })
6493
- .live( "pageshow", function( event, ui ) {
6494
-
6649
+ .delegate( ".ui-page", "pageshow", function( event, ui ) {
6495
6650
  var $this = $( this );
6496
6651
 
6497
6652
  if ( stickyFooter && stickyFooter.length ) {
6498
-
6499
6653
  setTimeout(function() {
6500
6654
  setTop( stickyFooter.appendTo( $this ).addClass( "fade" ) );
6501
6655
  stickyFooter = null;
@@ -6505,8 +6659,8 @@ $.mobile.fixedToolbars = (function() {
6505
6659
  $.mobile.fixedToolbars.show( true, this );
6506
6660
  });
6507
6661
 
6508
- // When a collapsiable is hidden or shown we need to trigger the fixed toolbar to reposition itself (#1635)
6509
- $( ".ui-collapsible-contain" ).live( "collapse expand", showEventCallback );
6662
+ // When a collapsible is hidden or shown we need to trigger the fixed toolbar to reposition itself (#1635)
6663
+ $( document ).delegate( ".ui-collapsible-contain", "collapse expand", showEventCallback );
6510
6664
 
6511
6665
  // element.getBoundingClientRect() is broken in iOS 3.2.1 on the iPad. The
6512
6666
  // coordinates inside of the rect it returns don't have the page scroll position
@@ -6822,13 +6976,27 @@ $( document ).bind( "pagecreate", function( event ) {
6822
6976
  // find and enhance the pages in the dom and transition to the first page.
6823
6977
  initializePage: function() {
6824
6978
  // find present pages
6825
- var $pages = $( ":jqmData(role='page')" );
6979
+ var $dialogs, $pages = $( ":jqmData(role='page')" );
6826
6980
 
6827
- // if no pages are found, create one with body's inner html
6981
+ // if no pages are found, check for dialogs or create one with body's inner html
6828
6982
  if ( !$pages.length ) {
6829
- $pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role='page'></div>" ).children( 0 );
6983
+ $dialogs = $( ":jqmData(role='dialog')" );
6984
+
6985
+ // if there are no pages but a dialog is present, load it as a page
6986
+ if( $dialogs.length ) {
6987
+ // alter the attribute so it will be treated as a page unpon enhancement
6988
+ // TODO allow for the loading of a dialog as the first page (many considerations)
6989
+ $dialogs.first().attr( "data-" + $.mobile.ns + "role", "page" );
6990
+
6991
+ // remove the first dialog from the set of dialogs since it's now a page
6992
+ // add it to the empty set of pages to be loaded by the initial changepage
6993
+ $pages = $pages.add( $dialogs.get().shift() );
6994
+ } else {
6995
+ $pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role='page'></div>" ).children( 0 );
6996
+ }
6830
6997
  }
6831
6998
 
6999
+
6832
7000
  // add dialogs, set data-url attrs
6833
7001
  $pages.add( ":jqmData(role='dialog')" ).each(function() {
6834
7002
  var $this = $(this);