PageSourceSearch

https://www.ronduffyart.com/js/jquery.mobile.custom/jquery.mobile.custom.js

js ronduffyart.com collected 2026-10-05 19:01:54 UTC 83,848 bytes, 2,666 lines download raw bytes

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 = "&shy;<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.