1(function () { 2 var apps = {}; 3 var themesLoaded = {}; 4 var widgetsets = {}; 5 6 7 var log; 8 if (typeof console === "undefined" || !window.location.search.match(/[&?]debug(&|$)/)) { 9 //If no console.log present, just use a no-op 10 log = function () { 11 }; 12 } else if (typeof console.log === "function") { 13 //If it's a function, use it with apply 14 log = function () { 15 console.log.apply(console, arguments); 16 }; 17 } else { 18 //In IE, its a native function for which apply is not defined, but it works without a proper 'this' reference 19 log = console.log; 20 } 21 22 var loadTheme = function (url, version) { 23 if (!themesLoaded[url]) { 24 log("loadTheme", url, version); 25 26 var href = url + '/styles.css'; 27 if (version) { 28 href += '?v=' + version; 29 } 30 31 var stylesheet = document.createElement('link'); 32 stylesheet.setAttribute('rel', 'stylesheet'); 33 stylesheet.setAttribute('type', 'text/css'); 34 stylesheet.setAttribute('href', href); 35 document.getElementsByTagName('head')[0].appendChild(stylesheet); 36 themesLoaded[url] = true; 37 } 38 }; 39 40 var getCookie = function (cname) { 41 var b = document.cookie.match('(^|;)\\s*' + cname + '\\s*=\\s*([^;]+)'); 42 return b ? b.pop() : ''; 43 }; 44 45 var isWidgetsetLoaded = function (widgetset) { 46 var className = widgetset.replace(/\./g, "_"); 47 return (typeof window[className]) != "undefined"; 48 }; 49 50 var loadWidgetset = function (url, widgetset, ready) { 51 if (widgetsets[widgetset]) { 52 return; 53 } 54 log("load widgetset", url, widgetset); 55 setTimeout(function () { 56 if (!isWidgetsetLoaded(widgetset)) { 57 if (ready) { 58 alert("Failed to load the widgetset: " + url); 59 } else { 60 if (window.confirm("Failed to load the widgetset. If using CDN for the widgetset, it is possible that compiling it takes up to a few minutes. Would you like to try again?")) { 61 window[widgetset] = undefined; 62 window.location.reload(false); 63 } else { 64 alert("Failed to load the widgetset: " + url); 65 } 66 } 67 } 68 }, 15000); 69 70 var scriptTag = document.createElement('script'); 71 scriptTag.setAttribute('type', 'text/javascript'); 72 scriptTag.setAttribute('src', url); 73 document.getElementsByTagName('head')[0].appendChild(scriptTag); 74 75 widgetsets[widgetset] = { 76 pendingApps: [] 77 }; 78 }; 79 80 var isInitializedInDom = function (appId) { 81 var appDiv = document.getElementById(appId); 82 if (!appDiv) { 83 return false; 84 } 85 for (var i = 0; i < appDiv.childElementCount; i++) { 86 var className = appDiv.childNodes[i].className; 87 // If the app div contains a child with the class 88 // "v-app-loading" we have only received the HTML 89 // but not yet started the widget set 90 // (UIConnector removes the v-app-loading div). 91 if (className && className.indexOf("v-app-loading") != -1) { 92 return false; 93 } 94 } 95 return true; 96 }; 97 98 window.vaadin = window.vaadin || { 99 initApplication: function (appId, config) { 100 var testbenchId = appId.replace(/-\d+$/, ''); 101 102 if (apps[appId]) { 103 if (window.vaadin && window.vaadin.clients && window.vaadin.clients[testbenchId] && window.vaadin.clients[testbenchId].initializing) { 104 throw "Application " + appId + " is already being initialized"; 105 }
106 if (isInitializedInDom(appId)) { 107 throw "Application " + appId + " already initialized"; 108 } 109 } 110 111 log("init application", appId, config); 112 113 window.vaadin.clients[testbenchId] = { 114 isActive: function () { 115 return true; 116 }, 117 initializing: true 118 }; 119 120 var getConfig = function (name) { 121 var value = config[name]; 122 return value; 123 }; 124 125 var fetchRootConfig = function (callback) { 126 log('Fetching root config'); 127 var url = getConfig('browserDetailsUrl'); 128 if (!url) { 129 // No special url defined, use the same URL that loaded this page (without the fragment) 130 url = window.location.href.replace(/#.*/, ''); 131 } 132 // Timestamp to avoid caching 133 url += ((/\?/).test(url) ? "&" : "?") + "v-" + (new Date()).getTime(); 134 135 var params = "v-browserDetails=1"; 136 var rootId = getConfig("v-rootId"); 137 if (rootId !== undefined) { 138 params += "&v-rootId=" + rootId; 139 } 140 141 // Tell the UI what theme it is configured to use 142 var theme = getConfig('theme'); 143 if (theme !== undefined) { 144 params += '&theme=' + encodeURIComponent(theme); 145 } 146 147 params += "&v-appId=" + appId; 148 149 var extraParams = getConfig('extraParams') 150 if (extraParams !== undefined) { 151 params += extraParams; 152 } 153 154 params += '&' + vaadin.getBrowserDetailsParameters(appId, getConfig('sendUrlsAsParameters')); 155 156 var r = new XMLHttpRequest(); 157 r.open('POST', url, true); 158 r.onreadystatechange = function (aEvt) { 159 if (r.readyState == 4) { 160 // Save responseStatus so as Offline Applications know what happened 161 // when loading root configuration from server, and depending on the 162 // error status display an error message or the offline UI. 163 config.rootResponseStatus = r.status; 164 config.rootResponseText = r.responseText; 165 166 var text = r.responseText; 167 if (r.status == 200) { 168 log("Got root config response", text); 169 var updatedConfig = JSON.parse(text); 170 171 // Copy new properties to the config object 172 for (var property in updatedConfig) { 173 if (updatedConfig.hasOwnProperty(property)) { 174 config[property] = updatedConfig[property]; 175 } 176 } 177 178 // Try bootstrapping again, this time without fetching missing info 179 bootstrapApp(false); 180 } else { 181 log('Error', r.statusText, text); 182 183 //Let TB waitForVaadin work again 184 delete window.vaadin.clients[testbenchId]; 185 186 // Show the error in the app's div 187 var appDiv = document.getElementById(appId); 188 appDiv.innerHTML = text; 189 appDiv.style['overflow'] = 'auto'; 190 } 191 192 // Run the fetchRootConfig callback if present. 193 callback && callback(r); 194 } 195 }; 196 // send parameters as POST data 197 r.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 198 199 var xsrfToken = getCookie("XSRF-TOKEN"); 200 if (xsrfToken && xsrfToken.length > 0) { 201 r.setRequestHeader("X-XSRF-TOKEN", xsrfToken); 202 } 203 204 r.send(params); 205 206 log('sending request to ', url); 207 }; 208 209 //Export public data 210 var app = { 211 getConfig: getConfig, 212 // Used when the app was started in offline, so as it is possible 213 // to defer root configuration loading until network is available. 214 fetchRootConfig: fetchRootConfig 215 }; 216 apps[appId] = app; 217 218 if (!window.name) { 219 window.name = appId + '-' + Math.random(); 220 } 221 222 var bootstrapApp = function (mayDefer) { 223 var vaadinDir = getConfig('vaadinDir'); 224 225 var versionInfo = getConfig('versionInfo'); 226 227 var themeUri = vaadinDir + 'themes/' + getConfig('theme'); 228 loadTheme(themeUri, versionInfo && versionInfo['vaadinVersion']); 229 230 var widgetset = getConfig('widgetset'); 231 var widgetsetUrl = getConfig('widgetsetUrl'); 232 if (!widgetsetUrl) { 233 widgetsetUrl = vaadinDir + 'widgetsets/' + widgetset + "/"
233+ widgetset + ".nocache.js?" + new Date().getTime(); 234 } 235 var widgetsetReady = getConfig('widgetsetReady'); 236 loadWidgetset(widgetsetUrl, widgetset, widgetsetReady); 237 238 if (getConfig('uidl') === undefined) { 239 if (mayDefer) { 240 fetchRootConfig(); 241 } else { 242 throw "May not defer bootstrap any more"; 243 } 244 } else { 245 if (widgetsets[widgetset].callback) { 246 log("Starting from bootstrap", appId); 247 widgetsets[widgetset].callback(appId); 248 } else { 249 log("Setting pending startup", appId); 250 widgetsets[widgetset].pendingApps.push(appId); 251 } 252 } 253 }; 254 bootstrapApp(true); 255 256 if (getConfig("debug")) { 257 // TODO debug state is now global for the entire page, but should somehow only be set for the current application 258 window.vaadin.debug = true; 259 } 260 261 return app; 262 }, 263 clients: {}, 264 getAppIds: function () { 265 var ids = []; 266 for (var id in apps) { 267 if (apps.hasOwnProperty(id)) { 268 ids.push(id); 269 } 270 } 271 return ids; 272 }, 273 getApp: function (appId) { 274 return apps[appId]; 275 }, 276 loadTheme: loadTheme, 277 registerWidgetset: function (widgetset, callback) { 278 log("Widgetset registered", widgetset); 279 var ws = widgetsets[widgetset]; 280 if (ws && ws.pendingApps) { 281 ws.callback = callback; 282 for (var i = 0; i < ws.pendingApps.length; i++) { 283 var appId = ws.pendingApps[i]; 284 log("Starting from register widgetset", appId); 285 callback(appId); 286 } 287 ws.pendingApps = null; 288 } 289 }, 290 getBrowserDetailsParameters: function (parentElementId, sendUrlsAsParameters) { 291 // Screen height and width 292 var params = 'v-sh=' + window.screen.height; 293 params += '&v-sw=' + window.screen.width; 294
295 // Window height and width 296 var cw = 0; 297 var ch = 0; 298 if (typeof(window.innerWidth) == 'number') { 299 // Modern browsers 300 cw = window.innerWidth; 301 ch = window.innerHeight; 302 } else { 303 // IE 8 304 cw = document.documentElement.clientWidth; 305 ch = document.documentElement.clientHeight; 306 } 307 params += '&v-cw=' + cw + '&v-ch=' + ch; 308 309 310 var d = new Date(); 311 312 params += '&v-curdate=' + d.getTime(); 313 314 var tzo1 = d.getTimezoneOffset(); // current offset 315 var dstDiff = 0; 316 var rtzo = tzo1; 317 318 for (var m = 12; m > 0; m--) { 319 d.setUTCMonth(m); 320 var tzo2 = d.getTimezoneOffset(); 321 if (tzo1 != tzo2) { 322 dstDiff = (tzo1 > tzo2 ? tzo1 - tzo2 : tzo2 - tzo1); // offset w/o DST 323 rtzo = (tzo1 > tzo2 ? tzo1 : tzo2); // offset w/o DST 324 break; 325 } 326 } 327 328 // Time zone offset 329 params += '&v-tzo=' + tzo1; 330 331 // DST difference 332 params += '&v-dstd=' + dstDiff; 333 334 // Raw time zone offset 335 params += '&v-rtzo=' + rtzo; 336 337 // DST in effect? 338 params += '&v-dston=' + (tzo1 != rtzo); 339 340 // Time zone id (if available) 341 try { 342 params += '&v-tzid=' + encodeURIComponent(Intl.DateTimeFormat().resolvedOptions().timeZone); 343 } catch (err) { 344 345 } 346 347 var pe = document.getElementById(parentElementId); 348 if (pe) { 349 params += '&v-vw=' + pe.offsetWidth; 350 params += '&v-vh=' + pe.offsetHeight; 351 } 352 353 // Location 354 if (sendUrlsAsParameters !== false) { 355 params += '&v-loc=' + encodeURIComponent(location.href); 356 } 357
358 // Window name 359 if (window.name) { 360 params += '&v-wn=' + encodeURIComponent(window.name); 361 } 362 363 // This parameter is used in multiplatform-runtime as a key for 364 // storing the MPR UI content in the session 365 if (window.mprUiId) { 366 params += '&v-mui=' + encodeURIComponent(window.mprUiId); 367 } 368 369 // Detect touch device support 370 var supportsTouch = false; 371 try { 372 document.createEvent("TouchEvent"); 373 supportsTouch = true; 374 } catch (e) { 375 // Chrome and IE10 touch detection 376 supportsTouch = 'ontouchstart' in window 377 || navigator.msMaxTouchPoints; 378 } 379 380 if (window.navigator.maxTouchPoints) { 381 params += '&v-mtp=' + window.navigator.maxTouchPoints; 382 } else { 383 params += '&v-mtp=0'; 384 } 385 386 if (supportsTouch) { 387 params += '&v-td=1'; 388 } 389 390 return params; 391 } 392 }; 393 394 log('Vaadin bootstrap loaded'); 395})();
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.