pagelayout: fix jslint error
[platform/framework/web/web-ui-fw.git] / src / widgets / pagelayout / js / jquery.mobile.tizen.pagelayout.js
1 /* ***************************************************************************
2  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  * ***************************************************************************
22  *
23  *      Author: Jinhyuk Jun <jinhyuk.jun@samsung.com>
24  */
25
26 (function ( $, undefined ) {
27
28         $.widget( "mobile.pagelayout", $.mobile.widget, {
29                 options: {
30                         visibleOnPageShow: true,
31                         disablePageZoom: true,
32                         transition: "slide", //can be none, fade, slide (slide maps to slideup or slidedown)
33                         fullscreen: false,
34                         tapToggle: true,
35                         tapToggleBlacklist: "a, input, select, textarea, .ui-header-fixed, .ui-footer-fixed",
36                         hideDuringFocus: "input, textarea, select",
37                         updatePagePadding: true,
38                         trackPersistentToolbars: true,
39                         // Browser detection! Weeee, here we go...
40                         // Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.
41                         // Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.
42                         // Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window
43                         // The following function serves to rule out some popular browsers with known fixed-positioning issues
44                         // This is a plugin option like any other, so feel free to improve or overwrite it
45                         supportBlacklist: function () {
46                                 var w = window,
47                                         ua = navigator.userAgent,
48                                         platform = navigator.platform,
49                                         // Rendering engine is Webkit, and capture major version
50                                         wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ ),
51                                         wkversion = !!wkmatch && wkmatch[ 1 ],
52                                         ffmatch = ua.match( /Fennec\/([0-9]+)/ ),
53                                         ffversion = !!ffmatch && ffmatch[ 1 ],
54                                         operammobilematch = ua.match( /Opera Mobi\/([0-9]+)/ ),
55                                         omversion = !!operammobilematch && operammobilematch[ 1 ];
56
57                                 if (
58                                         // iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)
59                                         ( ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1  || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534 ) ||
60                                                 // Opera Mini
61                                                 ( w.operamini && ({}).toString.call( w.operamini ) === "[object OperaMini]" ) ||
62                                                 ( operammobilematch && omversion < 7458 ) ||
63                                                 //Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)
64                                                 ( ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533 ) ||
65                                                 // Firefox Mobile before 6.0 -
66                                                 ( ffversion && ffversion < 6 ) ||
67                                                 // WebOS less than 3
68                                                 ( window.palmGetResource !== undefined && wkversion && wkversion < 534 ) ||
69                                                 // MeeGo
70                                                 ( ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1 )
71                                 ) {
72                                         return true;
73                                 }
74
75                                 return false;
76                         },
77                         initSelector: ":jqmData(role='content')"
78                 },
79
80                 _create: function () {
81
82                         var self = this,
83                                 o = self.options,
84                                 $el = self.element;
85
86                         // Feature detecting support for
87                         if ( o.supportBlacklist() ) {
88                                 self.destroy();
89                                 return;
90                         }
91
92                         self._addFixedClass();
93                         self._addTransitionClass();
94                         self._bindPageEvents();
95
96                         // only content
97                         self._bindContentControlEvents();
98                 },
99
100                 /* add minimum fixed css style to bar(header/footer) and content
101                 *  it need to update when core source modified(jquery.mobile.page.section.js)
102                 *  modified from core source cuz initSelector different */
103                 _addFixedClass: function () {
104                         var self = this,
105                                 o = self.options,
106                                 $el = self.element,
107                                 $elHeader = $el.siblings( ":jqmData(role='header')" ),
108                                 $elFooter = $el.siblings( ":jqmData(role='footer')" ),
109                                 $elPage = $el.closest(".ui-page");
110
111                         $elHeader.addClass( "ui-header-fixed" );
112                         $elFooter.addClass( "ui-footer-fixed" );
113
114                         // "fullscreen" overlay positioning
115                         if ( o.fullscreen ) {
116                                 $elHeader.addClass( "ui-header-fullscreen" );
117                                 $elFooter.addClass( "ui-footer-fullscreen" );
118                                 $elPage
119                                         .addClass( "ui-page-header-fullscreen" )
120                                         .addClass( "ui-page-footer-fullscreen" );
121                         } else {
122                         // If not fullscreen, add class to page to set top or bottom padding
123                                 $elPage.addClass( "ui-page-header-fixed" )
124                                         .addClass( "ui-page-footer-fixed" );
125                         }
126                 },
127
128                 /* original core source(jquery.mobile.fixedToolbar.js)
129                 * never changed */
130                 _addTransitionClass: function () {
131                         var tclass = this.options.transition;
132
133                         if ( tclass && tclass !== "none" ) {
134                                 // use appropriate slide for header or footer
135                                 if ( tclass === "slide" ) {
136                                         tclass = this.element.is( ".ui-header" ) ? "slidedown" : "slideup";
137                                 }
138
139                                 this.element.addClass( tclass );
140                         }
141                 },
142
143
144                 /* Set default page positon
145                 * 1. add title style to header
146                 * 2. Set default header/footer position */
147                 setHeaderFooter: function ( thisPage ) {
148                         var $elPage = $( thisPage ),
149                                 $elHeader = $elPage.find( ":jqmData(role='header')" ).length ? $elPage.find( ":jqmData(role='header')") : $elPage.siblings( ":jqmData(role='header')"),
150                                 $elContent = $elPage.find( ".ui-content" ),
151                                 $elFooter = $elPage.find( ":jqmData(role='footer')" ),
152                                 $elFooterGroup = $elFooter.find( ":jqmData(role='fieldcontain')" );
153
154                         // divide content mode scrollview and non-scrollview
155                         if ( !$elPage.is( ".ui-dialog" ) ) {
156                                 if ( $elHeader.jqmData("position") == "fixed" || ( $.support.scrollview && $.tizen.frameworkData.theme.match(/tizen/) ) ) {
157                                         $elHeader
158                                                 .css( "position", "fixed" )
159                                                 .css( "top", "0px" );
160                                 } else if ( !$.support.scrollview && $elHeader.jqmData("position") != "fixed" ) {
161                                         $elHeader.css( "position", "relative" );
162                                 }
163                         }
164
165                         /* set Title style */
166                         if ( $elHeader.find("span.ui-title-text-sub").length ) {
167                                 $elHeader.addClass( "ui-title-multiline");
168                         }
169
170                         if ( $elFooterGroup.find( "div" ).is( ".ui-controlgroup-label" ) ) {
171                                 $elFooterGroup.find( "div.ui-controlgroup-label" ).remove();
172                         }
173                 },
174
175                 _bindPageEvents: function () {
176                         var self = this,
177                                 o = self.options,
178                                 $el = self.element,
179                                 $elCurrentFooter;
180
181                         //page event bindings
182                         // Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up
183                         // This method is meant to disable zoom while a fixed-positioned toolbar page is visible
184                         $el.closest( ".ui-page" )
185                                 .bind( "pagebeforeshow", function ( event ) {
186                                         var thisPage = this;
187                                         if ( o.disablePageZoom ) {
188                                                 $.mobile.zoom.disable( true );
189                                         }
190                                         if ( !o.visibleOnPageShow ) {
191                                                 self.hide( true );
192                                         }
193                                         self.setHeaderFooter( thisPage );
194                                         self._setContentMinHeight( thisPage );
195                                 } )
196                                 .bind( "webkitAnimationStart animationstart updatelayout", function ( e, data ) {
197                                         var thisPage = this;
198                                         if ( o.updatePagePadding ) {
199                                                 self.updatePagePadding(thisPage);
200                                                 self.updatePageLayout( false, thisPage);
201                                         }
202                                 })
203
204                                 .bind( "pageshow", function ( event ) {
205                                         var thisPage = this;
206                                         self._setContentMinHeight( thisPage );
207                                         self.updatePagePadding( thisPage );
208                                         self._updateHeaderArea( thisPage );
209                                         if ( o.updatePagePadding ) {
210                                                 $( window ).bind( "throttledresize." + self.widgetName, function () {
211                                                         self.updatePagePadding(thisPage);
212
213                                                         self.updatePageLayout( false, thisPage);
214                                                         self._updateHeaderArea( thisPage );
215                                                         self._setContentMinHeight( thisPage );
216                                                 });
217                                         }
218                                 })
219
220                                 .bind( "pagebeforehide", function ( e, ui ) {
221                                         if ( o.disablePageZoom ) {
222                                                 $.mobile.zoom.enable( true );
223                                         }
224                                         if ( o.updatePagePadding ) {
225                                                 $( window ).unbind( "throttledresize." + self.widgetName );
226                                         }
227
228                                         if ( o.trackPersistentToolbars ) {
229                                                 var thisFooter = $( ".ui-footer-fixed:jqmData(id)", this ),
230                                                         thisHeader = $( ".ui-header-fixed:jqmData(id)", this ),
231                                                         nextFooter = thisFooter.length && ui.nextPage && $( ".ui-footer-fixed:jqmData(id='" + thisFooter.jqmData( "id" ) + "')", ui.nextPage ),
232                                                         nextHeader = thisHeader.length && ui.nextPage && $( ".ui-header-fixed:jqmData(id='" + thisHeader.jqmData( "id" ) + "')", ui.nextPage );
233
234                                                 nextFooter = nextFooter || $();
235
236                                                 if ( nextFooter.length || nextHeader.length ) {
237
238                                                         nextFooter.add( nextHeader ).appendTo( $.mobile.pageContainer );
239
240                                                         ui.nextPage.one( "pageshow", function () {
241                                                                 nextFooter.add( nextHeader ).appendTo( this );
242                                                         });
243                                                 }
244                                         }
245                                 });
246
247                         window.addEventListener( "softkeyboardchange", function ( e ) {
248                                 var thisPage = this;
249
250                                 if ( e.state == "on" ) {
251                                         $elCurrentFooter = $( ".ui-page-active .ui-footer" );
252                                         $elCurrentFooter.hide();
253                                 } else if (e.state == "off") {
254                                         $elCurrentFooter.show();
255                                 }
256                                 self.updatePagePadding( thisPage );
257                                 self.updatePageLayout( true, thisPage );
258                         });
259                 },
260
261                 _bindContentControlEvents: function () {
262                         var self = this,
263                                 o = self.options,
264                                 $el = self.element;
265
266                         $el.closest( ".ui-page" )
267                                 .bind( "pagebeforeshow", function ( event ) {
268
269                                 });
270                 },
271
272                 _setContentMinHeight : function ( thisPage ) {
273                         var $elPage = $( thisPage ),
274                                 $elHeader = $elPage.find( ":jqmData(role='header')" ),
275                                 $elFooter = $elPage.find( ":jqmData(role='footer')" ),
276                                 $elContent = $elPage.find( ":jqmData(role='content')" ),
277                                 resultMinHeight;
278
279                         resultMinHeight = window.innerHeight - $elHeader.height() - $elFooter.height();
280
281                         $elContent.css( "min-height", resultMinHeight - parseFloat( $elContent.css("padding-top") ) - parseFloat( $elContent.css("padding-bottom") ) + "px" );
282                 },
283
284                 _updateHeaderArea : function ( thisPage ) {
285                         var $elPage = $( thisPage ),
286                                 $elHeader = $elPage.find( ":jqmData(role='header')" ).length ? $elPage.find( ":jqmData(role='header')") : $elPage.siblings( ":jqmData(role='header')"),
287                                 headerBtnNum = $elHeader.children("a").length,
288                                 headerSrcNum = $elHeader.children("img").length;
289
290                         if ( !$elPage.is( ".ui-dialog" ) ) {
291                                 $elHeader.find( "h1" ).css( "width", window.innerWidth - $elHeader.children( "a" ).width() * headerBtnNum - $elHeader.children( "a" ).width() / 4 - $elHeader.children( "img" ).width() * headerSrcNum * 4 );
292                         }
293                         /* add half width for default space between text and button, and img tag area is too narrow, so multiply three for img width*/
294                 },
295
296                 _visible: true,
297
298                 // This will set the content element's top or bottom padding equal to the toolbar's height
299                 updatePagePadding: function ( tbPage ) {
300                         var $el = this.element,
301                                 header = $el.siblings( ".ui-header" ).length,
302                                 footer = $el.siblings( ".ui-footer" ).length;
303
304                         // This behavior only applies to "fixed", not "fullscreen"
305                         if ( this.options.fullscreen ) {
306                                 return;
307                         }
308
309                         tbPage = tbPage || $el.closest( ".ui-page" );
310
311                         if ( $el.siblings( ".ui-header" ).jqmData("position") == "fixed" || $.support.scrollview ) {
312                                 $( tbPage ).css( "padding-top", ( header ? $el.siblings( ".ui-header" ).outerHeight() : 0 ) );
313                         }
314                         $( tbPage ).css( "padding-bottom", ( footer ? $el.siblings( ".ui-footer" ).outerHeight() : 0 ) );
315                 },
316
317                 /* 1. Calculate and update content height   */
318                 updatePageLayout: function ( receiveType, thisPage ) {
319                         var $elFooter,
320                                 $elPage = $( thisPage ),
321                                 $elHeader = $elPage.find( ":jqmData(role='header')" ),
322                                 $elContent = $elPage.find( ":jqmData(role='content')" ),
323                                 resultContentHeight = 0,
324                                 resultFooterHeight = 0,
325                                 resultHeaderHeight = 0;
326
327                         if ( $elPage.length ) {
328                                 $elFooter = $elPage.find( ":jqmData(role='footer')" );
329                         } else {
330                                 $elFooter = $( document ).find( ":jqmData(role='footer')" ).eq( 0 );
331                         }
332
333                         // calculate footer height
334                         resultFooterHeight = ( $elFooter.css( "display" ) == "none" ) ? 0 : $elFooter.height();
335                         resultHeaderHeight = ( $elHeader.css( "display" ) == "none" ) ? 0 : $elHeader.height();
336
337                         if (resultFooterHeight != 0 ) {
338                                 $elFooter.css( "bottom", 0 );
339                         }
340
341                         resultContentHeight = window.innerHeight - resultFooterHeight - resultHeaderHeight;
342
343                         if ( $.support.scrollview ) {
344                                 $elContent.height( resultContentHeight -
345                                                 parseFloat( $elContent.css("padding-top") ) -
346                                                 parseFloat( $elContent.css("padding-bottom") ) );
347                         }
348
349                         // External call page( "refresh") - in case title changed
350                         if ( receiveType ) {
351                                 $elPage
352                                         .css( "min-height", resultContentHeight )
353                                         .css( "padding-top", resultHeaderHeight )
354                                         .css( "padding-bottom", resultFooterHeight );
355                         }
356                 },
357
358                 show: function ( notransition ) {
359                         /* blank function: deprecated */
360                 },
361
362                 hide: function ( notransition ) {
363                         /* blank function: deprecated */
364                 },
365
366                 toggle: function () {
367                         this[ this._visible ? "hide" : "show" ]();
368                 },
369
370                 destroy: function () {
371                         this.element.removeClass( "ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden" );
372                         this.element.closest( ".ui-page" ).removeClass( "ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen" );
373                 }
374         });
375
376         //auto self-init widgets
377         $( document )
378                 .bind( "pagecreate create", function ( e ) {
379                         // DEPRECATED in 1.1: support for data-fullscreen=true|false on the page element.
380                         // This line ensures it still works, but we recommend moving the attribute to the toolbars themselves.
381                         if ( $( e.target ).jqmData( "fullscreen" ) ) {
382                                 $( $.mobile.pagelayout.prototype.options.initSelector, e.target ).not( ":jqmData(fullscreen)" ).jqmData( "fullscreen", true );
383                         }
384                         $.mobile.pagelayout.prototype.enhanceWithin( e.target );
385                 });
386
387 }( jQuery ));