rhodes 3.3.3.beta.1 → 3.3.3.beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. data/CHANGELOG +3 -0
  2. data/Manifest.txt +23 -9
  3. data/Rakefile +13 -2
  4. data/doc/build.txt +18 -11
  5. data/doc/device-caps.txt +4 -68
  6. data/doc/rhom.txt +33 -0
  7. data/doc/test-log-debug.txt +18 -42
  8. data/lib/framework/rho/render.rb +1 -1
  9. data/lib/framework/rho/rho.rb +31 -1
  10. data/lib/framework/rho/rhocontroller.rb +2 -2
  11. data/lib/framework/rhodes.rb +1 -1
  12. data/lib/framework/rhoframework.rb +4 -0
  13. data/lib/framework/rholang/localization_simplified.rb +1 -1
  14. data/lib/framework/rhom/rhom_object_factory.rb +22 -1
  15. data/lib/framework/version.rb +1 -1
  16. data/lib/rhodes.rb +1 -1
  17. data/platform/android/Rhodes/AndroidManifest.xml +2 -2
  18. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_RhodesService.h +25 -9
  19. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_extmanager_RhoExtManagerImpl.h +21 -0
  20. data/platform/android/Rhodes/jni/src/extmanager.cpp +36 -0
  21. data/platform/android/Rhodes/jni/src/nativeview.cpp +1 -1
  22. data/platform/android/Rhodes/jni/src/rhodesapp.cpp +14 -5
  23. data/platform/android/Rhodes/jni/src/rhodessystem.cpp +5 -0
  24. data/platform/android/Rhodes/jni/src/signature.cpp +29 -3
  25. data/platform/android/Rhodes/src/com/rhomobile/rhodes/NativeBar.java +3 -3
  26. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesActivity.java +4 -0
  27. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesService.java +42 -7
  28. data/platform/android/Rhodes/src/com/rhomobile/rhodes/WebView.java +61 -10
  29. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/IRhoExtData.java +6 -0
  30. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/IRhoExtManager.java +39 -0
  31. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/IRhoExtension.java +18 -0
  32. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/RhoExtDataImpl.java +18 -0
  33. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/RhoExtManagerImpl.java +142 -0
  34. data/platform/android/Rhodes/src/com/rhomobile/rhodes/extmanager/RhoExtManagerSingleton.java +15 -0
  35. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/MainView.java +6 -3
  36. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/SimpleMainView.java +25 -13
  37. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/SplashScreen.java +15 -9
  38. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/TabbedMainView.java +15 -5
  39. data/platform/android/Rhodes/src/com/rhomobile/rhodes/nativeview/RhoNativeViewManager.java +3 -3
  40. data/platform/android/Rhodes/src/com/rhomobile/rhodes/signature/ImageCapture.java +14 -8
  41. data/platform/android/Rhodes/src/com/rhomobile/rhodes/signature/Signature.java +218 -51
  42. data/platform/android/Rhodes/src/com/rhomobile/rhodes/signature/SignatureProperties.java +94 -0
  43. data/platform/android/Rhodes/src/com/rhomobile/rhodes/signature/SignatureView.java +122 -37
  44. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/GoogleWebView.java +6 -2
  45. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/{WebView.java → IRhoWebView.java} +2 -1
  46. data/platform/android/Rhodes/src/com/rhomobile/rhodes/webview/RhoWebViewClient.java +4 -0
  47. data/platform/android/build/RhodesSRC_build.files +8 -1
  48. data/platform/android/build/android.rake +5 -1
  49. data/platform/android/build/librhodes_build.files +1 -0
  50. data/platform/bb/RubyVM/src/com/rho/RhodesApp.java +22 -1
  51. data/platform/bb/RubyVM/src/com/rho/sync/SyncSource.java +15 -0
  52. data/platform/bb/RubyVM/src/com/xruby/runtime/lang/RhoSupport.java +4 -0
  53. data/platform/bb/RubyVM/src/com/xruby/runtime/lang/RubyRuntime.java +4 -2
  54. data/platform/bb/build/rhodes_build.files +2 -0
  55. data/platform/bb/rhodes/src/com/rho/RhoRubyHelper.java +1 -1
  56. data/platform/bb/rhodes/src/com/rho/rubyext/PNGEncoder.java +613 -0
  57. data/platform/bb/rhodes/src/com/rho/rubyext/SignatureCapture.java +314 -0
  58. data/platform/bb/rhodes/src/com/rho/rubyext/WebView.java +1 -1
  59. data/platform/iphone/Classes/AppManager/AppManager.m +11 -0
  60. data/platform/iphone/Classes/Rhodes.m +1 -1
  61. data/platform/iphone/Classes/Signature/SignatureDelegate.h +5 -1
  62. data/platform/iphone/Classes/Signature/SignatureDelegate.m +186 -5
  63. data/platform/iphone/Classes/Signature/SignatureView.h +12 -0
  64. data/platform/iphone/Classes/Signature/SignatureView.m +11 -3
  65. data/platform/iphone/Classes/SimpleMainView.m +4 -0
  66. data/platform/iphone/Classes/rho/net/NetRequestImpl.m +98 -3
  67. data/platform/iphone/Info.plist +1 -1
  68. data/platform/iphone/rbuild/iphone.rake +18 -5
  69. data/platform/shared/RhoConnectClient/RhoConnectClient.cpp +1 -1
  70. data/platform/shared/common/ExtManager.h +64 -9
  71. data/platform/shared/common/RhoSimConf.h +1 -0
  72. data/platform/shared/common/RhodesApp.cpp +77 -28
  73. data/platform/shared/common/RhodesApp.h +9 -4
  74. data/platform/shared/common/RhodesAppBase.cpp +4 -3
  75. data/platform/shared/common/RhodesAppBase.h +5 -3
  76. data/platform/shared/net/HttpServer.cpp +4 -4
  77. data/platform/shared/net/HttpServer.h +2 -2
  78. data/platform/shared/qt/rhodes/impl/MainWindowImpl.cpp +1 -1
  79. data/platform/shared/qt/rhodes/main.cpp +1 -1
  80. data/platform/shared/ruby/ext/rho/rhoruby.c +12 -2
  81. data/platform/shared/ruby/ext/rho/rhosupport.c +11 -1
  82. data/platform/shared/ruby/thread_win32.c +2 -1
  83. data/platform/shared/rubyext/System.cpp +6 -0
  84. data/platform/shared/sync/SyncSource.cpp +15 -0
  85. data/platform/wm/RhoLib/RhoLib.vcproj +0 -4
  86. data/platform/wm/build/build_inf.js +34 -4
  87. data/platform/wm/build/wm.rake +75 -25
  88. data/platform/wm/rhodes/AppManager.cpp +14 -3
  89. data/platform/wm/rhodes/IBrowserEngine.h +7 -0
  90. data/platform/wm/rhodes/IEBrowserEngine.cpp +43 -0
  91. data/platform/wm/rhodes/IEBrowserEngine.h +7 -0
  92. data/platform/wm/rhodes/LogOptionsDlg.cpp +1 -1
  93. data/platform/wm/rhodes/MainWindow.cpp +92 -7
  94. data/platform/wm/rhodes/MainWindow.h +28 -1
  95. data/platform/wm/rhodes/MapView/MapViewManager.cpp +4 -4
  96. data/platform/wm/rhodes/Rhodes.cpp +149 -10
  97. data/platform/wm/rhodes/resource.h +5 -1
  98. data/platform/wm/rhodes/rho/common/ExtManager.cpp +307 -0
  99. data/platform/wm/rhodes/rho/rubyext/NativeToolbar.cpp +1 -1
  100. data/platform/wm/rhodes/rho/rubyext/RhoSignature.cpp +1 -1
  101. data/platform/wm/rhodes/rho/rubyext/RhoSignature.h +1 -1
  102. data/platform/wm/rhodes/rho/rubyext/SystemImpl.cpp +14 -2
  103. data/platform/wm/rhodes/rho/rubyext/WebView.cpp +6 -3
  104. data/platform/wm/rhodes/rhodes.vcproj +5 -1
  105. data/platform/wm/rhodes/simulator/MainWindowQt.cpp +22 -1
  106. data/platform/wm/rhodes/simulator/MainWindowQt.h +4 -0
  107. data/platform/wp7/RhoRubyExtGen/RhoWebView.cs +1 -1
  108. data/platform/wp7/RhoRubyLib/Initializers.Generated.cs +1 -1
  109. data/platform/wp7/RhoRubyLib/common/RhodesApp.cs +33 -38
  110. data/platform/wp7/RhoRubyLib/net/HttpServer.cs +134 -29
  111. data/platform/wp7/RhoRubyLib/rubyext/RhoWebView.cs +12 -2
  112. data/platform/wp7/RhoRubyLib/sync/SyncSource.cs +17 -1
  113. data/platform/wp7/RhoRubyLib/views/RhoTabHeader.xaml +3 -3
  114. data/platform/wp7/RhoRubyLib/views/RhoView.xaml.cs +48 -8
  115. data/rakefile.rb +13 -2
  116. data/res/build-tools/iphonesim/build/Release/iphonesim_43 +0 -0
  117. data/res/build-tools/iphonesim/iphonesim.xcodeproj/project.pbxproj +158 -0
  118. data/res/generators/rhogen.rb +33 -28
  119. data/res/generators/templates/application/app/layout.erb +6 -5
  120. data/res/generators/templates/application/public/css/android.css +21 -315
  121. data/res/generators/templates/application/public/css/iphone.css +1 -499
  122. data/res/generators/templates/application/public/css/jqmobile-patch.css +18 -5
  123. data/res/generators/templates/application/public/css/windows_phone7.css +378 -0
  124. data/res/generators/templates/application/public/jqmobile/images/icons-18-black.png +0 -0
  125. data/res/generators/templates/application/public/jqmobile/images/icons-36-black.png +0 -0
  126. data/res/generators/templates/application/public/jqmobile/{jquery.mobile-1.0.css → jquery.mobile-1.0.1.css} +33 -11
  127. data/res/generators/templates/application/public/jqmobile/{jquery.mobile-1.0.js → jquery.mobile-1.0.1.js} +249 -125
  128. data/res/generators/templates/application/public/jqmobile/jquery.mobile-1.0.1.min.css +2 -0
  129. data/res/generators/templates/application/public/jqmobile/jquery.mobile-1.0.1.min.js +177 -0
  130. data/res/generators/templates/application/public/jqmobile/{jquery.mobile.structure-1.0.css → jquery.mobile.structure-1.0.1.css} +33 -11
  131. data/res/generators/templates/application/public/jqmobile/jquery.mobile.structure-1.0.1.min.css +2 -0
  132. data/res/generators/templates/application/public/jquery/jquery.json-2.3.js +193 -0
  133. data/res/generators/templates/application/public/jquery/jquery.json-2.3.min.js +23 -0
  134. data/res/generators/templates/application/public/js/jquery-wp7-patch.js +68 -20
  135. data/spec/phone_spec/app/Case/case.rb +22 -0
  136. data/spec/phone_spec/app/Customer/customer.rb +16 -0
  137. data/spec/phone_spec/app/spec/rhom_object_spec.rb +108 -11
  138. data/spec/phone_spec/app/spec/syncengine_spec.rb +43 -1
  139. data/spec/phone_spec/build.yml +2 -1
  140. data/version +1 -1
  141. metadata +27 -13
  142. data/platform/shared/common/ExtManager.cpp +0 -103
  143. data/res/generators/templates/application/public/jqmobile/jquery-mobile-iphone.css +0 -9
  144. data/res/generators/templates/application/public/jqmobile/jquery.mobile-1.0.min.css +0 -2
  145. data/res/generators/templates/application/public/jqmobile/jquery.mobile-1.0.min.js +0 -172
  146. data/res/generators/templates/application/public/jqmobile/jquery.mobile.structure-1.0.min.css +0 -2
@@ -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,
@@ -3859,8 +3915,7 @@ $.widget( "mobile.collapsible", $.mobile.widget, {
3859
3915
  collapsible = $el.addClass( "ui-collapsible" ),
3860
3916
  collapsibleHeading = $el.children( o.heading ).first(),
3861
3917
  collapsibleContent = collapsible.wrapInner( "<div class='ui-collapsible-content'></div>" ).find( ".ui-collapsible-content" ),
3862
- collapsibleSet = $el.closest( ":jqmData(role='collapsible-set')" ).addClass( "ui-collapsible-set" ),
3863
- collapsiblesInSet = collapsibleSet.children( ":jqmData(role='collapsible')" );
3918
+ collapsibleSet = $el.closest( ":jqmData(role='collapsible-set')" ).addClass( "ui-collapsible-set" );
3864
3919
 
3865
3920
  // Replace collapsibleHeading if it's a legend
3866
3921
  if ( collapsibleHeading.is( "legend" ) ) {
@@ -3897,52 +3952,9 @@ $.widget( "mobile.collapsible", $.mobile.widget, {
3897
3952
  iconPos: "left",
3898
3953
  icon: "plus",
3899
3954
  theme: o.theme
3900
- });
3901
-
3902
- if ( !collapsibleSet.length ) {
3903
- collapsibleHeading
3904
- .find( "a" ).first().add( collapsibleHeading.find( ".ui-btn-inner" ) )
3905
- .addClass( "ui-corner-top ui-corner-bottom" );
3906
- } else {
3907
- // If we are in a collapsible set
3908
-
3909
- // Initialize the collapsible set if it's not already initialized
3910
- if ( !collapsibleSet.jqmData( "collapsiblebound" ) ) {
3911
-
3912
- collapsibleSet
3913
- .jqmData( "collapsiblebound", true )
3914
- .bind( "expand", function( event ) {
3915
-
3916
- $( event.target )
3917
- .closest( ".ui-collapsible" )
3918
- .siblings( ".ui-collapsible" )
3919
- .trigger( "collapse" );
3920
-
3921
- });
3922
- }
3923
-
3924
- collapsiblesInSet.first()
3925
- .find( "a" )
3926
- .first()
3927
- .addClass( "ui-corner-top" )
3928
- .find( ".ui-btn-inner" )
3929
- .addClass( "ui-corner-top" );
3930
-
3931
- collapsiblesInSet.last()
3932
- .jqmData( "collapsible-last", true )
3933
- .find( "a" )
3934
- .first()
3935
- .addClass( "ui-corner-bottom" )
3936
- .find( ".ui-btn-inner" )
3937
- .addClass( "ui-corner-bottom" );
3938
-
3939
-
3940
- if ( collapsible.jqmData( "collapsible-last" ) ) {
3941
- collapsibleHeading
3942
- .find( "a" ).first().add ( collapsibleHeading.find( ".ui-btn-inner" ) )
3943
- .addClass( "ui-corner-bottom" );
3944
- }
3945
- }
3955
+ })
3956
+ .add( ".ui-btn-inner" )
3957
+ .addClass( "ui-corner-top ui-corner-bottom" );
3946
3958
 
3947
3959
  //events
3948
3960
  collapsible
@@ -3996,6 +4008,88 @@ $( document ).bind( "pagecreate create", function( e ){
3996
4008
  $( $.mobile.collapsible.prototype.options.initSelector, e.target ).collapsible();
3997
4009
  });
3998
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
+
3999
4093
  })( jQuery );
4000
4094
  /*
4001
4095
  * "fieldcontain" plugin - simple class additions to make form row separators
@@ -4097,8 +4191,10 @@ $.widget( "mobile.navbar", $.mobile.widget, {
4097
4191
  });
4098
4192
 
4099
4193
  $navbar.delegate( "a", "vclick", function( event ) {
4100
- $navbtns.not( ".ui-state-persist" ).removeClass( $.mobile.activeBtnClass );
4101
- $( 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
+ }
4102
4198
  });
4103
4199
  }
4104
4200
  });
@@ -4521,7 +4617,7 @@ $.mobile.listview.prototype.options.filterCallback = function( text, searchValue
4521
4617
  return text.toLowerCase().indexOf( searchValue ) === -1;
4522
4618
  };
4523
4619
 
4524
- $( ":jqmData(role='listview')" ).live( "listviewcreate", function() {
4620
+ $( document ).delegate( ":jqmData(role='listview')", "listviewcreate", function() {
4525
4621
 
4526
4622
  var list = $( this ),
4527
4623
  listview = list.data( "listview" );
@@ -4547,13 +4643,11 @@ $( ":jqmData(role='listview')" ).live( "listviewcreate", function() {
4547
4643
  lastval = $this.jqmData( "lastval" ) + "",
4548
4644
  childItems = false,
4549
4645
  itemtext = "",
4550
- item, change;
4646
+ item;
4551
4647
 
4552
4648
  // Change val as lastval for next execution
4553
4649
  $this.jqmData( "lastval" , val );
4554
- change = val.substr( 0 , lastval.length - 1 ).replace( lastval , "" );
4555
-
4556
- if ( val.length < lastval.length || change.length != ( val.length - lastval.length ) ) {
4650
+ if ( val.length < lastval.length || val.indexOf(lastval) !== 0 ) {
4557
4651
 
4558
4652
  // Removed chars or pasted something totally different, check all items
4559
4653
  listItems = list.children();
@@ -4648,7 +4742,7 @@ $.widget( "mobile.checkboxradio", $.mobile.widget, {
4648
4742
  input = this.element,
4649
4743
  // NOTE: Windows Phone could not find the label through a selector
4650
4744
  // filter works though.
4651
- 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 + "']" ),
4652
4746
  inputtype = input.attr( "type" ),
4653
4747
  checkedState = inputtype + "-on",
4654
4748
  uncheckedState = inputtype + "-off",
@@ -4852,6 +4946,12 @@ $.widget( "mobile.button", $.mobile.widget, {
4852
4946
  name,
4853
4947
  $buttonPlaceholder;
4854
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
+
4855
4955
  // Add ARIA role
4856
4956
  this.button = $( "<div></div>" )
4857
4957
  .text( $el.text() || $el.val() )
@@ -5004,7 +5104,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
5004
5104
  if ( cType == "select" ) {
5005
5105
 
5006
5106
  slider.wrapInner( "<div class='ui-slider-inneroffset'></div>" );
5007
-
5107
+
5008
5108
  // make the handle move with a smooth transition
5009
5109
  handle.addClass( "ui-slider-handle-snapping" );
5010
5110
 
@@ -5047,14 +5147,14 @@ $.widget( "mobile.slider", $.mobile.widget, {
5047
5147
  if ( self.dragging ) {
5048
5148
  // self.mouseMoved must be updated before refresh() because it will be used in the control "change" event
5049
5149
  self.mouseMoved = true;
5050
-
5150
+
5051
5151
  if ( cType === "select" ) {
5052
5152
  // make the handle move in sync with the mouse
5053
5153
  handle.removeClass( "ui-slider-handle-snapping" );
5054
5154
  }
5055
-
5155
+
5056
5156
  self.refresh( event );
5057
-
5157
+
5058
5158
  // only after refresh() you can calculate self.userModified
5059
5159
  self.userModified = self.beforeStart !== control[0].selectedIndex;
5060
5160
  return false;
@@ -5069,7 +5169,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
5069
5169
  if ( cType === "select" ) {
5070
5170
  self.beforeStart = control[0].selectedIndex;
5071
5171
  }
5072
-
5172
+
5073
5173
  self.refresh( event );
5074
5174
  return false;
5075
5175
  });
@@ -5081,12 +5181,12 @@ $.widget( "mobile.slider", $.mobile.widget, {
5081
5181
  self.dragging = false;
5082
5182
 
5083
5183
  if ( cType === "select") {
5084
-
5184
+
5085
5185
  // make the handle move with a smooth transition
5086
5186
  handle.addClass( "ui-slider-handle-snapping" );
5087
-
5187
+
5088
5188
  if ( self.mouseMoved ) {
5089
-
5189
+
5090
5190
  // this is a drag, change the value only if user dragged enough
5091
5191
  if ( self.userModified ) {
5092
5192
  self.refresh( self.beforeStart == 0 ? 1 : 0 );
@@ -5094,17 +5194,17 @@ $.widget( "mobile.slider", $.mobile.widget, {
5094
5194
  else {
5095
5195
  self.refresh( self.beforeStart );
5096
5196
  }
5097
-
5197
+
5098
5198
  }
5099
5199
  else {
5100
5200
  // this is just a click, change the value
5101
5201
  self.refresh( self.beforeStart == 0 ? 1 : 0 );
5102
5202
  }
5103
-
5203
+
5104
5204
  }
5105
-
5205
+
5106
5206
  self.mouseMoved = false;
5107
-
5207
+
5108
5208
  return false;
5109
5209
  }
5110
5210
  });
@@ -5177,14 +5277,15 @@ $.widget( "mobile.slider", $.mobile.widget, {
5177
5277
 
5178
5278
  refresh: function( val, isfromControl, preventInputUpdate ) {
5179
5279
 
5180
- if ( this.options.disabled || this.element.attr('disabled')) {
5280
+ if ( this.options.disabled || this.element.attr('disabled')) {
5181
5281
  this.disable();
5182
5282
  }
5183
5283
 
5184
5284
  var control = this.element, percent,
5185
5285
  cType = control[0].nodeName.toLowerCase(),
5186
5286
  min = cType === "input" ? parseFloat( control.attr( "min" ) ) : 0,
5187
- 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;
5188
5289
 
5189
5290
  if ( typeof val === "object" ) {
5190
5291
  var data = val,
@@ -5198,7 +5299,7 @@ $.widget( "mobile.slider", $.mobile.widget, {
5198
5299
  percent = Math.round( ( ( data.pageX - this.slider.offset().left ) / this.slider.width() ) * 100 );
5199
5300
  } else {
5200
5301
  if ( val == null ) {
5201
- val = cType === "input" ? parseFloat( control.val() ) : control[0].selectedIndex;
5302
+ val = cType === "input" ? parseFloat( control.val() || 0 ) : control[0].selectedIndex;
5202
5303
  }
5203
5304
  percent = ( parseFloat( val ) - min ) / ( max - min ) * 100;
5204
5305
  }
@@ -5215,7 +5316,18 @@ $.widget( "mobile.slider", $.mobile.widget, {
5215
5316
  percent = 100;
5216
5317
  }
5217
5318
 
5218
- 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) );
5219
5331
 
5220
5332
  if ( newval < min ) {
5221
5333
  newval = min;
@@ -5225,15 +5337,11 @@ $.widget( "mobile.slider", $.mobile.widget, {
5225
5337
  newval = max;
5226
5338
  }
5227
5339
 
5228
- // Flip the stack of the bg colors
5229
- if ( percent > 60 && cType === "select" ) {
5230
- // TODO: Dead path?
5231
- }
5232
5340
  this.handle.css( "left", percent + "%" );
5233
5341
  this.handle.attr( {
5234
5342
  "aria-valuenow": cType === "input" ? newval : control.find( "option" ).eq( newval ).attr( "value" ),
5235
5343
  "aria-valuetext": cType === "input" ? newval : control.find( "option" ).eq( newval ).getEncodedText(),
5236
- title: newval
5344
+ title: cType === "input" ? newval : control.find( "option" ).eq( newval ).getEncodedText()
5237
5345
  });
5238
5346
 
5239
5347
  // add/remove classes for flip toggle switch
@@ -5382,15 +5490,15 @@ $.widget( "mobile.textinput", $.mobile.widget, {
5382
5490
  keyupTimeout = setTimeout( keyup, keyupTimeoutBuffer );
5383
5491
  });
5384
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
+
5385
5497
  // Issue 509: the browser is not providing scrollHeight properly until the styles load
5386
5498
  if ( $.trim( input.val() ) ) {
5387
5499
  // bind to the window load to make sure the height is calculated based on BOTH
5388
5500
  // the DOM and CSS
5389
5501
  $( window ).load( keyup );
5390
-
5391
- // binding to pagechange here ensures that for pages loaded via
5392
- // ajax the height is recalculated without user input
5393
- $( document ).one( "pagechange", keyup );
5394
5502
  }
5395
5503
  }
5396
5504
  },
@@ -5711,11 +5819,11 @@ $( document ).bind( "pagecreate create", function( e ){
5711
5819
  menuWidth = self.list.parent().outerWidth(),
5712
5820
  activePage = $( ".ui-page-active" ),
5713
5821
  tOverflow = $.support.touchOverflow && $.mobile.touchOverflowEnabled,
5714
- tScrollElem = activePage.is( ".ui-native-fixed" ) ? activePage.find( ".ui-content" ) : activePage;
5822
+ tScrollElem = activePage.is( ".ui-native-fixed" ) ? activePage.find( ".ui-content" ) : activePage,
5715
5823
  scrollTop = tOverflow ? tScrollElem.scrollTop() : $( window ).scrollTop(),
5716
5824
  btnOffset = self.button.offset().top,
5717
- screenHeight = window.innerHeight,
5718
- screenWidth = window.innerWidth;
5825
+ screenHeight = $(window).height(),
5826
+ screenWidth = $(window).width();
5719
5827
 
5720
5828
  //add active class to button
5721
5829
  self.button.addClass( $.mobile.activeBtnClass );
@@ -5897,7 +6005,7 @@ $( document ).bind( "pagecreate create", function( e ){
5897
6005
  });
5898
6006
  };
5899
6007
 
5900
- $( "select" ).live( "selectmenubeforecreate", function(){
6008
+ $( document ).delegate( "select", "selectmenubeforecreate", function(){
5901
6009
  var selectmenuWidget = $( this ).data( "selectmenu" );
5902
6010
 
5903
6011
  if( !selectmenuWidget.options.nativeMenu ){
@@ -6118,7 +6226,6 @@ $( document ).bind( "pagecreate create", function( e ){
6118
6226
 
6119
6227
  $.fn.buttonMarkup = function( options ) {
6120
6228
  options = options || {};
6121
-
6122
6229
  for ( var i = 0; i < this.length; i++ ) {
6123
6230
  var el = this.eq( i ),
6124
6231
  e = el[ 0 ],
@@ -6142,6 +6249,15 @@ $.fn.buttonMarkup = function( options ) {
6142
6249
  buttonText = document.createElement( o.wrapperEls ),
6143
6250
  buttonIcon = o.icon ? document.createElement( "span" ) : null;
6144
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
+
6145
6261
  if ( attachEvents ) {
6146
6262
  attachEvents();
6147
6263
  }
@@ -6189,7 +6305,6 @@ $.fn.buttonMarkup = function( options ) {
6189
6305
  el.addClass( buttonClass );
6190
6306
 
6191
6307
  buttonInner.className = innerClass;
6192
- buttonInner.setAttribute("aria-hidden", "true");
6193
6308
 
6194
6309
  buttonText.className = textClass;
6195
6310
  buttonInner.appendChild( buttonText );
@@ -6204,7 +6319,7 @@ $.fn.buttonMarkup = function( options ) {
6204
6319
  }
6205
6320
 
6206
6321
  e.appendChild( buttonInner );
6207
-
6322
+
6208
6323
  // TODO obviously it would be nice to pull this element out instead of
6209
6324
  // retrieving it from the DOM again, but this change is much less obtrusive
6210
6325
  // and 1.0 draws nigh
@@ -6230,12 +6345,11 @@ function closestEnabledButton( element ) {
6230
6345
  // handed could be in an SVG DOM where className on SVG elements is defined to
6231
6346
  // be of a different type (SVGAnimatedString). We only operate on HTML DOM
6232
6347
  // elements, so we look for plain "string".
6233
-
6234
- cname = ( typeof element.className === 'string' ) && element.className.split(' ');
6235
-
6236
- 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 ) {
6237
6350
  break;
6238
6351
  }
6352
+
6239
6353
  element = element.parentNode;
6240
6354
  }
6241
6355
 
@@ -6519,9 +6633,7 @@ $.mobile.fixedToolbars = (function() {
6519
6633
 
6520
6634
  // 1. Before page is shown, check for duplicate footer
6521
6635
  // 2. After page is shown, append footer to new page
6522
- $( ".ui-page" )
6523
- .live( "pagebeforeshow", function( event, ui ) {
6524
-
6636
+ $( document ).delegate( ".ui-page", "pagebeforeshow", function( event, ui ) {
6525
6637
  var page = $( event.target ),
6526
6638
  footer = page.find( ":jqmData(role='footer')" ),
6527
6639
  id = footer.data( "id" ),
@@ -6534,12 +6646,10 @@ $.mobile.fixedToolbars = (function() {
6534
6646
  setTop( stickyFooter.removeClass( "fade in out" ).appendTo( $.mobile.pageContainer ) );
6535
6647
  }
6536
6648
  })
6537
- .live( "pageshow", function( event, ui ) {
6538
-
6649
+ .delegate( ".ui-page", "pageshow", function( event, ui ) {
6539
6650
  var $this = $( this );
6540
6651
 
6541
6652
  if ( stickyFooter && stickyFooter.length ) {
6542
-
6543
6653
  setTimeout(function() {
6544
6654
  setTop( stickyFooter.appendTo( $this ).addClass( "fade" ) );
6545
6655
  stickyFooter = null;
@@ -6549,8 +6659,8 @@ $.mobile.fixedToolbars = (function() {
6549
6659
  $.mobile.fixedToolbars.show( true, this );
6550
6660
  });
6551
6661
 
6552
- // When a collapsiable is hidden or shown we need to trigger the fixed toolbar to reposition itself (#1635)
6553
- $( ".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 );
6554
6664
 
6555
6665
  // element.getBoundingClientRect() is broken in iOS 3.2.1 on the iPad. The
6556
6666
  // coordinates inside of the rect it returns don't have the page scroll position
@@ -6866,13 +6976,27 @@ $( document ).bind( "pagecreate", function( event ) {
6866
6976
  // find and enhance the pages in the dom and transition to the first page.
6867
6977
  initializePage: function() {
6868
6978
  // find present pages
6869
- var $pages = $( ":jqmData(role='page')" );
6979
+ var $dialogs, $pages = $( ":jqmData(role='page')" );
6870
6980
 
6871
- // 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
6872
6982
  if ( !$pages.length ) {
6873
- $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
+ }
6874
6997
  }
6875
6998
 
6999
+
6876
7000
  // add dialogs, set data-url attrs
6877
7001
  $pages.add( ":jqmData(role='dialog')" ).each(function() {
6878
7002
  var $this = $(this);