| //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude); |
| //>>description: Consistent styling for native select menus. Tapping opens a native select menu. |
| //>>label: Selects |
| //>>group: Forms |
| //>>css.structure: ../css/structure/jquery.mobile.forms.select.css |
| //>>css.theme: ../css/themes/default/jquery.mobile.theme.css |
| |
| define( [ "jquery", "../../jquery.mobile.core", "../../jquery.mobile.widget", "../../jquery.mobile.buttonMarkup", "../../jquery.mobile.zoom" ], function( jQuery ) { |
| //>>excludeEnd("jqmBuildExclude"); |
| (function( $, undefined ) { |
| |
| $.widget( "mobile.selectmenu", $.mobile.widget, { |
| options: { |
| theme: null, |
| disabled: false, |
| icon: "arrow-d", |
| iconpos: "right", |
| inline: false, |
| corners: true, |
| shadow: true, |
| iconshadow: true, |
| overlayTheme: "a", |
| hidePlaceholderMenuItems: true, |
| closeText: "Close", |
| nativeMenu: true, |
| // This option defaults to true on iOS devices. |
| preventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1, |
| initSelector: "select:not( :jqmData(role='slider') )", |
| mini: false |
| }, |
| |
| _button: function() { |
| return $( "<div/>" ); |
| }, |
| |
| _setDisabled: function( value ) { |
| this.element.attr( "disabled", value ); |
| this.button.attr( "aria-disabled", value ); |
| return this._setOption( "disabled", value ); |
| }, |
| |
| _focusButton : function() { |
| var self = this; |
| |
| setTimeout( function() { |
| self.button.focus(); |
| }, 40); |
| }, |
| |
| _selectOptions: function() { |
| return this.select.find( "option" ); |
| }, |
| |
| // setup items that are generally necessary for select menu extension |
| _preExtension: function() { |
| var classes = ""; |
| // TODO: Post 1.1--once we have time to test thoroughly--any classes manually applied to the original element should be carried over to the enhanced element, with an `-enhanced` suffix. See https://github.com/jquery/jquery-mobile/issues/3577 |
| /* if ( $el[0].className.length ) { |
| classes = $el[0].className; |
| } */ |
| if ( !!~this.element[0].className.indexOf( "ui-btn-left" ) ) { |
| classes = " ui-btn-left"; |
| } |
| |
| if ( !!~this.element[0].className.indexOf( "ui-btn-right" ) ) { |
| classes = " ui-btn-right"; |
| } |
| |
| this.select = this.element.wrap( "<div class='ui-select" + classes + "'>" ); |
| this.selectID = this.select.attr( "id" ); |
| this.label = $( "label[for='"+ this.selectID +"']" ).addClass( "ui-select" ); |
| this.isMultiple = this.select[ 0 ].multiple; |
| if ( !this.options.theme ) { |
| this.options.theme = $.mobile.getInheritedTheme( this.select, "c" ); |
| } |
| }, |
| |
| _create: function() { |
| this._preExtension(); |
| |
| // Allows for extension of the native select for custom selects and other plugins |
| // see select.custom for example extension |
| // TODO explore plugin registration |
| this._trigger( "beforeCreate" ); |
| |
| this.button = this._button(); |
| |
| var self = this, |
| |
| options = this.options, |
| |
| inline = options.inline || $.mobile.getAttrFixed( this.select[0], "data-" + $.mobile.ns + "inline" ), |
| mini = options.mini || $.mobile.getAttrFixed( this.select[0], "data-" + $.mobile.ns + "mini" ), |
| iconpos = options.icon ? ( options.iconpos || $.mobile.getAttrFixed( this.select[0], "data-" + $.mobile.ns + "iconpos" ) ) : false, |
| |
| // IE throws an exception at options.item() function when |
| // there is no selected item |
| // select first in this case |
| selectedIndex = this.select[ 0 ].selectedIndex === -1 ? 0 : this.select[ 0 ].selectedIndex, |
| |
| // TODO values buttonId and menuId are undefined here |
| button = this.button |
| .insertBefore( this.select ) |
| .buttonMarkup( { |
| theme: options.theme, |
| icon: options.icon, |
| iconpos: iconpos, |
| inline: inline, |
| corners: options.corners, |
| shadow: options.shadow, |
| iconshadow: options.iconshadow, |
| mini: mini |
| }); |
| |
| this.setButtonText(); |
| |
| // TIZEN fix: The TIZEN buttonMarkup patch adds 'ui-btn-icon-only' class to the ui-btn-inner. |
| // It makes the text not to be shown, so the class must be removed. (Like JQM) |
| button.children('.ui-btn-inner').removeClass('ui-btn-icon-only'); |
| |
| // Opera does not properly support opacity on select elements |
| // In Mini, it hides the element, but not its text |
| // On the desktop,it seems to do the opposite |
| // for these reasons, using the nativeMenu option results in a full native select in Opera |
| if ( options.nativeMenu && window.opera && window.opera.version ) { |
| button.addClass( "ui-select-nativeonly" ); |
| } |
| |
| // Add counter for multi selects |
| if ( this.isMultiple ) { |
| this.buttonCount = $( "<span>" ) |
| .addClass( "ui-li-count ui-btn-up-c ui-btn-corner-all" ) |
| .hide() |
| .appendTo( button.addClass('ui-li-has-count') ); |
| } |
| |
| // Disable if specified |
| if ( options.disabled || this.element.attr('disabled')) { |
| this.disable(); |
| } |
| |
| // Events on native select |
| this.select.change(function() { |
| self.refresh(); |
| }); |
| |
| this.build(); |
| }, |
| |
| build: function() { |
| var self = this; |
| |
| this.select |
| .appendTo( self.button ) |
| .bind( "vmousedown", function() { |
| // Add active class to button |
| self.button.addClass( $.mobile.activeBtnClass ); |
| }) |
| .bind( "focus", function() { |
| self.button.addClass( $.mobile.focusClass ); |
| }) |
| .bind( "blur", function() { |
| self.button.removeClass( $.mobile.focusClass ); |
| }) |
| .bind( "focus vmouseover", function() { |
| self.button.trigger( "vmouseover" ); |
| }) |
| .bind( "vmousemove", function() { |
| // Remove active class on scroll/touchmove |
| self.button.removeClass( $.mobile.activeBtnClass ); |
| }) |
| .bind( "change blur vmouseout", function() { |
| self.button.trigger( "vmouseout" ) |
| .removeClass( $.mobile.activeBtnClass ); |
| }) |
| .bind( "change blur", function() { |
| self.button.removeClass( "ui-btn-down-" + self.options.theme ); |
| }); |
| |
| // In many situations, iOS will zoom into the select upon tap, this prevents that from happening |
| self.button.bind( "vmousedown", function() { |
| if ( self.options.preventFocusZoom ) { |
| $.mobile.zoom.disable( true ); |
| } |
| }).bind( "mouseup", function() { |
| if ( self.options.preventFocusZoom ) { |
| setTimeout(function() { |
| $.mobile.zoom.enable( true ); |
| }, 0); |
| } |
| }); |
| }, |
| |
| selected: function() { |
| return this._selectOptions().filter( ":selected" ); |
| }, |
| |
| selectedIndices: function() { |
| var self = this; |
| |
| return this.selected().map(function() { |
| return self._selectOptions().index( this ); |
| }).get(); |
| }, |
| |
| setButtonText: function() { |
| var self = this, |
| selected = this.selected(), |
| text = this.placeholder, |
| span = $( document.createElement( "span" ) ); |
| |
| this.button.find( ".ui-btn-text" ).html(function() { |
| if ( selected.length ) { |
| text = selected.map(function() { |
| return $( this ).text(); |
| }).get().join( ", " ); |
| } else { |
| text = self.placeholder; |
| } |
| |
| // TODO possibly aggregate multiple select option classes |
| return span.text( text ) |
| .addClass( self.select.attr( "class" ) ) |
| .addClass( selected.attr( "class" ) ); |
| }); |
| }, |
| |
| setButtonCount: function() { |
| var selected = this.selected(); |
| |
| // multiple count inside button |
| if ( this.isMultiple ) { |
| this.buttonCount[ selected.length > 1 ? "show" : "hide" ]().text( selected.length ); |
| } |
| }, |
| |
| refresh: function() { |
| this.setButtonText(); |
| this.setButtonCount(); |
| }, |
| |
| // open and close preserved in native selects |
| // to simplify users code when looping over selects |
| open: $.noop, |
| close: $.noop, |
| |
| disable: function() { |
| this._setDisabled( true ); |
| this.button.addClass( "ui-disabled" ); |
| }, |
| |
| enable: function() { |
| this._setDisabled( false ); |
| this.button.removeClass( "ui-disabled" ); |
| } |
| }); |
| |
| //auto self-init widgets |
| $.mobile.$document.bind( "pagecreate create", function( e ) { |
| $.mobile.selectmenu.prototype.enhanceWithin( e.target, true ); |
| }); |
| })( jQuery ); |
| //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude); |
| }); |
| //>>excludeEnd("jqmBuildExclude"); |