Revert "Export"
[framework/web/web-ui-fw.git] / libs / js / jquery-mobile-1.1.0 / js / jquery.mobile.fixedToolbar.js
1 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
2 //>>description: Behavior for "fixed" headers and footers
3 //>>label: Toolbars: Fixed
4 //>>group: Widgets
5 //>>css: ../css/themes/default/jquery.mobile.theme.css,../css/structure/jquery.mobile.fixedToolbar.css
6
7 define( [ "jquery", "./jquery.mobile.widget", "./jquery.mobile.core", "./jquery.mobile.navigation", "./jquery.mobile.page", "./jquery.mobile.page.sections", "./jquery.mobile.zoom" ], function( $ ) {
8 //>>excludeEnd("jqmBuildExclude");
9 (function( $, undefined ) {
10
11
12         $.widget( "mobile.fixedtoolbar", $.mobile.widget, {
13                 options: {
14                         visibleOnPageShow: true,
15                         disablePageZoom: true,
16                         transition: "slide", //can be none, fade, slide (slide maps to slideup or slidedown)
17                         fullscreen: false,
18                         tapToggle: true,
19                         tapToggleBlacklist: "a, input, select, textarea, .ui-header-fixed, .ui-footer-fixed",
20                         hideDuringFocus: "input, textarea, select",
21                         updatePagePadding: true,
22                         trackPersistentToolbars: true,
23
24                         // Browser detection! Weeee, here we go...
25                         // Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.
26                         // Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.
27                         // Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window
28                         // The following function serves to rule out some popular browsers with known fixed-positioning issues
29                         // This is a plugin option like any other, so feel free to improve or overwrite it
30                         supportBlacklist: function(){
31                                 var w = window,
32                                         ua = navigator.userAgent,
33                                         platform = navigator.platform,
34                                         // Rendering engine is Webkit, and capture major version
35                                         wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ ),
36                                         wkversion = !!wkmatch && wkmatch[ 1 ],
37                                         ffmatch = ua.match( /Fennec\/([0-9]+)/ ),
38                                         ffversion = !!ffmatch && ffmatch[ 1 ],
39                                         operammobilematch = ua.match( /Opera Mobi\/([0-9]+)/ ),
40                                         omversion = !!operammobilematch && operammobilematch[ 1 ];
41
42                                 if(
43                                         // iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)
44                                         ( ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1  || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534 )
45                                         ||
46                                         // Opera Mini
47                                         ( w.operamini && ({}).toString.call( w.operamini ) === "[object OperaMini]" )
48                                         ||
49                                         ( operammobilematch && omversion < 7458 )
50                                         ||
51                                         //Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)
52                                         ( ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533 )
53                                         ||
54                                         // Firefox Mobile before 6.0 -
55                                         ( ffversion && ffversion < 6 )
56                                         ||
57                                         // WebOS less than 3
58                                         ( "palmGetResource" in window && wkversion && wkversion < 534 )
59                                         ||
60                                         // MeeGo
61                                         ( ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1 )
62                                 ){
63                                         return true;
64                                 }
65
66                                 return false;
67                         },
68                         initSelector: ":jqmData(position='fixed')"
69                 },
70
71                 _create: function() {
72
73                         var self = this,
74                                 o = self.options,
75                                 $el = self.element,
76                                 tbtype = $el.is( ":jqmData(role='header')" ) ? "header" : "footer",
77                                 $page = $el.closest(".ui-page");
78
79                         // Feature detecting support for
80                         if( o.supportBlacklist() ){
81                                 self.destroy();
82                                 return;
83                         }
84
85                         $el.addClass( "ui-"+ tbtype +"-fixed" );
86
87                         // "fullscreen" overlay positioning
88                         if( o.fullscreen ){
89                                 $el.addClass( "ui-"+ tbtype +"-fullscreen" );
90                                 $page.addClass( "ui-page-" + tbtype + "-fullscreen" );
91                         }
92                         // If not fullscreen, add class to page to set top or bottom padding
93                         else{
94                                 $page.addClass( "ui-page-" + tbtype + "-fixed" );
95                         }
96
97                         self._addTransitionClass();
98                         self._bindPageEvents();
99                         self._bindToggleHandlers();
100                 },
101
102                 _addTransitionClass: function(){
103                         var tclass = this.options.transition;
104
105                         if( tclass && tclass !== "none" ){
106                                 // use appropriate slide for header or footer
107                                 if( tclass === "slide" ){
108                                         tclass = this.element.is( ".ui-header" ) ? "slidedown" : "slideup";
109                                 }
110
111                                 this.element.addClass( tclass );
112                         }
113                 },
114
115                 _bindPageEvents: function(){
116                         var self = this,
117                                 o = self.options,
118                                 $el = self.element;
119
120                         //page event bindings
121                         // Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up
122                         // This method is meant to disable zoom while a fixed-positioned toolbar page is visible
123                         $el.closest( ".ui-page" )
124                                 .bind( "pagebeforeshow", function(){
125                                         if( o.disablePageZoom ){
126                                                 $.mobile.zoom.disable( true );
127                                         }
128                                         if( !o.visibleOnPageShow ){
129                                                 self.hide( true );
130                                         }
131                                 } )
132                                 .bind( "webkitAnimationStart animationstart updatelayout", function(){
133                                         if( o.updatePagePadding ){
134                                                 self.updatePagePadding();
135                                         }
136                                 })
137                                 .bind( "pageshow", function(){
138                                         self.updatePagePadding();
139                                         if( o.updatePagePadding ){
140                                                 $( window ).bind( "throttledresize." + self.widgetName, function(){
141                                                         self.updatePagePadding();
142                                                 });
143                                         }
144                                 })
145                                 .bind( "pagebeforehide", function( e, ui ){
146                                         if( o.disablePageZoom ){
147                                                 $.mobile.zoom.enable( true );
148                                         }
149                                         if( o.updatePagePadding ){
150                                                 $( window ).unbind( "throttledresize." + self.widgetName );
151                                         }
152
153                                         if( o.trackPersistentToolbars ){
154                                                 var thisFooter = $( ".ui-footer-fixed:jqmData(id)", this ),
155                                                         thisHeader = $( ".ui-header-fixed:jqmData(id)", this ),
156                                                         nextFooter = thisFooter.length && ui.nextPage && $( ".ui-footer-fixed:jqmData(id='" + thisFooter.jqmData( "id" ) + "')", ui.nextPage ),
157                                                         nextHeader = thisHeader.length && ui.nextPage && $( ".ui-header-fixed:jqmData(id='" + thisHeader.jqmData( "id" ) + "')", ui.nextPage );
158
159                                                 nextFooter = nextFooter || $();
160
161                                                         if( nextFooter.length || nextHeader.length ){
162
163                                                                 nextFooter.add( nextHeader ).appendTo( $.mobile.pageContainer );
164
165                                                                 ui.nextPage.one( "pageshow", function(){
166                                                                         nextFooter.add( nextHeader ).appendTo( this );
167                                                                 });
168                                                         }
169                                         }
170                                 });
171                 },
172
173                 _visible: true,
174
175                 // This will set the content element's top or bottom padding equal to the toolbar's height
176                 updatePagePadding: function() {
177                         var $el = this.element,
178                                 header = $el.is( ".ui-header" );
179
180                         // This behavior only applies to "fixed", not "fullscreen"
181                         if( this.options.fullscreen ){ return; }
182
183                         $el.closest( ".ui-page" ).css( "padding-" + ( header ? "top" : "bottom" ), $el.outerHeight() );
184                 },
185                 
186                 _useTransition: function( notransition ){
187                         var $win = $( window ),
188                                 $el = this.element,
189                                 scroll = $win.scrollTop(),
190                                 elHeight = $el.height(),
191                                 pHeight = $el.closest( ".ui-page" ).height(),
192                                 viewportHeight = $.mobile.getScreenHeight(),
193                                 tbtype = $el.is( ":jqmData(role='header')" ) ? "header" : "footer";
194                                 
195                         return !notransition &&
196                                 ( this.options.transition && this.options.transition !== "none" &&
197                                 (
198                                         ( tbtype === "header" && !this.options.fullscreen && scroll > elHeight ) ||
199                                         ( tbtype === "footer" && !this.options.fullscreen && scroll + viewportHeight < pHeight - elHeight )
200                                 ) || this.options.fullscreen
201                                 );
202                 },
203
204                 show: function( notransition ){
205                         var hideClass = "ui-fixed-hidden",
206                                 $el = this.element;
207
208                                 if( this._useTransition( notransition ) ){
209                                 $el
210                                         .removeClass( "out " + hideClass )
211                                         .addClass( "in" );
212                         }
213                         else {
214                                 $el.removeClass( hideClass );
215                         }
216                         this._visible = true;
217                 },
218
219                 hide: function( notransition ){
220                         var hideClass = "ui-fixed-hidden",
221                                 $el = this.element,
222                                 // if it's a slide transition, our new transitions need the reverse class as well to slide outward
223                                 outclass = "out" + ( this.options.transition === "slide" ? " reverse" : "" );
224
225                         if( this._useTransition( notransition ) ){
226                                 $el
227                                         .addClass( outclass )
228                                         .removeClass( "in" )
229                                         .animationComplete( function(){
230                                                 $el.addClass( hideClass ).removeClass( outclass );
231                                         });
232                         }
233                         else {
234                                 $el.addClass( hideClass ).removeClass( outclass );
235                         }
236                         this._visible = false;
237                 },
238
239                 toggle: function(){
240                         this[ this._visible ? "hide" : "show" ]();
241                 },
242
243                 _bindToggleHandlers: function(){
244                         var self = this,
245                                 o = self.options,
246                                 $el = self.element;
247
248                         // tap toggle
249                         $el.closest( ".ui-page" )
250                                 .bind( "vclick", function( e ){
251                                         if( o.tapToggle && !$( e.target ).closest( o.tapToggleBlacklist ).length ){
252                                                 self.toggle();
253                                         }
254                                 })
255                                 .bind( "focusin focusout", function( e ){
256                                         if( screen.width < 500 && $( e.target ).is( o.hideDuringFocus ) && !$( e.target ).closest( ".ui-header-fixed, .ui-footer-fixed" ).length ){
257                                                 self[ ( e.type === "focusin" && self._visible ) ? "hide" : "show" ]();
258                                         }
259                                 });
260                 },
261
262                 destroy: function(){
263                         this.element.removeClass( "ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden" );
264                         this.element.closest( ".ui-page" ).removeClass( "ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen" );
265                 }
266
267         });
268
269         //auto self-init widgets
270         $( document )
271                 .bind( "pagecreate create", function( e ){
272                         
273                         // DEPRECATED in 1.1: support for data-fullscreen=true|false on the page element.
274                         // This line ensures it still works, but we recommend moving the attribute to the toolbars themselves.
275                         if( $( e.target ).jqmData( "fullscreen" ) ){
276                                 $( $.mobile.fixedtoolbar.prototype.options.initSelector, e.target ).not( ":jqmData(fullscreen)" ).jqmData( "fullscreen", true );
277                         }
278                         
279                         $.mobile.fixedtoolbar.prototype.enhanceWithin( e.target );
280                 });
281
282 })( jQuery );
283 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
284 });
285 //>>excludeEnd("jqmBuildExclude");