1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * Information about the browser and run-time environment. 26 * @class 27 */ 28 AjxEnv = function() { 29 }; 30 31 // 32 // Constants 33 // 34 35 /** User locale. */ 36 AjxEnv.DEFAULT_LOCALE = window.navigator.userLanguage || window.navigator.language || window.navigator.systemLanguage; 37 38 // 39 // Data 40 // 41 42 AjxEnv._inited = false; 43 44 // NOTE: These are here so that the documentation tool can pick them up 45 46 /** Gecko date. */ 47 AjxEnv.geckoDate; 48 /** Mozilla version. */ 49 AjxEnv.mozVersion; 50 /** WebKit version. */ 51 AjxEnv.webKitVersion; 52 /** Trident version. */ 53 AjxEnv.tridentVersion; 54 /** Macintosh. */ 55 AjxEnv.isMac; 56 /** Windows. */ 57 AjxEnv.isWindows; 58 /** Windows 64-bit. */ 59 AjxEnv.isWindows64; 60 /** Linux. */ 61 AjxEnv.isLinux; 62 /** Netscape Navigator compatible. */ 63 AjxEnv.isNav; 64 /** Netscape Navigator version 4. */ 65 AjxEnv.isNav4; 66 /** "legacy" Internet Explorer -- i.e. version 10 and earlier */ 67 AjxEnv.isIE; 68 /** "modern" Internet Explorer -- i.e. version 11 and Edge */ 69 AjxEnv.isModernIE; 70 71 72 AjxEnv.trueNs; 73 74 75 /** Netscape Navigator version 6. */ 76 AjxEnv.isNav6; 77 /** Netscape Navigator version 6 (or higher). */ 78 AjxEnv.isNav6up; 79 /** Netscape Navigator version 7. */ 80 AjxEnv.isNav7; 81 /** Internet Explorer version 3. */ 82 AjxEnv.isIE3; 83 /** Internet Explorer version 4. */ 84 AjxEnv.isIE4; 85 /** Internet Explorer version 4 (or higher). */ 86 AjxEnv.isIE4up; 87 /** Internet Explorer version 5. */ 88 AjxEnv.isIE5; 89 /** Internet Explorer version 5.5. */ 90 AjxEnv.isIE5_5; 91 /** Internet Explorer version 5 (or higher). */ 92 AjxEnv.isIE5up; 93 /** Internet Explorer version 5.5 (or higher). */ 94 AjxEnv.isIE5_5up; 95 /** Internet Explorer version 6. */ 96 AjxEnv.isIE6; 97 /** Internet Explorer version 6 (or higher). */ 98 AjxEnv.isIE6up; 99 /** Internet Explorer version 7. */ 100 AjxEnv.isIE7; 101 /** Internet Explorer version 7 (or higher). */ 102 AjxEnv.isIE7up; 103 /** Internet Explorer version 8. */ 104 AjxEnv.isIE8; 105 /** Internet Explorer version 8 (or higher). */ 106 AjxEnv.isIE8up; 107 /** Internet Explorer version 9. */ 108 AjxEnv.isIE9; 109 /** Internet Explorer version 9 (or higher). */ 110 AjxEnv.isIE9up; 111 /** Internet Explorer version 10. */ 112 AjxEnv.isIE10; 113 114 AjxEnv.isNormalResolution; 115 AjxEnv.ieScaleFactor; 116 117 118 /** Mozilla Firefox. */ 119 AjxEnv.isFirefox; 120 /** Mozilla Firefox version 1 (or higher). */ 121 AjxEnv.isFirefox1up; 122 /** Mozilla Firefox version 1.5 (or higher). */ 123 AjxEnv.isFirefox1_5up; 124 /** Mozilla Firefox version 3 (or higher). */ 125 AjxEnv.isFirefox3up; 126 /** Mozilla Firefox version 3.6 (or higher). */ 127 AjxEnv.isFirefox3_6up; 128 /** Mozilla Firefox version 4 (or higher). */ 129 AjxEnv.isFirefox4up; 130 /** Mozilla. */ 131 AjxEnv.isMozilla; 132 /** Mozilla version 1.4 (or higher). */ 133 AjxEnv.isMozilla1_4up; 134 /** Safari. */ 135 AjxEnv.isSafari; 136 /** Safari version 2. */ 137 AjxEnv.isSafari2; 138 /** Safari version 3. */ 139 AjxEnv.isSafari3; 140 /** Safari version 3 (or higher). */ 141 AjxEnv.isSafari3up; 142 /** Safari version 4. */ 143 AjxEnv.isSafari4; 144 /** Safari version 4 (or higher). */ 145 AjxEnv.isSafari4up; 146 /** Safari version 5 (or higher). */ 147 AjxEnv.isSafari5up; 148 /** Safari version 5.1 (or higher). */ 149 AjxEnv.isSafari5_1up; 150 /** Camino. */ 151 AjxEnv.isCamino; 152 /** Chrome. */ 153 AjxEnv.isChrome; 154 AjxEnv.isChrome2up; 155 AjxEnv.isChrome7; 156 AjxEnv.isChrome10up; 157 /** Gecko-based. */ 158 AjxEnv.isGeckoBased; 159 /** WebKit-based. */ 160 AjxEnv.isWebKitBased; 161 /** Trident, i.e. the MSIE rendering engine */ 162 AjxEnv.isTrident; 163 /** Opera. */ 164 AjxEnv.isOpera; 165 166 167 AjxEnv.useTransparentPNGs; 168 169 170 /** Zimbra Desktop. */ 171 AjxEnv.isDesktop; 172 /** Zimbra Desktop version 2 (or higher). */ 173 AjxEnv.isDesktop2up; 174 /** Screen size is less then 800x600. */ 175 AjxEnv.is800x600orLower; 176 /** Screen size is less then 1024x768. */ 177 AjxEnv.is1024x768orLower; 178 179 /** HTML5 Support **/ 180 AjxEnv.supportsHTML5File; 181 182 AjxEnv.supported = Modernizr; 183 184 // Test for HTML's New Template Tag support 185 AjxEnv.supported.addTest('template', function() { 186 return 'content' in document.createElement('template'); 187 }); 188 189 /** Supports indirect global eval() **/ 190 AjxEnv.indirectEvalIsGlobal; 191 (function(){ 192 // Feature detection to see if eval referenced by alias runs in global scope 193 // See davidflanagan.com/2010/12/global-eval-in.html 194 AjxEnv.indirectEvalIsGlobal=false; 195 var evl=window.eval; 196 try{ 197 evl('__indirectEval=true'); 198 if('__indirectEval' in window){ 199 AjxEnv.indirectEvalIsGlobal=true; 200 delete __indirectEval; 201 } 202 }catch(e){} 203 })(); 204 205 // 206 // Public functions 207 // 208 209 AjxEnv.reset = 210 function() { 211 AjxEnv.geckoDate = 0; 212 AjxEnv.mozVersion = -1; 213 AjxEnv.webKitVersion = -1; 214 AjxEnv.isMac = false; 215 AjxEnv.isWindows = false; 216 AjxEnv.isWindows64 = false; 217 AjxEnv.isLinux = false; 218 AjxEnv.isNav = false; 219 AjxEnv.isIE = false; 220 AjxEnv.isNav4 = false; 221 AjxEnv.trueNs = true; 222 AjxEnv.isNav6 = false; 223 AjxEnv.isNav6up = false; 224 AjxEnv.isNav7 = false; 225 AjxEnv.isIE3 = false; 226 AjxEnv.isIE4 = false; 227 AjxEnv.isIE4up = false; 228 AjxEnv.isIE5 = false; 229 AjxEnv.isIE5_5 = false; 230 AjxEnv.isIE5up = false; 231 AjxEnv.isIE5_5up = false; 232 AjxEnv.isIE6 = false; 233 AjxEnv.isIE6up = false; 234 AjxEnv.isIE7 = false; 235 AjxEnv.isIE7up = false; 236 AjxEnv.isIE8 = false; 237 AjxEnv.isIE8up = false; 238 AjxEnv.isIE9 = false; 239 AjxEnv.isIE9up = false; 240 AjxEnv.isIE10 = false; 241 AjxEnv.isModernIE = false; 242 AjxEnv.isMSEdge = false; 243 AjxEnv.isNormalResolution = false; 244 AjxEnv.ieScaleFactor = 1; 245 AjxEnv.isFirefox = false; 246 AjxEnv.isFirefox1up = false; 247 AjxEnv.isFirefox1_5up = false; 248 AjxEnv.isFirefox3up = false; 249 AjxEnv.isFirefox3_6up = false; 250 AjxEnv.isFirefox4up = false; 251 AjxEnv.isMozilla = false; 252 AjxEnv.isMozilla1_4up = false; 253 AjxEnv.isSafari = false; 254 AjxEnv.isSafari2 = false; 255 AjxEnv.isSafari3 = false; 256 AjxEnv.isSafari4 = false; 257 AjxEnv.isSafari3up = false; 258 AjxEnv.isSafari4up = false; 259 AjxEnv.isSafari5up = false; 260 AjxEnv.isSafari5_1up = false; 261 AjxEnv.isSafari6up = false; 262 AjxEnv.isCamino = false; 263 AjxEnv.isChrome = false; 264 AjxEnv.isChrome2up = false; 265 AjxEnv.isChrome7 = false; 266 AjxEnv.isChrome10up = false; 267 AjxEnv.isChrome19up = false; 268 AjxEnv.isGeckoBased = false; 269 AjxEnv.isWebKitBased = false; 270 AjxEnv.isTrident = false; 271 AjxEnv.isOpera = false; 272 AjxEnv.useTransparentPNGs = false; 273 AjxEnv.isDesktop = false; 274 AjxEnv.isDesktop2up = false; 275 276 //HTML5 277 AjxEnv.supportsHTML5File = false; 278 AjxEnv.supportsPlaceholder = false; 279 AjxEnv.supportsCSS3RemUnits = false; 280 281 // screen resolution - ADD MORE RESOLUTION CHECKS AS NEEDED HERE: 282 AjxEnv.is800x600orLower = screen && (screen.width <= 800 && screen.height <= 600); 283 AjxEnv.is1024x768orLower = screen && (screen.width <= 1024 && screen.height <= 768); 284 }; 285 286 AjxEnv.parseUA = 287 function() { 288 AjxEnv.reset(); 289 290 var agt = navigator.userAgent.toLowerCase(); 291 var agtArr = agt.split(" "); 292 var isSpoofer = false; 293 var isWebTv = false; 294 var isHotJava = false; 295 var beginsWithMozilla = false; 296 var isCompatible = false; 297 var isTrident = false; 298 299 if (agtArr != null) { 300 var browserVersion; 301 var index = -1; 302 303 if ((index = agtArr[0].search(/^\s*mozilla\//))!= -1) { 304 beginsWithMozilla = true; 305 AjxEnv.browserVersion = parseFloat(agtArr[0].substring(index + 8)); 306 AjxEnv.isNav = true; 307 } 308 309 var token; 310 for (var i = 0; i < agtArr.length; ++i) { 311 token = agtArr[i]; 312 if (token.indexOf('compatible') != -1 ) { 313 isCompatible = true; 314 AjxEnv.isNav = false; 315 } else if ((token.indexOf('opera')) != -1) { 316 AjxEnv.isOpera = true; 317 AjxEnv.isNav = false; 318 browserVersion = parseFloat(agtArr[i+1]); 319 } else if ((token.indexOf('spoofer')) != -1) { 320 isSpoofer = true; 321 AjxEnv.isNav = false; 322 } else if ((token.indexOf('webtv')) != -1) { 323 isWebTv = true; 324 AjxEnv.isNav = false; 325 } else if ((token.indexOf('hotjava')) != -1) { 326 isHotJava = true; 327 AjxEnv.isNav = false; 328 } else if ((index = token.indexOf('msie')) != -1) { 329 AjxEnv.isIE = true; 330 browserVersion = parseFloat(agtArr[i+1]); 331 } else if ((index = token.indexOf('trident/')) != -1) { 332 AjxEnv.isTrident = true; 333 AjxEnv.tridentVersion = parseFloat(token.substr(index + 8)); 334 } else if ((index = token.indexOf('edge/')) != -1) { 335 AjxEnv.isMSEdge = true; 336 browserVersion = parseFloat(token.substr(index + 5)); 337 AjxEnv.isSafari = false; 338 AjxEnv.isChrome = false; 339 AjxEnv.isWebKitBased = false; 340 } else if ((index = token.indexOf('gecko/')) != -1) { 341 AjxEnv.isGeckoBased = true; 342 AjxEnv.geckoDate = parseFloat(token.substr(index + 6)); 343 } else if ((index = token.indexOf('applewebkit/')) != -1) { 344 AjxEnv.isWebKitBased = true; 345 AjxEnv.webKitVersion = parseFloat(token.substr(index + 12)); 346 } else if ((index = token.indexOf('rv:')) != -1) { 347 AjxEnv.mozVersion = parseFloat(token.substr(index + 3)); 348 browserVersion = AjxEnv.mozVersion; 349 } else if ((index = token.indexOf('firefox/')) != -1) { 350 AjxEnv.isFirefox = true; 351 browserVersion = parseFloat(token.substr(index + 8)); 352 } else if ((index = token.indexOf('prism')) != -1) { 353 AjxEnv.isPrism = true; 354 } else if ((index = token.indexOf('camino/')) != -1) { 355 AjxEnv.isCamino = true; 356 browserVersion = parseFloat(token.substr(index + 7)); 357 } else if ((index = token.indexOf('netscape6/')) != -1) { 358 AjxEnv.trueNs = true; 359 browserVersion = parseFloat(token.substr(index + 10)); 360 } else if ((index = token.indexOf('netscape/')) != -1) { 361 AjxEnv.trueNs = true; 362 browserVersion = parseFloat(token.substr(index + 9)); 363 } else if ((index = token.indexOf('safari/')) != -1) { 364 AjxEnv.isSafari = true; 365 } else if ((index = token.indexOf('chrome/')) != -1) { 366 AjxEnv.isChrome = true; 367 browserVersion = parseFloat(token.substr(index + 7)); 368 } else if (index = token.indexOf('version/') != -1) { 369 // this is how safari sets browser version 370 browserVersion = parseFloat(token.substr(index + 7)); 371 } else if (token.indexOf('windows') != -1) { 372 AjxEnv.isWindows = true; 373 } else if (token.indexOf('win64') != -1) { 374 AjxEnv.isWindows64 = true; 375 } else if ((token.indexOf('macintosh') != -1) || 376 (token.indexOf('mac_') != -1)) { 377 AjxEnv.isMac = true; 378 } else if (token.indexOf('linux') != -1) { 379 AjxEnv.isLinux = true; 380 } else if ((index = token.indexOf('zdesktop/')) != -1) { 381 AjxEnv.isDesktop = true; 382 browserVersion = parseFloat(token.substr(index + 9)); 383 } 384 } 385 AjxEnv.browserVersion = browserVersion; 386 387 // Note: Opera and WebTV spoof Navigator. We do strict client detection. 388 AjxEnv.isNav = (beginsWithMozilla && !isSpoofer && !isCompatible && !AjxEnv.isOpera && !isWebTv && !isHotJava && !AjxEnv.isSafari); 389 AjxEnv.isIE = (AjxEnv.isIE && !AjxEnv.isOpera); 390 AjxEnv.isNav4 = (AjxEnv.isNav && (browserVersion == 4) && (!AjxEnv.isIE)); 391 AjxEnv.isNav6 = (AjxEnv.isNav && AjxEnv.trueNs && (browserVersion >= 6.0 && browserVersion < 7.0)); 392 AjxEnv.isNav6up = (AjxEnv.isNav && AjxEnv.trueNs && (browserVersion >= 6.0)); 393 AjxEnv.isNav7 = (AjxEnv.isNav && AjxEnv.trueNs && (browserVersion >= 7.0 && browserVersion < 8.0)); 394 AjxEnv.isIE3 = (AjxEnv.isIE && browserVersion < 4.0); 395 AjxEnv.isIE4 = (AjxEnv.isIE && browserVersion >= 4.0 && browserVersion < 5.0); 396 AjxEnv.isIE4up = (AjxEnv.isIE && browserVersion >= 4.0); 397 AjxEnv.isIE5 = (AjxEnv.isIE && browserVersion >= 5.0 && browserVersion < 6.0); 398 AjxEnv.isIE5_5 = (AjxEnv.isIE && browserVersion == 5.5); 399 AjxEnv.isIE5up = (AjxEnv.isIE && browserVersion >= 5.0); 400 AjxEnv.isIE5_5up = (AjxEnv.isIE && browserVersion >= 5.5); 401 AjxEnv.isIE6 = (AjxEnv.isIE && browserVersion >= 6.0 && browserVersion < 7.0); 402 AjxEnv.isIE6up = (AjxEnv.isIE && browserVersion >= 6.0); 403 AjxEnv.isIE7 = (AjxEnv.isIE && browserVersion >= 7.0 && browserVersion < 8.0); 404 AjxEnv.isIE7up = (AjxEnv.isIE && browserVersion >= 7.0); 405 AjxEnv.isIE8 = (AjxEnv.isIE && browserVersion >= 8.0 && browserVersion < 9.0); 406 AjxEnv.isIE8up = (AjxEnv.isIE && browserVersion >= 8.0); 407 AjxEnv.isIE9 = (AjxEnv.isIE && browserVersion >= 9.0 && browserVersion < 10.0); 408 AjxEnv.isIE9up = (AjxEnv.isIE && browserVersion >= 9.0); 409 AjxEnv.isIE10 = (AjxEnv.isIE && browserVersion >= 10.0 && browserVersion < 11.0); 410 // IE11 411 AjxEnv.isModernIE = (!AjxEnv.isIE && AjxEnv.mozVersion >= 11.0 && AjxEnv.tridentVersion >= 7.0); 412 // IE12 413 AjxEnv.isModernIE = AjxEnv.isModernIE || (!AjxEnv.isIE && AjxEnv.isMSEdge && browserVersion >= 12.0); 414 if (AjxEnv.isModernIE) { 415 AjxEnv.isSafari = false; 416 AjxEnv.isChrome = false; 417 AjxEnv.isIE12 = (browserVersion >= 12.0); 418 } 419 420 421 AjxEnv.isMozilla = ((AjxEnv.isNav && AjxEnv.mozVersion && AjxEnv.isGeckoBased && (AjxEnv.geckoDate != 0))); 422 AjxEnv.isMozilla1_4up = (AjxEnv.isMozilla && (AjxEnv.mozVersion >= 1.4)); 423 AjxEnv.isFirefox = ((AjxEnv.isMozilla && AjxEnv.isFirefox)); 424 AjxEnv.isFirefox1up = (AjxEnv.isFirefox && browserVersion >= 1.0); 425 AjxEnv.isFirefox1_5up = (AjxEnv.isFirefox && browserVersion >= 1.5); 426 AjxEnv.isFirefox2_0up = (AjxEnv.isFirefox && browserVersion >= 2.0); 427 AjxEnv.isFirefox3up = (AjxEnv.isFirefox && browserVersion >= 3.0); 428 AjxEnv.isFirefox3_5up = (AjxEnv.isFirefox && browserVersion >= 3.5); 429 AjxEnv.isFirefox3_6up = (AjxEnv.isFirefox && browserVersion >= 3.6); 430 AjxEnv.isFirefox4up = (AjxEnv.isFirefox && browserVersion >= 4.0); 431 AjxEnv.isSafari2 = (AjxEnv.isSafari && browserVersion >= 2.0 && browserVersion < 3.0); 432 AjxEnv.isSafari3 = (AjxEnv.isSafari && browserVersion >= 3.0 && browserVersion < 4.0) || AjxEnv.isChrome; 433 AjxEnv.isSafari4 = (AjxEnv.isSafari && browserVersion >= 4.0); 434 AjxEnv.isSafari3up = (AjxEnv.isSafari && browserVersion >= 3.0) || AjxEnv.isChrome; 435 AjxEnv.isSafari4up = (AjxEnv.isSafari && browserVersion >= 4.0) || AjxEnv.isChrome; 436 AjxEnv.isSafari5up = (AjxEnv.isSafari && browserVersion >= 5.0) || AjxEnv.isChrome; 437 AjxEnv.isSafari5_1up = (AjxEnv.isSafari && browserVersion >= 5.1) || AjxEnv.isChrome; 438 AjxEnv.isSafari6up = AjxEnv.isSafari && browserVersion >= 6.0; 439 AjxEnv.isDesktop2up = (AjxEnv.isDesktop && browserVersion >= 2.0); 440 AjxEnv.isChrome2up = (AjxEnv.isChrome && browserVersion >= 2.0); 441 AjxEnv.isChrome7 = (AjxEnv.isChrome && browserVersion >= 7.0); 442 AjxEnv.isChrome10up = (AjxEnv.isChrome && browserVersion >= 10.0); 443 AjxEnv.isChrome19up = (AjxEnv.isChrome && browserVersion >= 19.0); 444 445 AjxEnv.browser = "[unknown]"; 446 if (AjxEnv.isOpera) { AjxEnv.browser = "OPERA"; } 447 else if (AjxEnv.isChrome) { AjxEnv.browser = "GC" + browserVersion; } 448 else if (AjxEnv.isSafari) { AjxEnv.browser = "SAF" + browserVersion; } 449 else if (AjxEnv.isCamino) { AjxEnv.browser = "CAM"; } 450 else if (isWebTv) { AjxEnv.browser = "WEBTV"; } 451 else if (isHotJava) { AjxEnv.browser = "HOTJAVA"; } 452 else if (AjxEnv.isFirefox) { AjxEnv.browser = "FF" + browserVersion; } 453 else if (AjxEnv.isPrism) { AjxEnv.browser = "PRISM"; } 454 else if (AjxEnv.isNav7) { AjxEnv.browser = "NAV7"; } 455 else if (AjxEnv.isNav6) { AjxEnv.browser = "NAV6"; } 456 else if (AjxEnv.isNav4) { AjxEnv.browser = "NAV4"; } 457 else if (AjxEnv.isIE) { AjxEnv.browser = "IE" + browserVersion; } 458 else if (AjxEnv.isModernIE) { AjxEnv.browser = "IE" + browserVersion; } 459 else if (AjxEnv.isDesktop) { AjxEnv.browser = "ZD" + browserVersion; } 460 461 AjxEnv.platform = "[unknown]"; 462 if (AjxEnv.isWindows) { AjxEnv.platform = "Win"; } 463 else if (AjxEnv.isMac) { AjxEnv.platform = "Mac"; } 464 else if (AjxEnv.isLinux) { AjxEnv.platform = "Linux"; } 465 } 466 467 // setup some global setting we can check for high resolution 468 if (AjxEnv.isIE) { 469 AjxEnv.isNormalResolution = true; 470 AjxEnv.ieScaleFactor = screen.deviceXDPI / screen.logicalXDPI; 471 if (AjxEnv.ieScaleFactor > 1) { 472 AjxEnv.isNormalResolution = false; 473 } 474 } 475 476 AjxEnv._inited = !AjxEnv.isIE; 477 478 // test for safari nightly 479 if (AjxEnv.isSafari) { 480 var webkit = AjxEnv.getWebkitVersion(); 481 AjxEnv.isSafariNightly = (webkit && webkit['is_nightly']); 482 // if not safari v3 or the nightly, assume we're dealing with v2 :/ 483 AjxEnv.isSafari2 = !AjxEnv.isSafari3 && !AjxEnv.isSafariNightly; 484 } 485 486 //HTML5 487 AjxEnv.supportsHTML5File = !!( window.FileReader || AjxEnv.isChrome || AjxEnv.isSafari6up ); 488 AjxEnv.supportsPlaceholder = 'placeholder' in document.createElement('INPUT'); 489 490 try { 491 // IE8 doesn't support REM units 492 var div = document.createElement('div'); 493 div.style.fontSize = '1rem'; 494 AjxEnv.supportsCSS3RemUnits = (div.style.fontSize == '1rem'); 495 } catch (e) { 496 AjxEnv.supportsCSS3RemUnits = false; 497 } 498 }; 499 500 // code provided by webkit authors to determine if nightly browser 501 AjxEnv.getWebkitVersion = 502 function() { 503 504 var webkit_version; 505 var regex = new RegExp("\\(.*\\) AppleWebKit/(.*) \\((.*)"); 506 var matches = regex.exec(navigator.userAgent); 507 if (matches) { 508 var version = matches[1]; 509 var bits = version.split("."); 510 var is_nightly = (version[version.length - 1] == "+"); 511 var minor = is_nightly ? "+" : parseInt(bits[1]); 512 // If minor is Not a Number (NaN) return an empty string 513 if (isNaN(minor)) minor = ""; 514 515 webkit_version = {major:parseInt(bits[0]), minor:minor, is_nightly:is_nightly}; 516 } 517 return webkit_version || {}; 518 }; 519 520 521 AjxEnv.parseUA(); 522 523 AjxEnv.isOfflineSupported = (AjxEnv.isFirefox || AjxEnv.isChrome) && AjxEnv.supported.localstorage && AjxEnv.supported.applicationcache && AjxEnv.supported.indexeddb && AjxEnv.supported.template; 524 525 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind 526 /* 527 if ( !Function.prototype.bind ) { 528 Function.prototype.bind = function( obj ) { 529 var slice = [].slice, 530 args = slice.call(arguments, 1), 531 self = this, 532 nop = function () {}, 533 bound = function () { 534 return self.apply( this instanceof nop ? this : ( obj || {} ), 535 args.concat( slice.call(arguments) ) ); 536 }; 537 nop.prototype = self.prototype; 538 bound.prototype = new nop(); 539 return bound; 540 }; 541 } 542 */ 543 544 // An alternative, simpler implementation. Not sure whether it does everything that the above version does, 545 // but it should work fine as a basic closure-style callback. 546 if (!Function.prototype.bind) { 547 Function.prototype.bind = function(thisObj) { 548 var that = this; 549 var args; 550 551 if (arguments.length > 1) { 552 // optimization: create the extra array object only if needed. 553 args = Array.prototype.slice.call(arguments, 1); 554 } 555 556 return function () { 557 var allArgs = args; 558 559 // optimization: concat array only if needed 560 if (arguments.length > 0) { 561 allArgs = (args && args.length) ? args.concat(Array.prototype.slice.call(arguments)) : arguments; 562 } 563 564 // for some reason, IE does not like the undefined allArgs hence the below condition. 565 return allArgs ? that.apply(thisObj, allArgs) : that.apply(thisObj); 566 }; 567 }; 568 } 569 570 /** 571 * This should be a temporary hack as we transition from AjxCallback to bind(). Rather 572 * than change hundreds of call sites with 'callback.run()' to see if the callback is 573 * an AjxCallback or a closure, add a run() method to Function which just invokes the 574 * closure. 575 */ 576 Function.prototype.run = function() { 577 return this.apply(this, arguments); 578 }; 579 580 /** 581 * Polyfill for Object.getPrototypeOf -- currently only required by IE8. 582 * 583 * Written by John Resig: http://ejohn.org/blog/objectgetprototypeof/ 584 */ 585 if (typeof Object.getPrototypeOf !== "function") { 586 if (typeof "test".__proto__ === "object") { 587 Object.getPrototypeOf = function(object) { 588 return object.__proto__; 589 }; 590 } else { 591 Object.getPrototypeOf = function(object) { 592 // May break if the constructor has been tampered with 593 return object.constructor.prototype; 594 }; 595 } 596 } 597 598 /** 599 * Polyfill for Object.keys -- currently only required by IE8. 600 * 601 * From Mozilla: 602 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys 603 */ 604 if (typeof Object.keys !== "function") { 605 Object.keys = (function() { 606 'use strict'; 607 var hasOwnProperty = Object.prototype.hasOwnProperty, 608 hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'), 609 dontEnums = [ 610 'toString', 611 'toLocaleString', 612 'valueOf', 613 'hasOwnProperty', 614 'isPrototypeOf', 615 'propertyIsEnumerable', 616 'constructor' 617 ], 618 dontEnumsLength = dontEnums.length; 619 620 return function(obj) { 621 if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { 622 throw new TypeError('Object.keys called on non-object'); 623 } 624 625 var result = [], prop, i; 626 627 for (prop in obj) { 628 if (hasOwnProperty.call(obj, prop)) { 629 result.push(prop); 630 } 631 } 632 633 if (hasDontEnumBug) { 634 for (i = 0; i < dontEnumsLength; i++) { 635 if (hasOwnProperty.call(obj, dontEnums[i])) { 636 result.push(dontEnums[i]); 637 } 638 } 639 } 640 return result; 641 }; 642 }()); 643 } 644 645 /** 646 * Polyfill for String.startsWith -- currently required by Safari, Opera, and IE. 647 */ 648 if (typeof String.prototype.startsWith != 'function') { 649 String.prototype.startsWith = function(searchString, position) { 650 position = position || 0; 651 return this.indexOf(searchString, position) === position; 652 }; 653 } 654 655 /** 656 * Polyfill for Array.prototype.indexOf -- currently only required by IE8. 657 * 658 * From Mozilla: 659 * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf 660 */ 661 if (!Array.prototype.indexOf) { 662 Array.prototype.indexOf = function(searchElement, fromIndex) { 663 664 var k; 665 666 // 1. Let O be the result of calling ToObject passing 667 // the this value as the argument. 668 if (this == null) { 669 throw new TypeError('"this" is null or not defined'); 670 } 671 672 var O = Object(this); 673 674 // 2. Let lenValue be the result of calling the Get 675 // internal method of O with the argument "length". 676 // 3. Let len be ToUint32(lenValue). 677 var len = O.length >>> 0; 678 679 // 4. If len is 0, return -1. 680 if (len === 0) { 681 return -1; 682 } 683 684 // 5. If argument fromIndex was passed let n be 685 // ToInteger(fromIndex); else let n be 0. 686 var n = +fromIndex || 0; 687 688 if (Math.abs(n) === Infinity) { 689 n = 0; 690 } 691 692 // 6. If n >= len, return -1. 693 if (n >= len) { 694 return -1; 695 } 696 697 // 7. If n >= 0, then Let k be n. 698 // 8. Else, n<0, Let k be len - abs(n). 699 // If k is less than 0, then let k be 0. 700 k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); 701 702 // 9. Repeat, while k < len 703 while (k < len) { 704 // a. Let Pk be ToString(k). 705 // This is implicit for LHS operands of the in operator 706 // b. Let kPresent be the result of calling the 707 // HasProperty internal method of O with argument Pk. 708 // This step can be combined with c 709 // c. If kPresent is true, then 710 // i. Let elementK be the result of calling the Get 711 // internal method of O with the argument ToString(k). 712 // ii. Let same be the result of applying the 713 // Strict Equality Comparison Algorithm to 714 // searchElement and elementK. 715 // iii. If same is true, return k. 716 if (k in O && O[k] === searchElement) { 717 return k; 718 } 719 k++; 720 } 721 return -1; 722 }; 723 } 724 725 /** 726 * Polyfill for Array.prototype.some -- currently only required by IE8. 727 * 728 * From Mozilla: 729 * https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/some 730 */ 731 if (!Array.prototype.some) { 732 // Production steps of ECMA-262, Edition 5, 15.4.4.17 733 // Reference: http://es5.github.io/#x15.4.4.17 734 Array.prototype.some = function(fun/*, thisArg*/) { 735 'use strict'; 736 737 if (this == null) { 738 throw new TypeError('Array.prototype.some called on null or undefined'); 739 } 740 741 if (typeof fun !== 'function') { 742 throw new TypeError(); 743 } 744 745 var t = Object(this); 746 var len = t.length >>> 0; 747 748 var thisArg = arguments.length >= 2 ? arguments[1] : void 0; 749 for (var i = 0; i < len; i++) { 750 if (i in t && fun.call(thisArg, t[i], i, t)) { 751 return true; 752 } 753 } 754 755 return false; 756 }; 757 } 758