1/** 2 * Device Detection Utilities 3 * 4 * Provides client-side device detection based on User-Agent, screen size, and touch capabilities. 5 * More accurate than server-side detection for responsive behavior. 6 * 7 * @version 1.0 8 */ 9 10(function(window) { 11 'use strict'; 12 13 /** 14 * Detects if the device is Android mobile 15 * @returns {boolean} 16 */ 17 function isDeviceAndroid() { 18 var ua = navigator.userAgent.toLowerCase(); 19 var isMobile = /mobile|android|touch|webos|hpwos/i.test(ua); 20 return ua.indexOf("android") > -1 && isMobile; 21 } 22 23 /** 24 * Detects if the device is an Apple device (iPhone, iPad, or Mac) 25 * @returns {boolean} 26 */ 27 function isDeviceApple() { 28 var ua = navigator.userAgent; 29 return /iPhone|iPad|Macintosh/i.test(ua); 30 } 31 32 /** 33 * Detects if the user agent is Outlook 34 * @returns {boolean} 35 */ 36 function isOutlook() { 37 var ua = navigator.userAgent; 38 return /Outlook|Microsoft Office/i.test(ua); 39 } 40 41 /** 42 * Detects if the device is Windows 43 * @returns {boolean} 44 */ 45 function isWindows() { 46 var ua = navigator.userAgent; 47 return /Windows/i.test(ua); 48 } 49 50 /** 51 * Detects if the current device is a mobile phone (not tablet) 52 * More accurate than server-side detection as it checks screen size 53 * @returns {boolean} 54 */ 55 function isMobile() { 56 var ua = navigator.userAgent; 57 var hasTouch = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0); 58 var isSmallScreen = window.innerWidth <= 768; 59 60 // Check common mobile patterns 61 var isMobileUA = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua); 62 63 // Exclude tablets (iPad, Android tablets) 64 var isTabletUA = /iPad|Android(?!.*Mobile)/i.test(ua); 65 66 return (isMobileUA || (hasTouch && isSmallScreen)) && !isTabletUA; 67 } 68 69 /** 70 * Detects if the current device is a tablet 71 * @returns {boolean} 72 */ 73 function isTablet() { 74 var ua = navigator.userAgent; 75 var hasTouch = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0); 76 var isMediumScreen = window.innerWidth > 768 && window.innerWidth <= 1024; 77 78 // Check common tablet patterns 79 var isTabletUA = /iPad|Android(?!.*Mobile)|Tablet|PlayBook|Silk/i.test(ua); 80 81 return isTabletUA || (hasTouch && isMediumScreen); 82 } 83 84 /** 85 * Dynamically update body classes based on client-side detection 86 * 87 * This function ONLY modifies is-mobile and is-tablet classes. 88 * Other classes (qld-gov, tas-gov, has-footer, etc.) are set by PHP 89 * and depend on database settings/routes that can't be replicated client-side. 90 * 91 * Runs automatically on page load to correct server-side User-Agent misdetection. 92 * Can also be manually triggered (e.g., after window resize). 93 */ 94 function updateBodyClasses() { 95 var body = document.body || document.getElementsByTagName('body')[0]; 96 if (!body) { 97 // Body not ready yet, wait for DOMContentLoaded 98 if (document.readyState === 'loading') { 99 document.addEventListener('DOMContentLoaded', updateBodyClasses); 100 } 101 return; 102 } 103 104 var isMobileDevice = isMobile(); 105 var isTabletDevice = isTablet(); 106 var changed = false; 107 108 // Update is-mobile class (only if detection differs from current state) 109 if (isMobileDevice && !body.classList.contains('is-mobile')) { 110 body.classList.add('is-mobile'); 111 changed = true; 112 } else if (!isMobileDevice && body.classList.contains('is-mobile')) { 113 body.classList.remove('is-mobile'); 114 changed = true; 115 } 116 117 // Update is-tablet class (only if detection differs from current state) 118 if (isTabletDevice && !body.classList.contains('is-tablet')) { 119 body.classList.add('is-tablet'); 120 changed = true; 121 } else if (!isTabletDevice && body.classList.contains('is-tablet')) { 122 body.classList.remove('is-tablet'); 123 changed = true; 124 } 125 126 // Debug logging (only if something changed) 127 if (changed) { 128 console.log('DeviceUtils: Corrected body classes - isMobile:', isMobileDevice, 'isTablet:', isTabletDevice); 129 } 130 } 131 132 // Expose functions to global scope 133 window.DeviceUtils = { 134 isDeviceAndroid: isDeviceAndroid, 135 isDeviceApple: isDeviceApple, 136 isOutlook: isOutlook, 137 isWindows: isWindows, 138 isMobile: isMobile, 139 isTablet: isTablet, 140 updateBodyClasses: updateBodyClasses 141 }; 142 143 // Log successful load for debugging 144 console.log('DeviceUtils loaded successfully'); 145 146 // Backward compatibility: expose isDeviceAndroid globally 147 if (typeof window.isDeviceAndroid === 'undefined') { 148 window.isDeviceAndroid = isDeviceAndroid; 149 } 150 151 // Run immediately if DOM is ready, otherwise wait 152 if (document.readyState === 'loading') { 153 document.addEventListener('DOMContentLoaded', updateBodyClasses); 154 } else { 155 updateBodyClasses(); 156 } 157 158})(window); 159
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.