qedproject 0.0.9 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * jQuery Mobile v1.0b3
2
+ * jQuery Mobile v1.0rc1
3
3
  * http://jquerymobile.com/
4
4
  *
5
5
  * Copyright 2010, jQuery Project
@@ -278,6 +278,16 @@ $.Widget.prototype = {
278
278
  (function( $, undefined ) {
279
279
 
280
280
  $.widget( "mobile.widget", {
281
+ // decorate the parent _createWidget to trigger `widgetinit` for users
282
+ // who wish to do post post `widgetcreate` alterations/additions
283
+ //
284
+ // TODO create a pull request for jquery ui to trigger this event
285
+ // in the original _createWidget
286
+ _createWidget: function() {
287
+ $.Widget.prototype._createWidget.apply( this, arguments );
288
+ this._trigger( 'init' );
289
+ },
290
+
281
291
  _getCreateOptions: function() {
282
292
 
283
293
  var elem = this.element,
@@ -301,7 +311,7 @@ $.widget( "mobile.widget", {
301
311
 
302
312
  })( jQuery );
303
313
  /*
304
- * jQuery Mobile Framework : resolution and CSS media query related helpers and behavior
314
+ * jQuery Mobile Framework : a workaround for window.matchMedia
305
315
  * Copyright (c) jQuery Project
306
316
  * Dual licensed under the MIT or GPL Version 2 licenses.
307
317
  * http://jquery.org/license
@@ -421,9 +431,7 @@ $.extend( $.support, {
421
431
  touchOverflow: !!propExists( "overflowScrolling" ),
422
432
  boxShadow: !!propExists( "boxShadow" ) && !bb,
423
433
  scrollTop: ( "pageXOffset" in window || "scrollTop" in document.documentElement || "scrollTop" in fakeBody[ 0 ] ) && !webos,
424
- dynamicBaseTag: baseTagTest(),
425
- // TODO: This is a weak test. We may want to beef this up later.
426
- eventCapture: "addEventListener" in document
434
+ dynamicBaseTag: baseTagTest()
427
435
  });
428
436
 
429
437
  fakeBody.remove();
@@ -502,7 +510,7 @@ var dataPropertyName = "virtualMouseBindings",
502
510
  clickBlockList = [],
503
511
  blockMouseTriggers = false,
504
512
  blockTouchTriggers = false,
505
- eventCaptureSupported = $.support.eventCapture,
513
+ eventCaptureSupported = "addEventListener" in document,
506
514
  $document = $( document ),
507
515
  nextTouchID = 1,
508
516
  lastTouchID = 0;
@@ -542,6 +550,12 @@ function createVirtualEvent( event, eventType ) {
542
550
  }
543
551
  }
544
552
 
553
+ // make sure that if the mouse and click virtual events are generated
554
+ // without a .which one is defined
555
+ if ( t.search(/mouse(down|up)|click/) > -1 && !event.which ){
556
+ event.which = 1;
557
+ }
558
+
545
559
  if ( t.search(/^touch/) !== -1 ) {
546
560
  ne = getNativeEvent( oe );
547
561
  t = ne.touches;
@@ -1809,11 +1823,19 @@ $.widget( "mobile.page", $.mobile.widget, {
1809
1823
  // Mobile version of data and removeData and hasData methods
1810
1824
  // ensures all data is set and retrieved using jQuery Mobile's data namespace
1811
1825
  $.fn.jqmData = function( prop, value ) {
1812
- return this.data( prop ? $.mobile.nsNormalize( prop ) : prop, value );
1826
+ var result;
1827
+ if ( typeof prop != "undefined" ) {
1828
+ result = this.data( prop ? $.mobile.nsNormalize( prop ) : prop, value );
1829
+ }
1830
+ return result;
1813
1831
  };
1814
1832
 
1815
1833
  $.jqmData = function( elem, prop, value ) {
1816
- return $.data( elem, $.mobile.nsNormalize( prop ), value );
1834
+ var result;
1835
+ if ( typeof prop != "undefined" ) {
1836
+ result = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value );
1837
+ }
1838
+ return result;
1817
1839
  };
1818
1840
 
1819
1841
  $.fn.jqmRemoveData = function( prop ) {
@@ -1824,8 +1846,32 @@ $.widget( "mobile.page", $.mobile.widget, {
1824
1846
  return $.removeData( elem, $.mobile.nsNormalize( prop ) );
1825
1847
  };
1826
1848
 
1827
- $.jqmHasData = function( elem, prop ) {
1828
- return $.hasData( elem, $.mobile.nsNormalize( prop ) );
1849
+ $.fn.removeWithDependents = function() {
1850
+ $.removeWithDependents( this );
1851
+ };
1852
+
1853
+ $.removeWithDependents = function( elem ) {
1854
+ var $elem = $( elem );
1855
+
1856
+ ( $elem.jqmData('dependents') || $() ).remove();
1857
+ $elem.remove();
1858
+ };
1859
+
1860
+ $.fn.addDependents = function( newDependents ) {
1861
+ $.addDependents( $(this), newDependents );
1862
+ };
1863
+
1864
+ $.addDependents = function( elem, newDependents ) {
1865
+ var dependents = $(elem).jqmData( 'dependents' ) || $();
1866
+
1867
+ $(elem).jqmData( 'dependents', $.merge(dependents, newDependents) );
1868
+ };
1869
+
1870
+ // note that this helper doesn't attempt to handle the callback
1871
+ // or setting of an html elements text, its only purpose is
1872
+ // to return the html encoded version of the text in all cases. (thus the name)
1873
+ $.fn.getEncodedText = function() {
1874
+ return $( "<div/>" ).text( $(this).text() ).html();
1829
1875
  };
1830
1876
 
1831
1877
  // Monkey-patching Sizzle to filter the :jqmData selector
@@ -1875,20 +1921,21 @@ $.widget( "mobile.page", $.mobile.widget, {
1875
1921
  // [2]: http://jblas:password@mycompany.com:8080/mail/inbox
1876
1922
  // [3]: http://jblas:password@mycompany.com:8080
1877
1923
  // [4]: http:
1878
- // [5]: jblas:password@mycompany.com:8080
1879
- // [6]: jblas:password
1880
- // [7]: jblas
1881
- // [8]: password
1882
- // [9]: mycompany.com:8080
1883
- // [10]: mycompany.com
1884
- // [11]: 8080
1885
- // [12]: /mail/inbox
1886
- // [13]: /mail/
1887
- // [14]: inbox
1888
- // [15]: ?msg=1234&type=unread
1889
- // [16]: #msg-content
1924
+ // [5]: //
1925
+ // [6]: jblas:password@mycompany.com:8080
1926
+ // [7]: jblas:password
1927
+ // [8]: jblas
1928
+ // [9]: password
1929
+ // [10]: mycompany.com:8080
1930
+ // [11]: mycompany.com
1931
+ // [12]: 8080
1932
+ // [13]: /mail/inbox
1933
+ // [14]: /mail/
1934
+ // [15]: inbox
1935
+ // [16]: ?msg=1234&type=unread
1936
+ // [17]: #msg-content
1890
1937
  //
1891
- urlParseRE: /^(((([^:\/#\?]+:)?(?:\/\/((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
1938
+ urlParseRE: /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
1892
1939
 
1893
1940
  //Parse a URL into a structure that allows easy access to
1894
1941
  //all of the URL components by name.
@@ -1899,34 +1946,31 @@ $.widget( "mobile.page", $.mobile.widget, {
1899
1946
  return url;
1900
1947
  }
1901
1948
 
1902
- var u = url || "",
1903
- matches = path.urlParseRE.exec( url ),
1904
- results;
1905
- if ( matches ) {
1949
+ var matches = path.urlParseRE.exec( url || "" ) || [];
1950
+
1906
1951
  // Create an object that allows the caller to access the sub-matches
1907
1952
  // by name. Note that IE returns an empty string instead of undefined,
1908
1953
  // like all other browsers do, so we normalize everything so its consistent
1909
1954
  // no matter what browser we're running on.
1910
- results = {
1911
- href: matches[0] || "",
1912
- hrefNoHash: matches[1] || "",
1913
- hrefNoSearch: matches[2] || "",
1914
- domain: matches[3] || "",
1915
- protocol: matches[4] || "",
1916
- authority: matches[5] || "",
1917
- username: matches[7] || "",
1918
- password: matches[8] || "",
1919
- host: matches[9] || "",
1920
- hostname: matches[10] || "",
1921
- port: matches[11] || "",
1922
- pathname: matches[12] || "",
1923
- directory: matches[13] || "",
1924
- filename: matches[14] || "",
1925
- search: matches[15] || "",
1926
- hash: matches[16] || ""
1955
+ return {
1956
+ href: matches[ 0 ] || "",
1957
+ hrefNoHash: matches[ 1 ] || "",
1958
+ hrefNoSearch: matches[ 2 ] || "",
1959
+ domain: matches[ 3 ] || "",
1960
+ protocol: matches[ 4 ] || "",
1961
+ doubleSlash: matches[ 5 ] || "",
1962
+ authority: matches[ 6 ] || "",
1963
+ username: matches[ 8 ] || "",
1964
+ password: matches[ 9 ] || "",
1965
+ host: matches[ 10 ] || "",
1966
+ hostname: matches[ 11 ] || "",
1967
+ port: matches[ 12 ] || "",
1968
+ pathname: matches[ 13 ] || "",
1969
+ directory: matches[ 14 ] || "",
1970
+ filename: matches[ 15 ] || "",
1971
+ search: matches[ 16 ] || "",
1972
+ hash: matches[ 17 ] || ""
1927
1973
  };
1928
- }
1929
- return results || {};
1930
1974
  },
1931
1975
 
1932
1976
  //Turn relPath into an asbolute path. absPath is
@@ -1986,13 +2030,14 @@ $.widget( "mobile.page", $.mobile.widget, {
1986
2030
  var relObj = path.parseUrl( relUrl ),
1987
2031
  absObj = path.parseUrl( absUrl ),
1988
2032
  protocol = relObj.protocol || absObj.protocol,
2033
+ doubleSlash = relObj.protocol ? relObj.doubleSlash : ( relObj.doubleSlash || absObj.doubleSlash );
1989
2034
  authority = relObj.authority || absObj.authority,
1990
2035
  hasPath = relObj.pathname !== "",
1991
2036
  pathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ),
1992
2037
  search = relObj.search || ( !hasPath && absObj.search ) || "",
1993
2038
  hash = relObj.hash;
1994
2039
 
1995
- return protocol + "//" + authority + pathname + search + hash;
2040
+ return protocol + doubleSlash + authority + pathname + search + hash;
1996
2041
  },
1997
2042
 
1998
2043
  //Add search (aka query) params to the specified url.
@@ -2248,41 +2293,83 @@ $.widget( "mobile.page", $.mobile.widget, {
2248
2293
  $.mobile.changePage.apply( null, pageTransitionQueue.pop() );
2249
2294
  }
2250
2295
  }
2251
-
2296
+
2252
2297
  // Save the last scroll distance per page, before it is hidden
2253
- var getLastScroll = (function( lastScrollEnabled ){
2254
- return function(){
2255
- if( !lastScrollEnabled ){
2256
- lastScrollEnabled = true;
2257
- return;
2258
- }
2259
-
2260
- lastScrollEnabled = false;
2261
-
2262
- var active = $.mobile.urlHistory.getActive(),
2263
- activePage = $( ".ui-page-active" ),
2264
- scrollElem = $( window ),
2265
- touchOverflow = $.support.touchOverflow && $.mobile.touchOverflowEnabled;
2266
-
2267
- if( touchOverflow ){
2268
- scrollElem = activePage.is( ".ui-native-fixed" ) ? activePage.find( ".ui-content" ) : activePage;
2269
- }
2270
-
2271
- if( active ){
2272
- var lastScroll = scrollElem.scrollTop();
2298
+ var setLastScrollEnabled = true,
2299
+ firstScrollElem, getScrollElem, setLastScroll, delayedSetLastScroll;
2300
+
2301
+ getScrollElem = function() {
2302
+ var scrollElem = $window, activePage,
2303
+ touchOverflow = $.support.touchOverflow && $.mobile.touchOverflowEnabled;
2304
+
2305
+ if( touchOverflow ){
2306
+ activePage = $( ".ui-page-active" );
2307
+ scrollElem = activePage.is( ".ui-native-fixed" ) ? activePage.find( ".ui-content" ) : activePage;
2308
+ }
2309
+
2310
+ return scrollElem;
2311
+ };
2312
+
2313
+ setLastScroll = function( scrollElem ) {
2314
+ // this barrier prevents setting the scroll value based on the browser
2315
+ // scrolling the window based on a hashchange
2316
+ if( !setLastScrollEnabled ) {
2317
+ return;
2318
+ }
2319
+
2320
+ var active = $.mobile.urlHistory.getActive();
2321
+
2322
+ if( active ) {
2323
+ var lastScroll = scrollElem && scrollElem.scrollTop();
2324
+
2325
+ // Set active page's lastScroll prop.
2326
+ // If the location we're scrolling to is less than minScrollBack, let it go.
2327
+ active.lastScroll = lastScroll < $.mobile.minScrollBack ? $.mobile.defaultHomeScroll : lastScroll;
2328
+ }
2329
+ };
2330
+
2331
+ // bind to scrollstop to gather scroll position. The delay allows for the hashchange
2332
+ // event to fire and disable scroll recording in the case where the browser scrolls
2333
+ // to the hash targets location (sometimes the top of the page). once pagechange fires
2334
+ // getLastScroll is again permitted to operate
2335
+ delayedSetLastScroll = function() {
2336
+ setTimeout( setLastScroll, 100, $(this) );
2337
+ };
2338
+
2339
+ // disable an scroll setting when a hashchange has been fired, this only works
2340
+ // because the recording of the scroll position is delayed for 100ms after
2341
+ // the browser might have changed the position because of the hashchange
2342
+ $window.bind( $.support.pushState ? "popstate" : "hashchange", function() {
2343
+ setLastScrollEnabled = false;
2344
+ });
2345
+
2346
+ // handle initial hashchange from chrome :(
2347
+ $window.one( $.support.pushState ? "popstate" : "hashchange", function() {
2348
+ setLastScrollEnabled = true;
2349
+ });
2350
+
2351
+ // wait until the mobile page container has been determined to bind to pagechange
2352
+ $window.one( "pagecontainercreate", function(){
2353
+ // once the page has changed, re-enable the scroll recording
2354
+ $.mobile.pageContainer.bind( "pagechange", function() {
2355
+ var scrollElem = getScrollElem();
2356
+
2357
+ setLastScrollEnabled = true;
2358
+
2359
+ // remove any binding that previously existed on the get scroll
2360
+ // which may or may not be different than the scroll element determined for
2361
+ // this page previously
2362
+ scrollElem.unbind( "scrollstop", delayedSetLastScroll );
2363
+
2364
+ // determine and bind to the current scoll element which may be the window
2365
+ // or in the case of touch overflow the element with touch overflow
2366
+ scrollElem.bind( "scrollstop", delayedSetLastScroll );
2367
+ });
2368
+ });
2369
+
2370
+ // bind to scrollstop for the first page as "pagechange" won't be fired in that case
2371
+ getScrollElem().bind( "scrollstop", delayedSetLastScroll );
2273
2372
 
2274
- // Set active page's lastScroll prop.
2275
- // If the Y location we're scrolling to is less than minScrollBack, let it go.
2276
- active.lastScroll = lastScroll < $.mobile.minScrollBack ? $.mobile.defaultHomeScroll : lastScroll;
2277
- }
2278
- };
2279
- })( true );
2280
-
2281
- // to get last scroll, we need to get scrolltop before the page change
2282
- // using beforechangepage or popstate/hashchange (whichever comes first)
2283
- $( document ).bind( "beforechangepage", getLastScroll );
2284
- $( window ).bind( $.support.pushState ? "popstate" : "hashchange", getLastScroll );
2285
-
2286
2373
  // Make the iOS clock quick-scroll work again if we're using native overflow scrolling
2287
2374
  /*
2288
2375
  if( $.support.touchOverflow ){
@@ -2304,7 +2391,7 @@ $.widget( "mobile.page", $.mobile.widget, {
2304
2391
  touchOverflow = $.support.touchOverflow && $.mobile.touchOverflowEnabled,
2305
2392
  toScroll = active.lastScroll || ( touchOverflow ? 0 : $.mobile.defaultHomeScroll ),
2306
2393
  screenHeight = getScreenHeight();
2307
-
2394
+
2308
2395
  // Scroll to top, hide addr bar
2309
2396
  window.scrollTo( 0, $.mobile.defaultHomeScroll );
2310
2397
 
@@ -2312,22 +2399,22 @@ $.widget( "mobile.page", $.mobile.widget, {
2312
2399
  //trigger before show/hide events
2313
2400
  fromPage.data( "page" )._trigger( "beforehide", null, { nextPage: toPage } );
2314
2401
  }
2315
-
2402
+
2316
2403
  if( !touchOverflow){
2317
2404
  toPage.height( screenHeight + toScroll );
2318
- }
2319
-
2405
+ }
2406
+
2320
2407
  toPage.data( "page" )._trigger( "beforeshow", null, { prevPage: fromPage || $( "" ) } );
2321
2408
 
2322
2409
  //clear page loader
2323
2410
  $.mobile.hidePageLoadingMsg();
2324
-
2411
+
2325
2412
  if( touchOverflow && toScroll ){
2326
-
2413
+
2327
2414
  toPage.addClass( "ui-mobile-pre-transition" );
2328
2415
  // Send focus to page as it is now display: block
2329
2416
  reFocus( toPage );
2330
-
2417
+
2331
2418
  //set page's scrollTop to remembered distance
2332
2419
  if( toPage.is( ".ui-native-fixed" ) ){
2333
2420
  toPage.find( ".ui-content" ).scrollTop( toScroll );
@@ -2350,7 +2437,7 @@ $.widget( "mobile.page", $.mobile.widget, {
2350
2437
  // Send focus to the newly shown page
2351
2438
  reFocus( toPage );
2352
2439
  }
2353
-
2440
+
2354
2441
  // Jump to top or prev scroll, sometimes on iOS the page has not rendered yet.
2355
2442
  if( !touchOverflow ){
2356
2443
  $.mobile.silentScroll( toScroll );
@@ -2361,7 +2448,7 @@ $.widget( "mobile.page", $.mobile.widget, {
2361
2448
  if( !touchOverflow ){
2362
2449
  fromPage.height( "" );
2363
2450
  }
2364
-
2451
+
2365
2452
  fromPage.data( "page" )._trigger( "hide", null, { nextPage: toPage } );
2366
2453
  }
2367
2454
 
@@ -2383,11 +2470,15 @@ $.widget( "mobile.page", $.mobile.widget, {
2383
2470
 
2384
2471
  return pageMin;
2385
2472
  }
2386
-
2473
+
2387
2474
  $.mobile.getScreenHeight = getScreenHeight;
2388
2475
 
2389
2476
  //simply set the active page's minimum height to screen height, depending on orientation
2390
2477
  function resetActivePageHeight(){
2478
+ // Don't apply this height in touch overflow enabled mode
2479
+ if( $.support.touchOverflow && $.mobile.touchOverflowEnabled ){
2480
+ return;
2481
+ }
2391
2482
  $( "." + $.mobile.activePageClass ).css( "min-height", getScreenHeight() );
2392
2483
  }
2393
2484
 
@@ -2417,20 +2508,12 @@ $.widget( "mobile.page", $.mobile.widget, {
2417
2508
  }
2418
2509
  };
2419
2510
 
2420
- //update location.hash, with or without triggering hashchange event
2421
- //TODO - deprecate this one at 1.0
2422
- $.mobile.updateHash = path.set;
2423
-
2424
2511
  //expose path object on $.mobile
2425
2512
  $.mobile.path = path;
2426
2513
 
2427
2514
  //expose base object on $.mobile
2428
2515
  $.mobile.base = base;
2429
2516
 
2430
- //url stack, useful when plugins need to be aware of previous pages viewed
2431
- //TODO: deprecate this one at 1.0
2432
- $.mobile.urlstack = urlHistory.stack;
2433
-
2434
2517
  //history stack
2435
2518
  $.mobile.urlHistory = urlHistory;
2436
2519
 
@@ -2467,6 +2550,26 @@ $.widget( "mobile.page", $.mobile.widget, {
2467
2550
  return asParsedObject ? $.extend( {}, documentBase ) : documentBase.href;
2468
2551
  };
2469
2552
 
2553
+ $.mobile._bindPageRemove = function() {
2554
+ var page = $(this);
2555
+
2556
+ // when dom caching is not enabled or the page is embedded bind to remove the page on hide
2557
+ if( !page.data("page").options.domCache
2558
+ && page.is(":jqmData(external-page='true')") ) {
2559
+
2560
+ page.bind( 'pagehide.remove', function() {
2561
+ var $this = $( this ),
2562
+ prEvent = new $.Event( "pageremove" );
2563
+
2564
+ $this.trigger( prEvent );
2565
+
2566
+ if( !prEvent.isDefaultPrevented() ){
2567
+ $this.removeWithDependents();
2568
+ }
2569
+ });
2570
+ }
2571
+ };
2572
+
2470
2573
  // Load a page into the DOM.
2471
2574
  $.mobile.loadPage = function( url, options ) {
2472
2575
  // This function uses deferred notifications to let callers
@@ -2504,6 +2607,11 @@ $.widget( "mobile.page", $.mobile.widget, {
2504
2607
  settings.data = undefined;
2505
2608
  }
2506
2609
 
2610
+ // If the caller is using a "post" request, reloadPage must be true
2611
+ if( settings.data && settings.type === "post" ){
2612
+ settings.reloadPage = true;
2613
+ }
2614
+
2507
2615
  // The absolute version of the URL minus any dialog/subpage params.
2508
2616
  // In otherwords the real URL of the page to be loaded.
2509
2617
  var fileUrl = path.getFilePath( absUrl ),
@@ -2521,6 +2629,15 @@ $.widget( "mobile.page", $.mobile.widget, {
2521
2629
  // Check to see if the page already exists in the DOM.
2522
2630
  page = settings.pageContainer.children( ":jqmData(url='" + dataUrl + "')" );
2523
2631
 
2632
+ // If we failed to find the page, check to see if the url is a
2633
+ // reference to an embedded page. If so, it may have been dynamically
2634
+ // injected by a developer, in which case it would be lacking a data-url
2635
+ // attribute and in need of enhancement.
2636
+ if ( page.length === 0 && !path.isPath( dataUrl ) ) {
2637
+ page = settings.pageContainer.children( "#" + dataUrl )
2638
+ .attr( "data-" + $.mobile.ns + "url", dataUrl )
2639
+ }
2640
+
2524
2641
  // If we failed to find a page in the DOM, check the URL to see if it
2525
2642
  // refers to the first page in the application.
2526
2643
  if ( page.length === 0 && $.mobile.firstPage && path.isFirstPageUrl( absUrl ) ) {
@@ -2545,6 +2662,18 @@ $.widget( "mobile.page", $.mobile.widget, {
2545
2662
  dupCachedPage = page;
2546
2663
  }
2547
2664
 
2665
+ var mpc = settings.pageContainer,
2666
+ pblEvent = new $.Event( "pagebeforeload" ),
2667
+ triggerData = { url: url, absUrl: absUrl, dataUrl: dataUrl, deferred: deferred, options: settings };
2668
+
2669
+ // Let listeners know we're about to load a page.
2670
+ mpc.trigger( pblEvent, triggerData );
2671
+
2672
+ // If the default behavior is prevented, stop here!
2673
+ if( pblEvent.isDefaultPrevented() ){
2674
+ return deferred.promise();
2675
+ }
2676
+
2548
2677
  if ( settings.showLoadMsg ) {
2549
2678
 
2550
2679
  // This configurable timeout allows cached pages a brief delay to load without showing a message
@@ -2581,7 +2710,7 @@ $.widget( "mobile.page", $.mobile.widget, {
2581
2710
  newPageTitle = html.match( /<title[^>]*>([^<]*)/ ) && RegExp.$1,
2582
2711
 
2583
2712
  // TODO handle dialogs again
2584
- pageElemRegex = new RegExp( ".*(<[^>]+\\bdata-" + $.mobile.ns + "role=[\"']?page[\"']?[^>]*>).*" ),
2713
+ pageElemRegex = new RegExp( "(<[^>]+\\bdata-" + $.mobile.ns + "role=[\"']?page[\"']?[^>]*>)" ),
2585
2714
  dataUrlRegex = new RegExp( "\\bdata-" + $.mobile.ns + "url=[\"']?([^\"'>]*)[\"']?" );
2586
2715
 
2587
2716
 
@@ -2593,9 +2722,6 @@ $.widget( "mobile.page", $.mobile.widget, {
2593
2722
  && RegExp.$1 ) {
2594
2723
  url = fileUrl = path.getFilePath( RegExp.$1 );
2595
2724
  }
2596
- else{
2597
-
2598
- }
2599
2725
 
2600
2726
  if ( base ) {
2601
2727
  base.set( fileUrl );
@@ -2634,20 +2760,16 @@ $.widget( "mobile.page", $.mobile.widget, {
2634
2760
  }
2635
2761
 
2636
2762
  //append to page and enhance
2763
+ // TODO taging a page with external to make sure that embedded pages aren't removed
2764
+ // by the various page handling code is bad. Having page handling code in many
2765
+ // places is bad. Solutions post 1.0
2637
2766
  page
2638
2767
  .attr( "data-" + $.mobile.ns + "url", path.convertUrlToDataUrl( fileUrl ) )
2768
+ .attr( "data-" + $.mobile.ns + "external-page", true )
2639
2769
  .appendTo( settings.pageContainer );
2640
2770
 
2641
2771
  // wait for page creation to leverage options defined on widget
2642
- page.one('pagecreate', function(){
2643
-
2644
- // when dom caching is not enabled bind to remove the page on hide
2645
- if( !page.data("page").options.domCache ){
2646
- page.bind( "pagehide.remove", function(){
2647
- $(this).remove();
2648
- });
2649
- }
2650
- });
2772
+ page.one( 'pagecreate', $.mobile._bindPageRemove );
2651
2773
 
2652
2774
  enhancePage( page, settings.role );
2653
2775
 
@@ -2665,6 +2787,12 @@ $.widget( "mobile.page", $.mobile.widget, {
2665
2787
  hideMsg();
2666
2788
  }
2667
2789
 
2790
+ // Add the page reference to our triggerData.
2791
+ triggerData.page = page;
2792
+
2793
+ // Let listeners know the page loaded successfully.
2794
+ settings.pageContainer.trigger( "pageload", triggerData );
2795
+
2668
2796
  deferred.resolve( absUrl, options, page, dupCachedPage );
2669
2797
  },
2670
2798
  error: function() {
@@ -2673,6 +2801,19 @@ $.widget( "mobile.page", $.mobile.widget, {
2673
2801
  base.set( path.get() );
2674
2802
  }
2675
2803
 
2804
+ var plfEvent = new $.Event( "pageloadfailed" );
2805
+
2806
+ // Let listeners know the page load failed.
2807
+ settings.pageContainer.trigger( plfEvent, triggerData );
2808
+
2809
+ // If the default behavior is prevented, stop here!
2810
+ // Note that it is the responsibility of the listener/handler
2811
+ // that called preventDefault(), to resolve/reject the
2812
+ // deferred object within the triggerData.
2813
+ if( plfEvent.isDefaultPrevented() ){
2814
+ return;
2815
+ }
2816
+
2676
2817
  // Remove loading message.
2677
2818
  if ( settings.showLoadMsg ) {
2678
2819
 
@@ -2709,43 +2850,6 @@ $.widget( "mobile.page", $.mobile.widget, {
2709
2850
 
2710
2851
  // Show a specific page in the page container.
2711
2852
  $.mobile.changePage = function( toPage, options ) {
2712
- // XXX: REMOVE_BEFORE_SHIPPING_1.0
2713
- // This is temporary code that makes changePage() compatible with previous alpha versions.
2714
- if ( typeof options !== "object" ) {
2715
- var opts = null;
2716
-
2717
- // Map old-style call signature for form submit to the new options object format.
2718
- if ( typeof toPage === "object" && toPage.url && toPage.type ) {
2719
- opts = {
2720
- type: toPage.type,
2721
- data: toPage.data,
2722
- forcePageLoad: true
2723
- };
2724
- toPage = toPage.url;
2725
- }
2726
-
2727
- // The arguments passed into the function need to be re-mapped
2728
- // to the new options object format.
2729
- var len = arguments.length;
2730
- if ( len > 1 ) {
2731
- var argNames = [ "transition", "reverse", "changeHash", "fromHashChange" ], i;
2732
- for ( i = 1; i < len; i++ ) {
2733
- var a = arguments[ i ];
2734
- if ( typeof a !== "undefined" ) {
2735
- opts = opts || {};
2736
- opts[ argNames[ i - 1 ] ] = a;
2737
- }
2738
- }
2739
- }
2740
-
2741
- // If an options object was created, then we know changePage() was called
2742
- // with an old signature.
2743
- if ( opts ) {
2744
- return $.mobile.changePage( toPage, opts );
2745
- }
2746
- }
2747
- // XXX: REMOVE_BEFORE_SHIPPING_1.0
2748
-
2749
2853
  // If we are in the midst of a transition, queue the current request.
2750
2854
  // We'll call changePage() once we're done with the current transition to
2751
2855
  // service the request.
@@ -2769,8 +2873,6 @@ $.widget( "mobile.page", $.mobile.widget, {
2769
2873
  // Let listeners know we're about to change the current page.
2770
2874
  mpc.trigger( pbcEvent, triggerData );
2771
2875
 
2772
- mpc.trigger( "beforechangepage", triggerData ); // XXX: DEPRECATED for 1.0
2773
-
2774
2876
  // If the default behavior is prevented, stop here!
2775
2877
  if( pbcEvent.isDefaultPrevented() ){
2776
2878
  return;
@@ -2799,7 +2901,6 @@ $.widget( "mobile.page", $.mobile.widget, {
2799
2901
  $.mobile.changePage( newPage, options );
2800
2902
  })
2801
2903
  .fail(function( url, options ) {
2802
- // XXX_jblas: Fire off changepagefailed notificaiton.
2803
2904
  isPageTransitioning = false;
2804
2905
 
2805
2906
  //clear out the active button state
@@ -2808,7 +2909,6 @@ $.widget( "mobile.page", $.mobile.widget, {
2808
2909
  //release transition lock so navigation is free again
2809
2910
  releasePageTransitionLock();
2810
2911
  settings.pageContainer.trigger( "pagechangefailed", triggerData );
2811
- settings.pageContainer.trigger( "changepagefailed", triggerData ); // XXX: DEPRECATED for 1.0
2812
2912
  });
2813
2913
  return;
2814
2914
  }
@@ -2826,16 +2926,19 @@ $.widget( "mobile.page", $.mobile.widget, {
2826
2926
  pageTitle = document.title,
2827
2927
  isDialog = settings.role === "dialog" || toPage.jqmData( "role" ) === "dialog";
2828
2928
 
2829
- // If we are trying to transition to the same page that we are currently on ignore the request.
2830
- // an illegal same page request is defined by the current page being the same as the url, as long as there's history
2831
- // and toPage is not an array or object (those are allowed to be "same")
2832
- //
2833
- // XXX_jblas: We need to remove this at some point when we allow for transitions
2834
- // to the same page.
2835
- if( fromPage && fromPage[0] === toPage[0] ) {
2929
+ // By default, we prevent changePage requests when the fromPage and toPage
2930
+ // are the same element, but folks that generate content manually/dynamically
2931
+ // and reuse pages want to be able to transition to the same page. To allow
2932
+ // this, they will need to change the default value of allowSamePageTransition
2933
+ // to true, *OR*, pass it in as an option when they manually call changePage().
2934
+ // It should be noted that our default transition animations assume that the
2935
+ // formPage and toPage are different elements, so they may behave unexpectedly.
2936
+ // It is up to the developer that turns on the allowSamePageTransitiona option
2937
+ // to either turn off transition animations, or make sure that an appropriate
2938
+ // animation transition is used.
2939
+ if( fromPage && fromPage[0] === toPage[0] && !settings.allowSamePageTransition ) {
2836
2940
  isPageTransitioning = false;
2837
2941
  mpc.trigger( "pagechange", triggerData );
2838
- mpc.trigger( "changepage", triggerData ); // XXX: DEPRECATED for 1.0
2839
2942
  return;
2840
2943
  }
2841
2944
 
@@ -2923,8 +3026,6 @@ $.widget( "mobile.page", $.mobile.widget, {
2923
3026
 
2924
3027
  // Let listeners know we're all done changing the current page.
2925
3028
  mpc.trigger( "pagechange", triggerData );
2926
-
2927
- mpc.trigger( "changepage", triggerData ); // XXX: DEPRECATED for 1.0
2928
3029
  });
2929
3030
  };
2930
3031
 
@@ -2938,7 +3039,8 @@ $.widget( "mobile.page", $.mobile.widget, {
2938
3039
  pageContainer: undefined,
2939
3040
  showLoadMsg: true, //loading message shows by default when pages are being fetched during changePage
2940
3041
  dataUrl: undefined,
2941
- fromPage: undefined
3042
+ fromPage: undefined,
3043
+ allowSamePageTransition: false
2942
3044
  };
2943
3045
 
2944
3046
  /* Event Bindings - hashchange, submit, and click */
@@ -3023,6 +3125,12 @@ $.widget( "mobile.page", $.mobile.widget, {
3023
3125
 
3024
3126
  //add active state on vclick
3025
3127
  $( document ).bind( "vclick", function( event ) {
3128
+ // if this isn't a left click we don't care. Its important to note
3129
+ // that when the virtual event is generated it will create
3130
+ if ( event.which > 1 ){
3131
+ return;
3132
+ }
3133
+
3026
3134
  var link = findClosestLink( event.target );
3027
3135
  if ( link ) {
3028
3136
  if ( path.parseUrl( link.getAttribute( "href" ) || "#" ).hash !== "#" ) {
@@ -3037,7 +3145,10 @@ $.widget( "mobile.page", $.mobile.widget, {
3037
3145
  // click routing - direct to HTTP or Ajax, accordingly
3038
3146
  $( document ).bind( "click", function( event ) {
3039
3147
  var link = findClosestLink( event.target );
3040
- if ( !link ) {
3148
+
3149
+ // If there is no link associated with the click or its not a left
3150
+ // click we want to ignore the click
3151
+ if ( !link || event.which > 1) {
3041
3152
  return;
3042
3153
  }
3043
3154
 
@@ -3053,18 +3164,18 @@ $.widget( "mobile.page", $.mobile.widget, {
3053
3164
  return false;
3054
3165
  }
3055
3166
 
3167
+ var baseUrl = getClosestBaseUrl( $link ),
3168
+
3169
+ //get href, if defined, otherwise default to empty hash
3170
+ href = path.makeUrlAbsolute( $link.attr( "href" ) || "#", baseUrl );
3171
+
3056
3172
  //if ajax is disabled, exit early
3057
- if( !$.mobile.ajaxEnabled ){
3173
+ if( !$.mobile.ajaxEnabled && !path.isEmbeddedPage( href ) ){
3058
3174
  httpCleanup();
3059
3175
  //use default click handling
3060
3176
  return;
3061
3177
  }
3062
3178
 
3063
- var baseUrl = getClosestBaseUrl( $link ),
3064
-
3065
- //get href, if defined, otherwise default to empty hash
3066
- href = path.makeUrlAbsolute( $link.attr( "href" ) || "#", baseUrl );
3067
-
3068
3179
  // XXX_jblas: Ideally links to application pages should be specified as
3069
3180
  // an url to the application document with a hash that is either
3070
3181
  // the site relative path or id to the page. But some of the
@@ -3172,7 +3283,7 @@ $.widget( "mobile.page", $.mobile.widget, {
3172
3283
  isForward: function() { window.history.forward(); }
3173
3284
  });
3174
3285
 
3175
- // prevent changepage
3286
+ // prevent changePage()
3176
3287
  return;
3177
3288
  } else {
3178
3289
  // if the current active page is a dialog and we're navigating
@@ -3201,7 +3312,12 @@ $.widget( "mobile.page", $.mobile.widget, {
3201
3312
 
3202
3313
  //if to is defined, load it
3203
3314
  if ( to ) {
3204
- to = ( typeof to === "string" && !path.isPath( to ) ) ? ( '#' + to ) : to;
3315
+ // At this point, 'to' can be one of 3 things, a cached page element from
3316
+ // a history stack entry, an id, or site-relative/absolute URL. If 'to' is
3317
+ // an id, we need to resolve it against the documentBase, not the location.href,
3318
+ // since the hashchange could've been the result of a forward/backward navigation
3319
+ // that crosses from an external page/dialog to an internal page/dialog.
3320
+ to = ( typeof to === "string" && !path.isPath( to ) ) ? ( path.makeUrlAbsolute( '#' + to, documentBase ) ) : to;
3205
3321
  $.mobile.changePage( to, changePageOptions );
3206
3322
  } else {
3207
3323
  //there's no hash, go to the first page in the dom
@@ -3271,28 +3387,47 @@ $.widget( "mobile.page", $.mobile.widget, {
3271
3387
  return url;
3272
3388
  },
3273
3389
 
3390
+ // TODO sort out a single barrier to hashchange functionality
3391
+ nextHashChangePrevented: function( value ) {
3392
+ $.mobile.urlHistory.ignoreNextHashChange = value;
3393
+ self.onHashChangeDisabled = value;
3394
+ },
3395
+
3274
3396
  // on hash change we want to clean up the url
3275
3397
  // NOTE this takes place *after* the vanilla navigation hash change
3276
3398
  // handling has taken place and set the state of the DOM
3277
3399
  onHashChange: function( e ) {
3278
- var href, state;
3279
-
3280
- self.hashchangeFired = true;
3281
-
3282
- // only replaceState when the hash doesn't represent an embeded page
3283
- if( $.mobile.path.isPath(location.hash) ) {
3400
+ // disable this hash change
3401
+ if( self.onHashChangeDisabled ){
3402
+ return;
3403
+ }
3404
+
3405
+ var href, state,
3406
+ hash = location.hash,
3407
+ isPath = $.mobile.path.isPath( hash );
3408
+ hash = isPath ? hash.replace( "#", "" ) : hash;
3284
3409
 
3285
- // propulate the hash when its not available
3286
- state = self.state();
3410
+ // propulate the hash when its not available
3411
+ state = self.state();
3287
3412
 
3288
- // make the hash abolute with the current href
3289
- href = $.mobile.path.makeUrlAbsolute( state.hash.replace("#", ""), location.href );
3413
+ // make the hash abolute with the current href
3414
+ href = $.mobile.path.makeUrlAbsolute( hash, location.href );
3290
3415
 
3416
+ if ( isPath ) {
3291
3417
  href = self.resetUIKeys( href );
3292
-
3293
- // replace the current url with the new href and store the state
3294
- history.replaceState( state, document.title, href );
3295
3418
  }
3419
+
3420
+ // replace the current url with the new href and store the state
3421
+ // Note that in some cases we might be replacing an url with the
3422
+ // same url. We do this anyways because we need to make sure that
3423
+ // all of our history entries have a state object associated with
3424
+ // them. This allows us to work around the case where window.history.back()
3425
+ // is called to transition from an external page to an embedded page.
3426
+ // In that particular case, a hashchange event is *NOT* generated by the browser.
3427
+ // Ensuring each history entry has a state object means that onPopState()
3428
+ // will always trigger our hashchange callback even when a hashchange event
3429
+ // is not fired.
3430
+ history.replaceState( state, document.title, href );
3296
3431
  },
3297
3432
 
3298
3433
  // on popstate (ie back or forward) we need to replace the hash that was there previously
@@ -3304,14 +3439,14 @@ $.widget( "mobile.page", $.mobile.widget, {
3304
3439
  // or forward popstate
3305
3440
  if( poppedState ) {
3306
3441
  // disable any hashchange triggered by the browser
3307
- $.mobile.urlHistory.ignoreNextHashChange = true;
3442
+ self.nextHashChangePrevented( true );
3308
3443
 
3309
3444
  // defer our manual hashchange until after the browser fired
3310
3445
  // version has come and gone
3311
3446
  setTimeout(function() {
3312
3447
  // make sure that the manual hash handling takes place
3313
- $.mobile.urlHistory.ignoreNextHashChange = false;
3314
-
3448
+ self.nextHashChangePrevented( false );
3449
+
3315
3450
  // change the page based on the hash
3316
3451
  $.mobile._handleHashChange( poppedState.hash );
3317
3452
  }, 100);
@@ -3356,7 +3491,7 @@ function css3TransitionHandler( name, reverse, $to, $from ) {
3356
3491
 
3357
3492
  $to.add( $from ).removeClass( "out in reverse " + name );
3358
3493
 
3359
- if ( $from ) {
3494
+ if ( $from && $from[ 0 ] !== $to[ 0 ] ) {
3360
3495
  $from.removeClass( $.mobile.activePageClass );
3361
3496
  }
3362
3497
 
@@ -3427,10 +3562,13 @@ $( document ).bind( "pagecreate enhance", function( e ){
3427
3562
  optType = o.degradeInputs[ type ] || "text";
3428
3563
 
3429
3564
  if ( o.degradeInputs[ type ] ) {
3430
- $this.replaceWith(
3431
- $( "<div>" ).html( $this.clone() ).html()
3432
- .replace( /\s+type=["']?\w+['"]?/, " type=\"" + optType + "\" data-" + $.mobile.ns + "type=\"" + type + "\" " )
3433
- );
3565
+ var html = $( "<div>" ).html( $this.clone() ).html(),
3566
+ // In IE browsers, the type sometimes doesn't exist in the cloned markup, so we replace the closing tag instead
3567
+ hasType = html.indexOf( " type=" ) > -1,
3568
+ findstr = hasType ? /\s+type=["']?\w+['"]?/ : /\/?>/,
3569
+ repstr = " type=\"" + optType + "\" data-" + $.mobile.ns + "type=\"" + type + "\"" + ( hasType ? "" : ">" );
3570
+
3571
+ $this.replaceWith( html.replace( findstr, repstr ) );
3434
3572
  }
3435
3573
  });
3436
3574
 
@@ -3451,27 +3589,36 @@ $.widget( "mobile.dialog", $.mobile.widget, {
3451
3589
  initSelector : ":jqmData(role='dialog')"
3452
3590
  },
3453
3591
  _create: function() {
3454
- var $el = this.element,
3455
- pageTheme = $el.attr( "class" ).match( /ui-body-[a-z]/ );
3456
-
3592
+ var self = this,
3593
+ $el = this.element,
3594
+ pageTheme = $el.attr( "class" ).match( /ui-body-[a-z]/ ),
3595
+ headerCloseButton = $( "<a href='#' data-" + $.mobile.ns + "icon='delete' data-" + $.mobile.ns + "iconpos='notext'>"+ this.options.closeBtnText + "</a>" );
3596
+
3457
3597
  if( pageTheme.length ){
3458
3598
  $el.removeClass( pageTheme[ 0 ] );
3459
- }
3460
-
3599
+ }
3600
+
3461
3601
  $el.addClass( "ui-body-" + this.options.theme );
3462
-
3602
+
3463
3603
  // Class the markup for dialog styling
3464
3604
  // Set aria role
3465
3605
  $el.attr( "role", "dialog" )
3466
3606
  .addClass( "ui-dialog" )
3467
3607
  .find( ":jqmData(role='header')" )
3468
3608
  .addClass( "ui-corner-top ui-overlay-shadow" )
3469
- .prepend( "<a href='#' data-" + $.mobile.ns + "icon='delete' data-" + $.mobile.ns + "rel='back' data-" + $.mobile.ns + "iconpos='notext'>"+ this.options.closeBtnText + "</a>" )
3609
+ .prepend( headerCloseButton )
3470
3610
  .end()
3471
3611
  .find( ":jqmData(role='content'),:jqmData(role='footer')" )
3472
3612
  .last()
3473
3613
  .addClass( "ui-corner-bottom ui-overlay-shadow" );
3474
3614
 
3615
+ // this must be an anonymous function so that select menu dialogs can replace
3616
+ // the close method. This is a change from previously just defining data-rel=back
3617
+ // on the button and letting nav handle it
3618
+ headerCloseButton.bind( "vclick", function() {
3619
+ self.close();
3620
+ });
3621
+
3475
3622
  /* bind events
3476
3623
  - clicks and submits should use the closing transition that the dialog opened with
3477
3624
  unless a data-transition is specified on the link/form
@@ -3613,6 +3760,7 @@ $.widget( "mobile.collapsible", $.mobile.widget, {
3613
3760
  collapsed: true,
3614
3761
  heading: ">:header,>legend",
3615
3762
  theme: null,
3763
+ contentTheme: null,
3616
3764
  iconTheme: "d",
3617
3765
  initSelector: ":jqmData(role='collapsible')"
3618
3766
  },
@@ -3620,10 +3768,11 @@ $.widget( "mobile.collapsible", $.mobile.widget, {
3620
3768
 
3621
3769
  var $el = this.element,
3622
3770
  o = this.options,
3623
- collapsibleContain = $el.addClass( "ui-collapsible-contain" ),
3771
+ collapsible = $el.addClass( "ui-collapsible" ),
3624
3772
  collapsibleHeading = $el.find( o.heading ).eq( 0 ),
3625
- collapsibleContent = collapsibleContain.wrapInner( "<div class='ui-collapsible-content'></div>" ).find( ".ui-collapsible-content" ),
3626
- collapsibleParent = $el.closest( ":jqmData(role='collapsible-set')" ).addClass( "ui-collapsible-set" );
3773
+ collapsibleContent = collapsible.wrapInner( "<div class='ui-collapsible-content'></div>" ).find( ".ui-collapsible-content" ),
3774
+ collapsibleSet = $el.closest( ":jqmData(role='collapsible-set')" ).addClass( "ui-collapsible-set" ),
3775
+ colllapsiblesInSet = collapsibleSet.children( ":jqmData(role='collapsible')" );
3627
3776
 
3628
3777
  // Replace collapsibleHeading if it's a legend
3629
3778
  if ( collapsibleHeading.is( "legend" ) ) {
@@ -3631,6 +3780,20 @@ $.widget( "mobile.collapsible", $.mobile.widget, {
3631
3780
  collapsibleHeading.next().remove();
3632
3781
  }
3633
3782
 
3783
+ // If we are in a collapsible set
3784
+ if ( collapsibleSet.length ) {
3785
+ // Inherit the theme from collapsible-set
3786
+ if ( !o.theme ) {
3787
+ o.theme = collapsibleSet.jqmData( "theme" );
3788
+ }
3789
+ // Inherit the content-theme from collapsible-set
3790
+ if ( !o.contentTheme ) {
3791
+ o.contentTheme = collapsibleSet.jqmData( "content-theme" );
3792
+ }
3793
+ }
3794
+
3795
+ collapsibleContent.addClass( ( o.contentTheme ) ? ( "ui-body-" + o.contentTheme ) : "");
3796
+
3634
3797
  collapsibleHeading
3635
3798
  //drop heading in before content
3636
3799
  .insertBefore( collapsibleContent )
@@ -3640,117 +3803,96 @@ $.widget( "mobile.collapsible", $.mobile.widget, {
3640
3803
  .wrapInner( "<a href='#' class='ui-collapsible-heading-toggle'></a>" )
3641
3804
  .find( "a:eq(0)" )
3642
3805
  .buttonMarkup({
3643
- shadow: !collapsibleParent.length,
3806
+ shadow: false,
3644
3807
  corners: false,
3645
3808
  iconPos: "left",
3646
3809
  icon: "plus",
3647
3810
  theme: o.theme
3648
- })
3649
- .find( ".ui-icon" )
3650
- .removeAttr( "class" )
3651
- .buttonMarkup({
3652
- shadow: true,
3653
- corners: true,
3654
- iconPos: "notext",
3655
- icon: "plus",
3656
- theme: o.iconTheme
3811
+ });
3812
+
3813
+ if ( !collapsibleSet.length ) {
3814
+ collapsibleHeading
3815
+ .find( "a:eq(0), .ui-btn-inner" )
3816
+ .addClass( "ui-corner-top ui-corner-bottom" );
3817
+ } else {
3818
+ // If we are in a collapsible set
3819
+
3820
+ // Initialize the collapsible set if it's not already initialized
3821
+ if ( !collapsibleSet.jqmData( "collapsiblebound" ) ) {
3822
+
3823
+ collapsibleSet
3824
+ .jqmData( "collapsiblebound", true )
3825
+ .bind( "expand", function( event ) {
3826
+
3827
+ $( event.target )
3828
+ .closest( ".ui-collapsible" )
3829
+ .siblings( ".ui-collapsible" )
3830
+ .trigger( "collapse" );
3831
+
3657
3832
  });
3833
+ }
3658
3834
 
3659
- if ( !collapsibleParent.length ) {
3660
- collapsibleHeading
3661
- .find( "a:eq(0)" )
3662
- .addClass( "ui-corner-all" )
3835
+ colllapsiblesInSet.first()
3836
+ .find( "a:eq(0)" )
3837
+ .addClass( "ui-corner-top" )
3838
+ .find( ".ui-btn-inner" )
3839
+ .addClass( "ui-corner-top" );
3840
+
3841
+ colllapsiblesInSet.last()
3842
+ .jqmData( "collapsible-last", true )
3843
+ .find( "a:eq(0)" )
3844
+ .addClass( "ui-corner-bottom" )
3663
3845
  .find( ".ui-btn-inner" )
3664
- .addClass( "ui-corner-all" );
3665
- } else {
3666
- if ( collapsibleContain.jqmData( "collapsible-last" ) ) {
3667
- collapsibleHeading
3668
- .find( "a:eq(0), .ui-btn-inner" )
3669
3846
  .addClass( "ui-corner-bottom" );
3670
- }
3847
+
3848
+
3849
+ if ( collapsible.jqmData( "collapsible-last" ) ) {
3850
+ collapsibleHeading
3851
+ .find( "a:eq(0), .ui-btn-inner" )
3852
+ .addClass( "ui-corner-bottom" );
3671
3853
  }
3854
+ }
3672
3855
 
3673
3856
  //events
3674
- collapsibleContain
3675
- .bind( "collapse", function( event ) {
3676
- if ( ! event.isDefaultPrevented() &&
3677
- $( event.target ).closest( ".ui-collapsible-contain" ).is( collapsibleContain ) ) {
3857
+ collapsible
3858
+ .bind( "expand collapse", function( event ) {
3859
+ if ( !event.isDefaultPrevented() ) {
3678
3860
 
3679
3861
  event.preventDefault();
3680
3862
 
3863
+ var $this = $( this ),
3864
+ isCollapse = ( event.type === "collapse" ),
3865
+ contentTheme = o.contentTheme;
3866
+
3681
3867
  collapsibleHeading
3682
- .addClass( "ui-collapsible-heading-collapsed" )
3868
+ .toggleClass( "ui-collapsible-heading-collapsed", isCollapse)
3683
3869
  .find( ".ui-collapsible-heading-status" )
3684
3870
  .text( o.expandCueText )
3685
3871
  .end()
3686
3872
  .find( ".ui-icon" )
3687
- .removeClass( "ui-icon-minus" )
3688
- .addClass( "ui-icon-plus" );
3873
+ .toggleClass( "ui-icon-minus", !isCollapse )
3874
+ .toggleClass( "ui-icon-plus", isCollapse );
3689
3875
 
3690
- collapsibleContent.addClass( "ui-collapsible-content-collapsed" ).attr( "aria-hidden", true );
3876
+ $this.toggleClass( "ui-collapsible-collapsed", isCollapse );
3877
+ collapsibleContent.toggleClass( "ui-collapsible-content-collapsed", isCollapse ).attr( "aria-hidden", isCollapse );
3691
3878
 
3692
- if ( collapsibleContain.jqmData( "collapsible-last" ) ) {
3879
+ if ( contentTheme && ( !collapsibleSet.length || collapsible.jqmData( "collapsible-last" ) ) ) {
3693
3880
  collapsibleHeading
3694
3881
  .find( "a:eq(0), .ui-btn-inner" )
3695
- .addClass( "ui-corner-bottom" );
3696
- }
3697
- }
3698
- })
3699
- .bind( "expand", function( event ) {
3700
- if ( !event.isDefaultPrevented() ) {
3701
-
3702
- event.preventDefault();
3703
-
3704
- collapsibleHeading
3705
- .removeClass( "ui-collapsible-heading-collapsed" )
3706
- .find( ".ui-collapsible-heading-status" ).text( o.collapseCueText );
3707
-
3708
- collapsibleHeading.find( ".ui-icon" ).removeClass( "ui-icon-plus" ).addClass( "ui-icon-minus" );
3709
-
3710
- collapsibleContent.removeClass( "ui-collapsible-content-collapsed" ).attr( "aria-hidden", false );
3711
-
3712
- if ( collapsibleContain.jqmData( "collapsible-last" ) ) {
3713
-
3714
- collapsibleHeading
3715
- .find( "a:eq(0), .ui-btn-inner" )
3716
- .removeClass( "ui-corner-bottom" );
3882
+ .toggleClass( "ui-corner-bottom", isCollapse );
3883
+ collapsibleContent.toggleClass( "ui-corner-bottom", !isCollapse );
3717
3884
  }
3718
3885
  }
3719
3886
  })
3720
3887
  .trigger( o.collapsed ? "collapse" : "expand" );
3721
3888
 
3722
- // Close others in a set
3723
- if ( collapsibleParent.length && !collapsibleParent.jqmData( "collapsiblebound" ) ) {
3724
-
3725
- collapsibleParent
3726
- .jqmData( "collapsiblebound", true )
3727
- .bind( "expand", function( event ) {
3728
-
3729
- $( event.target )
3730
- .closest( ".ui-collapsible-contain" )
3731
- .siblings( ".ui-collapsible-contain" )
3732
- .trigger( "collapse" );
3733
-
3734
- });
3735
-
3736
- var set = collapsibleParent.children( ":jqmData(role='collapsible')" );
3737
-
3738
- set.first()
3739
- .find( "a:eq(0)" )
3740
- .addClass( "ui-corner-top" )
3741
- .find( ".ui-btn-inner" )
3742
- .addClass( "ui-corner-top" );
3743
-
3744
- set.last().jqmData( "collapsible-last", true );
3745
- }
3746
-
3747
3889
  collapsibleHeading
3748
- .bind( "vclick", function( event ) {
3890
+ .bind( "click", function( event ) {
3749
3891
 
3750
3892
  var type = collapsibleHeading.is( ".ui-collapsible-heading-collapsed" ) ?
3751
3893
  "expand" : "collapse";
3752
3894
 
3753
- collapsibleContain.trigger( type );
3895
+ collapsible.trigger( type );
3754
3896
 
3755
3897
  event.preventDefault();
3756
3898
  });
@@ -3965,7 +4107,7 @@ $.widget( "mobile.listview", $.mobile.widget, {
3965
4107
  $li = this.element.children( "li" );
3966
4108
  // at create time the li are not visible yet so we need to rely on .ui-screen-hidden
3967
4109
  $visibleli = create?$li.not( ".ui-screen-hidden" ):$li.filter( ":visible" );
3968
-
4110
+
3969
4111
  this._removeCorners( $li );
3970
4112
 
3971
4113
  // Select the first visible li element
@@ -4092,7 +4234,7 @@ $.widget( "mobile.listview", $.mobile.widget, {
4092
4234
 
4093
4235
  self._itemApply( $list, item );
4094
4236
  }
4095
-
4237
+
4096
4238
  this._refreshCorners( create );
4097
4239
  },
4098
4240
 
@@ -4155,8 +4297,12 @@ $.widget( "mobile.listview", $.mobile.widget, {
4155
4297
 
4156
4298
  }).listview();
4157
4299
 
4158
- //on pagehide, remove any nested pages along with the parent page, as long as they aren't active
4159
- if( hasSubPages && parentPage.data("page").options.domCache === false ){
4300
+ // on pagehide, remove any nested pages along with the parent page, as long as they aren't active
4301
+ // and aren't embedded
4302
+ if( hasSubPages &&
4303
+ parentPage.is( ":jqmData(external-page='true')" ) &&
4304
+ parentPage.data("page").options.domCache === false ) {
4305
+
4160
4306
  var newRemove = function( e, ui ){
4161
4307
  var nextPage = ui.nextPage, npURL;
4162
4308
 
@@ -4308,7 +4454,7 @@ $( ":jqmData(role='listview')" ).live( "listviewcreate", function() {
4308
4454
  });
4309
4455
 
4310
4456
  })( jQuery );/*
4311
- * jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
4457
+ * jQuery Mobile Framework : "nojs" plugin - class to make elements hidden to A grade browsers
4312
4458
  * Copyright (c) jQuery Project
4313
4459
  * Dual licensed under the MIT or GPL Version 2 licenses.
4314
4460
  * http://jquery.org/license
@@ -4538,7 +4684,9 @@ $.widget( "mobile.button", $.mobile.widget, {
4538
4684
  _create: function() {
4539
4685
  var $el = this.element,
4540
4686
  o = this.options,
4541
- type;
4687
+ type,
4688
+ name,
4689
+ $buttonPlaceholder;
4542
4690
 
4543
4691
  // Add ARIA role
4544
4692
  this.button = $( "<div></div>" )
@@ -4555,25 +4703,27 @@ $.widget( "mobile.button", $.mobile.widget, {
4555
4703
  .insertBefore( $el )
4556
4704
  .append( $el.addClass( "ui-btn-hidden" ) );
4557
4705
 
4558
- // Add hidden input during submit
4559
4706
  type = $el.attr( "type" );
4560
-
4561
- if ( type !== "button" && type !== "reset" ) {
4562
-
4563
- $el.bind( "vclick", function() {
4564
-
4565
- var $buttonPlaceholder = $( "<input>", {
4566
- type: "hidden",
4567
- name: $el.attr( "name" ),
4568
- value: $el.attr( "value" )
4569
- })
4570
- .insertBefore( $el );
4571
-
4572
- // Bind to doc to remove after submit handling
4573
- $( document ).submit(function(){
4574
- $buttonPlaceholder.remove();
4707
+ name = $el.attr( "name" );
4708
+
4709
+ // Add hidden input during submit if input type="submit" has a name.
4710
+ if ( type !== "button" && type !== "reset" && name ) {
4711
+ $el.bind( "vclick", function() {
4712
+ // Add hidden input if it doesn’t already exist.
4713
+ if( $buttonPlaceholder === undefined ) {
4714
+ $buttonPlaceholder = $( "<input>", {
4715
+ type: "hidden",
4716
+ name: $el.attr( "name" ),
4717
+ value: $el.attr( "value" )
4718
+ })
4719
+ .insertBefore( $el );
4720
+
4721
+ // Bind to doc to remove after submit handling
4722
+ $( document ).submit(function(){
4723
+ $buttonPlaceholder.remove();
4724
+ });
4725
+ }
4575
4726
  });
4576
- });
4577
4727
  }
4578
4728
 
4579
4729
  this.refresh();
@@ -4893,13 +5043,17 @@ $.widget( "mobile.slider", $.mobile.widget, {
4893
5043
  }
4894
5044
 
4895
5045
  if ( !preventInputUpdate ) {
5046
+ var valueChanged = false;
5047
+
4896
5048
  // update control"s value
4897
5049
  if ( cType === "input" ) {
5050
+ valueChanged = control.val() !== newval;
4898
5051
  control.val( newval );
4899
5052
  } else {
5053
+ valueChanged = control[ 0 ].selectedIndex !== newval;
4900
5054
  control[ 0 ].selectedIndex = newval;
4901
5055
  }
4902
- if ( !isfromControl ) {
5056
+ if ( !isfromControl && valueChanged ) {
4903
5057
  control.trigger( "change" );
4904
5058
  }
4905
5059
  }
@@ -4941,7 +5095,7 @@ $( document ).bind( "pagecreate create", function( e ){
4941
5095
  $.widget( "mobile.textinput", $.mobile.widget, {
4942
5096
  options: {
4943
5097
  theme: null,
4944
- initSelector: "input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea"
5098
+ initSelector: "input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea, input:not([type])"
4945
5099
  },
4946
5100
 
4947
5101
  _create: function() {
@@ -4964,18 +5118,21 @@ $.widget( "mobile.textinput", $.mobile.widget, {
4964
5118
  input.addClass("ui-input-text ui-body-"+ o.theme );
4965
5119
 
4966
5120
  focusedEl = input;
4967
-
4968
- // XXX: Temporary workaround for issue 785. Turn off autocorrect and
4969
- // autocomplete since the popup they use can't be dismissed by
4970
- // the user. Note that we test for the presence of the feature
4971
- // by looking for the autocorrect property on the input element.
4972
- if ( typeof input[0].autocorrect !== "undefined" ) {
5121
+
5122
+ // XXX: Temporary workaround for issue 785 (Apple bug 8910589).
5123
+ // Turn off autocorrect and autocomplete on non-iOS 5 devices
5124
+ // since the popup they use can't be dismissed by the user. Note
5125
+ // that we test for the presence of the feature by looking for
5126
+ // the autocorrect property on the input element. We currently
5127
+ // have no test for iOS 5 or newer so we're temporarily using
5128
+ // the touchOverflow support flag for jQM 1.0. Yes, I feel dirty. - jblas
5129
+ if ( typeof input[0].autocorrect !== "undefined" && !$.support.touchOverflow ) {
4973
5130
  // Set the attribute instead of the property just in case there
4974
5131
  // is code that attempts to make modifications via HTML.
4975
5132
  input[0].setAttribute( "autocorrect", "off" );
4976
5133
  input[0].setAttribute( "autocomplete", "off" );
4977
5134
  }
4978
-
5135
+
4979
5136
 
4980
5137
  //"search" input widget
4981
5138
  if ( input.is( "[type='search'],:jqmData(type='search')" ) ) {
@@ -5056,11 +5213,11 @@ $.widget( "mobile.textinput", $.mobile.widget, {
5056
5213
 
5057
5214
  //auto self-init widgets
5058
5215
  $( document ).bind( "pagecreate create", function( e ){
5059
-
5216
+
5060
5217
  $( $.mobile.textinput.prototype.options.initSelector, e.target )
5061
5218
  .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
5062
5219
  .textinput();
5063
-
5220
+
5064
5221
  });
5065
5222
 
5066
5223
  })( jQuery );
@@ -5079,13 +5236,13 @@ $( document ).bind( "pagecreate create", function( e ){
5079
5236
  label = widget.label,
5080
5237
  thisPage = widget.select.closest( ".ui-page" ),
5081
5238
  screen = $( "<div>", {"class": "ui-selectmenu-screen ui-screen-hidden"} ).appendTo( thisPage ),
5082
- selectOptions = widget.select.find("option"),
5239
+ selectOptions = widget._selectOptions(),
5083
5240
  isMultiple = widget.isMultiple = widget.select[ 0 ].multiple,
5084
5241
  buttonId = selectID + "-button",
5085
5242
  menuId = selectID + "-menu",
5086
5243
  menuPage = $( "<div data-" + $.mobile.ns + "role='dialog' data-" +$.mobile.ns + "theme='"+ widget.options.menuPageTheme +"'>" +
5087
5244
  "<div data-" + $.mobile.ns + "role='header'>" +
5088
- "<div class='ui-title'>" + label.text() + "</div>"+
5245
+ "<div class='ui-title'>" + label.getEncodedText() + "</div>"+
5089
5246
  "</div>"+
5090
5247
  "<div data-" + $.mobile.ns + "role='content'></div>"+
5091
5248
  "</div>" ).appendTo( $.mobile.pageContainer ).page(),
@@ -5174,7 +5331,7 @@ $( document ).bind( "pagecreate create", function( e ){
5174
5331
  // index of option tag to be selected
5175
5332
  var oldIndex = self.select[ 0 ].selectedIndex,
5176
5333
  newIndex = self.list.find( "li:not(.ui-li-divider)" ).index( this ),
5177
- option = self.selectOptions.eq( newIndex )[ 0 ];
5334
+ option = self._selectOptions().eq( newIndex )[ 0 ];
5178
5335
 
5179
5336
  // toggle selected status on the tag for multi selects
5180
5337
  option.selected = self.isMultiple ? !option.selected : true;
@@ -5252,6 +5409,20 @@ $( document ).bind( "pagecreate create", function( e ){
5252
5409
  self.menuPage.bind( "pagehide", function() {
5253
5410
  self.list.appendTo( self.listbox );
5254
5411
  self._focusButton();
5412
+
5413
+ // TODO centralize page removal binding / handling in the page plugin.
5414
+ // Suggestion from @jblas to do refcounting
5415
+ //
5416
+ // TODO extremely confusing dependency on the open method where the pagehide.remove
5417
+ // bindings are stripped to prevent the parent page from disappearing. The way
5418
+ // we're keeping pages in the DOM right now sucks
5419
+ //
5420
+ // rebind the page remove that was unbound in the open function
5421
+ // to allow for the parent page removal from actions other than the use
5422
+ // of a dialog sized custom select
5423
+ //
5424
+ // doing this here provides for the back button on the custom select dialog
5425
+ $.mobile._bindPageRemove.call( self.thisPage );
5255
5426
  });
5256
5427
 
5257
5428
  // Events on "screen" overlay
@@ -5266,18 +5437,32 @@ $( document ).bind( "pagecreate create", function( e ){
5266
5437
  return false;
5267
5438
  }
5268
5439
  });
5440
+
5441
+ // track this dependency so that when the parent page
5442
+ // is removed on pagehide it will also remove the menupage
5443
+ self.thisPage.addDependents( this.menuPage );
5269
5444
  },
5270
5445
 
5271
- refresh: function( forceRebuild ){
5446
+ _isRebuildRequired: function() {
5447
+ var list = this.list.find( "li" ),
5448
+ options = this._selectOptions();
5449
+
5450
+ // TODO exceedingly naive method to determine difference
5451
+ // ignores value changes etc in favor of a forcedRebuild
5452
+ // from the user in the refresh method
5453
+ return options.text() !== list.text();
5454
+ },
5455
+
5456
+ refresh: function( forceRebuild , foo ){
5272
5457
  var self = this,
5273
5458
  select = this.element,
5274
5459
  isMultiple = this.isMultiple,
5275
- options = this.selectOptions = select.find( "option" ),
5460
+ options = this._selectOptions(),
5276
5461
  selected = this.selected(),
5277
5462
  // return an array of all selected index's
5278
5463
  indicies = this.selectedIndices();
5279
5464
 
5280
- if ( forceRebuild || select[0].options.length != self.list.find( "li" ).length ) {
5465
+ if ( forceRebuild || this._isRebuildRequired() ) {
5281
5466
  self._buildList();
5282
5467
  }
5283
5468
 
@@ -5313,18 +5498,6 @@ $( document ).bind( "pagecreate create", function( e ){
5313
5498
  var self = this;
5314
5499
 
5315
5500
  if ( self.menuType == "page" ) {
5316
- // TODO centralize page removal binding / handling in the page plugin.
5317
- // Suggestion from @jblas to do refcounting
5318
- //
5319
- // rebind the page remove that was unbound in the open function
5320
- // to allow for the parent page removal from actions other than the use
5321
- // of a dialog sized custom select
5322
- if( !self.thisPage.data("page").options.domCache ){
5323
- self.thisPage.bind( "pagehide.remove", function() {
5324
- $(self).remove();
5325
- });
5326
- }
5327
-
5328
5501
  // doesn't solve the possible issue with calling change page
5329
5502
  // where the objects don't define data urls which prevents dialog key
5330
5503
  // stripping - changePage has incoming refactor
@@ -5348,7 +5521,10 @@ $( document ).bind( "pagecreate create", function( e ){
5348
5521
  var self = this,
5349
5522
  menuHeight = self.list.parent().outerHeight(),
5350
5523
  menuWidth = self.list.parent().outerWidth(),
5351
- scrollTop = $( window ).scrollTop(),
5524
+ activePage = $( ".ui-page-active" ),
5525
+ tOverflow = $.support.touchOverflow && $.mobile.touchOverflowEnabled,
5526
+ tScrollElem = activePage.is( ".ui-native-fixed" ) ? activePage.find( ".ui-content" ) : activePage;
5527
+ scrollTop = tOverflow ? tScrollElem.scrollTop() : $( window ).scrollTop(),
5352
5528
  btnOffset = self.button.offset().top,
5353
5529
  screenHeight = window.innerHeight,
5354
5530
  screenWidth = window.innerWidth;
@@ -5461,7 +5637,7 @@ $( document ).bind( "pagecreate create", function( e ){
5461
5637
  self.select.find( "option" ).each( function( i ) {
5462
5638
  var $this = $( this ),
5463
5639
  $parent = $this.parent(),
5464
- text = $this.text(),
5640
+ text = $this.getEncodedText(),
5465
5641
  anchor = "<a href='#'>"+ text +"</a>",
5466
5642
  classes = [],
5467
5643
  extraAttrs = [];
@@ -5572,6 +5748,10 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
5572
5748
  },
5573
5749
 
5574
5750
  _theme: function(){
5751
+ if ( this.options.theme ){
5752
+ return this.options.theme;
5753
+ }
5754
+
5575
5755
  var themedParent, theme;
5576
5756
  // if no theme is defined, try to find closest theme container
5577
5757
  // TODO move to core as something like findCurrentTheme
@@ -5597,6 +5777,10 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
5597
5777
  }, 40);
5598
5778
  },
5599
5779
 
5780
+ _selectOptions: function() {
5781
+ return this.select.find( "option" );
5782
+ },
5783
+
5600
5784
  // setup items that are generally necessary for select menu extension
5601
5785
  _preExtension: function(){
5602
5786
  this.select = this.element.wrap( "<div class='ui-select'>" );
@@ -5604,7 +5788,6 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
5604
5788
  this.label = $( "label[for='"+ this.selectID +"']" ).addClass( "ui-select" );
5605
5789
  this.isMultiple = this.select[ 0 ].multiple;
5606
5790
  this.options.theme = this._theme();
5607
- this.selectOptions = this.select.find( "option" );
5608
5791
  },
5609
5792
 
5610
5793
  _create: function() {
@@ -5653,7 +5836,7 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
5653
5836
  this.buttonCount = $( "<span>" )
5654
5837
  .addClass( "ui-li-count ui-btn-up-c ui-btn-corner-all" )
5655
5838
  .hide()
5656
- .appendTo( button );
5839
+ .appendTo( button.addClass('ui-li-has-count') );
5657
5840
  }
5658
5841
 
5659
5842
  // Disable if specified
@@ -5695,14 +5878,14 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
5695
5878
  },
5696
5879
 
5697
5880
  selected: function() {
5698
- return this.selectOptions.filter( ":selected" );
5881
+ return this._selectOptions().filter( ":selected" );
5699
5882
  },
5700
5883
 
5701
5884
  selectedIndices: function() {
5702
5885
  var self = this;
5703
5886
 
5704
5887
  return this.selected().map( function() {
5705
- return self.selectOptions.index( this );
5888
+ return self._selectOptions().index( this );
5706
5889
  }).get();
5707
5890
  },
5708
5891
 
@@ -5734,6 +5917,11 @@ $.widget( "mobile.selectmenu", $.mobile.widget, {
5734
5917
  this.setButtonCount();
5735
5918
  },
5736
5919
 
5920
+ // open and close preserved in native selects
5921
+ // to simplify users code when looping over selects
5922
+ open: $.noop,
5923
+ close: $.noop,
5924
+
5737
5925
  disable: function() {
5738
5926
  this._setDisabled( true );
5739
5927
  this.button.addClass( "ui-disabled" );
@@ -5763,7 +5951,12 @@ $( document ).bind( "pagecreate create", function( e ){
5763
5951
  $.fn.buttonMarkup = function( options ) {
5764
5952
  return this.each( function() {
5765
5953
  var el = $( this ),
5766
- o = $.extend( {}, $.fn.buttonMarkup.defaults, el.jqmData(), options ),
5954
+ o = $.extend( {}, $.fn.buttonMarkup.defaults, {
5955
+ icon: el.jqmData( "icon" ),
5956
+ iconpos: el.jqmData( "iconpos" ),
5957
+ theme: el.jqmData( "theme" ),
5958
+ inline: el.jqmData( "inline" )
5959
+ }, options ),
5767
5960
 
5768
5961
  // Classes Defined
5769
5962
  innerClass = "ui-btn-inner",
@@ -5831,6 +6024,7 @@ $.fn.buttonMarkup.defaults = {
5831
6024
  corners: true,
5832
6025
  shadow: true,
5833
6026
  iconshadow: true,
6027
+ inline: false,
5834
6028
  wrapperEls: "span"
5835
6029
  };
5836
6030
 
@@ -5957,7 +6151,7 @@ $( document ).bind( "pagecreate create", function( e ){
5957
6151
  });
5958
6152
 
5959
6153
  })(jQuery);/*
5960
- * jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
6154
+ * jQuery Mobile Framework : "links" plugin - simple class additions for links
5961
6155
  * Copyright (c) jQuery Project
5962
6156
  * Dual licensed under the MIT or GPL Version 2 licenses.
5963
6157
  * http://jquery.org/license
@@ -5992,7 +6186,7 @@ var slideDownClass = "ui-header-fixed ui-fixed-inline fade",
5992
6186
 
5993
6187
  $.fn.fixHeaderFooter = function( options ) {
5994
6188
 
5995
- if ( !$.support.scrollTop ) {
6189
+ if ( !$.support.scrollTop || ( $.support.touchOverflow && $.mobile.touchOverflowEnabled ) ) {
5996
6190
  return this;
5997
6191
  }
5998
6192
 
@@ -6014,7 +6208,7 @@ $.fn.fixHeaderFooter = function( options ) {
6014
6208
  // single controller for all showing,hiding,toggling
6015
6209
  $.mobile.fixedToolbars = (function() {
6016
6210
 
6017
- if ( !$.support.scrollTop || $.support.touchOverflow ) {
6211
+ if ( !$.support.scrollTop || ( $.support.touchOverflow && $.mobile.touchOverflowEnabled ) ) {
6018
6212
  return;
6019
6213
  }
6020
6214
 
@@ -6328,9 +6522,6 @@ $.mobile.fixedToolbars = (function() {
6328
6522
  };
6329
6523
  })();
6330
6524
 
6331
- // TODO - Deprecated namepace on $. Remove in a later release
6332
- $.fixedToolbars = $.mobile.fixedToolbars;
6333
-
6334
6525
  //auto self-init widgets
6335
6526
  $( document ).bind( "pagecreate create", function( event ) {
6336
6527
 
@@ -6338,7 +6529,7 @@ $( document ).bind( "pagecreate create", function( event ) {
6338
6529
 
6339
6530
  $( event.target ).each(function() {
6340
6531
 
6341
- if ( !$.support.scrollTop || $.support.touchOverflow ) {
6532
+ if ( !$.support.scrollTop || ( $.support.touchOverflow && $.mobile.touchOverflowEnabled ) ) {
6342
6533
  return this;
6343
6534
  }
6344
6535
 
@@ -6369,8 +6560,12 @@ $( document ).bind( "pagecreate create", function( event ) {
6369
6560
 
6370
6561
  (function( $, undefined ) {
6371
6562
 
6563
+ // Enable touch overflow scrolling when it's natively supported
6372
6564
  $.mobile.touchOverflowEnabled = false;
6373
6565
 
6566
+ // Enabled zoom when touch overflow is enabled. Can cause usability issues, unfortunately
6567
+ $.mobile.touchOverflowZoomEnabled = false;
6568
+
6374
6569
  $( document ).bind( "pagecreate", function( event ) {
6375
6570
  if( $.support.touchOverflow && $.mobile.touchOverflowEnabled ){
6376
6571
 
@@ -6419,108 +6614,7 @@ $( document ).bind( "pagecreate", function( event ) {
6419
6614
  });
6420
6615
 
6421
6616
  })( jQuery );
6422
- /*
6423
- * jQuery Mobile Framework : resolution and CSS media query related helpers and behavior
6424
- * Copyright (c) jQuery Project
6425
- * Dual licensed under the MIT or GPL Version 2 licenses.
6426
- * http://jquery.org/license
6427
- */
6428
- (function( $, undefined ) {
6429
-
6430
- var $window = $( window ),
6431
- $html = $( "html" ),
6432
-
6433
- //media-query-like width breakpoints, which are translated to classes on the html element
6434
- resolutionBreakpoints = [ 320, 480, 768, 1024 ];
6435
-
6436
- /*
6437
- private function for adding/removing breakpoint classes to HTML element for faux media-query support
6438
- It does not require media query support, instead using JS to detect screen width > cross-browser support
6439
- This function is called on orientationchange, resize, and mobileinit, and is bound via the 'htmlclass' event namespace
6440
- */
6441
- function detectResolutionBreakpoints() {
6442
- var currWidth = $window.width(),
6443
- minPrefix = "min-width-",
6444
- maxPrefix = "max-width-",
6445
- minBreakpoints = [],
6446
- maxBreakpoints = [],
6447
- unit = "px",
6448
- breakpointClasses;
6449
-
6450
- $html.removeClass( minPrefix + resolutionBreakpoints.join(unit + " " + minPrefix) + unit + " " +
6451
- maxPrefix + resolutionBreakpoints.join( unit + " " + maxPrefix) + unit );
6452
-
6453
- $.each( resolutionBreakpoints, function( i, breakPoint ) {
6454
- if( currWidth >= breakPoint ) {
6455
- minBreakpoints.push( minPrefix + breakPoint + unit );
6456
- }
6457
- if( currWidth <= breakPoint ) {
6458
- maxBreakpoints.push( maxPrefix + breakPoint + unit );
6459
- }
6460
- });
6461
-
6462
- if ( minBreakpoints.length ) {
6463
- breakpointClasses = minBreakpoints.join(" ");
6464
- }
6465
- if ( maxBreakpoints.length ) {
6466
- breakpointClasses += " " + maxBreakpoints.join(" ");
6467
- }
6468
-
6469
- $html.addClass( breakpointClasses );
6470
- };
6471
-
6472
- /* $.mobile.addResolutionBreakpoints method:
6473
- pass either a number or an array of numbers and they'll be added to the min/max breakpoint classes
6474
- Examples:
6475
- $.mobile.addResolutionBreakpoints( 500 );
6476
- $.mobile.addResolutionBreakpoints( [500, 1200] );
6477
- */
6478
- $.mobile.addResolutionBreakpoints = function( newbps ) {
6479
- if( $.type( newbps ) === "array" ){
6480
- resolutionBreakpoints = resolutionBreakpoints.concat( newbps );
6481
- } else {
6482
- resolutionBreakpoints.push( newbps );
6483
- }
6484
-
6485
- resolutionBreakpoints.sort(function( a, b ) {
6486
- return a - b;
6487
- });
6488
-
6489
- detectResolutionBreakpoints();
6490
- };
6491
-
6492
- /* on mobileinit, add classes to HTML element
6493
- and set handlers to update those on orientationchange and resize
6494
- */
6495
- $( document ).bind( "mobileinit.htmlclass", function() {
6496
- // bind to orientationchange and resize
6497
- // to add classes to HTML element for min/max breakpoints and orientation
6498
-
6499
- var ev = $.support.orientation;
6500
-
6501
- $window.bind( "orientationchange.htmlclass throttledresize.htmlclass", function( event ) {
6502
-
6503
- // add orientation class to HTML element on flip/resize.
6504
- if ( event.orientation ) {
6505
- $html.removeClass( "portrait landscape" ).addClass( event.orientation );
6506
- }
6507
-
6508
- // add classes to HTML element for min/max breakpoints
6509
- detectResolutionBreakpoints();
6510
- });
6511
- });
6512
-
6513
- /* Manually trigger an orientationchange event when the dom ready event fires.
6514
- This will ensure that any viewport meta tag that may have been injected
6515
- has taken effect already, allowing us to properly calculate the width of the
6516
- document.
6517
- */
6518
- $(function() {
6519
- //trigger event manually
6520
- $window.trigger( "orientationchange.htmlclass" );
6521
- });
6522
-
6523
- })(jQuery);/*!
6617
+ /*!
6524
6618
  * jQuery Mobile v@VERSION
6525
6619
  * http://jquerymobile.com/
6526
6620
  *
@@ -6582,15 +6676,6 @@ $(function() {
6582
6676
  $html.removeClass( "ui-loading" );
6583
6677
  },
6584
6678
 
6585
- // XXX: deprecate for 1.0
6586
- pageLoading: function ( done ) {
6587
- if ( done ) {
6588
- $.mobile.hidePageLoadingMsg();
6589
- } else {
6590
- $.mobile.showPageLoadingMsg();
6591
- }
6592
- },
6593
-
6594
6679
  // find and enhance the pages in the dom and transition to the first page.
6595
6680
  initializePage: function() {
6596
6681
  // find present pages
@@ -6617,6 +6702,10 @@ $(function() {
6617
6702
  // define page container
6618
6703
  $.mobile.pageContainer = $pages.first().parent().addClass( "ui-mobile-viewport" );
6619
6704
 
6705
+ // alert listeners that the pagecontainer has been determined for binding
6706
+ // to events triggered on it
6707
+ $window.trigger( "pagecontainercreate" );
6708
+
6620
6709
  // cue page loading message
6621
6710
  $.mobile.showPageLoadingMsg();
6622
6711
 
@@ -6630,6 +6719,24 @@ $(function() {
6630
6719
  }
6631
6720
  }
6632
6721
  });
6722
+
6723
+ // This function injects a meta viewport tag to prevent scaling. Off by default, on by default when touchOverflow scrolling is enabled
6724
+ function disableZoom() {
6725
+ var cont = "user-scalable=no",
6726
+ meta = $( "meta[name='viewport']" );
6727
+
6728
+ if( meta.length ){
6729
+ meta.attr( "content", meta.attr( "content" ) + ", " + cont );
6730
+ }
6731
+ else{
6732
+ $( "head" ).prepend( "<meta>", { "name": "viewport", "content": cont } );
6733
+ }
6734
+ }
6735
+
6736
+ // if touch-overflow is enabled, disable user scaling, as it creates usability issues
6737
+ if( $.support.touchOverflow && $.mobile.touchOverflowEnabled && !$.mobile.touchOverflowZoomEnabled ){
6738
+ disableZoom();
6739
+ }
6633
6740
 
6634
6741
  // initialize events now, after mobileinit has occurred
6635
6742
  $.mobile._registerInternalEvents();