Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Sign In

jquery / jquery-mobile / 2313

5 Feb 2015 - 11:04 coverage increased (+0.009%) to 82.482%
2313

Pull #7953

travis-ci

Acabeff49b5ba95a8e94de9445175f56?size=18&default=identicongabrielschulhof
Textinput: Update comment regarding deprecated style options
Pull Request #7953: Textinput: Implement classes option

3503 of 4247 relevant lines covered (82.48%)

924.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.4
/js/widgets/fixedToolbar.js
1
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
2
//>>description: Behavior for "fixed" headers and footers - be sure to also include the item 'Browser specific workarounds for "fixed" headers and footers' when supporting Android 2.x or iOS 5
3
//>>label: Toolbars: Fixed
4
//>>group: Widgets
5
//>>css.structure: ../css/structure/jquery.mobile.fixedToolbar.css
6
//>>css.theme: ../css/themes/default/jquery.mobile.theme.css
7

8
define( [ "jquery", "../widget", "../core", "../animationComplete", "../navigation", "./page","./toolbar","../zoom" ], function( jQuery ) {
32×
9
//>>excludeEnd("jqmBuildExclude");
10
(function( $, undefined ) {
32×
11

12
        $.widget( "mobile.toolbar", $.mobile.toolbar, {
32×
13
                options: {
14
                        position:null,
15
                        visibleOnPageShow: true,
16
                        disablePageZoom: true,
17
                        transition: "slide", //can be none, fade, slide (slide maps to slideup or slidedown)
18
                        fullscreen: false,
19
                        tapToggle: true,
20
                        tapToggleBlacklist: "a, button, input, select, textarea, .ui-header-fixed, .ui-footer-fixed, .ui-flipswitch, .ui-popup, .ui-panel, .ui-panel-dismiss-open",
21
                        hideDuringFocus: "input, textarea, select",
22
                        updatePagePadding: true,
23
                        trackPersistentToolbars: true,
24

25
                        // Browser detection! Weeee, here we go...
26
                        // Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.
27
                        // Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.
28
                        // Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window
29
                        // The following function serves to rule out some popular browsers with known fixed-positioning issues
30
                        // This is a plugin option like any other, so feel free to improve or overwrite it
31
                        supportBlacklist: function() {
32
                                return !$.support.fixedPosition;
434×
33
                        }
34
                },
35

36
                _create: function() {
37
                        this._super();
91×
38
                        if ( this.options.position === "fixed" && !this.options.supportBlacklist() ) {
91×
39
                                this.pagecontainer = this.element.closest( ".ui-mobile-viewport" );
70×
40
                                this._makeFixed();
70×
41
                        }
42
                },
43

44
                _makeFixed: function() {
45
                        this.element.addClass( "ui-"+ this.role +"-fixed" );
70×
46
                        this.updatePagePadding();
70×
47
                        this._addTransitionClass();
70×
48
                        this._bindPageEvents();
70×
49
                        this._bindToggleHandlers();
70×
50
                },
51

52
                _setOptions: function( o ) {
53
                        if ( o.position === "fixed" && this.options.position !== "fixed" ) {
385×
54
                                this._makeFixed();
!
55
                        }
56
                        if ( this.options.position === "fixed" && !this.options.supportBlacklist() ) {
385×
57
                                var $page = ( !!this.page )? this.page: ( $(".ui-page-active").length > 0 )? $(".ui-page-active"): $(".ui-page").eq(0);
364×
58

59
                                if ( o.fullscreen !== undefined) {
364×
60
                                        if ( o.fullscreen ) {
70×
61
                                                this.element.addClass( "ui-"+ this.role +"-fullscreen" );
14×
62
                                                $page.addClass( "ui-page-" + this.role + "-fullscreen" );
14×
63
                                        }
64
                                        // If not fullscreen, add class to page to set top or bottom padding
65
                                        else {
66
                                                this.element.removeClass( "ui-"+ this.role +"-fullscreen" );
56×
67
                                                $page.removeClass( "ui-page-" + this.role + "-fullscreen" ).addClass( "ui-page-" + this.role+ "-fixed" );
56×
68
                                        }
69
                                }
70
                        }
71
                        this._super(o);
385×
72
                },
73

74
                _addTransitionClass: function() {
75
                        var tclass = this.options.transition;
70×
76

77
                        if ( tclass && tclass !== "none" ) {
70×
78
                                // use appropriate slide for header or footer
79
                                if ( tclass === "slide" ) {
63×
80
                                        tclass = this.element.hasClass( "ui-header" ) ? "slidedown" : "slideup";
56×
81
                                }
82

83
                                this.element.addClass( tclass );
63×
84
                        }
85
                },
86

87
                _bindPageEvents: function() {
88
                        var page = ( !!this.page )? this.element.closest( ".ui-page" ): this.document;
70×
89
                        //page event bindings
90
                        // Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up
91
                        // This method is meant to disable zoom while a fixed-positioned toolbar page is visible
92
                        this._on( page , {
70×
93
                                "pagebeforeshow": "_handlePageBeforeShow",
94
                                "webkitAnimationStart":"_handleAnimationStart",
95
                                "animationstart":"_handleAnimationStart",
96
                                "updatelayout": "_handleAnimationStart",
97
                                "pageshow": "_handlePageShow",
98
                                "pagebeforehide": "_handlePageBeforeHide"
99
                        });
100
                },
101

102
                _handlePageBeforeShow: function( ) {
103
                        var o = this.options;
259×
104
                        if ( o.disablePageZoom ) {
259×
105
                                $.mobile.zoom.disable( true );
196×
106
                        }
107
                        if ( !o.visibleOnPageShow ) {
259×
UNCOV
108
                                this.hide( true );
!
109
                        }
110
                },
111

112
                _handleAnimationStart: function() {
UNCOV
113
                        if ( this.options.updatePagePadding ) {
!
UNCOV
114
                                this.updatePagePadding( ( !!this.page )? this.page: ".ui-page-active" );
!
115
                        }
116
                },
117

118
                _handlePageShow: function() {
119
                        this.updatePagePadding( ( !!this.page )? this.page: ".ui-page-active" );
70×
120
                        if ( this.options.updatePagePadding ) {
70×
121
                                this._on( this.window, { "throttledresize": "updatePagePadding" } );
70×
122
                        }
123
                },
124

125
                _handlePageBeforeHide: function( e, ui ) {
126
                        var o = this.options,
63×
127
                                thisFooter, thisHeader, nextFooter, nextHeader;
128

129
                        if ( o.disablePageZoom ) {
63×
130
                                $.mobile.zoom.enable( true );
63×
131
                        }
132
                        if ( o.updatePagePadding ) {
63×
133
                                this._off( this.window, "throttledresize" );
63×
134
                        }
135

136
                        if ( o.trackPersistentToolbars ) {
63×
137
                                thisFooter = $( ".ui-footer-fixed:jqmData(id)", this.page );
63×
138
                                thisHeader = $( ".ui-header-fixed:jqmData(id)", this.page );
63×
139
                                nextFooter = thisFooter.length && ui.nextPage && $( ".ui-footer-fixed:jqmData(id='" + thisFooter.jqmData( "id" ) + "')", ui.nextPage ) || $();
63×
140
                                nextHeader = thisHeader.length && ui.nextPage && $( ".ui-header-fixed:jqmData(id='" + thisHeader.jqmData( "id" ) + "')", ui.nextPage ) || $();
63×
141

142
                                if ( nextFooter.length || nextHeader.length ) {
63×
143

UNCOV
144
                                        nextFooter.add( nextHeader ).appendTo( $.mobile.pageContainer );
!
145

UNCOV
146
                                        ui.nextPage.one( "pageshow", function() {
!
UNCOV
147
                                                nextHeader.prependTo( this );
!
UNCOV
148
                                                nextFooter.appendTo( this );
!
149
                                        });
150
                                }
151
                        }
152
                },
153

154
                _visible: true,
155

156
                // This will set the content element's top or bottom padding equal to the toolbar's height
157
                updatePagePadding: function( tbPage ) {
158
                        var $el = this.element,
140×
159
                                header = ( this.role ==="header" ),
160
                                pos = parseFloat( $el.css( header ? "top" : "bottom" ) );
161

162
                        // This behavior only applies to "fixed", not "fullscreen"
163
                        if ( this.options.fullscreen ) { return; }
140×
164
                        // tbPage argument can be a Page object or an event, if coming from throttled resize.
165
                        tbPage = ( tbPage && tbPage.type === undefined && tbPage ) || this.page || $el.closest( ".ui-page" );
112×
166
                        tbPage = ( !!this.page )? this.page: ".ui-page-active";
112×
167
                        $( tbPage ).css( "padding-" + ( header ? "top" : "bottom" ), $el.outerHeight() + pos );
112×
168
                },
169

170
                _useTransition: function( notransition ) {
UNCOV
171
                        var $win = this.window,
!
172
                                $el = this.element,
173
                                scroll = $win.scrollTop(),
174
                                elHeight = $el.height(),
175
                                pHeight = ( !!this.page )? $el.closest( ".ui-page" ).height():$(".ui-page-active").height(),
176
                                viewportHeight = $.mobile.getScreenHeight();
177

UNCOV
178
                        return !notransition &&
!
179
                                ( this.options.transition && this.options.transition !== "none" &&
180
                                (
181
                                        ( this.role === "header" && !this.options.fullscreen && scroll > elHeight ) ||
182
                                        ( this.role === "footer" && !this.options.fullscreen && scroll + viewportHeight < pHeight - elHeight )
183
                                ) || this.options.fullscreen
184
                                );
185
                },
186

187
                show: function( notransition ) {
UNCOV
188
                        var hideClass = "ui-fixed-hidden",
!
189
                                $el = this.element;
190

UNCOV
191
                        if ( this._useTransition( notransition ) ) {
!
UNCOV
192
                                $el
!
193
                                        .removeClass( "out " + hideClass )
194
                                        .addClass( "in" )
195
                                        .animationComplete(function () {
UNCOV
196
                                                $el.removeClass( "in" );
!
197
                                        });
198
                        }
199
                        else {
UNCOV
200
                                $el.removeClass( hideClass );
!
201
                        }
UNCOV
202
                        this._visible = true;
!
203
                },
204

205
                hide: function( notransition ) {
UNCOV
206
                        var hideClass = "ui-fixed-hidden",
!
207
                                $el = this.element,
208
                                // if it's a slide transition, our new transitions need the reverse class as well to slide outward
209
                                outclass = "out" + ( this.options.transition === "slide" ? " reverse" : "" );
210

UNCOV
211
                        if ( this._useTransition( notransition ) ) {
!
UNCOV
212
                                $el
!
213
                                        .addClass( outclass )
214
                                        .removeClass( "in" )
215
                                        .animationComplete(function() {
UNCOV
216
                                                $el.addClass( hideClass ).removeClass( outclass );
!
217
                                        });
218
                        }
219
                        else {
UNCOV
220
                                $el.addClass( hideClass ).removeClass( outclass );
!
221
                        }
UNCOV
222
                        this._visible = false;
!
223
                },
224

225
                toggle: function() {
UNCOV
226
                        this[ this._visible ? "hide" : "show" ]();
!
227
                },
228

229
                _bindToggleHandlers: function() {
230
                        var self = this,
70×
231
                                o = self.options,
232
                                delayShow, delayHide,
233
                                isVisible = true,
234
                                page = ( !!this.page )? this.page: $(".ui-page");
235

236
                        // tap toggle
237
                        page
70×
238
                                .bind( "vclick", function( e ) {
239
                                        if ( o.tapToggle && !$( e.target ).closest( o.tapToggleBlacklist ).length ) {
!
240
                                                self.toggle();
!
241
                                        }
242
                                })
243
                                .bind( "focusin focusout", function( e ) {
244
                                        //this hides the toolbars on a keyboard pop to give more screen room and prevent ios bug which
245
                                        //positions fixed toolbars in the middle of the screen on pop if the input is near the top or
246
                                        //bottom of the screen addresses issues #4410 Footer navbar moves up when clicking on a textbox in an Android environment
247
                                        //and issue #4113 Header and footer change their position after keyboard popup - iOS
248
                                        //and issue #4410 Footer navbar moves up when clicking on a textbox in an Android environment
UNCOV
249
                                        if ( screen.width < 1025 && $( e.target ).is( o.hideDuringFocus ) && !$( e.target ).closest( ".ui-header-fixed, .ui-footer-fixed" ).length ) {
!
250
                                                //Fix for issue #4724 Moving through form in Mobile Safari with "Next" and "Previous" system
251
                                                //controls causes fixed position, tap-toggle false Header to reveal itself
252
                                                // isVisible instead of self._visible because the focusin and focusout events fire twice at the same time
253
                                                // Also use a delay for hiding the toolbars because on Android native browser focusin is direclty followed
254
                                                // by a focusout when a native selects opens and the other way around when it closes.
255
                                                if ( e.type === "focusout" && !isVisible ) {
!
256
                                                        isVisible = true;
!
257
                                                        //wait for the stack to unwind and see if we have jumped to another input
258
                                                        clearTimeout( delayHide );
!
259
                                                        delayShow = setTimeout( function() {
!
260
                                                                self.show();
!
261
                                                        }, 0 );
262
                                                } else if ( e.type === "focusin" && !!isVisible ) {
!
263
                                                        //if we have jumped to another input clear the time out to cancel the show.
264
                                                        clearTimeout( delayShow );
!
265
                                                        isVisible = false;
!
266
                                                        delayHide = setTimeout( function() {
!
267
                                                                self.hide();
!
268
                                                        }, 0 );
269
                                                }
270
                                        }
271
                                });
272
                },
273

274
                _setRelative: function() {
275
                        if( this.options.position !== "fixed" ){
!
276
                                $( "[data-"+ $.mobile.ns + "role='page']" ).css({ "position": "relative" });
!
277
                        }
278
                },
279

280
                _destroy: function() {
UNCOV
281
                        var pageClasses, toolbarClasses, hasFixed, header, hasFullscreen,
!
282
                                page = this.pagecontainer.pagecontainer( "getActivePage" );
283

UNCOV
284
                        this._super();
!
UNCOV
285
                        if ( this.options.position === "fixed" ) {
!
UNCOV
286
                                hasFixed = $(  "body>.ui-" + this.role + "-fixed" )
!
287
                                                        .add( page.find( ".ui-" + this.options.role + "-fixed" ) )
288
                                                        .not( this.element ).length > 0;
UNCOV
289
                                hasFullscreen = $(  "body>.ui-" + this.role + "-fixed" )
!
290
                                                        .add( page.find( ".ui-" + this.options.role + "-fullscreen" ) )
291
                                                        .not( this.element ).length > 0;
UNCOV
292
                                toolbarClasses =  "ui-header-fixed ui-footer-fixed ui-header-fullscreen in out" +
!
293
                                        " ui-footer-fullscreen fade slidedown slideup ui-fixed-hidden";
UNCOV
294
                                this.element.removeClass( toolbarClasses );
!
UNCOV
295
                                if ( !hasFullscreen ) {
!
UNCOV
296
                                        pageClasses = "ui-page-" + this.role + "-fullscreen";
!
297
                                }
UNCOV
298
                                if ( !hasFixed ) {
!
UNCOV
299
                                        header = this.role === "header";
!
UNCOV
300
                                        pageClasses += " ui-page-" + this.role + "-fixed";
!
UNCOV
301
                                        page.css( "padding-" + ( header ? "top" : "bottom" ), "" );
!
302
                                }
UNCOV
303
                                page.removeClass( pageClasses );
!
304
                        }
305
                }
306

307
        });
308
})( jQuery );
309
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
310
});
311
//>>excludeEnd("jqmBuildExclude");
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
BLOG · TWITTER · Legal & Privacy · Supported CI Services · What's a CI service? · Automated Testing

© 2022 Coveralls, Inc