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 627 var uuid = 0, 628 runiqueId = /^ui-id-\d+$/; 629
vendor: 4,159 bytes, lines 630-782
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 707 function 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 728 function 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 759 if (!$("<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) { 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 806 if (!$.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) 815 if ($("<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 }// deprecated 826 $.ui.ie = !!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()); 827 828 $.support.selectstart = "onselectstart" in document.createElement("div"); 829 $.fn.extend({ 830 disableSelection: function () { 831 return this.bind(($.support.selectstart ? "selectstart" : "mousedown") + 832 ".ui-disableSelection", function (event) { 833 event.preventDefault(); 834 }); 835 }, 836 837 enableSelection: function () { 838 return this.unbind(".ui-disableSelection"); 839 }, 840 841 zIndex: function (zIndex) { 842 if (zIndex !== undefined) { 843 return this.css("zIndex", zIndex); 844 } 845 846 if (this.length) { 847 var elem = $(this[0]), position, value; 848 while (elem.length && elem[0] !== document) { 849 // Ignore z-index if position is set to a value where z-index is ignored by the browser 850 // This makes behavior of this function consistent across browsers 851 // WebKit always returns auto if the element is positioned 852 position = elem.css("position"); 853 if (position === "absolute" || position === "relative" || position === "fixed") { 854 // IE returns 0 when zIndex is not specified 855 // other browsers return a string 856 // we ignore the case of nested elements with an explicit value of 0 857 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 858 value = parseInt(elem.css("zIndex"), 10); 859 if (!isNaN(value) && value !== 0) { 860 return value; 861 } 862 } 863 elem = elem.parent(); 864 } 865 } 866 867 return 0; 868 } 869 }); 870 871 // $.ui.plugin is deprecated. Use $.widget() extensions instead. 872 $.ui.plugin = { 873 add: function (module, option, set) { 874 var i, 875 proto = $.ui[module].prototype; 876 for (i in set) { 877 proto.plugins[i] = proto.plugins[i] || []; 878 proto.plugins[i].push([option, set[i]]); 879 } 880 }, 881 call: function (instance, name, args, allowDisconnected) { 882 var i, 883 set = instance.plugins[name]; 884 885 if (!set) { 886 return; 887 } 888 889 if (!allowDisconnected && (!instance.element[0].parentNode || instance.element[0].parentNode.nodeType === 11)) { 890 return; 891 } 892 893 for (i = 0; i < set.length; i++) { 894 if (instance.options[set[i][0]]) { 895 set[i][1].apply(instance.element, args); 896 } 897 } 898 } 899 }; 900 901 })(jQuery); 902 903 (function ($, window, undefined) { 904 905 // Subtract the height of external toolbars from the page height, if the page does not have 906 // internal toolbars of the same type. We take care to use the widget options if we find a 907 // widget instance and the element's data-attributes otherwise. 908 var compensateToolbars = function (page, desiredHeight) { 909 var pageParent = page.parent(), 910 toolbarsAffectingHeight = [], 911 912 // We use this function to filter fixed toolbars with option updatePagePadding set to 913 // true (which is the default) from our height subtraction, because fixed toolbars with 914 // option updatePagePadding set to true compensate for their presence by adding padding 915 // to the active page. We want to avoid double-counting by also subtracting their 916 // height from the desired page height. 917 noPadders = function () { 918 var theElement = $(this), 919 widgetOptions = $.mobile.toolbar && theElement.data("mobile-toolbar") ? 920 theElement.toolbar("option") : { 921 position: theElement.attr("data-" + $.mobile.ns + "position"), 922 updatePagePadding: (theElement.attr("data-" + $.mobile.ns + 923 "update-page-padding") !== false) 924 }; 925 926 return !(widgetOptions.position === "fixed" && 927 widgetOptions.updatePagePadding === true); 928 }, 929 externalHeaders = pageParent.children(":jqmData(role='header')").filter(noPadders), 930 internalHeaders = page.children(":jqmData(role='header')"), 931 externalFooters = pageParent.children(":jqmData(role='footer')").filter(noPadders), 932 internalFooters = page.children(":jqmData(role='footer')"); 933 934 // If we have no internal headers, but we do have external headers, then their height 935 // reduces the page height 936 if (internalHeaders.length === 0 && externalHeaders.length > 0) { 937 toolbarsAffectingHeight = toolbarsAffectingHeight.concat(externalHeaders.toArray()); 938 } 939 940 // If we have no internal footers, but we do have external footers, then their height 941 // reduces the page height 942 if (internalFooters.length === 0 && externalFooters.length > 0) { 943 toolbarsAffectingHeight = toolbarsAffectingHeight.concat(externalFooters.toArray()); 944 } 945 946 $.each(toolbarsAffectingHeight, function (index, value) { 947 desiredHeight -= $(value).outerHeight(); 948 }); 949 950 // Height must be at least zero 951 return Math.max(0, desiredHeight); 952 }; 953 954 $.extend($.mobile, { 955 // define the window and the document objects 956 window: $(window), 957 document: $(document), 958 959 // TODO: Remove and use $.ui.keyCode directly 960 keyCode: $.ui.keyCode, 961 962 // Place to store various widget extensions 963 behaviors: {}, 964 965 // Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value 966 silentScroll: function (ypos) { 967 if ($.type(ypos) !== "number") { 968 ypos = $.mobile.defaultHomeScroll; 969 } 970 971 // prevent scrollstart and scrollstop events 972 $.event.special.scrollstart.enabled = false;
973 974 setTimeout(function () { 975 window.scrollTo(0, ypos); 976 $.mobile.document.trigger("silentscroll", { x: 0, y: ypos }); 977 }, 20); 978 979 setTimeout(function () { 980 $.event.special.scrollstart.enabled = true; 981 }, 150); 982 }, 983 984 getClosestBaseUrl: function (ele) { 985 // Find the closest page and extract out its url. 986 var url = $(ele).closest(".ui-page").jqmData("url"), 987 base = $.mobile.path.documentBase.hrefNoHash; 988 989 if (!$.mobile.dynamicBaseEnabled || !url || !$.mobile.path.isPath(url)) { 990 url = base; 991 } 992 993 return $.mobile.path.makeUrlAbsolute(url, base); 994 }, 995 removeActiveLinkClass: function (forceRemoval) { 996 if (!!$.mobile.activeClickedLink && 997 (!$.mobile.activeClickedLink.closest("." + $.mobile.activePageClass).length || 998 forceRemoval)) { 999 1000 $.mobile.activeClickedLink.removeClass($.mobile.activeBtnClass); 1001 } 1002 $.mobile.activeClickedLink = null; 1003 }, 1004 1005 // DEPRECATED in 1.4 1006 // Find the closest parent with a theme class on it. Note that 1007 // we are not using $.fn.closest() on purpose here because this 1008 // method gets called quite a bit and we need it to be as fast 1009 // as possible. 1010 getInheritedTheme: function (el, defaultTheme) { 1011 var e = el[0], 1012 ltr = "", 1013 re = /ui-(bar|body|overlay)-([a-z])\b/, 1014 c, m; 1015 while (e) { 1016 c = e.className || ""; 1017 if (c && (m = re.exec(c)) && (ltr = m[2])) { 1018 // We found a parent with a theme class 1019 // on it so bail from this loop. 1020 break; 1021 } 1022 1023 e = e.parentNode; 1024 } 1025 // Return the theme letter we found, if none, return the 1026 // specified default. 1027 return ltr || defaultTheme || "a"; 1028 }, 1029 1030 enhanceable: function (elements) { 1031 return this.haveParents(elements, "enhance"); 1032 }, 1033 1034 hijackable: function (elements) { 1035 return this.haveParents(elements, "ajax"); 1036 }, 1037 1038 haveParents: function (elements, attr) { 1039 if (!$.mobile.ignoreContentEnabled) { 1040 return elements; 1041 } 1042 1043 var count = elements.length, 1044 $newSet = $(), 1045 e, $element, excluded, 1046 i, c; 1047 1048 for (i = 0; i < count; i++) { 1049 $element = elements.eq(i); 1050 excluded = false; 1051 e = elements[i]; 1052 1053 while (e) { 1054 c = e.getAttribute ? e.getAttribute("data-" + $.mobile.ns + attr) : ""; 1055 1056 if (c === "false") { 1057 excluded = true; 1058 break; 1059 } 1060 1061 e = e.parentNode; 1062 } 1063 1064 if (!excluded) { 1065 $newSet = $newSet.add($element); 1066 } 1067 } 1068 1069 return $newSet; 1070 }, 1071 1072 getScreenHeight: function () { 1073 // Native innerHeight returns more accurate value for this across platforms, 1074 // jQuery version is here as a normalized fallback for platforms like Symbian 1075 return window.innerHeight || $.mobile.window.height(); 1076 }, 1077 1078 //simply set the active page's minimum height to screen height, depending on orientation 1079 resetActivePageHeight: function (height) { 1080 var page = $("." + $.mobile.activePageClass), 1081 pageHeight = page.height(), 1082 pageOuterHeight = page.outerHeight(true); 1083 1084 height = compensateToolbars(page, 1085 (typeof height === "number") ? height : $.mobile.getScreenHeight()); 1086 1087 // Remove any previous min-height setting 1088 page.css("min-height", ""); 1089 1090 // Set the minimum height only if the height as determined by CSS is insufficient 1091 if (page.height() < height) { 1092 page.css("min-height", height - (pageOuterHeight - pageHeight)); 1093 } 1094 }, 1095 1096 loading: function () { 1097 // If this is the first call to this function, instantiate a loader widget 1098 var loader = this.loading._widget || $($.mobile.loader.prototype.defaultHtml).loader(), 1099 1100 // Call the appropriate method on the loader 1101 returnValue = loader.loader.apply(loader, arguments); 1102 1103 // Make sure the loader is retained for future calls to this function. 1104 this.loading._widget = loader; 1105 1106 return returnValue; 1107 } 1108 }); 1109 1110 $.addDependents = function (elem, newDependents) { 1111 var $elem = $(elem), 1112 dependents = $elem.jqmData("dependents") || $(); 1113 1114 $elem.jqmData("dependents", $(dependents).add(newDependents)); 1115 }; 1116 1117 // plugins 1118 $.fn.extend({ 1119 removeWithDependents: function () { 1120 $.removeWithDependents(this); 1121 }, 1122 1123 // Enhance child elements 1124 enhanceWithin: function () { 1125 var index, 1126 widgetElements = {}, 1127 keepNative = $.mobile.page.prototype.keepNativeSelector(), 1128 that = this; 1129 1130 // Add no js class to elements 1131 if ($.mobile.nojs) { 1132 $.mobile.nojs(this); 1133 } 1134 1135 // Bind links for ajax nav 1136 if ($.mobile.links) { 1137 $.mobile.links(this); 1138 } 1139 1140 // Degrade inputs for styleing 1141 if ($.mobile.degradeInputsWithin) { 1142 $.mobile.degradeInputsWithin(this); 1143 } 1144 1145 // Run buttonmarkup 1146 if ($.fn.buttonMarkup) { 1147 this.find($.fn.buttonMarkup.initSelector).not(keepNative) 1148 .jqmEnhanceable().buttonMarkup(); 1149 } 1150 1151 // Add classes for fieldContain 1152 if ($.fn.fieldcontain) { 1153 this.find(":jqmData(role='fieldcontain')").not(keepNative) 1154 .jqmEnhanceable().fieldcontain(); 1155 } 1156 1157 // Enhance widgets 1158 $.each($.mobile.widgets, function (name, constructor) { 1159 1160 // If initSelector not false find elements 1161 if (constructor.initSelector) { 1162 1163 // Filter elements that should not be enhanced based on parents 1164 var elements = $.mobile.enhanceable(that.find(constructor.initSelector)); 1165 1166 // If any matching elements remain filter ones with keepNativeSelector 1167 if (elements.length > 0) { 1168 1169 // $.mobile.page.prototype.keepNativeSelector is deprecated this is just for backcompat 1170 // Switch to $.mobile.keepNative in 1.5 which is just a value not a function 1171 elements = elements.not(keepNative); 1172 } 1173 1174 // Enhance whatever is left 1175 if (elements.length > 0) { 1176 widgetElements[constructor.prototype.widgetName] = elements; 1177 } 1178 } 1179 }); 1180 1181 for (index in widgetElements) { 1182 widgetElements[index][index](); 1183 } 1184 1185 return this; 1186 }, 1187 1188 addDependents: function (newDependents) { 1189 $.addDependents(this, newDependents); 1190 }, 1191 1192 // note that this helper doesn't attempt to handle the callback 1193 // or setting of an html element's text, its only purpose is 1194 // to return the html encoded version of the text in all cases. (thus the name) 1195 getEncodedText: function () { 1196 return $("<a>").text(this.text()).html(); 1197 }, 1198 1199 // fluent helper function for the mobile namespaced equivalent 1200 jqmEnhanceable: function () { 1201 return $.mobile.enhanceable(this); 1202 }, 1203 1204 jqmHijackable: function () { 1205 return $.mobile.hijackable(this); 1206 } 1207 }); 1208 1209 $.removeWithDependents = function (nativeElement) { 1210 var element = $(nativeElement); 1211 1212 (element.jqmData("dependents") || $()).remove(); 1213 element.remove(); 1214 }; 1215 $.addDependents = function (nativeElement, newDependents) { 1216 var element = $(nativeElement), 1217 dependents = element.jqmData("dependents") || $(); 1218 1219 element.jqmData("dependents", $(dependents).add(newDependents)); 1220 }; 1221 1222 $.find.matches = function (expr, set) { 1223 return $.find(expr, null, null, set); 1224 }; 1225 1226 $.find.matchesSelector = function (node, expr) {
1227 return $.find(expr, null, null, [node]).length > 0; 1228 }; 1229 1230 })(jQuery, this); (function ($, undefined) { 1231 1232 /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 1233 window.matchMedia = window.matchMedia || (function (doc, undefined) { 1234 1235 var bool, 1236 docElem = doc.documentElement, 1237 refNode = docElem.firstElementChild || docElem.firstChild, 1238 // fakeBody required for <FF4 when executed in <head> 1239 fakeBody = doc.createElement("body"), 1240 div = doc.createElement("div"); 1241 1242 div.id = "mq-test-1"; 1243 div.style.cssText = "position:absolute;top:-100em"; 1244 fakeBody.style.background = "none"; 1245 fakeBody.appendChild(div); 1246 1247 return function (q) { 1248 1249 div.innerHTML = "­<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>"; 1250 1251 docElem.insertBefore(fakeBody, refNode); 1252 bool = div.offsetWidth === 42; 1253 docElem.removeChild(fakeBody); 1254 1255 return { 1256 matches: bool, 1257 media: q 1258 }; 1259 1260 }; 1261 1262 }(document)); 1263 1264 // $.mobile.media uses matchMedia to return a boolean. 1265 $.mobile.media = function (q) { 1266 return window.matchMedia(q).matches; 1267 }; 1268 1269 })(jQuery); 1270 1271 (function ($, undefined) { 1272 var support = { 1273 touch: "ontouchend" in document 1274 }; 1275 1276 $.mobile.support = $.mobile.support || {}; 1277 $.extend($.support, support); 1278 $.extend($.mobile.support, support); 1279 }(jQuery)); 1280 1281 (function ($, undefined) { 1282 $.extend($.support, { 1283 orientation: "orientation" in window && "onorientationchange" in window 1284 }); 1285 }(jQuery)); 1286 1287 (function ($, undefined) { 1288 1289 // thx Modernizr 1290 function propExists(prop) { 1291 var uc_prop = prop.charAt(0).toUpperCase() + prop.substr(1), 1292 props = (prop + " " + vendors.join(uc_prop + " ") + uc_prop).split(" "), 1293 v; 1294 1295 for (v in props) { 1296 if (fbCSS[props[v]] !== undefined) { 1297 return true; 1298 } 1299 } 1300 } 1301 1302 var fakeBody = $("<body>").prependTo("html"), 1303 fbCSS = fakeBody[0].style, 1304 vendors = ["Webkit", "Moz", "O"], 1305 webos = "palmGetResource" in window, //only used to rule out scrollTop 1306 operamini = window.operamini && ({}).toString.call(window.operamini) === "[object OperaMini]", 1307 bb = window.blackberry && !propExists("-webkit-transform"), //only used to rule out box shadow, as it's filled opaque on BB 5 and lower 1308 nokiaLTE7_3; 1309 1310 // inline SVG support test 1311 function inlineSVG() { 1312 // Thanks Modernizr & Erik Dahlstrom 1313 var w = window, 1314 svg = !!w.document.createElementNS && !!w.document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGRect && !(w.opera && navigator.userAgent.indexOf("Chrome") === -1), 1315 support = function (data) { 1316 if (!(data && svg)) { 1317 $("html").addClass("ui-nosvg"); 1318 } 1319 }, 1320 img = new w.Image(); 1321 1322 img.onerror = function () { 1323 support(false); 1324 }; 1325 img.onload = function () { 1326 support(img.width === 1 && img.height === 1); 1327 }; 1328 img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; 1329 } 1330 1331 function transform3dTest() { 1332 var mqProp = "transform-3d", 1333 // Because the `translate3d` test below throws false positives in Android: 1334 ret = $.mobile.media("(-" + vendors.join("-" + mqProp + "),(-") + "-" + mqProp + "),(" + mqProp + ")"), 1335 el, transforms, t; 1336 1337 if (ret) { 1338 return !!ret; 1339 } 1340 1341 el = document.createElement("div"); 1342 transforms = { 1343 // Weâre omitting Opera for the time being; MS uses unprefixed. 1344 "MozTransform": "-moz-transform", 1345 "transform": "transform" 1346 }; 1347 1348 fakeBody.append(el); 1349 1350 for (t in transforms) { 1351 if (el.style[t] !== undefined) { 1352 el.style[t] = "translate3d( 100px, 1px, 1px )"; 1353 ret = window.getComputedStyle(el).getPropertyValue(transforms[t]); 1354 } 1355 } 1356 return (!!ret && ret !== "none"); 1357 } 1358 1359 // Test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting ) 1360 function baseTagTest() { 1361 var fauxBase = location.protocol + "//" + location.host + location.pathname + "ui-dir/", 1362 base = $("head base"), 1363 fauxEle = null, 1364 href = "", 1365 link, rebase; 1366 1367 if (!base.length) { 1368 base = fauxEle = $("<base>", { "href": fauxBase }).appendTo("head"); 1369 } else { 1370 href = base.attr("href"); 1371 } 1372 1373 link = $("<a href='testurl' />").prependTo(fakeBody); 1374 rebase = link[0].href; 1375 base[0].href = href || location.pathname; 1376 1377 if (fauxEle) { 1378 fauxEle.remove(); 1379 } 1380 return rebase.indexOf(fauxBase) === 0; 1381 } 1382 1383 // Thanks Modernizr 1384 function cssPointerEventsTest() { 1385 var element = document.createElement("x"), 1386 documentElement = document.documentElement, 1387 getComputedStyle = window.getComputedStyle, 1388 supports; 1389 1390 if (!("pointerEvents" in element.style)) { 1391 return false;
1392 } 1393 1394 element.style.pointerEvents = "auto"; 1395 element.style.pointerEvents = "x"; 1396 documentElement.appendChild(element); 1397 supports = getComputedStyle && 1398 getComputedStyle(element, "").pointerEvents === "auto"; 1399 documentElement.removeChild(element); 1400 return !!supports; 1401 } 1402 1403 function boundingRect() { 1404 var div = document.createElement("div"); 1405 return typeof div.getBoundingClientRect !== "undefined"; 1406 } 1407 1408 // non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683 1409 // allows for inclusion of IE 6+, including Windows Mobile 7 1410 $.extend($.mobile, { browser: {} }); 1411 $.mobile.browser.oldIE = (function () { 1412 var v = 3, 1413 div = document.createElement("div"), 1414 a = div.all || []; 1415 1416 do { 1417 div.innerHTML = "<!--[if gt IE " + (++v) + "]><br><![endif]-->"; 1418 } while (a[0]); 1419 1420 return v > 4 ? v : !v; 1421 })(); 1422 1423 function fixedPosition() { 1424 var w = window, 1425 ua = navigator.userAgent, 1426 platform = navigator.platform, 1427 // Rendering engine is Webkit, and capture major version 1428 wkmatch = ua.match(/AppleWebKit\/([0-9]+)/), 1429 wkversion = !!wkmatch && wkmatch[1], 1430 ffmatch = ua.match(/Fennec\/([0-9]+)/), 1431 ffversion = !!ffmatch && ffmatch[1], 1432 operammobilematch = ua.match(/Opera Mobi\/([0-9]+)/), 1433 omversion = !!operammobilematch && operammobilematch[1]; 1434 1435 if ( 1436 // iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5) 1437 ((platform.indexOf("iPhone") > -1 || platform.indexOf("iPad") > -1 || platform.indexOf("iPod") > -1) && wkversion && wkversion < 534) || 1438 // Opera Mini 1439 (w.operamini && ({}).toString.call(w.operamini) === "[object OperaMini]") || 1440 (operammobilematch && omversion < 7458) || 1441 //Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2) 1442 (ua.indexOf("Android") > -1 && wkversion && wkversion < 533) || 1443 // Firefox Mobile before 6.0 - 1444 (ffversion && ffversion < 6) || 1445 // WebOS less than 3 1446 ("palmGetResource" in window && wkversion && wkversion < 534) || 1447 // MeeGo 1448 (ua.indexOf("MeeGo") > -1 && ua.indexOf("NokiaBrowser/8.5.0") > -1)) { 1449 return false; 1450 } 1451 1452 return true; 1453 } 1454 1455 $.extend($.support, { 1456 // Note, Chrome for iOS has an extremely quirky implementation of popstate. 1457 // We've chosen to take the shortest path to a bug fix here for issue #5426 1458 // See the following link for information about the regex chosen 1459 // https://developers.google.com/chrome/mobile/docs/user-agent#chrome_for_ios_user-agent 1460 pushState: "pushState" in history && 1461 "replaceState" in history && 1462 // When running inside a FF iframe, calling replaceState causes an error 1463 !(window.navigator.userAgent.indexOf("Firefox") >= 0 && window.top !== window) &&
1464 (window.navigator.userAgent.search(/CriOS/) === -1), 1465 1466 mediaquery: $.mobile.media("only all"), 1467 cssPseudoElement: !!propExists("content"), 1468 touchOverflow: !!propExists("overflowScrolling"), 1469 cssTransform3d: transform3dTest(), 1470 boxShadow: !!propExists("boxShadow") && !bb, 1471 fixedPosition: fixedPosition(), 1472 scrollTop: ("pageXOffset" in window || 1473 "scrollTop" in document.documentElement || 1474 "scrollTop" in fakeBody[0]) && !webos && !operamini, 1475 1476 dynamicBaseTag: baseTagTest(), 1477 cssPointerEvents: cssPointerEventsTest(), 1478 boundingRect: boundingRect(), 1479 inlineSVG: inlineSVG 1480 }); 1481 1482 fakeBody.remove(); 1483 1484 // $.mobile.ajaxBlacklist is used to override ajaxEnabled on platforms that have known conflicts with hash history updates (BB5, Symbian) 1485 // or that generally work better browsing in regular http for full page refreshes (Opera Mini) 1486 // Note: This detection below is used as a last resort. 1487 // We recommend only using these detection methods when all other more reliable/forward-looking approaches are not possible 1488 nokiaLTE7_3 = (function () { 1489 1490 var ua = window.navigator.userAgent; 1491 1492 //The following is an attempt to match Nokia browsers that are running Symbian/s60, with webkit, version 7.3 or older 1493 return ua.indexOf("Nokia") > -1 && 1494 (ua.indexOf("Symbian/3") > -1 || ua.indexOf("Series60/5") > -1) && 1495 ua.indexOf("AppleWebKit") > -1 && 1496 ua.match(/(BrowserNG|NokiaBrowser)\/7\.[0-3]/); 1497 })(); 1498 1499 // Support conditions that must be met in order to proceed 1500 // default enhanced qualifications are media query support OR IE 7+ 1501 1502 $.mobile.gradeA = function () { 1503 return (($.support.mediaquery && $.support.cssPseudoElement) || $.mobile.browser.oldIE && $.mobile.browser.oldIE >
1503= 8) && ($.support.boundingRect || $.fn.jquery.match(/1\.[0-7+]\.[0-9+]?/) !== null); 1504 }; 1505 1506 $.mobile.ajaxBlacklist = 1507 // BlackBerry browsers, pre-webkit 1508 window.blackberry && !window.WebKitPoint || 1509 // Opera Mini 1510 operamini || 1511 // Symbian webkits pre 7.3 1512 nokiaLTE7_3; 1513 1514 // Lastly, this workaround is the only way we've found so far to get pre 7.3 Symbian webkit devices 1515 // to render the stylesheets when they're referenced before this script, as we'd recommend doing. 1516 // This simply reappends the CSS in place, which for some reason makes it apply 1517 if (nokiaLTE7_3) { 1518 $(function () { 1519 $("head link[rel='stylesheet']").attr("rel", "alternate stylesheet").attr("rel", "stylesheet"); 1520 }); 1521 } 1522 1523 // For ruling out shadows via css 1524 if (!$.support.boxShadow) { 1525 $("html").addClass("ui-noboxshadow"); 1526 } 1527 1528 })(jQuery); (function ($, undefined) { 1529 var $win = $.mobile.window, self, 1530 dummyFnToInitNavigate = function () { 1531 }; 1532 1533 $.event.special.beforenavigate = { 1534 setup: function () { 1535 $win.on("navigate", dummyFnToInitNavigate); 1536 }, 1537 1538 teardown: function () { 1539 $win.off("navigate", dummyFnToInitNavigate); 1540 } 1541 }; 1542 1543 $.event.special.navigate = self = { 1544 bound: false, 1545 1546 pushStateEnabled: true, 1547 1548 originalEventName: undefined, 1549 1550 // If pushstate support is present and push state support is defined to 1551 // be true on the mobile namespace. 1552 isPushStateEnabled: function () { 1553 return $.support.pushState && 1554 $.mobile.pushStateEnabled === true && 1555 this.isHashChangeEnabled(); 1556 }, 1557 1558 // !! assumes mobile namespace is present 1559 isHashChangeEnabled: function () { 1560 return $.mobile.hashListeningEnabled === true; 1561 }, 1562 1563 // TODO a lot of duplication between popstate and hashchange 1564 popstate: function (event) { 1565 var newEvent = new $.Event("navigate"), 1566 beforeNavigate = new $.Event("beforenavigate"), 1567 state = event.originalEvent.state || {}; 1568 1569 beforeNavigate.originalEvent = event; 1570 $win.trigger(beforeNavigate); 1571 1572 if (beforeNavigate.isDefaultPrevented()) { 1573 return; 1574 } 1575 1576 if (event.historyState) { 1577 $.extend(state, event.historyState); 1578 } 1579 1580 // Make sure the original event is tracked for the end 1581 // user to inspect incase they want to do something special 1582 newEvent.originalEvent = event; 1583 1584 // NOTE we let the current stack unwind because any assignment to 1585 // location.hash will stop the world and run this event handler. By 1586 // doing this we create a similar behavior to hashchange on hash 1587 // assignment 1588 setTimeout(function () { 1589 $win.trigger(newEvent, { 1590 state: state 1591 }); 1592 }, 0); 1593 }, 1594 1595 hashchange: function (event /*, data */) { 1596 var newEvent = new $.Event("navigate"), 1597 beforeNavigate = new $.Event("beforenavigate"); 1598 1599 beforeNavigate.originalEvent = event; 1600 $win.trigger(beforeNavigate); 1601 1602 if (beforeNavigate.isDefaultPrevented()) { 1603 return; 1604 } 1605 1606 // Make sure the original event is tracked for the end 1607 // user to inspect incase they want to do something special 1608 newEvent.originalEvent = event; 1609 1610 // Trigger the hashchange with state provided by the user 1611 // that altered the hash 1612 $win.trigger(newEvent, { 1613 // Users that want to fully normalize the two events 1614 // will need to do history management down the stack and 1615 // add the state to the event before this binding is fired 1616 // TODO consider allowing for the explicit addition of callbacks 1617 // to be fired before this value is set to avoid event timing issues 1618 state: event.hashchangeState || {} 1619 }); 1620 }, 1621 1622 // TODO We really only want to set this up once 1623 // but I'm not clear if there's a beter way to achieve 1624 // this with the jQuery special event structure 1625 setup: function ( /* data, namespaces */) { 1626 if (self.bound) { 1627 return; 1628 } 1629 1630 self.bound = true; 1631 1632 if (self.isPushStateEnabled()) { 1633 self.originalEventName = "popstate"; 1634 $win.bind("popstate.navigate", self.popstate); 1635 } else if (self.isHashChangeEnabled()) {
1636 self.originalEventName = "hashchange"; 1637 $win.bind("hashchange.navigate", self.hashchange); 1638 } 1639 } 1640 }; 1641 })(jQuery); 1642 // throttled resize event 1643 (function ($) { 1644 $.event.special.throttledresize = { 1645 setup: function () { 1646 $(this).bind("resize", handler); 1647 }, 1648 teardown: function () { 1649 $(this).unbind("resize", handler); 1650 } 1651 }; 1652 1653 var throttle = 250, 1654 handler = function () { 1655 curr = (new Date()).getTime(); 1656 diff = curr - lastCall; 1657 1658 if (diff >= throttle) { 1659 1660 lastCall = curr; 1661 $(this).trigger("throttledresize"); 1662 1663 } else { 1664 1665 if (heldCall) { 1666 clearTimeout(heldCall); 1667 } 1668 1669 // Promise a held call will still execute 1670 heldCall = setTimeout(handler, throttle - diff); 1671 } 1672 }, 1673 lastCall = 0, 1674 heldCall, 1675 curr, 1676 diff; 1677 })(jQuery); (function ($, window) { 1678 var win = $(window), 1679 event_name = "orientationchange", 1680 get_orientation, 1681 last_orientation, 1682 initial_orientation_is_landscape, 1683 initial_orientation_is_default, 1684 portrait_map = { "0": true, "180": true }, 1685 ww, wh, landscape_threshold; 1686 1687 // It seems that some device/browser vendors use window.orientation values 0 and 180 to 1688 // denote the "default" orientation. For iOS devices, and most other smart-phones tested, 1689 // the default orientation is always "portrait", but in some Android and RIM based tablets, 1690 // the default orientation is "landscape". The following code attempts to use the window 1691 // dimensions to figure out what the current orientation is, and then makes adjustments 1692 // to the to the portrait_map if necessary, so that we can properly decode the 1693 // window.orientation value whenever get_orientation() is called. 1694 // 1695 // Note that we used to use a media query to figure out what the orientation the browser 1696 // thinks it is in: 1697 // 1698 // initial_orientation_is_landscape = $.mobile.media("all and (orientation: landscape)"); 1699 // 1700 // but there was an iPhone/iPod Touch bug beginning with iOS 4.2, up through iOS 5.1, 1701 // where the browser *ALWAYS* applied the landscape media query. This bug does not 1702 // happen on iPad. 1703 1704 if ($.support.orientation) { 1705 1706 // Check the window width and height to figure out what the current orientation 1707 // of the device is at this moment. Note that we've initialized the portrait map 1708 // values to 0 and 180, *AND* we purposely check for landscape so that if we guess 1709 // wrong, , we default to the assumption that portrait is the default orientation. 1710 // We use a threshold check below because on some platforms like iOS, the iPhone 1711 // form-factor can report a larger width than height if the user turns on the 1712 // developer console. The actual threshold value is somewhat arbitrary, we just 1713 // need to make sure it is large enough to exclude the developer console case. 1714 1715 ww = window.innerWidth || win.width(); 1716 wh = window.innerHeight || win.height(); 1717 landscape_threshold = 50; 1718 1719 initial_orientation_is_landscape = ww > wh && (ww - wh) > landscape_threshold; 1720 1721 // Now check to see if the current window.orientation is 0 or 180. 1722 initial_orientation_is_default = portrait_map[window.orientation]; 1723 1724 // If the initial orientation is landscape, but window.orientation reports 0 or 180, *OR* 1725 // if the initial orientation is portrait, but window.orientation reports 90 or -90, we 1726 // need to flip our portrait_map values because landscape is the default orientation for 1727 // this device/browser. 1728 if ((initial_orientation_is_landscape && initial_orientation_is_default) || (!initial_orientation_is_landscape && !initial_orientation_is_default)) { 1729 portrait_map = { "-90": true, "90": true }; 1730 } 1731 } 1732 1733 $.event.special.orientationchange = $.extend({}, $.event.special.orientationchange, { 1734 setup: function () { 1735 // If the event is supported natively, return false so that jQuery 1736 // will bind to the event using DOM methods. 1737 if ($.support.orientation && !$.event.special.orientationchange.disabled) { 1738 return false; 1739 } 1740 1741 // Get the current orientation to avoid initial double-triggering. 1742 last_orientation = get_orientation(); 1743 1744 // Because the orientationchange event doesn't exist, simulate the 1745 // event by testing window dimensions on resize. 1746 win.bind("throttledresize", handler); 1747 }, 1748 teardown: function () { 1749 // If the event is not supported natively, return false so that 1750 // jQuery will unbind the event using DOM methods.
1751 if ($.support.orientation && !$.event.special.orientationchange.disabled) { 1752 return false; 1753 } 1754 1755 // Because the orientationchange event doesn't exist, unbind the 1756 // resize event handler. 1757 win.unbind("throttledresize", handler); 1758 }, 1759 add: function (handleObj) { 1760 // Save a reference to the bound event handler. 1761 var old_handler = handleObj.handler; 1762 1763 handleObj.handler = function (event) { 1764 // Modify event object, adding the .orientation property. 1765 event.orientation = get_orientation(); 1766 1767 // Call the originally-bound event handler and return its result. 1768 return old_handler.apply(this, arguments); 1769 }; 1770 } 1771 }); 1772 1773 // If the event is not supported natively, this handler will be bound to 1774 // the window resize event to simulate the orientationchange event. 1775 function handler() { 1776 // Get the current orientation. 1777 var orientation = get_orientation(); 1778 1779 if (orientation !== last_orientation) { 1780 // The orientation has changed, so trigger the orientationchange event. 1781 last_orientation = orientation; 1782 win.trigger(event_name); 1783 } 1784 } 1785 1786 // Get the current page orientation. This method is exposed publicly, should it 1787 // be needed, as jQuery.event.special.orientationchange.orientation() 1788 $.event.special.orientationchange.orientation = get_orientation = function () { 1789 var isPortrait = true, elem = document.documentElement; 1790 1791 // prefer window orientation to the calculation based on screensize as 1792 // the actual screen resize takes place before or after the orientation change event 1793 // has been fired depending on implementation (eg android 2.3 is before, iphone after). 1794 // More testing is required to determine if a more reliable method of determining the new screensize 1795 // is possible when orientationchange is fired. (eg, use media queries + element + opacity) 1796 if ($.support.orientation) { 1797 // if the window orientation registers as 0 or 180 degrees report 1798 // portrait, otherwise landscape 1799 isPortrait = portrait_map[window.orientation]; 1800 } else { 1801 isPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1; 1802 } 1803 1804 return isPortrait ? "portrait" : "landscape"; 1805 }; 1806 1807 $.fn[event_name] = function (fn) { 1808 return fn ? this.bind(event_name, fn) : this.trigger(event_name); 1809 }; 1810 1811 // jQuery < 1.8 1812 if ($.attrFn) { 1813 $.attrFn[event_name] = true; 1814 } 1815 1816 }(jQuery, this));// This plugin is an experiment for abstracting away the touch and mouse 1817 // events so that developers don't have to worry about which method of input 1818 // the device their document is loaded on supports. 1819 // 1820 // The idea here is to allow the developer to register listeners for the 1821 // basic mouse events, such as mousedown, mousemove, mouseup, and click, 1822 // and the plugin will take care of registering the correct listeners 1823 // behind the scenes to invoke the listener at the fastest possible time 1824 // for that device, while still retaining the order of event firing in 1825 // the traditional mouse environment, should multiple handlers be registered 1826 // on the same element for different events. 1827 // 1828 // The current version exposes the following virtual events to jQuery bind methods: 1829 // "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel" 1830 1831 (function ($, window, document, undefined) { 1832 1833 var dataPropertyName = "virtualMouseBindings", 1834 touchTargetPropertyName = "virtualTouchID", 1835 virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "), 1836 touchEventProps = "clientX clientY pageX pageY screenX screenY".split(" "), 1837 mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [], 1838 mouseEventProps = $.event.props.concat(mouseHookProps), 1839 activeDocHandlers = {}, 1840 resetTimerID = 0, 1841 startX = 0, 1842 startY = 0, 1843 didScroll = false, 1844 clickBlockList = [], 1845 blockMouseTriggers = false, 1846 blockTouchTriggers = false, 1847 eventCaptureSupported = "addEventListener" in document, 1848 $document = $(document), 1849 nextTouchID = 1, 1850 lastTouchID = 0, threshold, 1851 i; 1852 1853 $.vmouse = { 1854 moveDistanceThreshold: 10, 1855 clickDistanceThreshold: 10, 1856 resetTimerDuration: 1500 1857 }; 1858 1859 function getNativeEvent(event) { 1860 1861 while (event && typeof event.originalEvent !== "undefined") { 1862 event = event.originalEvent; 1863 } 1864 return event; 1865 } 1866
1867 function createVirtualEvent(event, eventType) { 1868 1869 var t = event.type, 1870 oe, props, ne, prop, ct, touch, i, j, len; 1871 1872 event = $.Event(event); 1873 event.type = eventType; 1874 1875 oe = event.originalEvent; 1876 props = $.event.props; 1877 1878 // addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280 1879 // https://github.com/jquery/jquery-mobile/issues/3280 1880 if (t.search(/^(mouse|click)/) > -1) { 1881 props = mouseEventProps; 1882 } 1883 1884 // copy original event properties over to the new event 1885 // this would happen if we could call $.event.fix instead of $.Event 1886 // but we don't have a way to force an event to be fixed multiple times 1887 if (oe) { 1888 for (i = props.length, prop; i;) { 1889 prop = props[--i]; 1890 event[prop] = oe[prop]; 1891 } 1892 } 1893 1894 // make sure that if the mouse and click virtual events are generated 1895 // without a .which one is defined 1896 if (t.search(/mouse(down|up)|click/) > -1 && !event.which) { 1897 event.which = 1; 1898 } 1899 1900 if (t.search(/^touch/) !== -1) { 1901 ne = getNativeEvent(oe); 1902 t = ne.touches; 1903 ct = ne.changedTouches; 1904 touch = (t && t.length) ? t[0] : ((ct && ct.length) ? ct[0] : undefined); 1905 1906 if (touch) { 1907 for (j = 0, len = touchEventProps.length; j < len; j++) { 1908 prop = touchEventProps[j]; 1909 event[prop] = touch[prop]; 1910 } 1911 } 1912 } 1913 1914 return event; 1915 } 1916 1917 function getVirtualBindingFlags(element) { 1918 1919 var flags = {}, 1920 b, k; 1921 1922 while (element) { 1923 1924 b = $.data(element, dataPropertyName); 1925 1926 for (k in b) { 1927 if (b[k]) { 1928 flags[k] = flags.hasVirtualBinding = true; 1929 } 1930 } 1931 element = element.parentNode; 1932 } 1933 return flags; 1934 } 1935 1936 function getClosestElementWithVirtualBinding(element, eventType) { 1937 var b; 1938 while (element) { 1939 1940 b = $.data(element, dataPropertyName); 1941 1942 if (b && (!eventType || b[eventType])) { 1943 return element; 1944 } 1945 element = element.parentNode; 1946 } 1947 return null; 1948 } 1949 1950 function enableTouchBindings() { 1951 blockTouchTriggers = false; 1952 } 1953 1954 function disableTouchBindings() { 1955 blockTouchTriggers = true; 1956 } 1957 1958 function enableMouseBindings() { 1959 lastTouchID = 0; 1960 clickBlockList.length = 0; 1961 blockMouseTriggers = false; 1962 1963 // When mouse bindings are enabled, our 1964 // touch bindings are disabled. 1965 disableTouchBindings(); 1966 } 1967 1968 function disableMouseBindings() { 1969 // When mouse bindings are disabled, our 1970 // touch bindings are enabled. 1971 enableTouchBindings(); 1972 } 1973 1974 function startResetTimer() { 1975 clearResetTimer(); 1976 resetTimerID = setTimeout(function () { 1977 resetTimerID = 0; 1978 enableMouseBindings(); 1979 }, $.vmouse.resetTimerDuration); 1980 } 1981 1982 function clearResetTimer() { 1983 if (resetTimerID) { 1984 clearTimeout(resetTimerID); 1985 resetTimerID = 0; 1986 } 1987 } 1988 1989 function triggerVirtualEvent(eventType, event, flags) { 1990 var ve; 1991 1992 if ((flags && flags[eventType]) || 1993 (!flags && getClosestElementWithVirtualBinding(event.target, eventType))) { 1994 1995 ve = createVirtualEvent(event, eventType); 1996 1997 $(event.target).trigger(ve); 1998 } 1999 2000 return ve; 2001 } 2002 2003 function mouseEventCallback(event) { 2004 var touchID = $.data(event.target, touchTargetPropertyName), 2005 ve; 2006 2007 if (!blockMouseTriggers && (!lastTouchID || lastTouchID !== touchID)) { 2008 ve = triggerVirtualEvent("v" + event.type, event); 2009 if (ve) { 2010 if (ve.isDefaultPrevented()) { 2011 event.preventDefault(); 2012 } 2013 if (ve.isPropagationStopped()) { 2014 event.stopPropagation(); 2015 } 2016 if (ve.isImmediatePropagationStopped()) { 2017 event.stopImmediatePropagation(); 2018 } 2019 } 2020 } 2021 } 2022 2023 function handleTouchStart(event) { 2024 2025 var touches = getNativeEvent(event).touches, 2026 target, flags, t; 2027 2028 if (touches && touches.length === 1) { 2029 2030 target = event.target; 2031 flags = getVirtualBindingFlags(target); 2032 2033 if (flags.hasVirtualBinding) { 2034 2035 lastTouchID = nextTouchID++; 2036 $.data(target, touchTargetPropertyName, lastTouchID); 2037 2038 clearResetTimer(); 2039 2040 disableMouseBindings(); 2041 didScroll = false; 2042 2043 t = getNativeEvent(event).touches[0]; 2044 startX = t.pageX; 2045 startY = t.pageY; 2046 2047 triggerVirtualEvent("vmouseover", event, flags); 2048 triggerVirtualEvent("vmousedown", event, flags); 2049 } 2050 } 2051 } 2052 2053 function handleScroll(event) { 2054 if (blockTouchTriggers) { 2055 return; 2056 } 2057 2058 if (!didScroll) { 2059 triggerVirtualEvent("vmousecancel", event, getVirtualBindingFlags(event.target)); 2060 } 2061 2062 didScroll = true; 2063 startResetTimer(); 2064 } 2065 2066 function handleTouchMove(event) { 2067 if (blockTouchTriggers) { 2068 return; 2069 } 2070 2071 var t = getNativeEvent(event).touches[0], 2072 didCancel = didScroll, 2073 moveThreshold = $.vmouse.moveDistanceThreshold, 2074 flags = getVirtualBindingFlags(event.target); 2075 2076 didScroll = didScroll || 2077 (Math.abs(t.pageX - startX) > moveThreshold || 2078 Math.abs(t.pageY - startY) > moveThreshold); 2079 2080 if (didScroll && !didCancel) { 2081 triggerVirtualEvent("vmousecancel", event, flags); 2082 } 2083 2084 triggerVirtualEvent("vmousemove", event, flags); 2085 startResetTimer(); 2086 } 2087 2088 function handleTouchEnd(event) { 2089 if (blockTouchTriggers) { 2090 return; 2091 } 2092 2093 disableTouchBindings(); 2094 2095 var flags = getVirtualBindingFlags(event.target), 2096 ve, t; 2097 triggerVirtualEvent("vmouseup", event, flags); 2098 2099 if (!didScroll) { 2100 ve = triggerVirtualEvent("vclick", event, flags); 2101 if (ve && ve.isDefaultPrevented()) { 2102 // The target of the mouse events that follow the touchend 2103 // event don't necessarily match the target used during the 2104 // touch. This means we need to rely on coordinates for blocking 2105 // any click that is generated. 2106 t = getNativeEvent(event).changedTouches[0]; 2107 clickBlockList.push({ 2108 touchID: lastTouchID, 2109 x: t.clientX, 2110 y: t.clientY 2111 }); 2112 2113 // Prevent any mouse events that follow from triggering 2114 // virtual event notifications. 2115 blockMouseTriggers = true; 2116 } 2117 } 2118 triggerVirtualEvent("vmouseout", event, flags); 2119 didScroll = false;
2120 2121 startResetTimer(); 2122 } 2123 2124 function hasVirtualBindings(ele) { 2125 var bindings = $.data(ele, dataPropertyName), 2126 k; 2127 2128 if (bindings) { 2129 for (k in bindings) { 2130 if (bindings[k]) { 2131 return true; 2132 } 2133 } 2134 } 2135 return false; 2136 } 2137 2138 function dummyMouseHandler() { } 2139 2140 function getSpecialEventObject(eventType) { 2141 var realType = eventType.substr(1); 2142 2143 return { 2144 setup: function (/* data, namespace */) { 2145 // If this is the first virtual mouse binding for this element, 2146 // add a bindings object to its data. 2147 2148 if (!hasVirtualBindings(this)) { 2149 $.data(this, dataPropertyName, {}); 2150 } 2151 2152 // If setup is called, we know it is the first binding for this 2153 // eventType, so initialize the count for the eventType to zero. 2154 var bindings = $.data(this, dataPropertyName); 2155 bindings[eventType] = true; 2156 2157 // If this is the first virtual mouse event for this type, 2158 // register a global handler on the document. 2159 2160 activeDocHandlers[eventType] = (activeDocHandlers[eventType] || 0) + 1; 2161 2162 if (activeDocHandlers[eventType] === 1) { 2163 $document.bind(realType, mouseEventCallback); 2164 } 2165 2166 // Some browsers, like Opera Mini, won't dispatch mouse/click events 2167 // for elements unless they actually have handlers registered on them. 2168 // To get around this, we register dummy handlers on the elements. 2169 2170 $(this).bind(realType, dummyMouseHandler); 2171 2172 // For now, if event capture is not supported, we rely on mouse handlers. 2173 if (eventCaptureSupported) { 2174 // If this is the first virtual mouse binding for the document, 2175 // register our touchstart handler on the document. 2176 2177 activeDocHandlers["touchstart"] = (activeDocHandlers["touchstart"] || 0) + 1; 2178 2179 if (activeDocHandlers["touchstart"] === 1) { 2180 $document.bind("touchstart", handleTouchStart, { passive: true }) 2181 .bind("touchend", handleTouchEnd) 2182 2183 // On touch platforms, touching the screen and then dragging your finger 2184 // causes the window content to scroll after some distance threshold is 2185 // exceeded. On these platforms, a scroll prevents a click event from being 2186 // dispatched, and on some platforms, even the touchend is suppressed. To 2187 // mimic the suppression of the click event, we need to watch for a scroll 2188 // event. Unfortunately, some platforms like iOS don't dispatch scroll 2189 // events until *AFTER* the user lifts their finger (touchend). This means 2190 // we need to watch both scroll and touchmove events to figure out whether 2191 // or not a scroll happenens before the touchend event is fired. 2192 2193 .bind("touchmove", handleTouchMove) 2194 .bind("scroll", handleScroll); 2195 } 2196 } 2197 }, 2198 2199 teardown: function (/* data, namespace */) { 2200 // If this is the last virtual binding for this eventType, 2201 // remove its global handler from the document. 2202 2203 --activeDocHandlers[eventType]; 2204 2205 if (!activeDocHandlers[eventType]) { 2206 $document.unbind(realType, mouseEventCallback); 2207 } 2208 2209 if (eventCaptureSupported) { 2210 // If this is the last virtual mouse binding in existence, 2211 // remove our document touchstart listener. 2212 2213 --activeDocHandlers["touchstart"]; 2214 2215 if (!activeDocHandlers["touchstart"]) { 2216 $document.unbind("touchstart", handleTouchStart) 2217 .unbind("touchmove", handleTouchMove) 2218 .unbind("touchend", handleTouchEnd) 2219 .unbind("scroll", handleScroll); 2220 } 2221 } 2222 2223 var $this = $(this), 2224 bindings = $.data(this, dataPropertyName); 2225 2226 // teardown may be called when an element was 2227 // removed from the DOM. If this is the case, 2228 // jQuery core may have already stripped the element 2229 // of any data bindings so we need to check it before 2230 // using it. 2231 if (bindings) { 2232 bindings[eventType] = false; 2233 } 2234 2235 // Unregister the dummy event handler. 2236 2237 $this.unbind(realType, dummyMouseHandler); 2238 2239 // If this is the last virtual mouse binding on the 2240 // element, remove the binding data from the element. 2241 2242 if (!hasVirtualBindings(this)) { 2243 $this.removeData(dataPropertyName); 2244 } 2245 } 2246 }; 2247 } 2248 2249 // Expose our custom events to the jQuery bind/unbind mechanism. 2250 2251 for (i = 0; i < virtualEventNames.length; i++) { 2252 $.event.special[virtualEventNames[i]] = getSpecialEventObject(virtualEventNames[i]); 2253 } 2254 2255 // Add a capture click handler to block clicks. 2256 // Note that we require event capture support for this so if the device 2257 // doesn't support it, we punt for now and rely solely on mouse events. 2258 if (eventCaptureSupported) { 2259 document.addEventListener("click", function (e) { 2260 var cnt = clickBlockList.length, 2261 target = e.target, 2262 x, y, ele, i, o, touchID; 2263 2264 if (cnt) { 2265 x = e.clientX; 2266 y = e.clientY; 2267 threshold = $.vmouse.clickDistanceThreshold; 2268 2269 // The idea here is to run through the clickBlockList to see if 2270 // the current click event is in the proximity of one of our 2271 // vclick events that had preventDefault() called on it. If we find 2272 // one, then we block the click. 2273 // 2274 // Why do we have to rely on proximity? 2275 // 2276 // Because the target of the touch event that triggered the vclick 2277 // can be different from the target of the click event synthesized 2278 // by the browser. The target of a mouse/click event that is synthesized 2279 // from a touch event seems to be implementation specific. For example, 2280 // some browsers will fire mouse/click events for a link that is near 2281 // a touch event, even though the target of the touchstart/touchend event 2282 // says the user touched outside the link. Also, it seems that with most 2283 // browsers, the target of the mouse/click event is not calculated until the 2284 // time it is dispatched, so if you replace an element that you touched 2285 // with another element, the target of the mouse/click will be the new 2286 // element underneath that point. 2287 // 2288 // Aside from proximity, we also check to see if the target and any 2289 // of its ancestors were the ones that blocked a click. This is necessary 2290 // because of the strange mouse/click target calculation done in the 2291 // Android 2.1 browser, where if you click on an element, and there is a 2292 // mouse/click handler on one of its ancestors, the target will be the 2293 // innermost child of the touched element, even if that child is no where 2294 // near the point of touch. 2295 2296 ele = target; 2297 2298 while (ele) { 2299 for (i = 0; i < cnt; i++) { 2300 o = clickBlockList[i]; 2301 touchID = 0; 2302 2303 if ((ele === target && Math.abs(o.x - x) < threshold && Math.abs(o.y - y) < threshold) || 2304 $.data(ele, touchTargetPropertyName) === o.touchID) { 2305 // XXX: We may want to consider removing matches from the block list 2306 // instead of waiting for the reset timer to fire. 2307 e.preventDefault(); 2308 e.stopPropagation(); 2309 return; 2310 } 2311 } 2312 ele = ele.parentNode; 2313 } 2314 } 2315 }, true); 2316 } 2317 })(jQuery, window, document); (function ($, window, undefined) { 2318 var $document = $(document),
2319 supportTouch = $.mobile.support.touch, 2320 scrollEvent = "touchmove scroll", 2321 touchStartEvent = supportTouch ? "touchstart" : "mousedown", 2322 touchStopEvent = supportTouch ? "touchend" : "mouseup", 2323 touchMoveEvent = supportTouch ? "touchmove" : "mousemove"; 2324 2325 // setup new event shortcuts 2326 $.each(("touchstart touchmove touchend " + 2327 "tap taphold " + 2328 "swipe swipeleft swiperight " + 2329 "scrollstart scrollstop").split(" "), function (i, name) { 2330 2331 $.fn[name] = function (fn) { 2332 return fn ? this.bind(name, fn) : this.trigger(name); 2333 }; 2334 2335 // jQuery < 1.8 2336 if ($.attrFn) { 2337 $.attrFn[name] = true; 2338 } 2339 }); 2340 2341 function triggerCustomEvent(obj, eventType, event, bubble) { 2342 var originalType = event.type; 2343 event.type = eventType; 2344 if (bubble) { 2345 $.event.trigger(event, undefined, obj); 2346 } else { 2347 $.event.dispatch.call(obj, event); 2348 } 2349 event.type = originalType; 2350 } 2351 2352 // also handles scrollstop 2353 $.event.special.scrollstart = { 2354 2355 enabled: true, 2356 setup: function () { 2357 2358 var thisObject = this, 2359 $this = $(thisObject), 2360 scrolling, 2361 timer; 2362 2363 function trigger(event, state) { 2364 scrolling = state; 2365 triggerCustomEvent(thisObject, scrolling ? "scrollstart" : "scrollstop", event); 2366 } 2367 2368 // iPhone triggers scroll after a small delay; use touchmove instead 2369 $this.bind(scrollEvent, function (event) { 2370 2371 if (!$.event.special.scrollstart.enabled) { 2372 return; 2373 } 2374 2375 if (!scrolling) { 2376 trigger(event, true); 2377 } 2378 2379 clearTimeout(timer); 2380 timer = setTimeout(function () { 2381 trigger(event, false); 2382 }, 50); 2383 }); 2384 }, 2385 teardown: function () { 2386 $(this).unbind(scrollEvent); 2387 } 2388 }; 2389 2390 // also handles taphold 2391 $.event.special.tap = { 2392 tapholdThreshold: 750, 2393 emitTapOnTaphold: true, 2394 setup: function () { 2395 var thisObject = this, 2396 $this = $(thisObject), 2397 isTaphold = false; 2398 2399 $this.bind("vmousedown", function (event) { 2400 isTaphold = false; 2401 if (event.which && event.which !== 1) { 2402 return false; 2403 } 2404 2405 var origTarget = event.target, 2406 timer; 2407 2408 function clearTapTimer() { 2409 clearTimeout(timer); 2410 } 2411 2412 function clearTapHandlers() { 2413 clearTapTimer(); 2414 2415 $this.unbind("vclick", clickHandler) 2416 .unbind("vmouseup", clearTapTimer); 2417 $document.unbind("vmousecancel", clearTapHandlers); 2418 } 2419 2420 function clickHandler(event) { 2421 clearTapHandlers(); 2422 2423 // ONLY trigger a 'tap' event if the start target is 2424 // the same as the stop target. 2425 if (!isTaphold && origTarget === event.target) { 2426 triggerCustomEvent(thisObject, "tap", event); 2427 } else if (isTaphold) { 2428 event.preventDefault(); 2429 } 2430 } 2431 2432 $this.bind("vmouseup", clearTapTimer) 2433 .bind("vclick", clickHandler); 2434 $document.bind("vmousecancel", clearTapHandlers); 2435 2436 timer = setTimeout(function () { 2437 if (!$.event.special.tap.emitTapOnTaphold) { 2438 isTaphold = true; 2439 } 2440 triggerCustomEvent(thisObject, "taphold", $.Event("taphold", { target: origTarget })); 2441 }, $.event.special.tap.tapholdThreshold); 2442 }); 2443 }, 2444 teardown: function () { 2445 $(this).unbind("vmousedown").unbind("vclick").unbind("vmouseup"); 2446 $document.unbind("vmousecancel"); 2447 } 2448 }; 2449 2450 // Also handles swipeleft, swiperight 2451 $.event.special.swipe = { 2452 2453 // More than this horizontal displacement, and we will suppress scrolling. 2454 scrollSupressionThreshold: 30, 2455 2456 // More time than this, and it isn't a swipe. 2457 durationThreshold: 1000, 2458 2459 // Swipe horizontal displacement must be more than this. 2460 horizontalDistanceThreshold: 30, 2461 2462 // Swipe vertical displacement must be less than this. 2463 verticalDistanceThreshold: 30, 2464 2465 getLocation: function (event) { 2466 var winPageX = window.pageXOffset, 2467 winPageY = window.pageYOffset, 2468 x = event.clientX, 2469 y = event.clientY; 2470 2471 if (event.pageY === 0 && Math.floor(y) > Math.floor(event.pageY) || 2472 event.pageX === 0 && Math.floor(x) > Math.floor(event.pageX)) { 2473 2474 // iOS4 clientX/clientY have the value that should have been 2475 // in pageX/pageY. While pageX/page/ have the value 0 2476 x = x - winPageX; 2477 y = y - winPageY; 2478 } else if (y < (event.pageY - winPageY) || x < (event.pageX - winPageX)) { 2479 2480 // Some Android browsers have totally bogus values for clientX/Y 2481 // when scrolling/zooming a page. Detectable since clientX/clientY 2482 // should never be smaller than pageX/pageY minus page scroll 2483 x = event.pageX - winPageX; 2484 y = event.pageY - winPageY; 2485 } 2486 2487 return { 2488 x: x, 2489 y: y 2490 }; 2491 }, 2492 2493 start: function (event) { 2494 var data = event.originalEvent.touches ? 2495 event.originalEvent.touches[0] : event, 2496 location = $.event.special.swipe.getLocation(data); 2497 return { 2498 time: (new Date()).getTime(), 2499 coords: [location.x, location.y], 2500 origin: $(event.target) 2501 }; 2502 }, 2503 2504 stop: function (event) { 2505 var data = event.originalEvent.touches ? 2506 event.originalEvent.touches[0] : event, 2507 location = $.event.special.swipe.getLocation(data); 2508 return { 2509 time: (new Date()).getTime(), 2510 coords: [location.x, location.y] 2511 }; 2512 }, 2513 2514 handleSwipe: function (start, stop, thisObject, origTarget) { 2515 if (stop.time - start.time < $.event.special.swipe.durationThreshold && 2516 Math.abs(start.coords[0] - stop.coords[0]) > $.event.special.swipe.horizontalDistanceThreshold && 2517 Math.abs(start.coords[1] - stop.coords[1]) < $.event.special.swipe.verticalDistanceThreshold) {
2518 var direction = start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight"; 2519 2520 triggerCustomEvent(thisObject, "swipe", $.Event("swipe", { target: origTarget, swipestart: start, swipestop: stop }), true); 2521 triggerCustomEvent(thisObject, direction, $.Event(direction, { target: origTarget, swipestart: start, swipestop: stop }), true); 2522 return true; 2523 } 2524 return false; 2525 2526 }, 2527 2528 // This serves as a flag to ensure that at most one swipe event event is 2529 // in work at any given time 2530 eventInProgress: false, 2531 2532 setup: function () { 2533 var events, 2534 thisObject = this, 2535 $this = $(thisObject), 2536 context = {}; 2537 2538 // Retrieve the events data for this element and add the swipe context 2539 events = $.data(this, "mobile-events"); 2540 if (!events) { 2541 events = { length: 0 }; 2542 $.data(this, "mobile-events", events); 2543 } 2544 events.length++; 2545 events.swipe = context; 2546 2547 context.start = function (event) { 2548 2549 // Bail if we're already working on a swipe event 2550 if ($.event.special.swipe.eventInProgress) { 2551 return; 2552 } 2553 $.event.special.swipe.eventInProgress = true; 2554 2555 var stop, 2556 start = $.event.special.swipe.start(event), 2557 origTarget = event.target, 2558 emitted = false; 2559 2560 context.move = function (event) { 2561 if (!start || event.isDefaultPrevented()) { 2562 return; 2563 } 2564 2565 stop = $.event.special.swipe.stop(event); 2566 if (!emitted) { 2567 emitted = $.event.special.swipe.handleSwipe(start, stop, thisObject, origTarget); 2568 if (emitted) { 2569 2570 // Reset the context to make way for the next swipe event 2571 $.event.special.swipe.eventInProgress = false; 2572 } 2573 } 2574 // prevent scrolling 2575 if (Math.abs(start.coords[0] - stop.coords[0]) > $.event.special.swipe.scrollSupressionThreshold) { 2576 if (event.cancelable) { 2577 // 夿é»è®¤è¡ä¸ºæ¯å¦å·²ç»è¢«ç¦ç¨ 2578 if (!event.defaultPrevented) { 2579 event.preventDefault(); 2580 } 2581 } 2582 } 2583 }; 2584 2585 context.stop = function () { 2586 emitted = true; 2587 2588 // Reset the context to make way for the next swipe event 2589 $.event.special.swipe.eventInProgress = false; 2590 $document.off(touchMoveEvent, context.move); 2591 context.move = null; 2592 }; 2593 2594 $document.on(touchMoveEvent, context.move) 2595 .one(touchStopEvent, context.stop); 2596 }; 2597 $this.on(touchStartEvent, context.start); 2598 }, 2599 2600 teardown: function () { 2601 var events, context; 2602 2603 events = $.data(this, "mobile-events"); 2604 if (events) { 2605 context = events.swipe; 2606 delete events.swipe; 2607 events.length--; 2608 if (events.length === 0) { 2609 $.removeData(this, "mobile-events"); 2610 } 2611 } 2612 2613 if (context) { 2614 if (context.start) { 2615 $(this).off(touchStartEvent, context.start); 2616 } 2617 if (context.move) { 2618 $document.off(touchMoveEvent, context.move); 2619 } 2620 if (context.stop) { 2621 $document.off(touchStopEvent, context.stop); 2622 } 2623 } 2624 } 2625 }; 2626 $.each({ 2627 scrollstop: "scrollstart", 2628 taphold: "tap", 2629 swipeleft: "swipe.left", 2630 swiperight: "swipe.right" 2631 }, function (event, sourceEvent) { 2632 2633 $.event.special[event] = { 2634 setup: function () { 2635 $(this).bind(sourceEvent, $.noop); 2636 }, 2637 teardown: function () { 2638 $(this).unbind(sourceEvent); 2639 } 2640 }; 2641 }); 2642 2643 })(jQuery, this); 2644})); 2645 2646(function ($, window, undefined) { 2647 2648 //custom handleSwipe with swiperight, swipeleft, swipeup, swipedown 2649 $.event.special.swipe.handleSwipe = function (start, stop, thisObject, origTarget) { 2650 if (stop.time - start.time < $.event.special.swipe.durationThreshold) { 2651 var horSwipe = Math.abs(start.coords[0] - stop.coords[0]) > $.event.special.swipe.horizontalDistanceThreshold; 2652 var verSwipe = Math.abs(start.coords[1] - stop.coords[1]) > $.event.special.swipe.verticalDistanceThreshold; 2653 if (horSwipe != verSwipe) { 2654 var direction; 2655 if (horSwipe) 2656 direction = start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight"; 2657 else 2658 direction = start.coords[1] > stop.coords[1] ? "swipeup" : "swipedown"; 2659 $.event.trigger($.Event("swipe", { target: origTarget, swipestart: start, swipestop: stop }), undefined, thisObject); 2660 $.event.trigger($.Event(direction, { target: origTarget, swipestart: start, swipestop: stop }), undefined, thisObject); 2661 return true; 2662 } 2663 return false;
2664 } 2665 return false; 2666 } 2667 2668 //do binding 2669 $.each({ 2670 swipeup: "swipe.up", 2671 swipedown: "swipe.down" 2672 }, function (event, sourceEvent) { 2673 $.event.special[event] = { 2674 setup: function () { 2675 $(this).bind(sourceEvent, $.noop); 2676 }, 2677 teardown: function () { 2678 $(this).unbind(sourceEvent); 2679 } 2680 }; 2681 }); 2682})(jQuery, this);
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.