| //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude); |
| //>>description: Base file for jQuery Mobile |
| //>>label: Core |
| //>>group: Core |
| //>>css.structure: ../css/structure/jquery.mobile.core.css |
| //>>css.theme: ../css/themes/default/jquery.mobile.theme.css |
| |
| define( [ "jquery" ], function( jQuery, __version__ ) { |
| //>>excludeEnd("jqmBuildExclude"); |
| (function( $, window, undefined ) { |
| |
| var nsNormalizeDict = {}; |
| |
| // jQuery.mobile configurable options |
| $.mobile = $.extend( {}, { |
| |
| // Version of the jQuery Mobile Framework |
| version: __version__, |
| |
| // Namespace used framework-wide for data-attrs. Default is no namespace |
| ns: "", |
| |
| // Define the url parameter used for referencing widget-generated sub-pages. |
| // Translates to to example.html&ui-page=subpageIdentifier |
| // hash segment before &ui-page= is used to make Ajax request |
| subPageUrlKey: "ui-page", |
| |
| // Class assigned to page currently in view, and during transitions |
| activePageClass: "ui-page-active", |
| |
| // Class used for "active" button state, from CSS framework |
| activeBtnClass: "ui-btn-active", |
| |
| // Class used for "focus" form element state, from CSS framework |
| focusClass: "ui-focus", |
| |
| // Automatically handle clicks and form submissions through Ajax, when same-domain |
| ajaxEnabled: true, |
| |
| // Automatically load and show pages based on location.hash |
| hashListeningEnabled: true, |
| |
| // disable to prevent jquery from bothering with links |
| linkBindingEnabled: true, |
| |
| // Set default page transition - 'none' for no transitions |
| defaultPageTransition: "fade", |
| |
| // Set maximum window width for transitions to apply - 'false' for no limit |
| maxTransitionWidth: false, |
| |
| // Minimum scroll distance that will be remembered when returning to a page |
| minScrollBack: 250, |
| |
| // DEPRECATED: the following property is no longer in use, but defined until 2.0 to prevent conflicts |
| touchOverflowEnabled: false, |
| |
| // Set default dialog transition - 'none' for no transitions |
| defaultDialogTransition: "pop", |
| |
| // Error response message - appears when an Ajax page request fails |
| pageLoadErrorMessage: "Error Loading Page", |
| |
| // For error messages, which theme does the box uses? |
| pageLoadErrorMessageTheme: "e", |
| |
| // replace calls to window.history.back with phonegaps navigation helper |
| // where it is provided on the window object |
| phonegapNavigationEnabled: false, |
| |
| //automatically initialize the DOM when it's ready |
| autoInitializePage: true, |
| |
| pushStateEnabled: true, |
| |
| // allows users to opt in to ignoring content by marking a parent element as |
| // data-ignored |
| ignoreContentEnabled: false, |
| |
| // turn of binding to the native orientationchange due to android orientation behavior |
| orientationChangeEnabled: true, |
| |
| buttonMarkup: { |
| hoverDelay: 200 |
| }, |
| |
| // define the window and the document objects |
| $window: $( window ), |
| $document: $( document ), |
| |
| getAttrFixed : function( e, key ) { |
| var value = e.getAttribute( key ); |
| |
| return value === "true" ? true : |
| value === "false" ? false : |
| value === null ? undefined : value; |
| }, |
| |
| // TODO might be useful upstream in jquery itself ? |
| keyCode: { |
| ALT: 18, |
| BACKSPACE: 8, |
| CAPS_LOCK: 20, |
| COMMA: 188, |
| COMMAND: 91, |
| COMMAND_LEFT: 91, // COMMAND |
| COMMAND_RIGHT: 93, |
| CONTROL: 17, |
| DELETE: 46, |
| DOWN: 40, |
| END: 35, |
| ENTER: 13, |
| ESCAPE: 27, |
| HOME: 36, |
| INSERT: 45, |
| LEFT: 37, |
| MENU: 93, // COMMAND_RIGHT |
| NUMPAD_ADD: 107, |
| NUMPAD_DECIMAL: 110, |
| NUMPAD_DIVIDE: 111, |
| NUMPAD_ENTER: 108, |
| NUMPAD_MULTIPLY: 106, |
| NUMPAD_SUBTRACT: 109, |
| PAGE_DOWN: 34, |
| PAGE_UP: 33, |
| PERIOD: 190, |
| RIGHT: 39, |
| SHIFT: 16, |
| SPACE: 32, |
| TAB: 9, |
| UP: 38, |
| WINDOWS: 91 // COMMAND |
| }, |
| |
| // Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value |
| silentScroll: function( ypos ) { |
| if ( $.type( ypos ) !== "number" ) { |
| ypos = $.mobile.defaultHomeScroll; |
| } |
| |
| // prevent scrollstart and scrollstop events |
| $.event.special.scrollstart.enabled = false; |
| |
| setTimeout( function() { |
| window.scrollTo( 0, ypos ); |
| $.mobile.$document.trigger( "silentscroll", { x: 0, y: ypos }); |
| }, 20 ); |
| |
| setTimeout( function() { |
| $.event.special.scrollstart.enabled = true; |
| }, 150 ); |
| }, |
| |
| // Expose our cache for testing purposes. |
| nsNormalizeDict: nsNormalizeDict, |
| |
| // Take a data attribute property, prepend the namespace |
| // and then camel case the attribute string. Add the result |
| // to our nsNormalizeDict so we don't have to do this again. |
| nsNormalize: function( prop ) { |
| if ( !prop ) { |
| return; |
| } |
| |
| return nsNormalizeDict[ prop ] || ( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) ); |
| }, |
| |
| // Find the closest parent with a theme class on it. Note that |
| // we are not using $.fn.closest() on purpose here because this |
| // method gets called quite a bit and we need it to be as fast |
| // as possible. |
| getInheritedTheme: function( el, defaultTheme ) { |
| var e = el[ 0 ], |
| ltr = "", |
| re = /ui-(bar|body|overlay)-([a-z])\b/, |
| c, m; |
| |
| while ( e ) { |
| c = e.className || ""; |
| if ( c && ( m = re.exec( c ) ) && ( ltr = m[ 2 ] ) ) { |
| // We found a parent with a theme class |
| // on it so bail from this loop. |
| break; |
| } |
| |
| e = e.parentNode; |
| } |
| |
| // Return the theme letter we found, if none, return the |
| // specified default. |
| |
| return ltr || defaultTheme || "a"; |
| }, |
| |
| // TODO the following $ and $.fn extensions can/probably should be moved into jquery.mobile.core.helpers |
| // |
| // Find the closest javascript page element to gather settings data jsperf test |
| // http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit |
| // possibly naive, but it shows that the parsing overhead for *just* the page selector vs |
| // the page and dialog selector is negligable. This could probably be speed up by |
| // doing a similar parent node traversal to the one found in the inherited theme code above |
| closestPageData: function( $target ) { |
| return $target |
| .closest( ':jqmData(role="page"), :jqmData(role="dialog")' ) |
| .data( "page" ); |
| }, |
| |
| enhanceable: function( $set ) { |
| return this.haveParents( $set, "enhance" ); |
| }, |
| |
| hijackable: function( $set ) { |
| return this.haveParents( $set, "ajax" ); |
| }, |
| |
| haveParents: function( $set, attr ) { |
| if ( !$.mobile.ignoreContentEnabled ) { |
| return $set; |
| } |
| |
| var count = $set.length, |
| $newSet = $(), |
| e, $element, excluded; |
| |
| for ( var i = 0; i < count; i++ ) { |
| $element = $set.eq( i ); |
| excluded = false; |
| e = $set[ i ]; |
| |
| while ( e ) { |
| var c = e.getAttribute ? e.getAttribute( "data-" + $.mobile.ns + attr ) : ""; |
| |
| if ( c === "false" ) { |
| excluded = true; |
| break; |
| } |
| |
| e = e.parentNode; |
| } |
| |
| if ( !excluded ) { |
| $newSet = $newSet.add( $element ); |
| } |
| } |
| |
| return $newSet; |
| }, |
| |
| getScreenHeight: function() { |
| // Native innerHeight returns more accurate value for this across platforms, |
| // jQuery version is here as a normalized fallback for platforms like Symbian |
| return window.innerHeight || $.mobile.$window.height(); |
| } |
| }, $.mobile ); |
| |
| // Mobile version of data and removeData and hasData methods |
| // ensures all data is set and retrieved using jQuery Mobile's data namespace |
| $.fn.jqmData = function( prop, value ) { |
| var result; |
| if ( typeof prop !== "undefined" ) { |
| if ( prop ) { |
| prop = $.mobile.nsNormalize( prop ); |
| } |
| |
| // undefined is permitted as an explicit input for the second param |
| // in this case it returns the value and does not set it to undefined |
| if( arguments.length < 2 || value === undefined ){ |
| result = this.data( prop ); |
| } else { |
| result = this.data( prop, value ); |
| } |
| } |
| return result; |
| }; |
| |
| $.jqmData = function( elem, prop, value ) { |
| var result; |
| if ( typeof prop !== "undefined" ) { |
| result = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value ); |
| } |
| return result; |
| }; |
| |
| $.fn.jqmRemoveData = function( prop ) { |
| return this.removeData( $.mobile.nsNormalize( prop ) ); |
| }; |
| |
| $.jqmRemoveData = function( elem, prop ) { |
| return $.removeData( elem, $.mobile.nsNormalize( prop ) ); |
| }; |
| |
| $.fn.removeWithDependents = function() { |
| $.removeWithDependents( this ); |
| }; |
| |
| $.removeWithDependents = function( elem ) { |
| var $elem = $( elem ); |
| |
| ( $elem.jqmData( 'dependents' ) || $() ).remove(); |
| $elem.remove(); |
| }; |
| |
| $.fn.addDependents = function( newDependents ) { |
| $.addDependents( $( this ), newDependents ); |
| }; |
| |
| $.addDependents = function( elem, newDependents ) { |
| var dependents = $( elem ).jqmData( 'dependents' ) || $(); |
| |
| $( elem ).jqmData( 'dependents', $.merge( dependents, newDependents ) ); |
| }; |
| |
| // note that this helper doesn't attempt to handle the callback |
| // or setting of an html elements text, its only purpose is |
| // to return the html encoded version of the text in all cases. (thus the name) |
| $.fn.getEncodedText = function() { |
| return $( "<div/>" ).text( $( this ).text() ).html(); |
| }; |
| |
| // fluent helper function for the mobile namespaced equivalent |
| $.fn.jqmEnhanceable = function() { |
| return $.mobile.enhanceable( this ); |
| }; |
| |
| $.fn.jqmHijackable = function() { |
| return $.mobile.hijackable( this ); |
| }; |
| |
| // Monkey-patching Sizzle to filter the :jqmData selector |
| var oldFind = $.find, |
| jqmDataRE = /:jqmData\(([^)]*)\)/g; |
| |
| $.find = function( selector, context, ret, extra ) { |
| selector = selector.replace( jqmDataRE, "[data-" + ( $.mobile.ns || "" ) + "$1]" ); |
| |
| return oldFind.call( this, selector, context, ret, extra ); |
| }; |
| |
| $.extend( $.find, oldFind ); |
| |
| $.find.matches = function( expr, set ) { |
| return $.find( expr, null, null, set ); |
| }; |
| |
| $.find.matchesSelector = function( node, expr ) { |
| return $.find( expr, null, null, [ node ] ).length > 0; |
| }; |
| |
| $.extend({ |
| creatorDict: {}, |
| |
| delegateSelfInitWithSingleSelector: function( target, useKeepNative ) { |
| if ( typeof target !== 'function' ) { |
| return false; |
| } |
| var selector = target.prototype.options.initSelector; |
| var selectorRE = /:jqmData\(role='[A-z\-]+'\)$/; |
| if ( selectorRE.test(selector) ) { |
| var firstIdx = selector.indexOf( "'" ) + 1; |
| var lastIdx = selector.lastIndexOf( "'" ); |
| var key = selector.substring( firstIdx, lastIdx ); |
| if ( !$.creatorDict.hasOwnProperty( key ) ) { |
| $.creatorDict[key] = {}; |
| $.creatorDict[key].target = target; |
| if ( useKeepNative === true ) { |
| $.creatorDict[key].useKeepNative = useKeepNative; |
| } |
| return true; |
| } |
| } |
| return false; |
| } |
| }); |
| |
| //auto self-init widgets |
| $( document ).bind( "pagecreate create", function( e ) { |
| var selector = "*[data-" + $.mobile.ns + "role]"; |
| $( selector, e.target ).each( function () { |
| var dataRoleValue = this.getAttribute( "data-role" ), |
| matchedObj = $.creatorDict[dataRoleValue]; |
| if ( matchedObj ) { |
| matchedObj.target.prototype.enhance( this, matchedObj.useKeepNative ); |
| } |
| }); |
| }); |
| })( jQuery, this ); |
| //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude); |
| }); |
| //>>excludeEnd("jqmBuildExclude"); |
| |