1/* 2* jQuery Mobile v1.4.5 3* http://jquerymobile.com 4* 5* Copyright 2010, 2014 jQuery Foundation, Inc. and other contributors 6* Released under the MIT license. 7* http://jquery.org/license 8* 9*/ 10 11(function ( root, doc, factory ) { 12 if ( typeof define === "function" && define.amd ) { 13 // AMD. Register as an anonymous module. 14 define( [ "jquery" ], function ( $ ) { 15 factory( $, root, doc ); 16 return $.mobile; 17 }); 18 } else { 19 // Browser globals 20 factory( root.jQuery, root, doc ); 21 } 22}( this, document, function ( jQuery, window, document, undefined ) {/*! 23 * jQuery hashchange event - v1.3 - 7/21/2010 24 * http://benalman.com/projects/jquery-hashchange-plugin/ 25 * 26 * Copyright (c) 2010 "Cowboy" Ben Alman 27 * Dual licensed under the MIT and GPL licenses. 28 * http://benalman.com/about/license/ 29 */ 30 31// Script: jQuery hashchange event 32// 33// *Version: 1.3, Last updated: 7/21/2010* 34// 35// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ 36// GitHub - http://github.com/cowboy/jquery-hashchange/ 37// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js 38// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped) 39// 40// About: License 41// 42// Copyright (c) 2010 "Cowboy" Ben Alman, 43// Dual licensed under the MIT and GPL licenses. 44// http://benalman.com/about/license/ 45// 46// About: Examples 47// 48// These working examples, complete with fully commented code, illustrate a few 49// ways in which this plugin can be used. 50// 51// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ 52// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/ 53// 54// About: Support and Testing 55// 56// Information about what version or versions of jQuery this plugin has been 57// tested with, what browsers it has been tested in, and where the unit tests 58// reside (so you can test it yourself). 59// 60// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2 61// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5, 62// Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5. 63// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ 64// 65// About: Known issues 66// 67// While this jQuery hashchange event implementation is quite stable and 68// robust, there are a few unfortunate browser bugs surrounding expected 69// hashchange event-based behaviors, independent of any JavaScript 70// window.onhashchange abstraction. See the following examples for more 71// information: 72// 73// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ 74// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ 75// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ 76// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ 77// 78// Also note that should a browser natively support the window.onhashchange 79// event, but not report that it does, the fallback polling loop will be used. 80// 81// About: Release History 82// 83// 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more 84// "removable" for mobile-only development. Added IE6/7 document.title 85// support. Attempted to make Iframe as hidden as possible by using 86// techniques from http://www.paciellogroup.com/blog/?p=604. Added 87// support for the "shortcut" format $(window).hashchange( fn ) and 88// $(window).hashchange() like jQuery provides for built-in events. 89// Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and 90// lowered its default value to 50. Added <jQuery.fn.hashchange.domain> 91// and <jQuery.fn.hashchange.src> properties plus document-domain.html 92// file to address access denied issues when setting document.domain in 93// IE6/7. 94// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin 95// from a page on another domain would cause an error in Safari 4. Also, 96// IE6/7 Iframe is now inserted after the body (this actually works), 97// which prevents the page from scrolling when the event is first bound. 98// Event can also now be bound before DOM ready, but it won't be usable 99// before then in IE6/7. 100// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug 101// where browser version is incorrectly reported as 8.0, despite 102// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. 103// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special 104// window.onhashchange functionality into a separate plugin for users 105// who want just the basic event & back button support, without all the 106// extra awesomeness that BBQ provides. This plugin will be included as 107// part of jQuery BBQ, but also be available separately. 108 109(function($,window,undefined){ 110 '$:nomunge'; // Used by YUI compressor. 111 112 // Reused string. 113 var str_hashchange = 'hashchange', 114 115 // Method / object references. 116 doc = document, 117 fake_onhashchange, 118 special = $.event.special, 119 120 // Does the browser support window.onhashchange? Note that IE8 running in 121 // IE7 compatibility mode reports true for 'onhashchange' in window, even 122 // though the event isn't supported, so also test document.documentMode. 123 doc_mode = doc.documentMode, 124 supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 ); 125 126 // Get location.hash (or what you'd expect location.hash to be) sans any 127 // leading #. Thanks for making this necessary, Firefox! 128 function get_fragment( url ) { 129 url = url || location.href; 130 return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' ); 131 }; 132 133 // Method: jQuery.fn.hashchange 134 // 135 // Bind a handler to the window.onhashchange event or trigger all bound 136 // window.onhashchange event handlers. This behavior is consistent with 137 // jQuery's built-in event handlers. 138 // 139 // Usage: 140 // 141 // > jQuery(window).hashchange( [ handler ] ); 142 // 143 // Arguments: 144 // 145 // handler - (Function) Optional handler to be bound to the hashchange 146 // event. This is a "shortcut" for the more verbose form:
147 // jQuery(window).bind( 'hashchange', handler ). If handler is omitted, 148 // all bound window.onhashchange event handlers will be triggered. This 149 // is a shortcut for the more verbose 150 // jQuery(window).trigger( 'hashchange' ). These forms are described in 151 // the <hashchange event> section. 152 // 153 // Returns: 154 // 155 // (jQuery) The initial jQuery collection of elements. 156 157 // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and 158 // $(elem).hashchange() for triggering, like jQuery does for built-in events. 159 $.fn[ str_hashchange ] = function( fn ) { 160 return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange ); 161 }; 162 163 // Property: jQuery.fn.hashchange.delay 164 // 165 // The numeric interval (in milliseconds) at which the <hashchange event> 166 // polling loop executes. Defaults to 50. 167 168 // Property: jQuery.fn.hashchange.domain 169 // 170 // If you're setting document.domain in your JavaScript, and you want hash 171 // history to work in IE6/7, not only must this property be set, but you must 172 // also set document.domain BEFORE jQuery is loaded into the page. This 173 // property is only applicable if you are supporting IE6/7 (or IE8 operating 174 // in "IE7 compatibility" mode). 175 // 176 // In addition, the <jQuery.fn.hashchange.src> property must be set to the 177 // path of the included "document-domain.html" file, which can be renamed or 178 // modified if necessary (note that the document.domain specified must be the 179 // same in both your main JavaScript as well as in this file). 180 // 181 // Usage: 182 // 183 // jQuery.fn.hashchange.domain = document.domain; 184 185 // Property: jQuery.fn.hashchange.src 186 // 187 // If, for some reason, you need to specify an Iframe src file (for example, 188 // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can 189 // do so using this property. Note that when using this property, history 190 // won't be recorded in IE6/7 until the Iframe src file loads. This property 191 // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7 192 // compatibility" mode). 193 // 194 // Usage: 195 // 196 // jQuery.fn.hashchange.src = 'path/to/file.html'; 197 198 $.fn[ str_hashchange ].delay = 50; 199 /* 200 $.fn[ str_hashchange ].domain = null; 201 $.fn[ str_hashchange ].src = null; 202 */ 203 204 // Event: hashchange event 205 // 206 // Fired when location.hash changes. In browsers that support it, the native 207 // HTML5 window.onhashchange event is used, otherwise a polling loop is 208 // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to 209 // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7 210 // compatibility" mode), a hidden Iframe is created to allow the back button 211 // and hash-based history to work. 212 // 213 // Usage as described in <jQuery.fn.hashchange>: 214 // 215 // > // Bind an event handler. 216 // > jQuery(window).hashchange( function(e) { 217 // > var hash = location.hash; 218 // > ... 219 // > }); 220 // > 221 // > // Manually trigger the event handler. 222 // > jQuery(window).hashchange(); 223 // 224 // A more verbose usage that allows for event namespacing: 225 // 226 // > // Bind an event handler. 227 // > jQuery(window).bind( 'hashchange', function(e) { 228 // > var hash = location.hash; 229 // > ... 230 // > }); 231 // > 232 // > // Manually trigger the event handler. 233 // > jQuery(window).trigger( 'hashchange' ); 234 // 235 // Additional Notes: 236 // 237 // * The polling loop and Iframe are not created until at least one handler 238 // is actually bound to the 'hashchange' event. 239 // * If you need the bound handler(s) to execute immediately, in cases where 240 // a location.hash exists on page load, via bookmark or page refresh for 241 // example, use jQuery(window).hashchange() or the more verbose 242 // jQuery(window).trigger( 'hashchange' ). 243 // * The event can be bound before DOM ready, but since it won't be usable 244 // before then in IE6/7 (due to the necessary Iframe), recommended usage is 245 // to bind it inside a DOM ready handler. 246 247 // Override existing $.event.special.hashchange methods (allowing this plugin 248 // to be defined after jQuery BBQ in BBQ's source code). 249 special[ str_hashchange ] = $.extend( special[ str_hashchange ], { 250 251 // Called only when the first 'hashchange' event is bound to window. 252 setup: function() { 253 // If window.onhashchange is supported natively, there's nothing to do.. 254 if ( supports_onhashchange ) { return false; } 255 256 // Otherwise, we need to create our own. And we don't want to call this 257 // until the user binds to the event, just in case they never do, since it 258 // will create a polling loop and possibly even a hidden Iframe. 259 $( fake_onhashchange.start ); 260 }, 261 262 // Called only when the last 'hashchange' event is unbound from window. 263 teardown: function() { 264 // If window.onhashchange is supported natively, there's nothing to do.. 265 if ( supports_onhashchange ) { return false; } 266 267 // Otherwise, we need to stop ours (if possible). 268 $( fake_onhashchange.stop ); 269 } 270 271 }); 272 273 // fake_onhashchange does all the work of triggering the window.onhashchange 274 // event for browsers that don't natively support it, including creating a
275 // polling loop to watch for hash changes and in IE 6/7 creating a hidden 276 // Iframe to enable back and forward. 277 fake_onhashchange = (function(){ 278 var self = {}, 279 timeout_id, 280 281 // Remember the initial hash so it doesn't get triggered immediately. 282 last_hash = get_fragment(), 283 284 fn_retval = function(val){ return val; }, 285 history_set = fn_retval, 286 history_get = fn_retval; 287 288 // Start the polling loop. 289 self.start = function() { 290 timeout_id || poll(); 291 }; 292 293 // Stop the polling loop. 294 self.stop = function() { 295 timeout_id && clearTimeout( timeout_id ); 296 timeout_id = undefined; 297 }; 298 299 // This polling loop checks every $.fn.hashchange.delay milliseconds to see 300 // if location.hash has changed, and triggers the 'hashchange' event on 301 // window when necessary. 302 function poll() { 303 var hash = get_fragment(), 304 history_hash = history_get( last_hash ); 305 306 if ( hash !== last_hash ) { 307 history_set( last_hash = hash, history_hash ); 308 309 $(window).trigger( str_hashchange ); 310 311 } else if ( history_hash !== last_hash ) { 312 location.href = location.href.replace( /#.*/, '' ) + history_hash; 313 } 314 315 timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay ); 316 }; 317 318 // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 319 // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv 320 // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 321 window.attachEvent && !window.addEventListener && !supports_onhashchange && (function(){ 322 // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8 323 // when running in "IE7 compatibility" mode. 324 325 var iframe, 326 iframe_src; 327 328 // When the event is bound and polling starts in IE 6/7, create a hidden 329 // Iframe for history handling. 330 self.start = function(){ 331 if ( !iframe ) { 332 iframe_src = $.fn[ str_hashchange ].src; 333 iframe_src = iframe_src && iframe_src + get_fragment(); 334 335 // Create hidden Iframe. Attempt to make Iframe as hidden as possible 336 // by using techniques from http://www.paciellogroup.com/blog/?p=604. 337 iframe = $('<iframe tabindex="-1" title="empty"/>').hide() 338 339 // When Iframe has completely loaded, initialize the history and 340 // start polling. 341 .one( 'load', function(){ 342 iframe_src || history_set( get_fragment() ); 343 poll(); 344 }) 345 346 // Load Iframe src if specified, otherwise nothing. 347 .attr( 'src', iframe_src || 'javascript:0' ) 348 349 // Append Iframe after the end of the body to prevent unnecessary 350 // initial page scrolling (yes, this works). 351 .insertAfter( 'body' )[0].contentWindow; 352 353 // Whenever `document.title` changes, update the Iframe's title to 354 // prettify the back/next history menu entries. Since IE sometimes 355 // errors with "Unspecified error" the very first time this is set 356 // (yes, very useful) wrap this with a try/catch block. 357 doc.onpropertychange = function(){ 358 try { 359 if ( event.propertyName === 'title' ) { 360 iframe.document.title = doc.title; 361 } 362 } catch(e) {} 363 }; 364 365 } 366 }; 367 368 // Override the "stop" method since an IE6/7 Iframe was created. Even 369 // if there are no longer any bound event handlers, the polling loop 370 // is still necessary for back/next to work at all! 371 self.stop = fn_retval; 372 373 // Get history by looking at the hidden Iframe's location.hash. 374 history_get = function() { 375 return get_fragment( iframe.location.href ); 376 }; 377 378 // Set a new history item by opening and then closing the Iframe 379 // document, *then* setting its location.hash. If document.domain has 380 // been set, update that as well. 381 history_set = function( hash, history_hash ) { 382 var iframe_doc = iframe.document, 383 domain = $.fn[ str_hashchange ].domain; 384 385 if ( hash !== history_hash ) { 386 // Update Iframe with any initial `document.title` that might be set. 387 iframe_doc.title = doc.title; 388 389 // Opening the Iframe's document after it has been closed is what 390 // actually adds a history entry. 391 iframe_doc.open(); 392 393 // Set document.domain for the Iframe document as well, if necessary. 394 domain && iframe_doc.write( '\x3cscript>document.domain="' + domain + '"\x3c/script>' ); 395 396 iframe_doc.close(); 397 398 // Update the Iframe's hash, for great justice. 399 iframe.location.hash = hash; 400 } 401 }; 402 403 })(); 404 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 405 // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^ 406 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 407 408 return self; 409 })(); 410 411})(jQuery,this); 412 413(function( $ ) { 414 $.mobile = {}; 415}( jQuery )); 416 417(function( $, window, undefined ) { 418 $.extend( $.mobile, { 419 420 // Version of the jQuery Mobile Framework 421 version: "1.4.5", 422 423 // Deprecated and no longer used in 1.4 remove in 1.5 424 // Define the url parameter used for referencing widget-generated sub-pages.
425 // Translates to example.html&ui-page=subpageIdentifier 426 // hash segment before &ui-page= is used to make Ajax request 427 subPageUrlKey: "ui-page", 428 429 hideUrlBar: true, 430 431 // Keepnative Selector 432 keepNative: ":jqmData(role='none'), :jqmData(role='nojs')", 433 434 // Deprecated in 1.4 remove in 1.5 435 // Class assigned to page currently in view, and during transitions 436 activePageClass: "ui-page-active", 437 438 // Deprecated in 1.4 remove in 1.5 439 // Class used for "active" button state, from CSS framework 440 activeBtnClass: "ui-btn-active", 441 442 // Deprecated in 1.4 remove in 1.5 443 // Class used for "focus" form element state, from CSS framework 444 focusClass: "ui-focus", 445 446 // Automatically handle clicks and form submissions through Ajax, when same-domain 447 ajaxEnabled: true, 448 449 // Automatically load and show pages based on location.hash 450 hashListeningEnabled: true, 451 452 // disable to prevent jquery from bothering with links 453 linkBindingEnabled: true, 454 455 // Set default page transition - 'none' for no transitions 456 defaultPageTransition: "fade", 457 458 // Set maximum window width for transitions to apply - 'false' for no limit 459 maxTransitionWidth: false, 460 461 // Minimum scroll distance that will be remembered when returning to a page 462 // Deprecated remove in 1.5 463 minScrollBack: 0, 464 465 // Set default dialog transition - 'none' for no transitions 466 defaultDialogTransition: "pop", 467 468 // Error response message - appears when an Ajax page request fails 469 pageLoadErrorMessage: "Error Loading Page", 470 471 // For error messages, which theme does the box use? 472 pageLoadErrorMessageTheme: "a", 473 474 // replace calls to window.history.back with phonegaps navigation helper 475 // where it is provided on the window object 476 phonegapNavigationEnabled: false, 477 478 //automatically initialize the DOM when it's ready 479 autoInitializePage: true, 480 481 pushStateEnabled: true, 482 483 // allows users to opt in to ignoring content by marking a parent element as 484 // data-ignored 485 ignoreContentEnabled: false, 486 487 buttonMarkup: { 488 hoverDelay: 200 489 }, 490 491 // disable the alteration of the dynamic base tag or links in the case 492 // that a dynamic base tag isn't supported 493 dynamicBaseEnabled: true, 494 495 // default the property to remove dependency on assignment in init module 496 pageContainer: $(), 497 498 //enable cross-domain page support 499 allowCrossDomainPages: false, 500 501 dialogHashKey: "&ui-state=dialog" 502 }); 503})( jQuery, this ); 504 505(function( $, window, undefined ) { 506 var nsNormalizeDict = {}, 507 oldFind = $.find, 508 rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, 509 jqmDataRE = /:jqmData\(([^)]*)\)/g; 510 511 $.extend( $.mobile, { 512 513 // Namespace used framework-wide for data-attrs. Default is no namespace 514 515 ns: "", 516 517 // Retrieve an attribute from an element and perform some massaging of the value 518 519 getAttribute: function( element, key ) { 520 var data; 521 522 element = element.jquery ? element[0] : element; 523 524 if ( element && element.getAttribute ) { 525 data = element.getAttribute( "data-" + $.mobile.ns + key ); 526 } 527 528 // Copied from core's src/data.js:dataAttr() 529 // Convert from a string to a proper data type 530 try { 531 data = data === "true" ? true : 532 data === "false" ? false : 533 data === "null" ? null : 534 // Only convert to a number if it doesn't change the string 535 +data + "" === data ? +data : 536 rbrace.test( data ) ? JSON.parse( data ) : 537 data; 538 } catch( err ) {} 539 540 return data; 541 }, 542 543 // Expose our cache for testing purposes. 544 nsNormalizeDict: nsNormalizeDict, 545 546 // Take a data attribute property, prepend the namespace 547 // and then camel case the attribute string. Add the result 548 // to our nsNormalizeDict so we don't have to do this again. 549 nsNormalize: function( prop ) { 550 return nsNormalizeDict[ prop ] || 551 ( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) ); 552 }, 553 554 // Find the closest javascript page element to gather settings data jsperf test 555 // http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit 556 // possibly naive, but it shows that the parsing overhead for *just* the page selector vs 557 // the page and dialog selector is negligable. This could probably be speed up by 558 // doing a similar parent node traversal to the one found in the inherited theme code above 559 closestPageData: function( $target ) { 560 return $target 561 .closest( ":jqmData(role='page'), :jqmData(role='dialog')" ) 562 .data( "mobile-page" ); 563 } 564 565 }); 566 567 // Mobile version of data and removeData and hasData methods 568 // ensures all data is set and retrieved using jQuery Mobile's data namespace 569 $.fn.jqmData = function( prop, value ) { 570 var result; 571 if ( typeof prop !== "undefined" ) { 572 if ( prop ) { 573 prop = $.mobile.nsNormalize( prop ); 574 } 575 576 // undefined is permitted as an explicit input for the second param 577 // in this case it returns the value and does not set it to undefined 578 if ( arguments.length < 2 || value === undefined ) { 579 result = this.data( prop ); 580 } else { 581 result = this.data( prop, value ); 582 } 583 } 584 return result; 585 }; 586 587 $.jqmData = function( elem, prop, value ) { 588 var result; 589 if ( typeof prop !== "undefined" ) { 590 result = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value ); 591 } 592 return result; 593 }; 594 595 $.fn.jqmRemoveData = function( prop ) { 596 return this.removeData( $.mobile.nsNormalize( prop ) ); 597 }; 598 599 $.jqmRemoveData = function( elem, prop ) { 600 return $.removeData( elem, $.mobile.nsNormalize( prop ) ); 601 }; 602 603 $.find = function( selector, context, ret, extra ) { 604 if ( selector.indexOf( ":jqmData" ) > -1 ) { 605 selector = selector.replace( jqmDataRE, "[data-" + ( $.mobile.ns || "" ) + "$1]" ); 606 } 607 608 return oldFind.call( this, selector, context, ret, extra ); 609 }; 610 611 $.extend( $.find, oldFind ); 612 613})( jQuery, this ); 614 615/*! 616 * jQuery UI Core c0ab71056b936627e8a7821f03c044aec6280a40 617 * http://jqueryui.com 618 * 619 * Copyright 2013 jQuery Foundation and other contributors 620 * Released under the MIT license. 621 * http://jquery.org/license 622 * 623 * http://api.jqueryui.com/category/ui-core/ 624 */ 625(function( $, undefined ) { 626 627var uuid = 0, 628 runiqueId = /^ui-id-\d+$/; 629
vendor: 4,260 bytes, lines 630-793
630// $.ui might exist from components with no dependencies, e.g., $.ui.position 631$.ui = $.ui || {}; 632 633$.extend( $.ui, { 634 version: "c0ab71056b936627e8a7821f03c044aec6280a40", 635 636 keyCode: { 637 BACKSPACE: 8, 638 COMMA: 188, 639 DELETE: 46, 640 DOWN: 40, 641 END: 35, 642 ENTER: 13, 643 ESCAPE: 27, 644 HOME: 36, 645 LEFT: 37, 646 PAGE_DOWN: 34, 647 PAGE_UP: 33, 648 PERIOD: 190, 649 RIGHT: 39, 650 SPACE: 32, 651 TAB: 9, 652 UP: 38 653 } 654}); 655 656// plugins 657$.fn.extend({ 658 focus: (function( orig ) { 659 return function( delay, fn ) { 660 return typeof delay === "number" ? 661 this.each(function() { 662 var elem = this; 663 setTimeout(function() { 664 $( elem ).focus(); 665 if ( fn ) { 666 fn.call( elem ); 667 } 668 }, delay ); 669 }) : 670 orig.apply( this, arguments ); 671 }; 672 })( $.fn.focus ), 673 674 scrollParent: function() { 675 var scrollParent; 676 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { 677 scrollParent = this.parents().filter(function() { 678 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 679 }).eq(0); 680 } else { 681 scrollParent = this.parents().filter(function() { 682 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 683 }).eq(0); 684 } 685 686 return ( /fixed/ ).test( this.css( "position") ) || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent; 687 }, 688 689 uniqueId: function() { 690 return this.each(function() { 691 if ( !this.id ) { 692 this.id = "ui-id-" + (++uuid); 693 } 694 }); 695 }, 696 697 removeUniqueId: function() { 698 return this.each(function() { 699 if ( runiqueId.test( this.id ) ) { 700 $( this ).removeAttr( "id" ); 701 } 702 }); 703 } 704}); 705 706// selectors 707function focusable( element, isTabIndexNotNaN ) { 708 var map, mapName, img, 709 nodeName = element.nodeName.toLowerCase(); 710 if ( "area" === nodeName ) { 711 map = element.parentNode; 712 mapName = map.name; 713 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 714 return false; 715 } 716 img = $( "img[usemap=#" + mapName + "]" )[0]; 717 return !!img && visible( img ); 718 } 719 return ( /input|select|textarea|button|object/.test( nodeName ) ? 720 !element.disabled : 721 "a" === nodeName ? 722 element.href || isTabIndexNotNaN : 723 isTabIndexNotNaN) && 724 // the element and all of its ancestors must be visible 725 visible( element ); 726} 727 728function visible( element ) { 729 return $.expr.filters.visible( element ) && 730 !$( element ).parents().addBack().filter(function() { 731 return $.css( this, "visibility" ) === "hidden"; 732 }).length; 733} 734 735$.extend( $.expr[ ":" ], { 736 data: $.expr.createPseudo ? 737 $.expr.createPseudo(function( dataName ) { 738 return function( elem ) { 739 return !!$.data( elem, dataName ); 740 }; 741 }) : 742 // support: jQuery <1.8 743 function( elem, i, match ) { 744 return !!$.data( elem, match[ 3 ] ); 745 }, 746 747 focusable: function( element ) { 748 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 749 }, 750 751 tabbable: function( element ) { 752 var tabIndex = $.attr( element, "tabindex" ), 753 isTabIndexNaN = isNaN( tabIndex ); 754 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 755 } 756}); 757 758// support: jQuery <1.8 759if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { 760 $.each( [ "Width", "Height" ], function( i, name ) { 761 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 762 type = name.toLowerCase(), 763 orig = { 764 innerWidth: $.fn.innerWidth, 765 innerHeight: $.fn.innerHeight, 766 outerWidth: $.fn.outerWidth, 767 outerHeight: $.fn.outerHeight 768 }; 769 770 function reduce( elem, size, border, margin ) { 771 $.each( side, function() { 772 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; 773 if ( border ) { 774 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; 775 } 776 if ( margin ) { 777 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; 778 } 779 }); 780 return size; 781 } 782 783 $.fn[ "inner" + name ] = function( size ) { 784 if ( size === undefined ) { 785 return orig[ "inner" + name ].call( this ); 786 } 787 788 return this.each(function() { 789 $( this ).css( type, reduce( this, size ) + "px" ); 790 }); 791 }; 792 793 $.fn[ "outer" + name] = function( size, margin ) {
vendor: 4,375 bytes, lines 794-935
794 if ( typeof size !== "number" ) { 795 return orig[ "outer" + name ].call( this, size ); 796 } 797 798 return this.each(function() { 799 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 800 }); 801 }; 802 }); 803} 804 805// support: jQuery <1.8 806if ( !$.fn.addBack ) { 807 $.fn.addBack = function( selector ) { 808 return this.add( selector == null ? 809 this.prevObject : this.prevObject.filter( selector ) 810 ); 811 }; 812} 813 814// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) 815if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { 816 $.fn.removeData = (function( removeData ) { 817 return function( key ) { 818 if ( arguments.length ) { 819 return removeData.call( this, $.camelCase( key ) ); 820 } else { 821 return removeData.call( this ); 822 } 823 }; 824 })( $.fn.removeData ); 825} 826 827 828 829 830 831// deprecated 832$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); 833 834$.support.selectstart = "onselectstart" in document.createElement( "div" ); 835$.fn.extend({ 836 disableSelection: function() { 837 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + 838 ".ui-disableSelection", function( event ) { 839 event.preventDefault(); 840 }); 841 }, 842 843 enableSelection: function() { 844 return this.unbind( ".ui-disableSelection" ); 845 }, 846 847 zIndex: function( zIndex ) { 848 if ( zIndex !== undefined ) { 849 return this.css( "zIndex", zIndex ); 850 } 851 852 if ( this.length ) { 853 var elem = $( this[ 0 ] ), position, value; 854 while ( elem.length && elem[ 0 ] !== document ) { 855 // Ignore z-index if position is set to a value where z-index is ignored by the browser 856 // This makes behavior of this function consistent across browsers 857 // WebKit always returns auto if the element is positioned 858 position = elem.css( "position" ); 859 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 860 // IE returns 0 when zIndex is not specified 861 // other browsers return a string 862 // we ignore the case of nested elements with an explicit value of 0 863 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 864 value = parseInt( elem.css( "zIndex" ), 10 ); 865 if ( !isNaN( value ) && value !== 0 ) { 866 return value; 867 } 868 } 869 elem = elem.parent(); 870 } 871 } 872 873 return 0; 874 } 875}); 876 877// $.ui.plugin is deprecated. Use $.widget() extensions instead. 878$.ui.plugin = { 879 add: function( module, option, set ) { 880 var i, 881 proto = $.ui[ module ].prototype; 882 for ( i in set ) { 883 proto.plugins[ i ] = proto.plugins[ i ] || []; 884 proto.plugins[ i ].push( [ option, set[ i ] ] ); 885 } 886 }, 887 call: function( instance, name, args, allowDisconnected ) { 888 var i, 889 set = instance.plugins[ name ]; 890 891 if ( !set ) { 892 return; 893 } 894 895 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) { 896 return; 897 } 898 899 for ( i = 0; i < set.length; i++ ) { 900 if ( instance.options[ set[ i ][ 0 ] ] ) { 901 set[ i ][ 1 ].apply( instance.element, args ); 902 } 903 } 904 } 905}; 906 907})( jQuery ); 908 909(function( $, window, undefined ) { 910 911 // Subtract the height of external toolbars from the page height, if the page does not have 912 // internal toolbars of the same type. We take care to use the widget options if we find a 913 // widget instance and the element's data-attributes otherwise. 914 var compensateToolbars = function( page, desiredHeight ) { 915 var pageParent = page.parent(), 916 toolbarsAffectingHeight = [], 917 918 // We use this function to filter fixed toolbars with option updatePagePadding set to 919 // true (which is the default) from our height subtraction, because fixed toolbars with 920 // option updatePagePadding set to true compensate for their presence by adding padding 921 // to the active page. We want to avoid double-counting by also subtracting their 922 // height from the desired page height. 923 noPadders = function() { 924 var theElement = $( this ), 925 widgetOptions = $.mobile.toolbar && theElement.data( "mobile-toolbar" ) ? 926 theElement.toolbar( "option" ) : { 927 position: theElement.attr( "data-" + $.mobile.ns + "position" ), 928 updatePagePadding: ( theElement.attr( "data-" + $.mobile.ns + 929 "update-page-padding" ) !== false ) 930 }; 931 932 return !( widgetOptions.position === "fixed" && 933 widgetOptions.updatePagePadding === true ); 934 }, 935 externalHeaders = pageParent.children( ":jqmData(role='header')" ).filter( n
935oPadders ), 936 internalHeaders = page.children( ":jqmData(role='header')" ), 937 externalFooters = pageParent.children( ":jqmData(role='footer')" ).filter( noPadders ), 938 internalFooters = page.children( ":jqmData(role='footer')" ); 939 940 // If we have no internal headers, but we do have external headers, then their height 941 // reduces the page height 942 if ( internalHeaders.length === 0 && externalHeaders.length > 0 ) { 943 toolbarsAffectingHeight = toolbarsAffectingHeight.concat( externalHeaders.toArray() ); 944 } 945 946 // If we have no internal footers, but we do have external footers, then their height 947 // reduces the page height 948 if ( internalFooters.length === 0 && externalFooters.length > 0 ) { 949 toolbarsAffectingHeight = toolbarsAffectingHeight.concat( externalFooters.toArray() ); 950 } 951 952 $.each( toolbarsAffectingHeight, function( index, value ) { 953 desiredHeight -= $( value ).outerHeight(); 954 }); 955 956 // Height must be at least zero 957 return Math.max( 0, desiredHeight ); 958 }; 959 960 $.extend( $.mobile, { 961 // define the window and the document objects 962 window: $( window ), 963 document: $( document ), 964 965 // TODO: Remove and use $.ui.keyCode directly 966 keyCode: $.ui.keyCode, 967 968 // Place to store various widget extensions 969 behaviors: {}, 970 971 // Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value 972 silentScroll: function( ypos ) { 973 if ( $.type( ypos ) !== "number" ) { 974 ypos = $.mobile.defaultHomeScroll; 975 } 976 977 // prevent scrollstart and scrollstop events 978 $.event.special.scrollstart.enabled = false; 979 980 setTimeout(function() { 981 window.scrollTo( 0, ypos ); 982 $.mobile.document.trigger( "silentscroll", { x: 0, y: ypos }); 983 }, 20 ); 984 985 setTimeout(function() { 986 $.event.special.scrollstart.enabled = true; 987 }, 150 ); 988 }, 989 990 getClosestBaseUrl: function( ele ) { 991 // Find the closest page and extract out its url. 992 var url = $( ele ).closest( ".ui-page" ).jqmData( "url" ), 993 base = $.mobile.path.documentBase.hrefNoHash; 994 995 if ( !$.mobile.dynamicBaseEnabled || !url || !$.mobile.path.isPath( url ) ) { 996 url = base; 997 } 998 999 return $.mobile.path.makeUrlAbsolute( url, base ); 1000 }, 1001 removeActiveLinkClass: function( forceRemoval ) { 1002 if ( !!$.mobile.activeClickedLink && 1003 ( !$.mobile.activeClickedLink.closest( "." + $.mobile.activePageClass ).length || 1004 forceRemoval ) ) { 1005 1006 $.mobile.activeClickedLink.removeClass( $.mobile.activeBtnClass ); 1007 } 1008 $.mobile.activeClickedLink = null; 1009 }, 1010 1011 // DEPRECATED in 1.4 1012 // Find the closest parent with a theme class on it. Note that 1013 // we are not using $.fn.closest() on purpose here because this 1014 // method gets called quite a bit and we need it to be as fast 1015 // as possible. 1016 getInheritedTheme: function( el, defaultTheme ) { 1017 var e = el[ 0 ], 1018 ltr = "", 1019 re = /ui-(bar|body|overlay)-([a-z])\b/, 1020 c, m; 1021 while ( e ) { 1022 c = e.className || ""; 1023 if ( c && ( m = re.exec( c ) ) && ( ltr = m[ 2 ] ) ) { 1024 // We found a parent with a theme class 1025 // on it so bail from this loop. 1026 break; 1027 } 1028 1029 e = e.parentNode; 1030 } 1031 // Return the theme letter we found, if none, return the 1032 // specified default. 1033 return ltr || defaultTheme || "a"; 1034 }, 1035 1036 enhanceable: function( elements ) { 1037 return this.haveParents( elements, "enhance" ); 1038 }, 1039 1040 hijackable: function( elements ) { 1041 return this.haveParents( elements, "ajax" ); 1042 }, 1043 1044 haveParents: function( elements, attr ) { 1045 if ( !$.mobile.ignoreContentEnabled ) { 1046 return elements; 1047 } 1048 1049 var count = elements.length, 1050 $newSet = $(), 1051 e, $element, excluded, 1052 i, c; 1053 1054 for ( i = 0; i < count; i++ ) { 1055 $element = elements.eq( i ); 1056 excluded = false; 1057 e = elements[ i ]; 1058 1059 while ( e ) { 1060 c = e.getAttribute ? e.getAttribute( "data-" + $.mobile.ns + attr ) : ""; 1061 1062 if ( c === "false" ) { 1063 excluded = true; 1064 break; 1065 } 1066 1067 e = e.parentNode; 1068 } 1069 1070 if ( !excluded ) { 1071 $newSet = $newSet.add( $element ); 1072 } 1073 } 1074 1075 return $newSet; 1076 }, 1077 1078 getScreenHeight: function() { 1079 // Native innerHeight returns more accurate value for this across platforms, 1080 // jQuery version is here as a normalized fallback for platforms like Symbian 1081 return window.innerHeight || $.mobile.window.height(); 1082 }, 1083 1084 //simply set the active page's minimum height to screen height, depending on orientation 1085 resetActivePageHeight: function( height ) { 1086 var page = $( "." + $.mobile.activePageClass ), 1087 pageHeight = page.height(), 1088 pageOuterHeight = page.outerHeight( true ); 1089 1090 height = compensateToolbars( page, 1091 ( typeof height === "number" ) ? height : $.mobile.getScreenHeight() ); 1092 1093 // Remove any previous min-height setting 1094 page.css( "min-height", "" ); 1095 1096 // Set the minimum height only if the height as determined by CSS is insufficient 1097 if ( page.height() < height ) { 1098 page.css( "min-height", height - ( pageOuterHeight - pageHeight ) ); 1099 } 1100 }, 1101 1102 loading: function() { 1103 // If this is the first call to this function, instantiate a loader widget 1104 var loader = this.loading._widget || $( $.mobile.loader.prototype.defaultHtml ).loader(), 1105 1106 // Call the appropriate method on the loader 1107 returnValue = loader.loader.apply( loader, arguments ); 1108 1109 // Make sure the loader is retained for future calls to this function. 1110 this.loading._widget = loader; 1111 1112 return returnValue; 1113 } 1114 }); 1115 1116 $.addDependents = function( elem, newDependents ) { 1117 var $elem = $( elem ), 1118 dependents = $elem.jqmData( "dependents" ) || $(); 1119 1120 $elem.jqmData( "dependents", $( dependents ).add( newDependents ) ); 1121 }; 1122 1123 // plugins 1124 $.fn.extend({ 1125 removeWithDependents: function() { 1126 $.removeWithDependents( this ); 1127 }, 1128 1129 // Enhance child elements 1130 enhanceWithin: function() { 1131 var index, 1132 widgetElements = {}, 1133 keepNative = $.mobile.page.prototype.keepNativeSelector(), 1134 that = this; 1135 1136 // Add no js class to elements 1137 if ( $.mobile.nojs ) { 1138 $.mobile.nojs( this ); 1139 } 1140 1141 // Bind links for ajax nav 1142 if ( $.mobile.links ) { 1143 $.mobile.links( this ); 1144 } 1145 1146 // Degrade inputs for styleing 1147 if ( $.mobile.degradeInputsWithin ) { 1148 $.mobile.degradeInputsWithin( this ); 1149 } 1150 1151 // Run buttonmarkup 1152 if ( $.fn.buttonMarkup ) { 1153 this.find( $.fn.buttonMarkup.initSelector ).not( keepNative ) 1154 .jqmEnhanceable().buttonMarkup(); 1155 } 1156 1157 // Add classes for fieldContain 1158 if ( $.fn.fieldcontain ) { 1159 this.find( ":jqmData(role='fieldcontain')" ).not( keepNative ) 1160 .jqmEnhanceable().fieldcontain(); 1161 } 1162 1163 // Enhance widgets 1164 $.each( $.mobile.widgets, function( name, constructor ) { 1165 1166 // If initSelector not false find elements 1167 if ( constructor.initSelector ) { 1168 1169 // Filter elements that should not be enhanced based on parents 1170 var elements = $.mobile.enhanceable( that.find( constructor.initSelector ) ); 1171 1172 // If any matching elements remain filter ones with keepNativeSelector 1173 if ( elements.length > 0 ) { 1174 1175 // $.mobile.page.prototype.keepNativeSelector is deprecated this is just for backcompat 1176 // Switch to $.mobile.keepNative in 1.5 which is just a value not a function 1177 elements = elements.not( keepNative ); 1178 } 1179 1180 // Enhance whatever is left 1181 if ( elements.length > 0 ) { 1182 widgetElements[ constructor.prototype.widgetName ] = elements; 1183 } 1184 } 1185 }); 1186 1187 for ( index in widgetElements ) { 1188 widgetElements[ index ][ index ](); 1189 } 1190 1191 return this; 1192 }, 1193 1194 addDependents: function( newDependents ) { 1195 $.addDependents( this, newDependents ); 1196 }, 1197 1198 // note that this helper doesn't attempt to handle the callback 1199 // or setting of an html element's text, its only purpose is 1200 // to return the html encoded version of the text in all cases. (thus the name) 1201 getEncodedText: function() { 1202 return $( "<a>" ).text( this.text() ).html(); 1203 }, 1204 1205 // fluent helper function for the mobile namespaced equivalent 1206 jqmEnhanceable: function() { 1207 return $.mobile.enhanceable( this ); 1208 }, 1209 1210 jqmHijackable: function() { 1211 return $.mobile.hijackable( this ); 1212 } 1213 }); 1214 1215 $.removeWithDependents = function( nativeElement ) { 1216 var element = $( nativeElement ); 1217 1218 ( element.jqmData( "dependents" ) || $() ).remove(); 1219 element.remove(); 1220 }; 1221 $.addDependents = function( nativeElement, newDependents ) { 1222 var element = $( nativeElement ), 1223 dependents = element.jqmData( "dependents" ) || $(); 1224 1225 element.jqmData( "dependents", $( dependents ).add( newDependents ) ); 1226 }; 1227 1228 $.find.matches = function( expr, set ) { 1229 return $.find( expr, null, null, set ); 1230 }; 1231 1232 $.find.matchesSelector = function( node, expr ) { 1233 return $.find( expr, null, null, [ node ] ).length > 0; 1234 }; 1235 1236})( jQuery, this ); 1237 1238 1239(function( $, undefined ) { 1240 1241 /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 1242 window.matchMedia = window.matchMedia || (function( doc, undefined ) { 1243 1244 var bool, 1245 docElem = doc.documentElement,
1246 refNode = docElem.firstElementChild || docElem.firstChild, 1247 // fakeBody required for <FF4 when executed in <head> 1248 fakeBody = doc.createElement( "body" ), 1249 div = doc.createElement( "div" ); 1250 1251 div.id = "mq-test-1"; 1252 div.style.cssText = "position:absolute;top:-100em"; 1253 fakeBody.style.background = "none"; 1254 fakeBody.appendChild(div); 1255 1256 return function(q){ 1257 1258 div.innerHTML = "­<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>"; 1259 1260 docElem.insertBefore( fakeBody, refNode ); 1261 bool = div.offsetWidth === 42; 1262 docElem.removeChild( fakeBody ); 1263 1264 return { 1265 matches: bool, 1266 media: q 1267 }; 1268 1269 }; 1270 1271 }( document )); 1272 1273 // $.mobile.media uses matchMedia to return a boolean. 1274 $.mobile.media = function( q ) { 1275 return window.matchMedia( q ).matches; 1276 }; 1277 1278})(jQuery); 1279 1280 (function( $, undefined ) { 1281 var support = { 1282 touch: "ontouchend" in document 1283 }; 1284 1285 $.mobile.support = $.mobile.support || {}; 1286 $.extend( $.support, support ); 1287 $.extend( $.mobile.support, support ); 1288 }( jQuery )); 1289 1290 (function( $, undefined ) { 1291 $.extend( $.support, { 1292 orientation: "orientation" in window && "onorientationchange" in window 1293 }); 1294 }( jQuery )); 1295 1296(function( $, undefined ) { 1297 1298// thx Modernizr 1299function propExists( prop ) { 1300 var uc_prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ), 1301 props = ( prop + " " + vendors.join( uc_prop + " " ) + uc_prop ).split( " " ), 1302 v; 1303 1304 for ( v in props ) { 1305 if ( fbCSS[ props[ v ] ] !== undefined ) { 1306 return true; 1307 } 1308 } 1309} 1310 1311var fakeBody = $( "<body>" ).prependTo( "html" ), 1312 fbCSS = fakeBody[ 0 ].style, 1313 vendors = [ "Webkit", "Moz", "O" ], 1314 webos = "palmGetResource" in window, //only used to rule out scrollTop 1315 operamini = window.operamini && ({}).toString.call( window.operamini ) === "[object OperaMini]", 1316 bb = window.blackberry && !propExists( "-webkit-transform" ), //only used to rule out box shadow, as it's filled opaque on BB 5 and lower 1317 nokiaLTE7_3; 1318 1319// inline SVG support test 1320function inlineSVG() { 1321 // Thanks Modernizr & Erik Dahlstrom 1322 var w = window, 1323 svg = !!w.document.createElementNS && !!w.document.createElementNS( "http://www.w3.org/2000/svg", "svg" ).createSVGRect && !( w.opera && navigator.userAgent.indexOf( "Chrome" ) === -1 ), 1324 support = function( data ) { 1325 if ( !( data && svg ) ) { 1326 $( "html" ).addClass( "ui-nosvg" ); 1327 } 1328 }, 1329 img = new w.Image(); 1330 1331 img.onerror = function() { 1332 support( false ); 1333 }; 1334 img.onload = function() { 1335 support( img.width === 1 && img.height === 1 ); 1336 }; 1337 img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; 1338} 1339 1340function transform3dTest() { 1341 var mqProp = "transform-3d", 1342 // Because the `translate3d` test below throws false positives in Android: 1343 ret = $.mobile.media( "(-" + vendors.join( "-" + mqProp + "),(-" ) + "-" + mqProp + "),(" + mqProp + ")" ), 1344 el, transforms, t; 1345 1346 if ( ret ) { 1347 return !!ret; 1348 } 1349 1350 el = document.createElement( "div" ); 1351 transforms = { 1352 // We’re omitting Opera for the time being; MS uses unprefixed. 1353 "MozTransform": "-moz-transform", 1354 "transform": "transform" 1355 }; 1356 1357 fakeBody.append( el ); 1358 1359 for ( t in transforms ) { 1360 if ( el.style[ t ] !== undefined ) { 1361 el.style[ t ] = "translate3d( 100px, 1px, 1px )"; 1362 ret = window.getComputedStyle( el ).getPropertyValue( transforms[ t ] ); 1363 } 1364 } 1365 return ( !!ret && ret !== "none" ); 1366} 1367 1368// Test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting ) 1369function baseTagTest() { 1370 var fauxBase = location.protocol + "//" + location.host + location.pathname + "ui-dir/", 1371 base = $( "head base" ), 1372 fauxEle = null, 1373 href = "", 1374 link, rebase; 1375 1376 if ( !base.length ) { 1377 base = fauxEle = $( "<base>", { "href": fauxBase }).appendTo( "head" ); 1378 } else { 1379 href = base.attr( "href" ); 1380 } 1381 1382 link = $( "<a href='testurl' />" ).prependTo( fakeBody ); 1383 rebase = link[ 0 ].href; 1384 base[ 0 ].href = href || location.pathname; 1385 1386 if ( fauxEle ) { 1387 fauxEle.remove(); 1388 } 1389 return rebase.indexOf( fauxBase ) === 0; 1390} 1391 1392// Thanks Modernizr 1393function cssPointerEventsTest() { 1394 var element = document.createElement( "x" ), 1395 documentElement = document.documentElement, 1396 getComputedStyle = window.getComputedStyle, 1397 supports; 1398 1399 if ( !( "pointerEvents" in element.style ) ) { 1400 return false;
1401 } 1402 1403 element.style.pointerEvents = "auto"; 1404 element.style.pointerEvents = "x"; 1405 documentElement.appendChild( element ); 1406 supports = getComputedStyle && 1407 getComputedStyle( element, "" ).pointerEvents === "auto"; 1408 documentElement.removeChild( element ); 1409 return !!supports; 1410} 1411 1412function boundingRect() { 1413 var div = document.createElement( "div" ); 1414 return typeof div.getBoundingClientRect !== "undefined"; 1415} 1416 1417// non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683 1418// allows for inclusion of IE 6+, including Windows Mobile 7 1419$.extend( $.mobile, { browser: {} } ); 1420$.mobile.browser.oldIE = (function() { 1421 var v = 3, 1422 div = document.createElement( "div" ), 1423 a = div.all || []; 1424 1425 do { 1426 div.innerHTML = "<!--[if gt IE " + ( ++v ) + "]><br><![endif]-->"; 1427 } while( a[0] ); 1428 1429 return v > 4 ? v : !v; 1430})(); 1431 1432function fixedPosition() { 1433 var w = window, 1434 ua = navigator.userAgent, 1435 platform = navigator.platform, 1436 // Rendering engine is Webkit, and capture major version 1437 wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ ), 1438 wkversion = !!wkmatch && wkmatch[ 1 ], 1439 ffmatch = ua.match( /Fennec\/([0-9]+)/ ), 1440 ffversion = !!ffmatch && ffmatch[ 1 ], 1441 operammobilematch = ua.match( /Opera Mobi\/([0-9]+)/ ), 1442 omversion = !!operammobilematch && operammobilematch[ 1 ]; 1443 1444 if ( 1445 // iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5) 1446 ( ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1 || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534 ) || 1447 // Opera Mini 1448 ( w.operamini && ({}).toString.call( w.operamini ) === "[object OperaMini]" ) || 1449 ( operammobilematch && omversion < 7458 ) || 1450 //Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2) 1451 ( ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533 ) || 1452 // Firefox Mobile before 6.0 - 1453 ( ffversion && ffversion < 6 ) || 1454 // WebOS less than 3 1455 ( "palmGetResource" in window && wkversion && wkversion < 534 ) || 1456 // MeeGo 1457 ( ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1 ) ) { 1458 return false; 1459 } 1460 1461 return true; 1462} 1463 1464$.extend( $.support, { 1465 // Note, Chrome for iOS has an extremely quirky implementation of popstate. 1466 // We've chosen to take the shortest path to a bug fix here for issue #5426 1467 // See the following link for information about the regex chosen 1468 // https://developers.google.com/chrome/mobile/docs/user-agent#chrome_for_ios_user-agent 1469 pushState: "pushState" in history && 1470 "replaceState" in history && 1471 // When running inside a FF iframe, calling replaceState causes an error 1472 !( window.navigator.userAgent.indexOf( "Firefox" ) >= 0 && window.top !== window ) &&
1473 ( window.navigator.userAgent.search(/CriOS/) === -1 ), 1474 1475 mediaquery: $.mobile.media( "only all" ), 1476 cssPseudoElement: !!propExists( "content" ), 1477 touchOverflow: !!propExists( "overflowScrolling" ), 1478 cssTransform3d: transform3dTest(), 1479 boxShadow: !!propExists( "boxShadow" ) && !bb, 1480 fixedPosition: fixedPosition(), 1481 scrollTop: ("pageXOffset" in window || 1482 "scrollTop" in document.documentElement || 1483 "scrollTop" in fakeBody[ 0 ]) && !webos && !operamini, 1484 1485 dynamicBaseTag: baseTagTest(), 1486 cssPointerEvents: cssPointerEventsTest(), 1487 boundingRect: boundingRect(), 1488 inlineSVG: inlineSVG 1489}); 1490 1491fakeBody.remove(); 1492 1493// $.mobile.ajaxBlacklist is used to override ajaxEnabled on platforms that have known conflicts with hash history updates (BB5, Symbian) 1494// or that generally work better browsing in regular http for full page refreshes (Opera Mini) 1495// Note: This detection below is used as a last resort. 1496// We recommend only using these detection methods when all other more reliable/forward-looking approaches are not possible 1497nokiaLTE7_3 = (function() { 1498 1499 var ua = window.navigator.userAgent; 1500 1501 //The following is an attempt to match Nokia browsers that are running Symbian/s60, with webkit, version 7.3 or older 1502 return ua.indexOf( "Nokia" ) > -1 && 1503 ( ua.indexOf( "Symbian/3" ) > -1 || ua.indexOf( "Series60/5" ) > -1 ) && 1504 ua.indexOf( "AppleWebKit" ) > -1 && 1505 ua.match( /(BrowserNG|NokiaBrowser)\/7\.[0-3]/ ); 1506})(); 1507 1508// Support conditions that must be met in order to proceed 1509// default enhanced qualifications are media query support OR IE 7+ 1510 1511$.mobile.gradeA = function() { 1512 return ( ( $.support.mediaquery && $.support.cssPseudoElement ) || $.mobile.browser.oldIE && $.mobile.browser.oldIE >= 8 ) && ( $.support.boundingRect || $.fn.jquery.match(/1\.[0-7+]\.[0-9+]?/) !== null ); 1513}; 1514 1515$.mobile.ajaxBlacklist = 1516 // BlackBerry browsers, pre-webkit 1517 window.blackberry && !window.WebKitPoint || 1518 // Opera Mini 1519 operamini || 1520 // Symbian webkits pre 7.3 1521 nokiaLTE7_3; 1522 1523// Lastly, this workaround is the only way we've found so far to get pre 7.3 Symbian webkit devices 1524// to render the stylesheets when they're referenced before this script, as we'd recommend doing. 1525// This simply reappends the CSS in place, which for some reason makes it apply 1526if ( nokiaLTE7_3 ) { 1527 $(function() { 1528 $( "head link[rel='stylesheet']" ).attr( "rel", "alternate stylesheet" ).attr( "rel", "stylesheet" ); 1529 }); 1530} 1531 1532// For ruling out shadows via css 1533if ( !$.support.boxShadow ) { 1534 $( "html" ).addClass( "ui-noboxshadow" ); 1535} 1536 1537})( jQuery ); 1538 1539 1540(function( $, undefined ) { 1541 var $win = $.mobile.window, self, 1542 dummyFnToInitNavigate = function() { 1543 }; 1544 1545 $.event.special.beforenavigate = { 1546 setup: function() { 1547 $win.on( "navigate", dummyFnToInitNavigate ); 1548 }, 1549 1550 teardown: function() { 1551 $win.off( "navigate", dummyFnToInitNavigate ); 1552 } 1553 }; 1554 1555 $.event.special.navigate = self = { 1556 bound: false, 1557 1558 pushStateEnabled: true, 1559 1560 originalEventName: undefined, 1561 1562 // If pushstate support is present and push state support is defined to 1563 // be true on the mobile namespace. 1564 isPushStateEnabled: function() { 1565 return $.support.pushState && 1566 $.mobile.pushStateEnabled === true && 1567 this.isHashChangeEnabled(); 1568 }, 1569 1570 // !! assumes mobile namespace is present 1571 isHashChangeEnabled: function() { 1572 return $.mobile.hashListeningEnabled === true; 1573 }, 1574 1575 // TODO a lot of duplication between popstate and hashchange 1576 popstate: function( event ) { 1577 var newEvent = new $.Event( "navigate" ), 1578 beforeNavigate = new $.Event( "beforenavigate" ), 1579 state = event.originalEvent.state || {}; 1580 1581 beforeNavigate.originalEvent = event; 1582 $win.trigger( beforeNavigate ); 1583 1584 if ( beforeNavigate.isDefaultPrevented() ) { 1585 return; 1586 } 1587 1588 if ( event.historyState ) { 1589 $.extend(state, event.historyState); 1590 } 1591 1592 // Make sure the original event is tracked for the end 1593 // user to inspect incase they want to do something special 1594 newEvent.originalEvent = event; 1595 1596 // NOTE we let the current stack unwind because any assignment to 1597 // location.hash will stop the world and run this event handler. By 1598 // doing this we create a similar behavior to hashchange on hash 1599 // assignment 1600 setTimeout(function() { 1601 $win.trigger( newEvent, { 1602 state: state 1603 }); 1604 }, 0); 1605 }, 1606 1607 hashchange: function( event /*, data */ ) { 1608 var newEvent = new $.Event( "navigate" ), 1609 beforeNavigate = new $.Event( "beforenavigate" ); 1610 1611 beforeNavigate.originalEvent = event; 1612 $win.trigger( beforeNavigate ); 1613 1614 if ( beforeNavigate.isDefaultPrevented() ) { 1615 return; 1616 } 1617 1618 // Make sure the original event is tracked for the end 1619 // user to inspect incase they want to do something special 1620 newEvent.originalEvent = event; 1621 1622 // Trigger the hashchange with state provided by the user 1623 // that altered the hash 1624 $win.trigger( newEvent, { 1625 // Users that want to fully normalize the two events 1626 // will need to do history management down the stack and 1627 // add the state to the event before this binding is fired 1628 // TODO consider allowing for the explicit addition of callbacks 1629 // to be fired before this value is set to avoid event timing issues 1630 state: event.hashchangeState || {} 1631 }); 1632 }, 1633 1634 // TODO We really only want to set this up once 1635 // but I'm not clear if there's a beter way to achieve 1636 // this with the jQuery special event structure 1637 setup: function( /* data, namespaces */ ) { 1638 if ( self.bound ) { 1639 return; 1640 } 1641 1642 self.bound = true; 1643 1644 if ( self.isPushStateEnabled() ) { 1645 self.originalEventName = "popstate"; 1646 $win.bind( "popstate.navigate", self.popstate ); 1647 } else if ( self.isHashChangeEnabled() ) {
1648 self.originalEventName = "hashchange"; 1649 $win.bind( "hashchange.navigate", self.hashchange ); 1650 } 1651 } 1652 }; 1653})( jQuery ); 1654 1655 1656 1657 // throttled resize event 1658 (function( $ ) { 1659 $.event.special.throttledresize = { 1660 setup: function() { 1661 $( this ).bind( "resize", handler ); 1662 }, 1663 teardown: function() { 1664 $( this ).unbind( "resize", handler ); 1665 } 1666 }; 1667 1668 var throttle = 250, 1669 handler = function() { 1670 curr = ( new Date() ).getTime(); 1671 diff = curr - lastCall; 1672 1673 if ( diff >= throttle ) { 1674 1675 lastCall = curr; 1676 $( this ).trigger( "throttledresize" ); 1677 1678 } else { 1679 1680 if ( heldCall ) { 1681 clearTimeout( heldCall ); 1682 } 1683 1684 // Promise a held call will still execute 1685 heldCall = setTimeout( handler, throttle - diff ); 1686 } 1687 }, 1688 lastCall = 0, 1689 heldCall, 1690 curr, 1691 diff; 1692 })( jQuery ); 1693 1694 1695(function( $, window ) { 1696 var win = $( window ), 1697 event_name = "orientationchange", 1698 get_orientation, 1699 last_orientation, 1700 initial_orientation_is_landscape, 1701 initial_orientation_is_default, 1702 portrait_map = { "0": true, "180": true }, 1703 ww, wh, landscape_threshold; 1704 1705 // It seems that some device/browser vendors use window.orientation values 0 and 180 to 1706 // denote the "default" orientation. For iOS devices, and most other smart-phones tested, 1707 // the default orientation is always "portrait", but in some Android and RIM based tablets, 1708 // the default orientation is "landscape". The following code attempts to use the window 1709 // dimensions to figure out what the current orientation is, and then makes adjustments 1710 // to the to the portrait_map if necessary, so that we can properly decode the 1711 // window.orientation value whenever get_orientation() is called. 1712 // 1713 // Note that we used to use a media query to figure out what the orientation the browser 1714 // thinks it is in: 1715 // 1716 // initial_orientation_is_landscape = $.mobile.media("all and (orientation: landscape)"); 1717 // 1718 // but there was an iPhone/iPod Touch bug beginning with iOS 4.2, up through iOS 5.1, 1719 // where the browser *ALWAYS* applied the landscape media query. This bug does not 1720 // happen on iPad. 1721 1722 if ( $.support.orientation ) { 1723 1724 // Check the window width and height to figure out what the current orientation 1725 // of the device is at this moment. Note that we've initialized the portrait map 1726 // values to 0 and 180, *AND* we purposely check for landscape so that if we guess 1727 // wrong, , we default to the assumption that portrait is the default orientation. 1728 // We use a threshold check below because on some platforms like iOS, the iPhone 1729 // form-factor can report a larger width than height if the user turns on the 1730 // developer console. The actual threshold value is somewhat arbitrary, we just 1731 // need to make sure it is large enough to exclude the developer console case. 1732 1733 ww = window.innerWidth || win.width(); 1734 wh = window.innerHeight || win.height(); 1735 landscape_threshold = 50; 1736 1737 initial_orientation_is_landscape = ww > wh && ( ww - wh ) > landscape_threshold; 1738 1739 // Now check to see if the current window.orientation is 0 or 180. 1740 initial_orientation_is_default = portrait_map[ window.orientation ]; 1741 1742 // If the initial orientation is landscape, but window.orientation reports 0 or 180, *OR* 1743 // if the initial orientation is portrait, but window.orientation reports 90 or -90, we 1744 // need to flip our portrait_map values because landscape is the default orientation for 1745 // this device/browser. 1746 if ( ( initial_orientation_is_landscape && initial_orientation_is_default ) || ( !initial_orientation_is_landscape && !initial_orientation_is_default ) ) { 1747 portrait_map = { "-90": true, "90": true }; 1748 } 1749 } 1750 1751 $.event.special.orientationchange = $.extend( {}, $.event.special.orientationchange, { 1752 setup: function() { 1753 // If the event is supported natively, return false so that jQuery 1754 // will bind to the event using DOM methods. 1755 if ( $.support.orientation && !$.event.special.orientationchange.disabled ) { 1756 return false; 1757 } 1758 1759 // Get the current orientation to avoid initial double-triggering. 1760 last_orientation = get_orientation(); 1761 1762 // Because the orientationchange event doesn't exist, simulate the 1763 // event by testing window dimensions on resize. 1764 win.bind( "throttledresize", handler ); 1765 }, 1766 teardown: function() { 1767 // If the event is not supported natively, return false so that 1768 // jQuery will unbind the event using DOM methods. 1769 if ( $.support.orientation && !$.event.special.orientationchange.disabled ) { 1770 return false;
1771 } 1772 1773 // Because the orientationchange event doesn't exist, unbind the 1774 // resize event handler. 1775 win.unbind( "throttledresize", handler ); 1776 }, 1777 add: function( handleObj ) { 1778 // Save a reference to the bound event handler. 1779 var old_handler = handleObj.handler; 1780 1781 handleObj.handler = function( event ) { 1782 // Modify event object, adding the .orientation property. 1783 event.orientation = get_orientation(); 1784 1785 // Call the originally-bound event handler and return its result. 1786 return old_handler.apply( this, arguments ); 1787 }; 1788 } 1789 }); 1790 1791 // If the event is not supported natively, this handler will be bound to 1792 // the window resize event to simulate the orientationchange event. 1793 function handler() { 1794 // Get the current orientation. 1795 var orientation = get_orientation(); 1796 1797 if ( orientation !== last_orientation ) { 1798 // The orientation has changed, so trigger the orientationchange event. 1799 last_orientation = orientation; 1800 win.trigger( event_name ); 1801 } 1802 } 1803 1804 // Get the current page orientation. This method is exposed publicly, should it 1805 // be needed, as jQuery.event.special.orientationchange.orientation() 1806 $.event.special.orientationchange.orientation = get_orientation = function() { 1807 var isPortrait = true, elem = document.documentElement; 1808 1809 // prefer window orientation to the calculation based on screensize as 1810 // the actual screen resize takes place before or after the orientation change event 1811 // has been fired depending on implementation (eg android 2.3 is before, iphone after). 1812 // More testing is required to determine if a more reliable method of determining the new screensize 1813 // is possible when orientationchange is fired. (eg, use media queries + element + opacity) 1814 if ( $.support.orientation ) { 1815 // if the window orientation registers as 0 or 180 degrees report 1816 // portrait, otherwise landscape 1817 isPortrait = portrait_map[ window.orientation ]; 1818 } else { 1819 isPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1; 1820 } 1821 1822 return isPortrait ? "portrait" : "landscape"; 1823 }; 1824 1825 $.fn[ event_name ] = function( fn ) { 1826 return fn ? this.bind( event_name, fn ) : this.trigger( event_name ); 1827 }; 1828 1829 // jQuery < 1.8 1830 if ( $.attrFn ) { 1831 $.attrFn[ event_name ] = true; 1832 } 1833 1834}( jQuery, this )); 1835 1836 1837// This plugin is an experiment for abstracting away the touch and mouse 1838// events so that developers don't have to worry about which method of input 1839// the device their document is loaded on supports. 1840// 1841// The idea here is to allow the developer to register listeners for the 1842// basic mouse events, such as mousedown, mousemove, mouseup, and click, 1843// and the plugin will take care of registering the correct listeners 1844// behind the scenes to invoke the listener at the fastest possible time 1845// for that device, while still retaining the order of event firing in 1846// the traditional mouse environment, should multiple handlers be registered 1847// on the same element for different events. 1848// 1849// The current version exposes the following virtual events to jQuery bind methods: 1850// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel" 1851 1852(function( $, window, document, undefined ) { 1853 1854var dataPropertyName = "virtualMouseBindings", 1855 touchTargetPropertyName = "virtualTouchID", 1856 virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ), 1857 touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ), 1858 mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [], 1859 mouseEventProps = $.event.props.concat( mouseHookProps ), 1860 activeDocHandlers = {}, 1861 resetTimerID = 0, 1862 startX = 0, 1863 startY = 0, 1864 didScroll = false, 1865 clickBlockList = [], 1866 blockMouseTriggers = false, 1867 blockTouchTriggers = false, 1868 eventCaptureSupported = "addEventListener" in document, 1869 $document = $( document ), 1870 nextTouchID = 1, 1871 lastTouchID = 0, threshold, 1872 i; 1873 1874$.vmouse = { 1875 moveDistanceThreshold: 10, 1876 clickDistanceThreshold: 10, 1877 resetTimerDuration: 1500 1878}; 1879 1880function getNativeEvent( event ) { 1881 1882 while ( event && typeof event.originalEvent !== "undefined" ) { 1883 event = event.originalEvent; 1884 } 1885 return event; 1886} 1887
1888function createVirtualEvent( event, eventType ) { 1889 1890 var t = event.type, 1891 oe, props, ne, prop, ct, touch, i, j, len; 1892 1893 event = $.Event( event ); 1894 event.type = eventType; 1895 1896 oe = event.originalEvent; 1897 props = $.event.props; 1898 1899 // addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280 1900 // https://github.com/jquery/jquery-mobile/issues/3280 1901 if ( t.search( /^(mouse|click)/ ) > -1 ) { 1902 props = mouseEventProps; 1903 } 1904 1905 // copy original event properties over to the new event 1906 // this would happen if we could call $.event.fix instead of $.Event 1907 // but we don't have a way to force an event to be fixed multiple times 1908 if ( oe ) { 1909 for ( i = props.length, prop; i; ) { 1910 prop = props[ --i ]; 1911 event[ prop ] = oe[ prop ]; 1912 } 1913 } 1914 1915 // make sure that if the mouse and click virtual events are generated 1916 // without a .which one is defined 1917 if ( t.search(/mouse(down|up)|click/) > -1 && !event.which ) { 1918 event.which = 1; 1919 } 1920 1921 if ( t.search(/^touch/) !== -1 ) { 1922 ne = getNativeEvent( oe ); 1923 t = ne.touches; 1924 ct = ne.changedTouches; 1925 touch = ( t && t.length ) ? t[0] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined ); 1926 1927 if ( touch ) { 1928 for ( j = 0, len = touchEventProps.length; j < len; j++) { 1929 prop = touchEventProps[ j ]; 1930 event[ prop ] = touch[ prop ]; 1931 } 1932 } 1933 } 1934 1935 return event; 1936} 1937 1938function getVirtualBindingFlags( element ) { 1939 1940 var flags = {}, 1941 b, k; 1942 1943 while ( element ) { 1944 1945 b = $.data( element, dataPropertyName ); 1946 1947 for ( k in b ) { 1948 if ( b[ k ] ) { 1949 flags[ k ] = flags.hasVirtualBinding = true; 1950 } 1951 } 1952 element = element.parentNode; 1953 } 1954 return flags; 1955} 1956 1957function getClosestElementWithVirtualBinding( element, eventType ) { 1958 var b; 1959 while ( element ) { 1960 1961 b = $.data( element, dataPropertyName ); 1962 1963 if ( b && ( !eventType || b[ eventType ] ) ) { 1964 return element; 1965 } 1966 element = element.parentNode; 1967 } 1968 return null; 1969} 1970 1971function enableTouchBindings() { 1972 blockTouchTriggers = false; 1973} 1974 1975function disableTouchBindings() { 1976 blockTouchTriggers = true; 1977} 1978 1979function enableMouseBindings() { 1980 lastTouchID = 0; 1981 clickBlockList.length = 0; 1982 blockMouseTriggers = false; 1983 1984 // When mouse bindings are enabled, our 1985 // touch bindings are disabled. 1986 disableTouchBindings(); 1987} 1988 1989function disableMouseBindings() { 1990 // When mouse bindings are disabled, our 1991 // touch bindings are enabled. 1992 enableTouchBindings(); 1993} 1994 1995function startResetTimer() { 1996 clearResetTimer(); 1997 resetTimerID = setTimeout( function() { 1998 resetTimerID = 0; 1999 enableMouseBindings(); 2000 }, $.vmouse.resetTimerDuration ); 2001} 2002 2003function clearResetTimer() { 2004 if ( resetTimerID ) { 2005 clearTimeout( resetTimerID ); 2006 resetTimerID = 0; 2007 } 2008} 2009 2010function triggerVirtualEvent( eventType, event, flags ) { 2011 var ve; 2012 2013 if ( ( flags && flags[ eventType ] ) || 2014 ( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) { 2015 2016 ve = createVirtualEvent( event, eventType ); 2017 2018 $( event.target).trigger( ve ); 2019 } 2020 2021 return ve; 2022} 2023 2024function mouseEventCallback( event ) { 2025 var touchID = $.data( event.target, touchTargetPropertyName ), 2026 ve; 2027 2028 if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) { 2029 ve = triggerVirtualEvent( "v" + event.type, event ); 2030 if ( ve ) { 2031 if ( ve.isDefaultPrevented() ) { 2032 event.preventDefault(); 2033 } 2034 if ( ve.isPropagationStopped() ) { 2035 event.stopPropagation(); 2036 } 2037 if ( ve.isImmediatePropagationStopped() ) { 2038 event.stopImmediatePropagation(); 2039 } 2040 } 2041 } 2042} 2043 2044function handleTouchStart( event ) { 2045 2046 var touches = getNativeEvent( event ).touches, 2047 target, flags, t; 2048 2049 if ( touches && touches.length === 1 ) { 2050 2051 target = event.target; 2052 flags = getVirtualBindingFlags( target ); 2053 2054 if ( flags.hasVirtualBinding ) { 2055 2056 lastTouchID = nextTouchID++; 2057 $.data( target, touchTargetPropertyName, lastTouchID ); 2058 2059 clearResetTimer(); 2060 2061 disableMouseBindings(); 2062 didScroll = false; 2063 2064 t = getNativeEvent( event ).touches[ 0 ]; 2065 startX = t.pageX; 2066 startY = t.pageY; 2067 2068 triggerVirtualEvent( "vmouseover", event, flags ); 2069 triggerVirtualEvent( "vmousedown", event, flags ); 2070 } 2071 } 2072} 2073 2074function handleScroll( event ) { 2075 if ( blockTouchTriggers ) { 2076 return; 2077 } 2078 2079 if ( !didScroll ) { 2080 triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) ); 2081 } 2082 2083 didScroll = true; 2084 startResetTimer(); 2085} 2086 2087function handleTouchMove( event ) { 2088 if ( blockTouchTriggers ) { 2089 return; 2090 } 2091 2092 var t = getNativeEvent( event ).touches[ 0 ], 2093 didCancel = didScroll, 2094 moveThreshold = $.vmouse.moveDistanceThreshold, 2095 flags = getVirtualBindingFlags( event.target ); 2096 2097 didScroll = didScroll || 2098 ( Math.abs( t.pageX - startX ) > moveThreshold || 2099 Math.abs( t.pageY - startY ) > moveThreshold ); 2100 2101 if ( didScroll && !didCancel ) { 2102 triggerVirtualEvent( "vmousecancel", event, flags ); 2103 } 2104 2105 triggerVirtualEvent( "vmousemove", event, flags ); 2106 startResetTimer(); 2107} 2108 2109function handleTouchEnd( event ) { 2110 if ( blockTouchTriggers ) { 2111 return; 2112 } 2113 2114 disableTouchBindings(); 2115 2116 var flags = getVirtualBindingFlags( event.target ), 2117 ve, t; 2118 triggerVirtualEvent( "vmouseup", event, flags ); 2119 2120 if ( !didScroll ) { 2121 ve = triggerVirtualEvent( "vclick", event, flags ); 2122 if ( ve && ve.isDefaultPrevented() ) { 2123 // The target of the mouse events that follow the touchend 2124 // event don't necessarily match the target used during the 2125 // touch. This means we need to rely on coordinates for blocking 2126 // any click that is generated. 2127 t = getNativeEvent( event ).changedTouches[ 0 ]; 2128 clickBlockList.push({ 2129 touchID: lastTouchID, 2130 x: t.clientX, 2131 y: t.clientY 2132 }); 2133 2134 // Prevent any mouse events that follow from triggering 2135 // virtual event notifications. 2136 blockMouseTriggers = true; 2137 } 2138 } 2139 triggerVirtualEvent( "vmouseout", event, flags); 2140 didScroll = false;
2141 2142 startResetTimer(); 2143} 2144 2145function hasVirtualBindings( ele ) { 2146 var bindings = $.data( ele, dataPropertyName ), 2147 k; 2148 2149 if ( bindings ) { 2150 for ( k in bindings ) { 2151 if ( bindings[ k ] ) { 2152 return true; 2153 } 2154 } 2155 } 2156 return false; 2157} 2158 2159function dummyMouseHandler() {} 2160 2161function getSpecialEventObject( eventType ) { 2162 var realType = eventType.substr( 1 ); 2163 2164 return { 2165 setup: function(/* data, namespace */) { 2166 // If this is the first virtual mouse binding for this element, 2167 // add a bindings object to its data. 2168 2169 if ( !hasVirtualBindings( this ) ) { 2170 $.data( this, dataPropertyName, {} ); 2171 } 2172 2173 // If setup is called, we know it is the first binding for this 2174 // eventType, so initialize the count for the eventType to zero. 2175 var bindings = $.data( this, dataPropertyName ); 2176 bindings[ eventType ] = true; 2177 2178 // If this is the first virtual mouse event for this type, 2179 // register a global handler on the document. 2180 2181 activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1; 2182 2183 if ( activeDocHandlers[ eventType ] === 1 ) { 2184 $document.bind( realType, mouseEventCallback ); 2185 } 2186 2187 // Some browsers, like Opera Mini, won't dispatch mouse/click events 2188 // for elements unless they actually have handlers registered on them. 2189 // To get around this, we register dummy handlers on the elements. 2190 2191 $( this ).bind( realType, dummyMouseHandler ); 2192 2193 // For now, if event capture is not supported, we rely on mouse handlers. 2194 if ( eventCaptureSupported ) { 2195 // If this is the first virtual mouse binding for the document, 2196 // register our touchstart handler on the document. 2197 2198 activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1; 2199 2200 if ( activeDocHandlers[ "touchstart" ] === 1 ) { 2201 $document.bind( "touchstart", handleTouchStart ) 2202 .bind( "touchend", handleTouchEnd ) 2203 2204 // On touch platforms, touching the screen and then dragging your finger 2205 // causes the window content to scroll after some distance threshold is 2206 // exceeded. On these platforms, a scroll prevents a click event from being 2207 // dispatched, and on some platforms, even the touchend is suppressed. To 2208 // mimic the suppression of the click event, we need to watch for a scroll 2209 // event. Unfortunately, some platforms like iOS don't dispatch scroll 2210 // events until *AFTER* the user lifts their finger (touchend). This means 2211 // we need to watch both scroll and touchmove events to figure out whether 2212 // or not a scroll happenens before the touchend event is fired. 2213 2214 .bind( "touchmove", handleTouchMove ) 2215 .bind( "scroll", handleScroll ); 2216 } 2217 } 2218 }, 2219 2220 teardown: function(/* data, namespace */) { 2221 // If this is the last virtual binding for this eventType, 2222 // remove its global handler from the document. 2223 2224 --activeDocHandlers[ eventType ]; 2225 2226 if ( !activeDocHandlers[ eventType ] ) { 2227 $document.unbind( realType, mouseEventCallback ); 2228 } 2229 2230 if ( eventCaptureSupported ) { 2231 // If this is the last virtual mouse binding in existence, 2232 // remove our document touchstart listener. 2233 2234 --activeDocHandlers[ "touchstart" ]; 2235 2236 if ( !activeDocHandlers[ "touchstart" ] ) { 2237 $document.unbind( "touchstart", handleTouchStart ) 2238 .unbind( "touchmove", handleTouchMove ) 2239 .unbind( "touchend", handleTouchEnd ) 2240 .unbind( "scroll", handleScroll ); 2241 } 2242 } 2243 2244 var $this = $( this ), 2245 bindings = $.data( this, dataPropertyName ); 2246 2247 // teardown may be called when an element was 2248 // removed from the DOM. If this is the case, 2249 // jQuery core may have already stripped the element 2250 // of any data bindings so we need to check it before 2251 // using it. 2252 if ( bindings ) { 2253 bindings[ eventType ] = false; 2254 } 2255 2256 // Unregister the dummy event handler. 2257 2258 $this.unbind( realType, dummyMouseHandler ); 2259 2260 // If this is the last virtual mouse binding on the 2261 // element, remove the binding data from the element. 2262 2263 if ( !hasVirtualBindings( this ) ) { 2264 $this.removeData( dataPropertyName ); 2265 } 2266 } 2267 }; 2268} 2269 2270// Expose our custom events to the jQuery bind/unbind mechanism. 2271 2272for ( i = 0; i < virtualEventNames.length; i++ ) { 2273 $.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] ); 2274} 2275 2276// Add a capture click handler to block clicks. 2277// Note that we require event capture support for this so if the device 2278// doesn't support it, we punt for now and rely solely on mouse events. 2279if ( eventCaptureSupported ) { 2280 document.addEventListener( "click", function( e ) { 2281 var cnt = clickBlockList.length, 2282 target = e.target, 2283 x, y, ele, i, o, touchID; 2284 2285 if ( cnt ) { 2286 x = e.clientX; 2287 y = e.clientY; 2288 threshold = $.vmouse.clickDistanceThreshold; 2289 2290 // The idea here is to run through the clickBlockList to see if 2291 // the current click event is in the proximity of one of our 2292 // vclick events that had preventDefault() called on it. If we find 2293 // one, then we block the click. 2294 // 2295 // Why do we have to rely on proximity? 2296 // 2297 // Because the target of the touch event that triggered the vclick 2298 // can be different from the target of the click event synthesized 2299 // by the browser. The target of a mouse/click event that is synthesized 2300 // from a touch event seems to be implementation specific. For example, 2301 // some browsers will fire mouse/click events for a link that is near 2302 // a touch event, even though the target of the touchstart/touchend event 2303 // says the user touched outside the link. Also, it seems that with most 2304 // browsers, the target of the mouse/click event is not calculated until the 2305 // time it is dispatched, so if you replace an element that you touched 2306 // with another element, the target of the mouse/click will be the new 2307 // element underneath that point. 2308 // 2309 // Aside from proximity, we also check to see if the target and any 2310 // of its ancestors were the ones that blocked a click. This is necessary 2311 // because of the strange mouse/click target calculation done in the 2312 // Android 2.1 browser, where if you click on an element, and there is a 2313 // mouse/click handler on one of its ancestors, the target will be the 2314 // innermost child of the touched element, even if that child is no where 2315 // near the point of touch. 2316 2317 ele = target; 2318 2319 while ( ele ) { 2320 for ( i = 0; i < cnt; i++ ) { 2321 o = clickBlockList[ i ]; 2322 touchID = 0; 2323 2324 if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) || 2325 $.data( ele, touchTargetPropertyName ) === o.touchID ) { 2326 // XXX: We may want to consider removing matches from the block list 2327 // instead of waiting for the reset timer to fire. 2328 e.preventDefault(); 2329 e.stopPropagation(); 2330 return; 2331 } 2332 } 2333 ele = ele.parentNode; 2334 } 2335 } 2336 }, true); 2337} 2338}
2338)( jQuery, window, document ); 2339 2340 2341(function( $, window, undefined ) { 2342 var $document = $( document ), 2343 supportTouch = $.mobile.support.touch, 2344 scrollEvent = "touchmove scroll", 2345 touchStartEvent = supportTouch ? "touchstart" : "mousedown", 2346 touchStopEvent = supportTouch ? "touchend" : "mouseup", 2347 touchMoveEvent = supportTouch ? "touchmove" : "mousemove"; 2348 2349 // setup new event shortcuts 2350 $.each( ( "touchstart touchmove touchend " + 2351 "tap taphold " + 2352 "swipe swipeleft swiperight " + 2353 "scrollstart scrollstop" ).split( " " ), function( i, name ) { 2354 2355 $.fn[ name ] = function( fn ) { 2356 return fn ? this.bind( name, fn ) : this.trigger( name ); 2357 }; 2358 2359 // jQuery < 1.8 2360 if ( $.attrFn ) { 2361 $.attrFn[ name ] = true; 2362 } 2363 }); 2364 2365 function triggerCustomEvent( obj, eventType, event, bubble ) { 2366 var originalType = event.type; 2367 event.type = eventType; 2368 if ( bubble ) { 2369 $.event.trigger( event, undefined, obj ); 2370 } else { 2371 $.event.dispatch.call( obj, event ); 2372 } 2373 event.type = originalType; 2374 } 2375 2376 // also handles scrollstop 2377 $.event.special.scrollstart = { 2378 2379 enabled: true, 2380 setup: function() { 2381 2382 var thisObject = this, 2383 $this = $( thisObject ), 2384 scrolling, 2385 timer; 2386 2387 function trigger( event, state ) { 2388 scrolling = state; 2389 triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event ); 2390 } 2391 2392 // iPhone triggers scroll after a small delay; use touchmove instead 2393 $this.bind( scrollEvent, function( event ) { 2394 2395 if ( !$.event.special.scrollstart.enabled ) { 2396 return; 2397 } 2398 2399 if ( !scrolling ) { 2400 trigger( event, true ); 2401 } 2402 2403 clearTimeout( timer ); 2404 timer = setTimeout( function() { 2405 trigger( event, false ); 2406 }, 50 ); 2407 }); 2408 }, 2409 teardown: function() { 2410 $( this ).unbind( scrollEvent ); 2411 } 2412 }; 2413 2414 // also handles taphold 2415 $.event.special.tap = { 2416 tapholdThreshold: 750, 2417 emitTapOnTaphold: true, 2418 setup: function() { 2419 var thisObject = this, 2420 $this = $( thisObject ), 2421 isTaphold = false; 2422 2423 $this.bind( "vmousedown", function( event ) { 2424 isTaphold = false; 2425 if ( event.which && event.which !== 1 ) { 2426 return false; 2427 } 2428 2429 var origTarget = event.target, 2430 timer; 2431 2432 function clearTapTimer() { 2433 clearTimeout( timer ); 2434 } 2435 2436 function clearTapHandlers() { 2437 clearTapTimer(); 2438 2439 $this.unbind( "vclick", clickHandler ) 2440 .unbind( "vmouseup", clearTapTimer ); 2441 $document.unbind( "vmousecancel", clearTapHandlers ); 2442 } 2443 2444 function clickHandler( event ) { 2445 clearTapHandlers(); 2446 2447 // ONLY trigger a 'tap' event if the start target is 2448 // the same as the stop target. 2449 if ( !isTaphold && origTarget === event.target ) { 2450 triggerCustomEvent( thisObject, "tap", event ); 2451 } else if ( isTaphold ) { 2452 event.preventDefault(); 2453 } 2454 } 2455 2456 $this.bind( "vmouseup", clearTapTimer ) 2457 .bind( "vclick", clickHandler ); 2458 $document.bind( "vmousecancel", clearTapHandlers ); 2459 2460 timer = setTimeout( function() { 2461 if ( !$.event.special.tap.emitTapOnTaphold ) { 2462 isTaphold = true; 2463 } 2464 triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) ); 2465 }, $.event.special.tap.tapholdThreshold ); 2466 }); 2467 }, 2468 teardown: function() { 2469 $( this ).unbind( "vmousedown" ).unbind( "vclick" ).unbind( "vmouseup" ); 2470 $document.unbind( "vmousecancel" ); 2471 } 2472 }; 2473 2474 // Also handles swipeleft, swiperight 2475 $.event.special.swipe = { 2476 2477 // More than this horizontal displacement, and we will suppress scrolling. 2478 scrollSupressionThreshold: 30, 2479 2480 // More time than this, and it isn't a swipe. 2481 durationThreshold: 1000, 2482 2483 // Swipe horizontal displacement must be more than this. 2484 horizontalDistanceThreshold: 30, 2485 2486 // Swipe vertical displacement must be less than this. 2487 verticalDistanceThreshold: 30, 2488 2489 getLocation: function ( event ) { 2490 var winPageX = window.pageXOffset, 2491 winPageY = window.pageYOffset, 2492 x = event.clientX, 2493 y = event.clientY; 2494 2495 if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) || 2496 event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) { 2497 2498 // iOS4 clientX/clientY have the value that should have been 2499 // in pageX/pageY. While pageX/page/ have the value 0 2500 x = x - winPageX; 2501 y = y - winPageY; 2502 } else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) { 2503 2504 // Some Android browsers have totally bogus values for clientX/Y 2505 // when scrolling/zooming a page. Detectable since clientX/clientY 2506 // should never be smaller than pageX/pageY minus page scroll 2507 x = event.pageX - winPageX; 2508 y = event.pageY - winPageY; 2509 } 2510 2511 return { 2512 x: x, 2513 y: y 2514 }; 2515 }, 2516 2517 start: function( event ) { 2518 var data = event.originalEvent.touches ? 2519 event.originalEvent.touches[ 0 ] : event, 2520 location = $.event.special.swipe.getLocation( data ); 2521 return { 2522 time: ( new Date() ).getTime(), 2523 coords: [ location.x, location.y ], 2524 origin: $( event.target ) 2525 }; 2526 }, 2527 2528 stop: function( event ) { 2529 var data = event.originalEvent.touches ? 2530 event.originalEvent.touches[ 0 ] : event, 2531 location = $.event.special.swipe.getLocation( data ); 2532 return { 2533 time: ( new Date() ).getTime(), 2534 coords: [ location.x, location.y ] 2535 }; 2536 }, 2537 2538 handleSwipe: function( start, stop, thisObject, origTarget ) { 2539 if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
2540 Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold && 2541 Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) { 2542 var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight"; 2543 2544 triggerCustomEvent( thisObject, "swipe", $.Event( "swipe", { target: origTarget, swipestart: start, swipestop: stop }), true ); 2545 triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true ); 2546 return true; 2547 } 2548 return false; 2549 2550 }, 2551 2552 // This serves as a flag to ensure that at most one swipe event event is 2553 // in work at any given time 2554 eventInProgress: false, 2555 2556 setup: function() { 2557 var events, 2558 thisObject = this, 2559 $this = $( thisObject ), 2560 context = {}; 2561 2562 // Retrieve the events data for this element and add the swipe context 2563 events = $.data( this, "mobile-events" ); 2564 if ( !events ) { 2565 events = { length: 0 }; 2566 $.data( this, "mobile-events", events ); 2567 } 2568 events.length++; 2569 events.swipe = context; 2570 2571 context.start = function( event ) { 2572 2573 // Bail if we're already working on a swipe event 2574 if ( $.event.special.swipe.eventInProgress ) { 2575 return; 2576 } 2577 $.event.special.swipe.eventInProgress = true; 2578 2579 var stop, 2580 start = $.event.special.swipe.start( event ), 2581 origTarget = event.target, 2582 emitted = false; 2583 2584 context.move = function( event ) { 2585 if ( !start || event.isDefaultPrevented() ) { 2586 return; 2587 } 2588 2589 stop = $.event.special.swipe.stop( event ); 2590 if ( !emitted ) { 2591 emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget ); 2592 if ( emitted ) { 2593 2594 // Reset the context to make way for the next swipe event 2595 $.event.special.swipe.eventInProgress = false; 2596 } 2597 } 2598 // prevent scrolling 2599 if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) { 2600 event.preventDefault(); 2601 } 2602 }; 2603 2604 context.stop = function() { 2605 emitted = true; 2606 2607 // Reset the context to make way for the next swipe event 2608 $.event.special.swipe.eventInProgress = false; 2609 $document.off( touchMoveEvent, context.move ); 2610 context.move = null; 2611 }; 2612 2613 $document.on( touchMoveEvent, context.move ) 2614 .one( touchStopEvent, context.stop ); 2615 }; 2616 $this.on( touchStartEvent, context.start ); 2617 }, 2618 2619 teardown: function() { 2620 var events, context; 2621 2622 events = $.data( this, "mobile-events" ); 2623 if ( events ) { 2624 context = events.swipe; 2625 delete events.swipe; 2626 events.length--; 2627 if ( events.length === 0 ) { 2628 $.removeData( this, "mobile-events" ); 2629 } 2630 } 2631 2632 if ( context ) { 2633 if ( context.start ) { 2634 $( this ).off( touchStartEvent, context.start ); 2635 } 2636 if ( context.move ) { 2637 $document.off( touchMoveEvent, context.move ); 2638 } 2639 if ( context.stop ) { 2640 $document.off( touchStopEvent, context.stop ); 2641 } 2642 } 2643 } 2644 }; 2645 $.each({ 2646 scrollstop: "scrollstart", 2647 taphold: "tap", 2648 swipeleft: "swipe.left", 2649 swiperight: "swipe.right" 2650 }, function( event, sourceEvent ) { 2651 2652 $.event.special[ event ] = { 2653 setup: function() { 2654 $( this ).bind( sourceEvent, $.noop ); 2655 }, 2656 teardown: function() { 2657 $( this ).unbind( sourceEvent ); 2658 } 2659 }; 2660 }); 2661 2662})( jQuery, this ); 2663 2664 2665 2666}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.