2.0_beta sync to rsa
[framework/web/web-ui-fw.git] / libs / js / jquery-mobile-1.1.0 / js / jquery.mobile.forms.select.js
1 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
2 //>>description: Consistent styling for native select menus. Tapping opens a native select menu.
3 //>>label: Selects
4 //>>group: Forms
5 //>>css: ../css/themes/default/jquery.mobile.theme.css, ../css/structure/jquery.mobile.forms.select.css
6
7 define( [ "jquery", "./jquery.mobile.core", "./jquery.mobile.widget", "./jquery.mobile.buttonMarkup", "./jquery.mobile.zoom" ], function( $ ) {
8 //>>excludeEnd("jqmBuildExclude");
9 (function( $, undefined ) {
10
11 $.widget( "mobile.selectmenu", $.mobile.widget, {
12         options: {
13                 theme: null,
14                 disabled: false,
15                 icon: "arrow-d",
16                 iconpos: "right",
17                 inline: false,
18                 corners: true,
19                 shadow: true,
20                 iconshadow: true,
21                 overlayTheme: "a",
22                 hidePlaceholderMenuItems: true,
23                 closeText: "Close",
24                 nativeMenu: true,
25                 // This option defaults to true on iOS devices.
26                 preventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1,
27                 initSelector: "select:not(:jqmData(role='slider'))",
28                 mini: false
29         },
30
31         _button: function(){
32                 return $( "<div/>" );
33         },
34
35         _setDisabled: function( value ) {
36                 this.element.attr( "disabled", value );
37                 this.button.attr( "aria-disabled", value );
38                 return this._setOption( "disabled", value );
39         },
40
41         _focusButton : function() {
42                 var self = this;
43
44                 setTimeout( function() {
45                         self.button.focus();
46                 }, 40);
47         },
48
49   _selectOptions: function() {
50     return this.select.find( "option" );
51   },
52
53         // setup items that are generally necessary for select menu extension
54         _preExtension: function(){
55                 var classes = "";
56                 // 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
57                 /* if( $el[0].className.length ) {
58                         classes = $el[0].className;
59                 } */
60                 if( !!~this.element[0].className.indexOf( "ui-btn-left" ) ) {
61                         classes =  " ui-btn-left";
62                 }
63                 
64                 if(  !!~this.element[0].className.indexOf( "ui-btn-right" ) ) {
65                         classes = " ui-btn-right";
66                 }
67                 
68                 this.select = this.element.wrap( "<div class='ui-select" + classes + "'>" );
69                 this.selectID  = this.select.attr( "id" );
70                 this.label = $( "label[for='"+ this.selectID +"']" ).addClass( "ui-select" );
71                 this.isMultiple = this.select[ 0 ].multiple;
72                 if ( !this.options.theme ) {
73                         this.options.theme = $.mobile.getInheritedTheme( this.select, "c" );
74                 }
75         },
76
77         _create: function() {
78                 this._preExtension();
79
80                 // Allows for extension of the native select for custom selects and other plugins
81                 // see select.custom for example extension
82                 // TODO explore plugin registration
83                 this._trigger( "beforeCreate" );
84
85                 this.button = this._button();
86
87                 var self = this,
88
89                         options = this.options,
90
91                         // IE throws an exception at options.item() function when
92                         // there is no selected item
93                         // select first in this case
94                         selectedIndex = this.select[ 0 ].selectedIndex == -1 ? 0 : this.select[ 0 ].selectedIndex,
95
96                         // TODO values buttonId and menuId are undefined here
97                         button = this.button
98                                 .text( $( this.select[ 0 ].options.item( selectedIndex ) ).text() )
99                                 .insertBefore( this.select )
100                                 .buttonMarkup( {
101                                         theme: options.theme,
102                                         icon: options.icon,
103                                         iconpos: options.iconpos,
104                                         inline: options.inline,
105                                         corners: options.corners,
106                                         shadow: options.shadow,
107                                         iconshadow: options.iconshadow,
108                                         mini: options.mini
109                                 });
110
111                 // Opera does not properly support opacity on select elements
112                 // In Mini, it hides the element, but not its text
113                 // On the desktop,it seems to do the opposite
114                 // for these reasons, using the nativeMenu option results in a full native select in Opera
115                 if ( options.nativeMenu && window.opera && window.opera.version ) {
116                         this.select.addClass( "ui-select-nativeonly" );
117                 }
118
119                 // Add counter for multi selects
120                 if ( this.isMultiple ) {
121                         this.buttonCount = $( "<span>" )
122                                 .addClass( "ui-li-count ui-btn-up-c ui-btn-corner-all" )
123                                 .hide()
124                                 .appendTo( button.addClass('ui-li-has-count') );
125                 }
126
127                 // Disable if specified
128                 if ( options.disabled || this.element.attr('disabled')) {
129                         this.disable();
130                 }
131
132                 // Events on native select
133                 this.select.change( function() {
134                         self.refresh();
135                 });
136
137                 this.build();
138         },
139
140         build: function() {
141                 var self = this;
142
143                 this.select
144                         .appendTo( self.button )
145                         .bind( "vmousedown", function() {
146                                 // Add active class to button
147                                 self.button.addClass( $.mobile.activeBtnClass );
148                         })
149             .bind( "focus", function() {
150                 self.button.addClass( $.mobile.focusClass );
151             })
152             .bind( "blur", function() {
153                 self.button.removeClass( $.mobile.focusClass );
154             })
155                         .bind( "focus vmouseover", function() {
156                                 self.button.trigger( "vmouseover" );
157                         })
158                         .bind( "vmousemove", function() {
159                                 // Remove active class on scroll/touchmove
160                                 self.button.removeClass( $.mobile.activeBtnClass );
161                         })
162                         .bind( "change blur vmouseout", function() {
163                                 self.button.trigger( "vmouseout" )
164                                         .removeClass( $.mobile.activeBtnClass );
165                         })
166                         .bind( "change blur", function() {
167                                 self.button.removeClass( "ui-btn-down-" + self.options.theme );
168                         });
169
170                 // In many situations, iOS will zoom into the select upon tap, this prevents that from happening
171                 self.button.bind( "vmousedown", function() {
172                         if( self.options.preventFocusZoom ){
173                                 $.mobile.zoom.disable( true );
174                         }
175                 })
176                 .bind( "mouseup", function() {
177                         if( self.options.preventFocusZoom ){
178                                 $.mobile.zoom.enable( true );
179                         }
180                 });
181         },
182
183         selected: function() {
184                 return this._selectOptions().filter( ":selected" );
185         },
186
187         selectedIndices: function() {
188                 var self = this;
189
190                 return this.selected().map( function() {
191                         return self._selectOptions().index( this );
192                 }).get();
193         },
194
195         setButtonText: function() {
196                 var self = this, selected = this.selected();
197
198                 this.button.find( ".ui-btn-text" ).text( function() {
199                         if ( !self.isMultiple ) {
200                                 return selected.text();
201                         }
202
203                         return selected.length ? selected.map( function() {
204                                 return $( this ).text();
205                         }).get().join( ", " ) : self.placeholder;
206                 });
207         },
208
209         setButtonCount: function() {
210                 var selected = this.selected();
211
212                 // multiple count inside button
213                 if ( this.isMultiple ) {
214                         this.buttonCount[ selected.length > 1 ? "show" : "hide" ]().text( selected.length );
215                 }
216         },
217
218         refresh: function() {
219                 this.setButtonText();
220                 this.setButtonCount();
221         },
222
223         // open and close preserved in native selects
224         // to simplify users code when looping over selects
225         open: $.noop,
226         close: $.noop,
227
228         disable: function() {
229                 this._setDisabled( true );
230                 this.button.addClass( "ui-disabled" );
231         },
232
233         enable: function() {
234                 this._setDisabled( false );
235                 this.button.removeClass( "ui-disabled" );
236         }
237 });
238
239 //auto self-init widgets
240 $( document ).bind( "pagecreate create", function( e ){
241         $.mobile.selectmenu.prototype.enhanceWithin( e.target, true );
242 });
243 })( jQuery );
244 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
245 });
246 //>>excludeEnd("jqmBuildExclude");