1 // ==========================================================================
  2 // Project:   The M-Project - Mobile HTML5 Application Framework
  3 // Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved.
  4 //            (c) 2011 panacoda GmbH. All rights reserved.
  5 // Creator:   Sebastian
  6 // Date:      22.11.2010
  7 // License:   Dual licensed under the MIT or GPL Version 2 licenses.
  8 //            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
  9 //            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
 10 // ==========================================================================
 11 
 12 m_require('core/foundation/object.js');
 13 
 14 /**
 15  * A constant value for being offline.
 16  *
 17  * @type String
 18  */
 19 M.OFFLINE = 'offline';
 20 
 21 /**
 22  * A constant value for being online.
 23  *
 24  * @type String
 25  */
 26 M.ONLINE = 'online';
 27 
 28 /**
 29  * A constant value for portrait orientation mode.
 30  *
 31  * @type String
 32  */
 33 M.PORTRAIT_TOP = 0;
 34 
 35 /**
 36  * A constant value for inverse portrait orientation mode.
 37  *
 38  * @type String
 39  */
 40 M.PORTRAIT_BOTTOM = 180;
 41 
 42 /**
 43  * A constant value for landscape right orientation mode.
 44  *
 45  * @type String
 46  */
 47 M.LANDSCAPE_RIGHT = -90;
 48 
 49 /**
 50  * A constant value for landscape left orientation mode.
 51  *
 52  * @type String
 53  */
 54 M.LANDSCAPE_LEFT = 90;
 55 
 56 /**
 57  * @class
 58  *
 59  * M.Environment encapsulates methods to retrieve information about the
 60  * environment, like browser used, platform, user agent (based on navigator
 61  * object) or whether or not the device is online (determined via an ajax
 62  * request).
 63  *
 64  * @extends M.Object
 65  */
 66 M.Environment = M.Object.extend(
 67 /** @scope M.Environment.prototype */ {
 68 
 69     /**
 70      * The type of this object.
 71      *
 72      * @type String
 73      */
 74     type: 'M.Environment',
 75 
 76     /**
 77      * This property contains a custom configuration of the awesome modernizr
 78      * library We currently only use this for detecting supported input types
 79      * of the browser.
 80      *
 81      * @private
 82      * @type Object
 83      */
 84     modernizr: function(a,b,c){function y(){e.inputtypes=function(a){for(var d=0,e,g,h,i=a.length;d<i;d++)k.setAttribute("type",g=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(g)&&k.style.WebkitAppearance!==c?(f.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,f.removeChild(k)):/^(search|tel)$/.test(g)||(/^(url|email)$/.test(g)?e=k.checkValidity&&k.checkValidity()===!1:/^color$/.test(g)?(f.appendChild(k),f.offsetWidth,e=k.value!=l,f.removeChild(k)):e=k.value!=l)),o[a[d]]=!!e;return o}("search tel url email datetime date month week time datetime-local number range color".split(" "))}function x(a,b){return!!~(""+a).indexOf(b)}function w(a,b){return typeof a===b}function v(a,b){return u(prefixes.join(a+";")+(b||""))}function u(a){j.cssText=a}var d="2.0.6",e={},f=b.documentElement,g=b.head||b.getElementsByTagName("head")[0],h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m=Object.prototype.toString,n={},o={},p={},q=[],r,s={}.hasOwnProperty,t;!w(s,c)&&!w(s.call,c)?t=function(a,b){return s.call(a,b)}:t=function(a,b){return b in a&&w(a.constructor.prototype[b],c)};for(var z in n)t(n,z)&&(r=z.toLowerCase(),e[r]=n[z](),q.push((e[r]?"":"no-")+r));e.input||y(),u(""),i=k=null,e._version=d;return e}(this,this.document),
 85 
 86     /**
 87      * Checks the connection status by sending an ajax request
 88      * and waiting for the response to decide whether online or offline.
 89      *
 90      * The callback is called when the request returns successful or times out. The parameter to callback is a
 91      * string saying either offline or online.
 92      *
 93      * @param {Object} callback The object, consisting of target and action, defining the callback.
 94      * @param {String} url Optional. The request url. When not given, a request is made to http://www.google.de/images/logos/ps_logo2.png.
 95      */
 96     getConnectionStatus: function(callback, url){
 97         url = url ? url : 'http://www.google.de/images/logos/ps_logo2.png';
 98         var that = this;
 99         var image = M.ImageView.design({
100             value: url,
101             events: {
102                 load: {
103                     action: function(id) {
104                         var image = M.ViewManager.getViewById(id);
105                         image.destroy();
106                         if(callback && M.EventDispatcher.checkHandler(callback, 'online')){
107                             that.bindToCaller(callback.target, callback.action, M.ONLINE)();
108                         }
109                     }
110                 },
111                 error: {
112                     action: function(id) {
113                         var image = M.ViewManager.getViewById(id);
114                         image.destroy();
115                         if(callback && M.EventDispatcher.checkHandler(callback, 'offline')){
116                             that.bindToCaller(callback.target, callback.action, M.OFFLINE)();
117                         }
118                     }
119                 }
120             }
121         });
122         $('body').append(image.render());
123         image.registerEvents();
124     },
125 
126     /**
127      * Returns the userAgent as received from navigator object.
128      * E.g. "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7"
129      *
130      * @returns {String} The user agent.
131      */
132     getUserAgent: function() {
133         return navigator.userAgent;
134     },
135 
136     /**
137      * Returns the platform as received from navigator object.
138      * E.g. "MacIntel"
139      *
140      * @returns {String} The user's platform.
141      */
142     getPlatform: function() {
143         return navigator.platform;
144     },
145 
146     /**
147      * Returns the currently available width and height of the browser window
148      * as an array:
149      *
150      * 0 -> width
151      * 1 -> height
152      *
153      * @returns {Array} The width and height of the user's browser window.
154      */
155     getSize: function() {
156         var viewportWidth;
157         var viewportHeight;
158 
159         if(typeof window.innerWidth != 'undefined') {
160             viewportWidth = window.innerWidth,
161             viewportHeight = window.innerHeight
162         } else if(typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0) {
163             viewportWidth = document.documentElement.clientWidth,
164             viewportHeight = document.documentElement.clientHeight
165         } else {
166             viewportWidth = document.getElementsByTagName('body')[0].clientWidth,
167             viewportHeight = document.getElementsByTagName('body')[0].clientHeight
168         }
169 
170         return [viewportWidth, viewportHeight];
171     },
172 
173     /**
174      * Returns the currently available width of the browser window.
175      *
176      * @returns {Number} The width of the user's browser window.
177      */
178     getWidth: function() {
179         return this.getSize()[0];
180     },
181 
182     /**
183      * Returns the currently available height of the browser window.
184      *
185      * @returns {Number} The height of the user's browser window.
186      */
187     getHeight: function() {
188         return this.getSize()[1];
189     },
190 
191     /**
192      * Returns the total size of the page/document, means not only the area of the browser window.
193      *
194      * 0 -> width
195      * 1 -> height
196      *
197      * @returns {Array} The width and height of the document.
198      */
199     getTotalSize: function() {
200         return [this.getTotalWidth(), this.getTotalHeight()];
201     },
202 
203     /**
204      * Returns the total width of the page/document, means not only the area of the browser window.
205      * Uses jQuery.
206      *
207      * @returns {Number} The total width of the document.
208      */
209     getTotalWidth: function() {
210         return $(document).width();
211     },
212 
213     /**
214      * Returns the total height of the page/document, means not only the area of the browser window.
215      * Uses jQuery.
216      *
217      * @returns {Number} The total height of the document.
218      */
219     getTotalHeight: function() {
220         return $(document).height();
221     },
222 
223     /**
224      * This method returns the device's current orientation, depending on whether
225      * or not the device is capable of detecting the current orientation. If the
226      * device is unable to detect the current orientation, this method will return
227      * NO.
228      *
229      * Possible return values are:
230      *
231      *   - M.PORTRAIT
232      *   - M.LANDSCAPE_LEFT
233      *   - M.LANDSCAPE_RIGHT
234      *
235      * @return {Number|Boolean} The orientation type as a constant value. (If the orientation can not be detected: NO.)
236      */
237     getOrientation: function() {
238         switch(window.orientation) {
239             case 0:
240                 return M.PORTRAIT_TOP;
241             case false:
242                 return M.PORTRAIT_BOTTOM;
243             case 90:
244                 return M.LANDSCAPE_LEFT;
245             case -90:
246                 return M.LANDSCAPE_RIGHT;
247             default:
248                 M.Logger.log('This device does not support orientation detection.', M.WARN);
249                 return NO;
250         }
251     },
252 
253     /**
254      * This method checks if the browser supports a certain input type specified with
255      * HTML5. This check is based on Modernizr. For further information abbout the
256      * input types, take a look at the W3C spec:
257      * http://dev.w3.org/html5/spec/Overview.html#states-of-the-type-attribute
258      *
259      * @param {String} inputTye The HTML5 input type to be checked.
260      * @return {Boolean} A flag telling you if the input type is supported or not.
261      */
262     supportsInputType: function(inputType) {
263         if(this.modernizr.inputtypes && this.modernizr.inputtypes[inputType] === YES) {
264             return YES;
265         }
266         return NO;
267     }
268 
269 });