upload tizen1.0 source
[framework/web/web-ui-fw.git] / src / loader / loader.js
1 /**
2  * loader.js : Loader for web-ui-fw
3  * Refactored from bootstrap.js
4  *
5  * By Youmin Ha <youmin.ha@samsung.com>
6  *
7  */
8
9 ( function ($, Globalize, window, undefined) {
10
11         window.S = {
12                 libFileName : "tizen-web-ui-fw(.min)?.js",
13
14                 frameworkData : {
15                         rootDir: '/usr/lib/tizen-web-ui-fw',
16                         version: '0.1',
17                         theme: "default",
18                         viewportScale: false,
19                 },
20
21                 util : {
22                         loadScriptSync : function ( scriptPath, successCB, errorCB ) {
23                                 $.ajax( {
24                                         url: scriptPath,
25                                         dataType: 'script',
26                                         async: false,
27                                         success: successCB,
28                                         error: function ( jqXHR, textStatus, errorThrown ) {
29                                                 if ( errorCB ) {
30                                                         errorCB( jqXHR, textStatus, errorThrown );
31                                                 } else {
32                                                         var ignoreStatusList = [ 404 ];  // 404: not found
33                                                         if ( -1 == $.inArray( jqXHR.status, ignoreStatusList ) ) {
34                                                                 window.alert( 'Error while loading ' + scriptPath + '\n' + jqXHR.status + ':' + jqXHR.statusText );
35                                                         } else {
36                                                                 console.log( 'Error while loading ' + scriptPath + '\n' + jqXHR.status + ':' + jqXHR.statusText );
37                                                         }
38                                                 }
39                                         }
40                                 } );
41                         },
42                         getScaleFactor: function ( ) {
43                                 var factor = window.scale,
44                                         width = 0,
45                                         defaultWidth = 720;
46
47                                 if ( !factor ) {
48                                         width = screen.width < screen.height ? screen.width : screen.height;
49                                         factor = width / defaultWidth;
50                                         if ( factor > 1 ) {
51                                                 // NOTE: some targets(e.g iPad) need to set scale equal or less than 1.0
52                                                 factor = 1;
53                                         }
54                                 }
55                                 console.log( "ScaleFactor: " + factor );
56                                 return factor;
57                         },
58                         isMobileBrowser: function ( ) {
59                                 var mobileIdx = window.navigator.appVersion.indexOf("Mobile"),
60                                         isMobile = -1 < mobileIdx;
61                                 return isMobile;
62                         }
63                 },
64
65                 css : {
66                         cacheBust: ( document.location.href.match( /debug=true/ ) ) ?
67                                         '?cacheBust=' + ( new Date( ) ).getTime( ) :
68                                         '',
69                         addElementToHead : function ( elem ) {
70                                 var head = document.getElementsByTagName( 'head' )[0];
71                                 head.appendChild( elem );
72                         },
73                         load: function ( path ) {
74                                 this.addElementToHead( this.makeLink( path + this.cacheBust ) );
75                         },
76                         makeLink : function ( href ) {
77                                 var customstylesheetLink = document.createElement( 'link' );
78                                 customstylesheetLink.setAttribute( 'rel', 'stylesheet' );
79                                 customstylesheetLink.setAttribute( 'href', href );
80                                 return customstylesheetLink;
81                         }
82                 },
83
84                 getParams: function ( ) {
85                         /* Get data-* params from <script> tag, and set S.frameworkData.* values
86                          * Returns true if proper <script> tag is found, or false if not.
87                          */
88                         // Find current <script> tag element
89                         var scriptElems = document.getElementsByTagName( 'script' ),
90                                 val = null,
91                                 foundScriptTag = false,
92                                 idx,
93                                 elem,
94                                 src,
95                                 tokens,
96                                 version_idx;
97                         for ( idx in scriptElems ) {
98                                 elem = scriptElems[idx];
99                                 src = elem.src ? elem.getAttribute( 'src' ) : undefined;
100                                 if (src && src.match( this.libFileName )) {
101                                         // Set framework data, only when they are given.
102                                         tokens = src.split(/[\/\\]/);
103                                         version_idx = -3;
104                                         this.frameworkData.rootDir = elem.getAttribute( 'data-framework-root' )
105                                                 || tokens.slice( 0, tokens.length + version_idx ).join( '/' )
106                                                 || this.frameworkData.rootDir;
107                                         this.frameworkData.version = elem.getAttribute( 'data-framework-version' )
108                                                 || tokens[ tokens.length + version_idx ]
109                                                 || this.frameworkData.version;
110                                         this.frameworkData.theme = elem.getAttribute( 'data-framework-theme' )
111                                                 || this.frameworkData.theme;
112                                         this.frameworkData.viewportScale = "true" === elem.getAttribute( 'data-framework-viewport-scale' ) ? true : this.frameworkData.viewportScale;
113                                         foundScriptTag = true;
114                                         break;
115                                 }
116                         }
117                         return foundScriptTag;
118                 },
119
120                 loadTheme: function ( ) {
121                         var themePath = [
122                                         this.frameworkData.rootDir,
123                                         this.frameworkData.version,
124                                         'themes',
125                                         this.frameworkData.theme
126                                 ].join( '/' ),
127                                 cssPath = [themePath, 'tizen-web-ui-fw-theme.css'].join( '/' ),
128                                 jsPath = [themePath, 'theme.js'].join( '/' );
129
130                         this.css.load( cssPath );
131                         this.util.loadScriptSync( jsPath );
132                 },
133
134                 /** Load Globalize culture file, and set default culture.
135                  *  @param[in]  language  Language code. ex) en-US, en, ko-KR, ko
136                  *                        If language is not given, read language from html 'lang' attribute, or from system setting.
137                  */
138                 loadGlobalizeCulture: function ( language ) {
139                         function getGlobalizeCultureFile( lang ) {
140                                 return ['globalize.culture.', lang, '.js'].join( '' );
141                         }
142                         function getGlobalizeCulturePath( self, file ) {
143                                 return [
144                                         self.frameworkData.rootDir,
145                                         self.frameworkData.version,
146                                         'js',
147                                         'cultures',
148                                         file,
149                                 ].join( '/' );
150                         }
151
152                         // Get lang, and change country code to uppercase chars.
153                         var self = this,
154                                 lang = language
155                                         || $( 'html' ).attr( 'lang' )
156                                         || window.navigator.language.split( '.' )[0]    /* Webkit, Safari + workaround for Tizen */
157                                         || window.navigator.userLanguage        /* IE */
158                                         || 'en',
159                                 countryCode = null,
160                                 countryCodeIdx = lang.lastIndexOf('-'),
161                                 ignoreCodes = ['Cyrl', 'Latn', 'Mong'], // Not country code!
162                                 globalizeCultureFile,
163                                 globalizeCulturePath,
164                                 neutralLangIndex;
165
166                         if ( countryCodeIdx != -1 ) {   // Found country code!
167                                 countryCode = lang.substr( countryCodeIdx + 1 );
168                                 if ( ignoreCodes.join( '-' ).indexOf( countryCode ) < 0 ) { // countryCode is not found from ignoreCodes
169                                         // Make countryCode to uppercase
170                                         lang = [ lang.substr( 0, countryCodeIdx ), countryCode.toUpperCase( ) ].join( '-' );
171                                 }
172                         }
173
174                         globalizeCultureFile = getGlobalizeCultureFile( lang );
175                         globalizeCulturePath = getGlobalizeCulturePath( self, globalizeCultureFile );
176                         neutralLangIndex = lang.lastIndexOf( '-' );
177
178                         // Run culture script
179                         console.log( 'Run globalize culture: ' + globalizeCulturePath );
180                         this.util.loadScriptSync(
181                                 globalizeCulturePath,
182                                 null,
183                                 function ( jqXHR, textStatus, errorThrown ) {   // Failed to load!
184                                         if ( jqXHR.status == 404 ) {
185                                                 // If culture file is not found, run neutral language culture. 
186                                                 // (e.g. en-US --> en)
187                                                 if ( neutralLangIndex != -1 ) {
188                                                         var neutralLang = lang.substr( 0, neutralLangIndex ),
189                                                                 neutralCultureFile = getGlobalizeCultureFile( neutralLang ),
190                                                                 neutralCulturePath = getGlobalizeCulturePath( self, neutralCultureFile );
191                                                         console.log( 'Run globalize culture of neutral lang: ' + neutralCulturePath );
192                                                         self.util.loadScriptSync( neutralCulturePath );
193                                                 }
194                                         } else {
195                                                 window.alert( 'Error while loading ' + globalizeCulturePath + '\n' + jqXHR.status + ':' + jqXHR.statusText );
196                                         }
197                                 }
198                         );
199                         return lang;
200                 },
201                 setGlobalize: function ( ) {
202                         var lang = this.loadGlobalizeCulture( );
203
204                         // Set culture
205                         // NOTE: It is not needed to set with neutral lang. 
206                         //       Globalize automatically deals with it.
207                         Globalize.culture( lang );
208                 },
209
210                 /** Set viewport meta tag for mobile devices.
211                  *
212                  * @param[in]   viewportWidth   Viewport width. 'device-dpi' is also allowed.
213                  * @param[in]   useAutoScale    If true, calculate & use scale factor. otherwise, scale factor is 1.
214                  * @param[in]   useDeviceDpi    If true, add 'target-densityDpi=device-dpi' to viewport meta content.
215                  */
216                 setViewport: function ( viewportWidth, useAutoScale, useDeviceDpi ) {
217                         var meta,
218                                 scale = 1,
219                                 head;
220                         // Do nothing if viewport setting code is already in the code.
221                         $( "meta" ).each( function ( ) {
222                                 if ( $( this ).attr( "name" ) === "viewport" ) {
223                                         console.log( "User set viewport... framework viewport will not be applied." );
224                                         meta = this;
225                                         return;
226                                 }
227                         });
228
229                         // Set meta tag
230                         meta = document.createElement( "meta" );
231                         if ( meta ) {
232                                 scale = useAutoScale ? this.util.getScaleFactor( ) : scale;
233                                 meta.name = "viewport";
234                                 meta.content = "width=" + viewportWidth + ", initial-scale=" + scale + ", maximum-scale=" + scale + ", user-scalable=0";
235                                 if ( useDeviceDpi ) {
236                                         meta.content += ", target-densityDpi=device-dpi";
237                                 }
238                                 console.log( meta.content );
239                                 head = document.getElementsByTagName( 'head' ).item( 0 );
240                                 head.insertBefore( meta, head.firstChild );
241                         }
242                 },
243
244                 /**     Read body's font-size, scale it, and reset it.
245                  *  param[in]   desired font-size / base font-size.
246                  */
247                 scaleBaseFontSize: function ( themeDefaultFontSize, ratio ) {
248                         var scaledFontSize = Math.round( themeDefaultFontSize * ratio );
249                         $( '.ui-mobile' ).css( { 'font-size': scaledFontSize + "px" } );
250                         $( '.ui-mobile').children( 'body' ).css( { 'font-size': scaledFontSize + "px" } );
251                 },
252
253                 setScaling: function ( ) {
254                         var baseWidth = 720,            // NOTE: need to be changed to get the value from theme.
255                                 standardWidth = 360,
256                                 themeDefaultFontSize = parseInt( $( 'body' ).css( 'font-size' ), 10 );
257                         $( 'body' ).attr( 'data-tizen-theme-default-font-size', themeDefaultFontSize );
258
259                         if ( this.frameworkData.viewportScale ) {
260                                 // Use viewport scaling with base font-size
261                                 // NOTE: No font-size setting is needed.
262                                 this.setViewport( baseWidth, true, true );
263                         } else {
264                                 // Fixed viewport scale(=1.0) with scaled font size
265                                 this.setViewport( "device-dpi", false, undefined );
266                                 this.scaleBaseFontSize( themeDefaultFontSize, parseFloat( standardWidth / baseWidth ) );
267                         }
268                 }
269         };
270 } ( jQuery, window.Globalize, window ) );
271
272
273 // Loader's job list
274 ( function ( S, $, undefined ) {
275         S.getParams( );
276         S.loadTheme( );
277         S.setGlobalize( );
278
279         // Turn off JQM's auto initialization option.
280         // NOTE: This job must be done before domready.
281         $.mobile.autoInitializePage = false;
282
283         $(document).ready( function ( ) {
284                 S.setScaling( );
285                 $.mobile.initializePage( );
286         });
287 } ( window.S, jQuery ) );