From: <jon...@us...> - 2011-06-24 13:43:37
|
Revision: 35039 http://tikiwiki.svn.sourceforge.net/tikiwiki/?rev=35039&view=rev Author: jonnybradley Date: 2011-06-24 13:43:28 +0000 (Fri, 24 Jun 2011) Log Message: ----------- [MOD] jquery.mobile: update to 1.0 beta 1 Modified Paths: -------------- third_party/jquery/jquery-tiki-readme.txt third_party/jquery/jquery.mobile/images/icons-18-black.png third_party/jquery/jquery.mobile/images/icons-18-white.png third_party/jquery/jquery.mobile/images/icons-36-black.png third_party/jquery/jquery.mobile/images/icons-36-white.png third_party/jquery/jquery.mobile/jquery.mobile.css third_party/jquery/jquery.mobile/jquery.mobile.js third_party/jquery/jquery.mobile/jquery.mobile.min.css third_party/jquery/jquery.mobile/jquery.mobile.min.js Modified: third_party/jquery/jquery-tiki-readme.txt =================================================================== --- third_party/jquery/jquery-tiki-readme.txt 2011-06-24 13:39:54 UTC (rev 35038) +++ third_party/jquery/jquery-tiki-readme.txt 2011-06-24 13:43:28 UTC (rev 35039) @@ -7,12 +7,12 @@ Updates: (for Tiki 7.1+) jquery.js 1.5.1 to 1.6.1 + jquery.mobile 1.0a4.1 to 1.0b1 (version "-1.0b1" removed from filenames) - jonnybradley 14 April 2011 Update - jquery.mobile.js 1.0a3 to 1.0a4.1 (version "-1.0a4.1" removed from filenames again) + jquery.mobile.js 1.0a3 to 1.0a4.1 (version "-1.0a4.1" removed c again) jonnybradley 23 March 2011 Modified: third_party/jquery/jquery.mobile/images/icons-18-black.png =================================================================== (Binary files differ) Modified: third_party/jquery/jquery.mobile/images/icons-18-white.png =================================================================== (Binary files differ) Modified: third_party/jquery/jquery.mobile/images/icons-36-black.png =================================================================== (Binary files differ) Modified: third_party/jquery/jquery.mobile/images/icons-36-white.png =================================================================== (Binary files differ) Modified: third_party/jquery/jquery.mobile/jquery.mobile.css =================================================================== --- third_party/jquery/jquery.mobile/jquery.mobile.css 2011-06-24 13:39:54 UTC (rev 35038) +++ third_party/jquery/jquery.mobile/jquery.mobile.css 2011-06-24 13:43:28 UTC (rev 35039) @@ -1,5 +1,5 @@ /*! - * jQuery Mobile v1.0a4.1 + * jQuery Mobile v1.0b1 * http://jquerymobile.com/ * * Copyright 2010, jQuery Project @@ -462,18 +462,7 @@ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#ffffff')"; } .ui-btn-down-d a.ui-link-inherit { - border: 1px solid #808080; - background: #ced0d2; - font-weight: bold; color: #111; - text-shadow: none; - background-image: -moz-linear-gradient(top, - #cccccc, - #eeeeee); - background-image: -webkit-gradient(linear,left top,left bottom, - color-stop(0, #cccccc), - color-stop(1, #eeeeee)); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#cccccc', EndColorStr='#eeeeee')"; } .ui-btn-up-d, .ui-btn-hover-d, @@ -712,7 +701,7 @@ } .ui-disabled, .ui-disabled a { - cursor: default !important; + cursor: default; } /* Icons @@ -1031,9 +1020,9 @@ /*orientations from js are available */ .portrait, -.portrait .ui-page { min-height: 100%; } +.portrait .ui-page { min-height: 420px; } .landscape, -.landscape .ui-page { min-height: 100%; } +.landscape .ui-page { min-height: 300px; } /* loading screen */ .ui-loading .ui-mobile-viewport { overflow: hidden !important; } @@ -1055,7 +1044,7 @@ .ui-page .ui-header, .ui-page .ui-footer { position: relative; } .ui-header .ui-btn-left { position: absolute; left: 10px; top: .4em; } .ui-header .ui-btn-right { position: absolute; right: 10px; top: .4em; } -.ui-header .ui-title, .ui-footer .ui-title { text-align: center; font-size: 16px; display: block; margin: .6em 90px .8em; padding: 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; outline: 0 !important; } +.ui-header .ui-title, .ui-footer .ui-title { min-height: 1.1em; text-align: center; font-size: 16px; display: block; margin: .6em 90px .8em; padding: 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; outline: 0 !important; } /*content area*/ .ui-content { border-width: 0; overflow: visible; overflow-x: hidden; padding: 15px; } @@ -1217,13 +1206,13 @@ -webkit-animation-name: fadeout; } -/* The properties in this body rule are only necessary for the 'flip' transition. +/* The properties in this rule are only necessary for the 'flip' transition. * We need specify the perspective to create a projection matrix. This will add * some depth as the element flips. The depth number represents the distance of * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate * value. */ -.ui-mobile-viewport-perspective { +.viewport-flip { -webkit-perspective: 1000; position: absolute; } @@ -1410,7 +1399,7 @@ .ui-btn:focus, .ui-btn:active { outline: none; } .ui-header .ui-btn, .ui-footer .ui-btn, .ui-bar .ui-btn { display: inline-block; font-size: 13px; margin: 0; } .ui-btn-inline { display: inline-block; } -.ui-btn-inner { padding: .6em 25px; display: block; height: 100%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; position: relative; } +.ui-btn-inner { padding: .6em 25px; display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; position: relative; } .ui-header .ui-btn-inner, .ui-footer .ui-btn-inner, .ui-bar .ui-btn-inner { padding: .4em 8px .5em; } .ui-btn-icon-notext { display: inline-block; width: 20px; height: 20px; padding: 2px 1px 2px 3px; text-indent: -9999px; } .ui-btn-icon-notext .ui-btn-inner { padding: 0; } @@ -1453,7 +1442,7 @@ .ui-btn-icon-top .ui-icon { top: 5px; } .ui-btn-icon-bottom .ui-icon { bottom: 5px; } /*hiding native button,inputs */ -.ui-btn-hidden { position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-appearance: button; opacity: 0; cursor: pointer; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter: alpha(opacity=0); } +.ui-btn-hidden { position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-appearance: button; opacity: 0; cursor: pointer; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter: alpha(opacity=0); background: transparent; } /* * jQuery Mobile Framework * Copyright (c) jQuery Project @@ -1464,7 +1453,7 @@ .ui-collapsible-heading a { text-align: left; margin: 0; } .ui-collapsible-heading a .ui-btn-inner { padding-left: 40px; } .ui-collapsible-heading a span.ui-btn { position: absolute; left: 6px; top: 50%; margin: -12px 0 0 0; width: 20px; height: 20px; padding: 1px 0px 1px 2px; text-indent: -9999px; } -.ui-collapsible-heading a span.ui-btn .ui-btn-inner { padding: 0; } +.ui-collapsible-heading a span.ui-btn .ui-btn-inner { padding: 10px 0; } .ui-collapsible-heading a span.ui-btn .ui-icon { left: 0; margin-top: -10px; } .ui-collapsible-heading-status { position:absolute; left:-9999px; } .ui-collapsible-content { display: block; padding: 10px 0 10px 8px; } @@ -1498,8 +1487,10 @@ .ui-controlgroup .ui-btn-icon-notext .ui-btn-inner { padding: 5px 6px 5px 5px; } */ -.min-width-480px .ui-controlgroup-label { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; } -.min-width-480px .ui-controlgroup-controls { width: 60%; display: inline-block; } /* +@media all and (min-width: 450px){ + .ui-controlgroup-label { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; } + .ui-controlgroup-controls { width: 60%; display: inline-block; } +} /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. @@ -1514,8 +1505,10 @@ */ .ui-checkbox, .ui-radio { position:relative; margin: .2em 0 .5em; z-index: 1; } .ui-checkbox .ui-btn, .ui-radio .ui-btn { margin: 0; text-align: left; z-index: 2; } +.ui-checkbox .ui-btn-inner, .ui-radio .ui-btn-inner { white-space: normal; } .ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner { padding-left: 45px; } .ui-checkbox .ui-btn-icon-right .ui-btn-inner, .ui-radio .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; } +.ui-checkbox .ui-icon, .ui-radio .ui-icon { top: 1.1em; } .ui-checkbox .ui-btn-icon-left .ui-icon, .ui-radio .ui-btn-icon-left .ui-icon {left: 15px; } .ui-checkbox .ui-btn-icon-right .ui-icon, .ui-radio .ui-btn-icon-right .ui-icon {right: 15px; } /* input, label positioning */ @@ -1526,7 +1519,9 @@ */ .ui-field-contain { background: none; padding: 1.5em 0; margin: 0; border-bottom-width: 1px; overflow: visible; } .ui-field-contain:first-child { border-top-width: 0; } -.min-width-480px .ui-field-contain { border-width: 0; padding: 0; margin: 1em 0; }/* +@media all and (min-width: 450px){ + .ui-field-contain { border-width: 0; padding: 0; margin: 1em 0; } +} /* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. @@ -1535,7 +1530,8 @@ .ui-select select { position: absolute; left: -9999px; top: -9999px; } .ui-select .ui-btn { overflow: hidden; } .ui-select .ui-btn select { cursor: pointer; -webkit-appearance: button; left: 0; top:0; width: 100%; height: 100%; opacity: 0; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter: alpha(opacity=0); } -.ui-select .ui-btn select.ui-select-nativeonly { opacity: 1; } +@-moz-document url-prefix() {.ui-select .ui-btn select { opacity: 0.0001; }} +.ui-select .ui-btn select.ui-select-nativeonly { opacity: 1; text-indent: 0; } .ui-select .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; } .ui-select .ui-btn-icon-right .ui-icon { right: 15px; } @@ -1557,8 +1553,10 @@ .ui-li.ui-selectmenu-placeholder { display: none; } .ui-selectmenu .ui-header .ui-title { margin: 0.6em 46px 0.8em; } -.min-width-480px label.ui-select { display: inline-block; width: 20%; margin: 0 2% 0 0; } -.min-width-480px .ui-select { width: 60%; display: inline-block; } +@media all and (min-width: 450px){ + label.ui-select { display: inline-block; width: 20%; margin: 0 2% 0 0; } + .ui-select { width: 60%; display: inline-block; } +} /* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button. this shim's content in there */ .ui-selectmenu .ui-header h1:after { content: '.'; visibility: hidden; }/* @@ -1576,14 +1574,14 @@ .ui-input-search .ui-input-clear-hidden { display: none; } /* orientation adjustments - incomplete!*/ -.min-width-480px label.ui-input-text { vertical-align: top; } -.min-width-480px label.ui-input-text { display: inline-block; width: 20%; margin: 0 2% 0 0; } -.min-width-480px input.ui-input-text, -.min-width-480px textarea.ui-input-text, -.min-width-480px .ui-input-search { width: 60%; display: inline-block; } -.min-width-480px .ui-input-search { width: 50%; } -.min-width-480px .ui-input-search input.ui-input-text { width: 98%; /*echos rule from above*/ } -/* +@media all and (min-width: 450px){ + label.ui-input-text { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0 } + input.ui-input-text, + textarea.ui-input-text, + .ui-input-search { width: 60%; display: inline-block; } + .ui-input-search { width: 50%; } + .ui-input-search input.ui-input-text { width: 98%; /*echos rule from above*/ } +}/* * jQuery Mobile Framework * Copyright (c) jQuery Project * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. @@ -1611,7 +1609,9 @@ .ui-li-thumb, .ui-li-icon, .ui-li-content { float: left; margin-right: 10px; } .ui-li-aside { float: right; width: 50%; text-align: right; margin: .3em 0; } -.min-width-480px .ui-li-aside { width: 45%; } +@media all and (min-width: 480px){ + .ui-li-aside { width: 45%; } +} .ui-li-divider { cursor: default; } .ui-li-has-alt .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-alt { padding-right: 95px; } .ui-li-count { position: absolute; font-size: 11px; font-weight: bold; padding: .2em .5em; top: 50%; margin-top: -.9em; right: 38px; } @@ -1626,7 +1626,7 @@ .ui-listview-filter .ui-input-search { margin: 5px; width: auto; display: block; } .ui-listview-filter-inset { margin: -15px -5px -15px -5px; background: transparent; } - +.ui-li.ui-screen-hidden{display:none;} /* Odd iPad positioning issue. */ @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) { .ui-li .ui-btn-text { overflow: visible; } @@ -1636,13 +1636,15 @@ * Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. */ label.ui-slider { display: block; } -input.ui-slider-input, .min-width-480px input.ui-slider-input { display: inline-block; width: 50px; } +input.ui-slider-input { display: inline-block; width: 50px; } select.ui-slider-switch { display: none; } div.ui-slider { position: relative; display: inline-block; overflow: visible; height: 15px; padding: 0; margin: 0 2% 0 20px; top: 4px; width: 66%; } a.ui-slider-handle { position: absolute; z-index: 10; top: 50%; width: 28px; height: 28px; margin-top: -15px; margin-left: -15px; } a.ui-slider-handle .ui-btn-inner { padding-left: 0; padding-right: 0; } -.min-width-480px label.ui-slider { display: inline-block; width: 20%; margin: 0 2% 0 0; } -.min-width-480px div.ui-slider { width: 45%; } +@media all and (min-width: 480px){ + label.ui-slider { display: inline-block; width: 20%; margin: 0 2% 0 0; } + div.ui-slider { width: 45%; } +} div.ui-slider-switch { height: 32px; overflow: hidden; margin-left: 0; } div.ui-slider-inneroffset { margin-left: 50%; position: absolute; top: 1px; height: 100%; width: 50%; } Modified: third_party/jquery/jquery.mobile/jquery.mobile.js =================================================================== --- third_party/jquery/jquery.mobile/jquery.mobile.js 2011-06-24 13:39:54 UTC (rev 35038) +++ third_party/jquery/jquery.mobile/jquery.mobile.js 2011-06-24 13:43:28 UTC (rev 35039) @@ -1,5 +1,5 @@ /*! - * jQuery Mobile v1.0a4.1 + * jQuery Mobile v1.0b1 * http://jquerymobile.com/ * * Copyright 2010, jQuery Project @@ -396,7 +396,8 @@ $(document).bind("mobileinit.htmlclass", function(){ /* bind to orientationchange and resize to add classes to HTML element for min/max breakpoints and orientation */ - $window.bind("orientationchange.htmlclass resize.htmlclass", function(event){ + var ev = $.support.orientation; + $window.bind("orientationchange.htmlclass throttledResize.htmlclass", function(event){ //add orientation class to HTML element on flip/resize. if(event.orientation){ $html.removeClass( "portrait landscape" ).addClass( event.orientation ); @@ -422,77 +423,78 @@ * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. * Note: Code is in draft form and is subject to change */ -(function($, undefined ) { +( function( $, undefined ) { - - -var fakeBody = $( "<body>" ).prependTo( "html" ), - fbCSS = fakeBody[0].style, - vendors = ['webkit','moz','o'], - webos = window.palmGetResource || window.PalmServiceBridge, //only used to rule out scrollTop +var fakeBody = $( "<body>" ).prependTo( "html" ), + fbCSS = fakeBody[ 0 ].style, + vendors = [ "webkit", "moz", "o" ], + webos = "palmGetResource" in window, //only used to rule out scrollTop bb = window.blackberry; //only used to rule out box shadow, as it's filled opaque on BB -//thx Modernizr -function propExists( prop ){ - var uc_prop = prop.charAt(0).toUpperCase() + prop.substr(1), - props = (prop + ' ' + vendors.join(uc_prop + ' ') + uc_prop).split(' '); - for(var v in props){ - if( fbCSS[ v ] !== undefined ){ +// thx Modernizr +function propExists( prop ){ + var uc_prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ), + props = ( prop + " " + vendors.join( uc_prop + " " ) + uc_prop ).split( " " ); + for( var v in props ){ + if( fbCSS[ v ] !== undefined ){ return true; } } -}; +} -//test for dynamic-updating base tag support (allows us to avoid href,src attr rewriting) +// test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting ) function baseTagTest(){ - var fauxBase = location.protocol + '//' + location.host + location.pathname + "ui-dir/", - base = $("head base"), + var fauxBase = location.protocol + "//" + location.host + location.pathname + "ui-dir/", + base = $( "head base" ), fauxEle = null, - href = ''; - if (!base.length) { - base = fauxEle = $("<base>", {"href": fauxBase}).appendTo("head"); + href = ""; + if ( !base.length ) { + base = fauxEle = $( "<base>", { "href": fauxBase} ).appendTo( "head" ); } else { - href = base.attr("href"); + href = base.attr( "href" ); } - var link = $( "<a href='testurl'></a>" ).prependTo( fakeBody ), - rebase = link[0].href; - base[0].href = href ? href : location.pathname; - if (fauxEle) { + var link = $( "<a href='testurl'></a>" ).prependTo( fakeBody ), + rebase = link[ 0 ].href; + base[ 0 ].href = href ? href : location.pathname; + if ( fauxEle ) { fauxEle.remove(); } - return rebase.indexOf(fauxBase) === 0; -}; + return rebase.indexOf( fauxBase ) === 0; +} -//non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683 -//allows for inclusion of IE 6+, including Windows Mobile 7 +// non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683 +// allows for inclusion of IE 6+, including Windows Mobile 7 $.mobile.browser = {}; -$.mobile.browser.ie = (function() { - var v = 3, div = document.createElement('div'), a = div.all || []; - while (div.innerHTML = '<!--[if gt IE '+(++v)+']><br><![endif]-->', a[0]); +$.mobile.browser.ie = ( function() { + var v = 3, + div = document.createElement( "div" ), + a = div.all || []; + while ( div.innerHTML = "<!--[if gt IE " + ( ++v ) + "]><br><![endif]-->", a[ 0 ] ); return v > 4 ? v : !v; -}()); +}() ); + $.extend( $.support, { orientation: "orientation" in window, touch: "ontouchend" in document, cssTransitions: "WebKitTransitionEvent" in window, pushState: !!history.pushState, - mediaquery: $.mobile.media('only all'), - cssPseudoElement: !!propExists('content'), - boxShadow: !!propExists('boxShadow') && !bb, - scrollTop: ("pageXOffset" in window || "scrollTop" in document.documentElement || "scrollTop" in fakeBody[0]) && !webos, + mediaquery: $.mobile.media( "only all" ), + cssPseudoElement: !!propExists( "content" ), + boxShadow: !!propExists( "boxShadow" ) && !bb, + scrollTop: ( "pageXOffset" in window || "scrollTop" in document.documentElement || "scrollTop" in fakeBody[ 0 ] ) && !webos, dynamicBaseTag: baseTagTest(), - eventCapture: ("addEventListener" in document) // This is a weak test. We may want to beef this up later. -}); + eventCapture: ( "addEventListener" in document ) // This is a weak test. We may want to beef this up later. +} ); fakeBody.remove(); -//for ruling out shadows via css -if( !$.support.boxShadow ){ $('html').addClass('ui-mobile-nosupport-boxshadow'); } +// for ruling out shadows via css +if( !$.support.boxShadow ){ $( "html" ).addClass( "ui-mobile-nosupport-boxshadow" ); } -})( jQuery );/* +} )( jQuery );/* * jQuery Mobile Framework : "mouse" plugin * Copyright (c) jQuery Project * Dual licensed under the MIT or GPL Version 2 licenses. @@ -524,12 +526,10 @@ resetTimerID = 0, startX = 0, startY = 0, - startScrollX = 0, - startScrollY = 0, didScroll = false, clickBlockList = [], blockMouseTriggers = false, - scrollTopSupported = $.support.scrollTop, + blockTouchTriggers = false, eventCaptureSupported = $.support.eventCapture, $document = $(document), nextTouchID = 1, @@ -587,62 +587,38 @@ function getVirtualBindingFlags(element) { var flags = {}; - var $ele = $(element); - while ($ele && $ele.length){ - var b = $ele.data(dataPropertyName); + while (element){ + var b = $.data(element, dataPropertyName); for (var k in b) { if (b[k]){ flags[k] = flags.hasVirtualBinding = true; } } - $ele = $ele.parent(); + element = element.parentNode; } return flags; } function getClosestElementWithVirtualBinding(element, eventType) { - var $ele = $(element); - while ($ele && $ele.length){ - var b = $ele.data(dataPropertyName); + while (element){ + var b = $.data(element, dataPropertyName); if (b && (!eventType || b[eventType])) { - return $ele; + return element; } - $ele = $ele.parent(); + element = element.parentNode; } return null; } function enableTouchBindings() { - if (!activeDocHandlers["touchbindings"]){ - $document.bind("touchend", handleTouchEnd) - - // On touch platforms, touching the screen and then dragging your finger - // causes the window content to scroll after some distance threshold is - // exceeded. On these platforms, a scroll prevents a click event from being - // dispatched, and on some platforms, even the touchend is suppressed. To - // mimic the suppression of the click event, we need to watch for a scroll - // event. Unfortunately, some platforms like iOS don't dispatch scroll - // events until *AFTER* the user lifts their finger (touchend). This means - // we need to watch both scroll and touchmove events to figure out whether - // or not a scroll happenens before the touchend event is fired. - - .bind("touchmove", handleTouchMove) - .bind("scroll", handleScroll); - - activeDocHandlers["touchbindings"] = 1; - } + blockTouchTriggers = false; } function disableTouchBindings() { - if (activeDocHandlers["touchbindings"]){ - $document.unbind("touchmove", handleTouchMove) - .unbind("touchend", handleTouchEnd) - .unbind("scroll", handleScroll); - activeDocHandlers["touchbindings"] = 0; - } + blockTouchTriggers = true; } function enableMouseBindings() @@ -695,7 +671,7 @@ function mouseEventCallback(event) { - var touchID = $(event.target).data(touchTargetPropertyName); + var touchID = $.data(event.target, touchTargetPropertyName); if (!blockMouseTriggers && (!lastTouchID || lastTouchID !== touchID)){ triggerVirtualEvent("v" + event.type, event); } @@ -710,7 +686,7 @@ if (flags.hasVirtualBinding){ lastTouchID = nextTouchID++; - $(target).data(touchTargetPropertyName, lastTouchID); + $.data(target, touchTargetPropertyName, lastTouchID); clearResetTimer(); @@ -721,11 +697,6 @@ startX = t.pageX; startY = t.pageY; - if (scrollTopSupported){ - startScrollX = window.pageXOffset; - startScrollY = window.pageYOffset; - } - triggerVirtualEvent("vmouseover", event, flags); triggerVirtualEvent("vmousedown", event, flags); } @@ -734,6 +705,10 @@ function handleScroll(event) { + if (blockTouchTriggers){ + return; + } + if (!didScroll){ triggerVirtualEvent("vmousecancel", event, getVirtualBindingFlags(event.target)); } @@ -744,12 +719,15 @@ function handleTouchMove(event) { + if (blockTouchTriggers){ + return; + } + var t = getNativeEvent(event).touches[0]; var didCancel = didScroll, moveThreshold = $.vmouse.moveDistanceThreshold; didScroll = didScroll - || (scrollTopSupported && (startScrollX !== window.pageXOffset || startScrollY !== window.pageYOffset)) || (Math.abs(t.pageX - startX) > moveThreshold || Math.abs(t.pageY - startY) > moveThreshold); var flags = getVirtualBindingFlags(event.target); @@ -762,6 +740,10 @@ function handleTouchEnd(event) { + if (blockTouchTriggers){ + return; + } + disableTouchBindings(); var flags = getVirtualBindingFlags(event.target); @@ -786,9 +768,9 @@ startResetTimer(); } -function hasVirtualBindings($ele) +function hasVirtualBindings(ele) { - var bindings = $ele.data(dataPropertyName), k; + var bindings = $.data(ele, dataPropertyName), k; if (bindings){ for (k in bindings){ if (bindings[k]){ @@ -809,16 +791,14 @@ // If this is the first virtual mouse binding for this element, // add a bindings object to its data. - var $this = $(this); - - if (!hasVirtualBindings($this)){ - $this.data(dataPropertyName, {}); + if (!hasVirtualBindings(this)){ + $.data(this, dataPropertyName, {}); } // If setup is called, we know it is the first binding for this // eventType, so initialize the count for the eventType to zero. - var bindings = $this.data(dataPropertyName); + var bindings = $.data(this, dataPropertyName); bindings[eventType] = true; // If this is the first virtual mouse event for this type, @@ -833,7 +813,7 @@ // for elements unless they actually have handlers registered on them. // To get around this, we register dummy handlers on the elements. - $this.bind(realType, dummyMouseHandler); + $(this).bind(realType, dummyMouseHandler); // For now, if event capture is not supported, we rely on mouse handlers. if (eventCaptureSupported){ @@ -842,7 +822,22 @@ activeDocHandlers["touchstart"] = (activeDocHandlers["touchstart"] || 0) + 1; if (activeDocHandlers["touchstart"] === 1) { - $document.bind("touchstart", handleTouchStart); + $document.bind("touchstart", handleTouchStart) + + .bind("touchend", handleTouchEnd) + + // On touch platforms, touching the screen and then dragging your finger + // causes the window content to scroll after some distance threshold is + // exceeded. On these platforms, a scroll prevents a click event from being + // dispatched, and on some platforms, even the touchend is suppressed. To + // mimic the suppression of the click event, we need to watch for a scroll + // event. Unfortunately, some platforms like iOS don't dispatch scroll + // events until *AFTER* the user lifts their finger (touchend). This means + // we need to watch both scroll and touchmove events to figure out whether + // or not a scroll happenens before the touchend event is fired. + + .bind("touchmove", handleTouchMove) + .bind("scroll", handleScroll); } } }, @@ -862,14 +857,25 @@ --activeDocHandlers["touchstart"]; if (!activeDocHandlers["touchstart"]) { - $document.unbind("touchstart", handleTouchStart); + $document.unbind("touchstart", handleTouchStart) + .unbind("touchmove", handleTouchMove) + .unbind("touchend", handleTouchEnd) + .unbind("scroll", handleScroll); } } var $this = $(this), - bindings = $this.data(dataPropertyName); - bindings[eventType] = false; + bindings = $.data(this, dataPropertyName); + // teardown may be called when an element was + // removed from the DOM. If this is the case, + // jQuery core may have already stripped the element + // of any data bindings so we need to check it before + // using it. + if (bindings){ + bindings[eventType] = false; + } + // Unregister the dummy event handler. $this.unbind(realType, dummyMouseHandler); @@ -877,7 +883,7 @@ // If this is the last virtual mouse binding on the // element, remove the binding data from the element. - if (!hasVirtualBindings($this)){ + if (!hasVirtualBindings(this)){ $this.removeData(dataPropertyName); } } @@ -934,7 +940,7 @@ for (var i = 0; i < cnt; i++) { var o = clickBlockList[i], touchID = 0; - if ((ele === target && Math.abs(o.x - x) < threshold && Math.abs(o.y - y) < threshold) || $(ele).data(touchTargetPropertyName) === o.touchID){ + if ((ele === target && Math.abs(o.x - x) < threshold && Math.abs(o.y - y) < threshold) || $.data(ele, touchTargetPropertyName) === o.touchID){ // XXX: We may want to consider removing matches from the block list // instead of waiting for the reset timer to fire. e.preventDefault(); @@ -947,7 +953,8 @@ } }, true); } -})(jQuery, window, document);/* +})(jQuery, window, document); +/* * jQuery Mobile Framework : events * Copyright (c) jQuery Project * Dual licensed under the MIT or GPL Version 2 licenses. @@ -956,7 +963,7 @@ (function($, undefined ) { // add new event shortcuts -$.each( "touchstart touchmove touchend orientationchange tap taphold swipe swipeleft swiperight scrollstart scrollstop".split( " " ), function( i, name ) { +$.each( "touchstart touchmove touchend orientationchange throttledresize tap taphold swipe swipeleft swiperight scrollstart scrollstop".split( " " ), function( i, name ) { $.fn[ name ] = function( fn ) { return fn ? this.bind( name, fn ) : this.trigger( name ); }; @@ -1131,7 +1138,7 @@ // Because the orientationchange event doesn't exist, simulate the // event by testing window dimensions on resize. - win.bind( "resize", handler ); + win.bind( "throttledresize", handler ); }, teardown: function(){ // If the event is not supported natively, return false so that @@ -1140,7 +1147,7 @@ // Because the orientationchange event doesn't exist, unbind the // resize event handler. - win.unbind( "resize", handler ); + win.unbind( "throttledresize", handler ); }, add: function( handleObj ) { // Save a reference to the bound event handler. @@ -1171,13 +1178,48 @@ // Get the current page orientation. This method is exposed publicly, should it // be needed, as jQuery.event.special.orientationchange.orientation() - special_event.orientation = get_orientation = function() { + $.event.special.orientationchange.orientation = get_orientation = function() { var elem = document.documentElement; return elem && elem.clientWidth / elem.clientHeight < 1.1 ? "portrait" : "landscape"; }; })(jQuery); + +// throttled resize event +(function(){ + $.event.special.throttledresize = { + setup: function() { + $( this ).bind( "resize", handler ); + }, + teardown: function(){ + $( this ).unbind( "resize", handler ); + } + }; + + var throttle = 250, + handler = function(){ + curr = ( new Date() ).getTime(); + diff = curr - lastCall; + if( diff >= throttle ){ + lastCall = curr; + $( this ).trigger( "throttledresize" ); + } + else{ + if( heldCall ){ + clearTimeout( heldCall ); + } + //promise a held call will still execute + heldCall = setTimeout( handler, throttle - diff ); + } + }, + lastCall = 0, + heldCall, + curr, + diff; +})(); + + $.each({ scrollstop: "scrollstart", taphold: "tap", @@ -1593,7 +1635,7 @@ $.widget( "mobile.page", $.mobile.widget, { options: { backBtnText: "Back", - addBackBtn: true, + addBackBtn: false, backBtnTheme: null, degradeInputs: { color: false, @@ -1816,7 +1858,7 @@ //hash segment before &ui-page= is used to make Ajax request subPageUrlKey: "ui-page", - //anchor links with a data-rel, or pages with a data-role, that match these selectors will be untrackable in history + //anchor links with a data-rel, or pages with a data-role, that match these selectors will be untrackable in history //(no change in URL, not bookmarkable) nonHistorySelectors: "dialog", @@ -1828,21 +1870,24 @@ //automatically handle clicks and form submissions through Ajax, when same-domain ajaxEnabled: true, + + //When enabled, clicks and taps that result in Ajax page changes will happen slightly sooner on touch devices. + //Also, it will prevent the address bar from appearing on platforms like iOS during page transitions. + //This option has no effect on non-touch devices, but enabling it may interfere with jQuery plugins that bind to click events + useFastClick: true, //automatically load and show pages based on location.hash hashListeningEnabled: true, - // TODO: deprecated - remove at 1.0 - //automatically handle link clicks through Ajax, when possible - ajaxLinksEnabled: true, + //set default page transition - 'none' for no transitions + defaultPageTransition: "slide", + + //minimum scroll distance that will be remembered when returning to a page + minScrollBack: screen.height / 2, - // TODO: deprecated - remove at 1.0 - //automatically handle form submissions through Ajax, when possible - ajaxFormsEnabled: true, + //set default dialog transition - 'none' for no transitions + defaultDialogTransition: "pop", - //set default transition - 'none' for no transitions - defaultTransition: "slide", - //show loading message during Ajax requests //if false, message will not appear, but loading classes will still be toggled on html el loadingMessage: "loading", @@ -1850,11 +1895,6 @@ //error response message - appears when an Ajax page request fails pageLoadErrorMessage: "Error Loading Page", - //configure meta viewport tag's content attr: - //note: this feature is deprecated in A4 in favor of adding - //the meta viewport element directly in the markup - metaViewportContent: "width=device-width, minimum-scale=1, maximum-scale=1", - //support conditions that must be met in order to proceed //default enhanced qualifications are media query support OR IE 7+ gradeA: function(){ @@ -1899,7 +1939,10 @@ //scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value silentScroll: function( ypos ) { - ypos = ypos || 0; + if( $.type( ypos ) !== "number" ){ + ypos = $.mobile.defaultHomeScroll; + } + // prevent scrollstart and scrollstop events $.event.special.scrollstart.enabled = false; @@ -1911,32 +1954,42 @@ setTimeout(function() { $.event.special.scrollstart.enabled = true; }, 150 ); + }, + + // compile the namespace normalization regex once + normalizeRegex: /-([a-z])/g, + + // take a data attribute property, prepend the namespace + // and then camel case the attribute string + nsNormalize: function(prop){ + if(!prop) return; + + return $.camelCase( $.mobile.ns + prop ); } }); //mobile version of data and removeData and hasData methods //ensures all data is set and retrieved using jQuery Mobile's data namespace - $.fn.jqmData = function( prop, value ){ - return this.data( prop ? $.mobile.ns + prop : prop, value ); - }; + $.fn.jqmData = function( prop, value ){ + return this.data( prop ? $.mobile.nsNormalize(prop) : prop, value ); + }; - $.jqmData = function( elem, prop, value ){ - return $.data( elem, prop && $.mobile.ns + prop, value ); - }; + $.jqmData = function( elem, prop, value ){ + return $.data( elem, $.mobile.nsNormalize(prop), value ); + }; - $.fn.jqmRemoveData = function( prop ){ - return this.removeData( $.mobile.ns + prop ); - }; + $.fn.jqmRemoveData = function( prop ){ + return this.removeData( $.mobile.nsNormalize(prop) ); + }; - $.jqmRemoveData = function( elem, prop ){ - return $.removeData( elem, prop && $.mobile.ns + prop ); - }; + $.jqmRemoveData = function( elem, prop ){ + return $.removeData( elem, $.mobile.nsNormalize(prop) ); + }; - $.jqmHasData = function( elem, prop ){ - return $.hasData( elem, prop && $.mobile.ns + prop ); - }; + $.jqmHasData = function( elem, prop ){ + return $.hasData( elem, $.mobile.nsNormalize(prop) ); + }; - // Monkey-patching Sizzle to filter the :jqmData selector var oldFind = $.find; @@ -1962,86 +2015,228 @@ * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license */ -(function($, undefined ) { +( function( $, undefined ) { //define vars for interal use - var $window = $(window), - $html = $('html'), - $head = $('head'), + var $window = $( window ), + $html = $( 'html' ), + $head = $( 'head' ), //url path helpers for use in relative url management path = { + // This scary looking regular expression parses an absolute URL or its relative + // variants (protocol, site, document, query, and hash), into the various + // components (protocol, host, path, query, fragment, etc that make up the + // URL as well as some other commonly used sub-parts. When used with RegExp.exec() + // or String.match, it parses the URL into a results array that looks like this: + // + // [0]: http://jblas:pas...@my...:8080/mail/inbox?msg=1234&type=unread#msg-content + // [1]: http://jblas:pas...@my...:8080/mail/inbox?msg=1234&type=unread + // [2]: http://jblas:pas...@my...:8080/mail/inbox + // [3]: http://jblas:pas...@my...:8080 + // [4]: http: + // [5]: jblas:pas...@my...:8080 + // [6]: jblas:password + // [7]: jblas + // [8]: password + // [9]: mycompany.com:8080 + // [10]: mycompany.com + // [11]: 8080 + // [12]: /mail/inbox + // [13]: /mail/ + // [14]: inbox + // [15]: ?msg=1234&type=unread + // [16]: #msg-content + // + urlParseRE: /^(((([^:\/#\?]+:)?(?:\/\/((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?]+)(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/, + + //Parse a URL into a structure that allows easy access to + //all of the URL components by name. + parseUrl: function( url ) { + // If we're passed an object, we'll assume that it is + // a parsed url object and just return it back to the caller. + if ( typeof url === "object" ) { + return url; + } + + var u = url || "", + matches = path.urlParseRE.exec( url ), + results; + if ( matches ) { + // Create an object that allows the caller to access the sub-matches + // by name. Note that IE returns an empty string instead of undefined, + // like all other browsers do, so we normalize everything so its consistent + // no matter what browser we're running on. + results = { + href: matches[0] || "", + hrefNoHash: matches[1] || "", + hrefNoSearch: matches[2] || "", + domain: matches[3] || "", + protocol: matches[4] || "", + authority: matches[5] || "", + username: matches[7] || "", + password: matches[8] || "", + host: matches[9] || "", + hostname: matches[10] || "", + port: matches[11] || "", + pathname: matches[12] || "", + directory: matches[13] || "", + filename: matches[14] || "", + search: matches[15] || "", + hash: matches[16] || "" + }; + } + return results || {}; + }, + + //Turn relPath into an asbolute path. absPath is + //an optional absolute path which describes what + //relPath is relative to. + makePathAbsolute: function( relPath, absPath ) { + if ( relPath && relPath.charAt( 0 ) === "/" ) { + return relPath; + } + + relPath = relPath || ""; + absPath = absPath ? absPath.replace( /^\/|\/?[^\/]*$/g, "" ) : ""; + + var absStack = absPath ? absPath.split( "/" ) : [], + relStack = relPath.split( "/" ); + for ( var i = 0; i < relStack.length; i++ ) { + var d = relStack[ i ]; + switch ( d ) { + case ".": + break; + case "..": + if ( absStack.length ) { + absStack.pop(); + } + break; + default: + absStack.push( d ); + break; + } + } + return "/" + absStack.join( "/" ); + }, + + //Returns true if both urls have the same domain. + isSameDomain: function( absUrl1, absUrl2 ) { + return path.parseUrl( absUrl1 ).domain === path.parseUrl( absUrl2 ).domain; + }, + + //Returns true for any relative variant. + isRelativeUrl: function( url ) { + // All relative Url variants have one thing in common, no protocol. + return path.parseUrl( url ).protocol === ""; + }, + + //Returns true for an absolute url. + isAbsoluteUrl: function( url ) { + return path.parseUrl( url ).protocol !== ""; + }, + + //Turn the specified realtive URL into an absolute one. This function + //can handle all relative variants (protocol, site, document, query, fragment). + makeUrlAbsolute: function( relUrl, absUrl ) { + if ( !path.isRelativeUrl( relUrl ) ) { + return relUrl; + } + + var relObj = path.parseUrl( relUrl ), + absObj = path.parseUrl( absUrl ), + protocol = relObj.protocol || absObj.protocol, + authority = relObj.authority || absObj.authority, + hasPath = relObj.pathname !== "", + pathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ), + search = relObj.search || ( !hasPath && absObj.search ) || "", + hash = relObj.hash; + + return protocol + "//" + authority + pathname + search + hash; + }, + + //Add search (aka query) params to the specified url. + addSearchParams: function( url, params ) { + var u = path.parseUrl( url ), + p = ( typeof params === "object" ) ? $.param( params ) : params, + s = u.search || "?"; + return u.hrefNoSearch + s + ( s.charAt( s.length - 1 ) !== "?" ? "&" : "" ) + p + ( u.hash || "" ); + }, + + convertUrlToDataUrl: function( absUrl ) { + var u = path.parseUrl( absUrl ); + if ( path.isEmbeddedPage( u ) ) { + return u.hash.replace( /^#/, "" ); + } else if ( path.isSameDomain( u, documentBase ) ) { + return u.hrefNoHash.replace( documentBase.domain, "" ); + } + return absUrl; + }, + //get path from current hash, or from a file path - get: function( newPath ){ - if( newPath === undefined ){ + get: function( newPath ) { + if( newPath === undefined ) { newPath = location.hash; } - return path.stripHash( newPath ).replace(/[^\/]*\.[^\/*]+$/, ''); + return path.stripHash( newPath ).replace( /[^\/]*\.[^\/*]+$/, '' ); }, //return the substring of a filepath before the sub-page key, for making a server request - getFilePath: function( path ){ + getFilePath: function( path ) { var splitkey = '&' + $.mobile.subPageUrlKey; return path && path.split( splitkey )[0].split( dialogHashKey )[0]; }, //set location hash to path - set: function( path ){ + set: function( path ) { location.hash = path; }, - //location pathname from intial directory request - origin: '', - - setOrigin: function(){ - path.origin = path.get( location.protocol + '//' + location.host + location.pathname ); + //test if a given url (string) is a path + //NOTE might be exceptionally naive + isPath: function( url ) { + return ( /\// ).test( url ); }, - //prefix a relative url with the current path - // TODO rename to reflect conditional functionality - makeAbsolute: function( url ){ - // only create an absolute path when the hash can be used as one - return path.isPath(window.location.hash) ? path.get() + url : url; - }, - - // test if a given url (string) is a path - // NOTE might be exceptionally naive - isPath: function( url ){ - return /\//.test(url); - }, - //return a url path with the window's location protocol/hostname/pathname removed - clean: function( url ){ - // Replace the protocol, host, and pathname only once at the beginning of the url to avoid - // problems when it's included as a part of a param - // Also, since all urls are absolute in IE, we need to remove the pathname as well. - var leadingUrlRootRegex = new RegExp("^" + location.protocol + "//" + location.host + location.pathname); - return url.replace(leadingUrlRootRegex, ""); + clean: function( url ) { + return url.replace( documentBase.domain, "" ); }, //just return the url without an initial # - stripHash: function( url ){ + stripHash: function( url ) { return url.replace( /^#/, "" ); }, + //remove the preceding hash, any query params, and dialog notations + cleanHash: function( hash ) { + return path.stripHash( hash.replace( /\?.*$/, "" ).replace( dialogHashKey, "" ) ); + }, + //check whether a url is referencing the same domain, or an external domain or different protocol //could be mailto, etc - isExternal: function( url ){ - return path.hasProtocol( path.clean( url ) ); + isExternal: function( url ) { + var u = path.parseUrl( url ); + return u.protocol && u.domain !== documentUrl.domain ? true : false; }, - hasProtocol: function( url ){ - return (/^(:?\w+:)/).test( url ); + hasProtocol: function( url ) { + return ( /^(:?\w+:)/ ).test( url ); }, - //check if the url is relative - isRelative: function( url ){ - return (/^[^\/|#]/).test( url ) && !path.hasProtocol( url ); - }, + isEmbeddedPage: function( url ) { + var u = path.parseUrl( url ); - isEmbeddedPage: function( url ){ - return (/^#/).test( url ); + //if the path is absolute, then we need to compare the url against + //both the documentUrl and the documentBase. The main reason for this + //is that links embedded within external documents will refer to the + //application document, whereas links embedded within the application + //document will be resolved against the document base. + if ( u.protocol !== "" ) { + return ( u.hash && ( u.hrefNoHash === documentUrl.hrefNoHash || ( documentBaseDiffers && u.hrefNoHash === documentBase.hrefNoHash ) ) ); + } + return (/^#/).test( u.href ); } }, @@ -2058,22 +2253,22 @@ activeIndex: 0, //get active - getActive: function(){ + getActive: function() { return urlHistory.stack[ urlHistory.activeIndex ]; }, - getPrev: function(){ + getPrev: function() { return urlHistory.stack[ urlHistory.activeIndex - 1 ]; }, - getNext: function(){ + getNext: function() { return urlHistory.stack[ urlHistory.activeIndex + 1 ]; }, // addNew is used whenever a new page is added - addNew: function( url, transition, title, storedTo ){ + addNew: function( url, transition, title, storedTo ) { //if there's forward history, wipe it - if( urlHistory.getNext() ){ + if( urlHistory.getNext() ) { urlHistory.clearForward(); } @@ -2083,18 +2278,18 @@ }, //wipe urls ahead of active index - clearForward: function(){ + clearForward: function() { urlHistory.stack = urlHistory.stack.slice( 0, urlHistory.activeIndex + 1 ); }, - directHashChange: function(opts){ + directHashChange: function( opts ) { var back , forward, newActiveIndex; // check if url isp in history and if it's ahead or behind current page - $.each( urlHistory.stack, function( i, historyEntry ){ + $.each( urlHistory.stack, function( i, historyEntry ) { //if the url is in the stack, it's a forward or a back - if( opts.currentUrl === historyEntry.url ){ + if( opts.currentUrl === historyEntry.url ) { //define back and forward by whether url is older or newer than current page back = i < urlHistory.activeIndex; forward = !back; @@ -2105,137 +2300,209 @@ // save new page index, null check to prevent falsey 0 result this.activeIndex = newActiveIndex !== undefined ? newActiveIndex : this.activeIndex; - if( back ){ + if( back ) { opts.isBack(); - } else if( forward ){ + } else if( forward ) { opts.isForward(); } }, //disable hashchange event listener internally to ignore one change //toggled internally when location.hash is updated to match the url of a successful page load - ignoreNextHashChange: true + ignoreNextHashChange: false }, //define first selector to receive focus when a page is shown focusable = "[tabindex],a,button:visible,select:visible,input", - //contains role for next page, if defined on clicked link via data-rel - nextPageRole = null, - //queue to hold simultanious page transitions pageTransitionQueue = [], - // indicates whether or not page is in process of transitioning + //indicates whether or not page is in process of transitioning isPageTransitioning = false, //nonsense hash change key for dialogs, so they create a history entry dialogHashKey = "&ui-state=dialog", //existing base tag? - $base = $head.children("base"), - hostURL = location.protocol + '//' + location.host, - docLocation = path.get( hostURL + location.pathname ), - docBase = docLocation; + $base = $head.children( "base" ), - if ($base.length){ - var href = $base.attr("href"); - if (href){ - if (href.search(/^[^:\/]+:\/\/[^\/]+\/?/) === -1){ - //the href is not absolute, we need to turn it into one - //so that we can turn paths stored in our location hash into - //relative paths. - if (href.charAt(0) === '/'){ - //site relative url - docBase = hostURL + href; - } - else { - //the href is a document relative url - docBase = docLocation + href; - //XXX: we need some code here to calculate the final path - // just in case the docBase contains up-level (../) references. - } - } - else { - //the href is an absolute url - docBase = href; - } - } - //make sure docBase ends with a slash - docBase = docBase + (docBase.charAt(docBase.length - 1) === '/' ? ' ' : '/'); - } + //tuck away the original document URL minus any fragment. + documentUrl = path.parseUrl( location.href ), + //if the document has an embedded base tag, documentBase is set to its + //initial value. If a base tag does not exist, then we default to the documentUrl. + documentBase = $base.length ? path.parseUrl( path.makeUrlAbsolute( $base.attr( "href" ), documentUrl.href ) ) : documentUrl, + + //cache the comparison once. + documentBaseDiffers = ( documentUrl.hrefNoHash !== documentBase.hrefNoHash ); + //base element management, defined depending on dynamic base tag support var base = $.support.dynamicBaseTag ? { //define base element, for use in routing asset urls that are referenced in Ajax-requested markup - element: ($base.length ? $base : $("<base>", { href: docBase }).prependTo( $head )), + element: ( $base.length ? $base : $( "<base>", { href: documentBase.hrefNoHash } ).prependTo( $head ) ), //set the generated BASE element's href attribute to a new page's base path - set: function( href ){ - base.element.attr('href', docBase + path.get( href )); + set: function( href ) { + base.element.attr( "href", path.makeUrlAbsolute( href, documentBase ) ); }, //set the generated BASE element's href attribute to a new page's base path - reset: function(){ - base.element.attr('href', docBase ); + reset: function() { + base.element.attr( "href", documentBase.hrefNoHash ); } } : undefined; - - - //set location pathname from intial directory request - path.setOrigin(); - /* internal utility functions --------------------------------------*/ //direct focus to the page title, or otherwise first focusable element - function reFocus( page ){ + function reFocus( page ) { var lastClicked = page.jqmData( "lastClicked" ); - - if( lastClicked && lastClicked.length ){ + + if( lastClicked && lastClicked.length ) { lastClicked.focus(); } else { var pageTitle = page.find( ".ui-title:eq(0)" ); - - if( pageTitle.length ){ + + if( pageTitle.length ) { pageTitle.focus(); } else{ - page.find( focusable ).eq(0).focus(); + page.find( focusable ).eq( 0 ).focus(); } } } //remove active classes after page transition or error - function removeActiveLinkClass( forceRemoval ){ - if( !!$activeClickedLink && (!$activeClickedLink.closest( '.ui-page-active' ).length || forceRemoval )){ + function removeActiveLinkClass( forceRemoval ) { + if( !!$activeClickedLink && ( !$activeClickedLink.closest( '.ui-page-active' ).length || forceRemoval ) ) { $activeClickedLink.removeClass( $.mobile.activeBtnClass ); } $activeClickedLink = null; } + function releasePageTransitionLock() { + isPageTransitioning = false; + if( pageTransitionQueue.length > 0 ) { + $.mobile.changePage.apply( null, pageTransitionQueue.pop() ); + } + } + + //function for transitioning between two existing pages + function transitionPages( toPage, fromPage, transition, reverse ) { + + //get current scroll distance + var currScroll = $.support.scrollTop ? $window.scrollTop() : true, + toScroll = toPage.data( "lastScroll" ) || $.mobile.defaultHomeScroll, + screenHeight = getScreenHeight(); + + //if scrolled down, scroll to top + if( currScroll ){ + window.scrollTo( 0, $.mobile.defaultHomeScroll ); + } + + //if the Y location we're scrolling to is less than 10px, let it go for sake of smoothness + if( toScroll < $.mobile.minScrollBack ){ + toScroll = 0; + } + + if( fromPage ) { + //set as data for returning to that spot + fromPage + .height( screenHeight + currScroll ) + .jqmData( "lastScroll", currScroll ) + .jqmData( "lastClicked", $activeClickedLink ); + + //trigger before show/hide events + fromPage.data( "page" )._trigger( "beforehide", null, { nextPage: toPage } ); + } + toPage + .height( screenHeight + toScroll ) + .data( "page" )._trigger( "beforeshow", null, { prevPage: fromPage || $( "" ) } ); + + //clear page loader + $.mobile.hidePageLoadingMsg(); + + //find the transition handler for the specified transition. If there + //isn't one in our transitionHandlers dictionary, use the default one. + //call the handler immediately to kick-off the transition. + var th = $.mobile.transitionHandlers[transition || "none"] || $.mobile.defaultTransitionHandler, + promise = th( transition, reverse, toPage, fromPage ); + + promise.done(function() { + //reset toPage height bac + toPage.height( "" ); + + //jump to top or prev scroll, sometimes on iOS the page has not rendered yet. + if( toScroll ){ + $.mobile.silentScroll( toScroll ); + $( document ).one( "silentscroll", function() { reFocus( toPage ); } ); + } + else{ + reFocus( toPage ); + } + + //trigger show/hide events + if( fromPage ) { + fromPage.height("").data( "page" )._trigger( "hide", null, { nextPage: toPage } ); + } + + //trigger pageshow, define prevPage as either fromPage or empty jQuery obj + toPage.data( "page" )._trigger( "show", null, { prevPage: fromPage || $( "" ) } ); + }); + + return promise; + } + + //simply set the active page's minimum height to screen height, depending on orientation + function getScreenHeight(){ + var orientation = jQuery.event.special.orientationchange.orientation(), + port = orientation === "portrait", + winMin = port ? 480 : 320, + screenHeight = port ? screen.availHeight : screen.availWidth, + winHeight = Math.max( winMin, $( window ).height() ), + pageMin = Math.min( screenHeight, winHeight ); + + return pageMin; + } + + //simply set the active page's minimum height to screen height, depending on orientation + function resetActivePageHeight(){ + $( "." + $.mobile.activePageClass ).css( "min-height", getScreenHeight() ); + } + + //shared page enhancements + function enhancePage( $page, role ) { + // If a role was specified, make sure the data-role attribute + // on the page element is in sync. + if( role ) { + $page.attr( "data-" + $.mobile.ns + "role", role ); + } + + //run page plugin + $page.page(); + } + +/* exposed $.mobile methods */ + //animation complete callback - $.fn.animationComplete = function( callback ){ - if($.support.cssTransitions){ - return $(this).one('webkitAnimationEnd', callback); + $.fn.animationComplete = function( callback ) { + if( $.support.cssTransitions ) { + return $( this ).one( 'webkitAnimationEnd', callback ); } else{ // defer execution for consistency between webkit/non webkit - setTimeout(callback, 0); - return $(this); + setTimeout( callback, 0 ); + return $( this ); } }; - - -/* exposed $.mobile methods */ - //update location.hash, with or without triggering hashchange event //TODO - deprecate this one at 1.0 $.mobile.updateHash = path.set; @@ -2253,503 +2520,586 @@ //history stack $.mobile.urlHistory = urlHistory; + //default non-animation transition handler + $.mobile.noneTransitionHandler = function( name, reverse, $toPage, $fromPage ) { + if ( $fromPage ) { + $fromPage.removeClass( $.mobile.activePageClass ); + } + $toPage.addClass( $.mobile.activePageClass ); + + return $.Deferred().resolve( name, reverse, $toPage, $fromPage ).promise(); + }; + + //default handler for unknown transitions + $.mobile.defaultTransitionHandler = $.mobile.noneTransitionHandler; + + //transition handler dictionary for 3rd party transitions + $.mobile.transitionHandlers = { + none: $.mobile.defaultTransitionHandler + }; + //enable cross-domain page support $.mobile.allowCrossDomainPages = false; - // changepage function - $.mobile.changePage = function( to, transition, reverse, changeHash, fromHashChange ){ - //from is always the currently viewed page - var toIsArray = $.type(to) === "array", - toIsObject = $.type(to) === "object", - from = toIsArray ? to[0] : $.mobile.activePage; + //return the original document url + $.mobile.getDocumentUrl = function(asParsedObject) { + return asParsedObject ? $.extend( {}, documentUrl ) : documentUrl.href; + }; - to = toIsArray ? to[1] : to; + //return the original document base url + $.mobile.getDocumentBase = function(asParsedObject) { + return asParsedObject ? $.extend( {}, documentBase ) : documentBase.href; + }; - var url = $.type(to) === "string" ? path.stripHash( to ) : "", - fileUrl = url, - data, - type = 'get', - isFormRequest = false, - duplicateCachedPage = null, - currPage = urlHistory.getActive(), - back = false, - forward = false, - pageTitle = document.title; + // Load a page into the DOM. + $.mobile.loadPage = function( url, options ) { + // This function uses deferred notifications to let callers + // know when the page is done loading, or if an error has occurred. + var deferred = $.Deferred(), + // The default loadPage options with overrides specified by + // the caller. + settings = $.extend( {}, $.mobile.loadPage.defaults, options ), - // If we are trying to transition to the same page that we are currently on ignore the request. - // an illegal same page request is defined by the current page being the same as the url, as long as there's history - // and to is not an array or object (those are allowed to be "same") - if( currPage && urlHistory.stack.length > 1 && currPage.url === url && !toIsArray && !toIsObject ) { - return; - } - else if(isPageTransitioning) { - pageTransitionQueue.unshift(arguments); - return; - } + // The DOM element for the page after it has been loaded. + page = null, - isPageTransitioning = true; + // If the reloadPage option is true, and the page is already + // in the DOM, dupCachedPage will be set to the page element + // so that it can be removed after the new version of the + // page is loaded off the network. + dupCachedPage = null, - // if the changePage was sent from a hashChange event guess if it came from the history menu - // and match the transition accordingly - if( fromHashChange ){ - urlHistory.directHashChange({ - currentUrl: url, - isBack: function(){ - forward = !(back = true); - reverse = true; - transition = transition || currPage.transition; - }, - isForward: function(){ - forward = !(back = false); - transition = transition || urlHistory.getActive().transition; - } - }); + // The absolute version of the URL passed into the function. This + // version of the URL may contain dialog/subpage params in it. + absUrl = path.makeUrlAbsolute( url, documentBase.hrefNoHash ); - //TODO forward = !back was breaking for some reason + + // If the caller provided data, and we're using "get" request, + // append the data to the URL. + if ( settings.data && settings.type === "get" ) { + absUrl = path.addSearchParams( absUrl, settings.data ); + settings.data = undefined; } - if( toIsObject && to.url ){ - url = to.url; - data = to.data; - type = to.type; - isFormRequest = true; - //make get requests bookmarkable - if( data && type === 'get' ){ - if($.type( data ) === "object" ){ - data = $.param(data); - } + // The absolute version of the URL minus any dialog/subpage params. + // In otherwords the real URL of the page to be loaded. + var fileUrl = path.getFilePath( absUrl ), - url += "?" + data; - data = undefined; - } - } + // The version of the Url actually stored in the data-url attribute of + // the page. For embedded p... [truncated message content] |