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; 157 try { 158 r = new XMLHttpRequest(); 159 } catch (e) { 160 r = new ActiveXObject("MSXML2.XMLHTTP.3.0"); 161 } 162 r.open('POST', url, true); 163 r.onreadystatechange = function (aEvt) { 164 if (r.readyState == 4) { 165 // Save responseStatus so as Offline Applications know what happened 166 // when loading root configuration from server, and depending on the 167 // error status display an error message or the offline UI. 168 config.rootResponseStatus = r.status; 169 config.rootResponseText = r.responseText; 170 171 var text = r.responseText; 172 if (r.status == 200) { 173 log("Got root config response", text); 174 var updatedConfig = JSON.parse(text); 175 176 // Copy new properties to the config object 177 for (var property in updatedConfig) { 178 if (updatedConfig.hasOwnProperty(property)) { 179 config[property] = updatedConfig[property]; 180 } 181 } 182 183 // Try bootstrapping again, this time without fetching missing info 184 bootstrapApp(false); 185 } else { 186 log('Error', r.statusText, text); 187 188 //Let TB waitForVaadin work again 189 delete window.vaadin.clients[testbenchId]; 190 191 // Show the error in the app's div 192 var appDiv = document.getElementById(appId); 193 appDiv.innerHTML = text; 194 appDiv.style['overflow'] = 'auto'; 195 } 196 197 // Run the fetchRootConfig callback if present. 198 callback && callback(r); 199 } 200 }; 201 // send parameters as POST data 202 r.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 203 204 var xsrfToken = getCookie("XSRF-TOKEN"); 205 if (xsrfToken && xsrfToken.length > 0) { 206 r.setRequestHeader("X-XSRF-TOKEN", xsrfToken); 207 } 208 209 r.send(params); 210 211 log('sending request to ', url); 212 }; 213 214 //Export public data 215 var app = { 216 getConfig: getConfig, 217 // Used when the app was started in offline, so as it is possible 218 // to defer root configuration loading until network is available. 219 fetchRootConfig: fetchRootConfig 220 }; 221 apps[appId] = app; 222 223 if (!window.name) { 224 window.name = appId + '-' + Math.random(); 225 } 226 227 var bootstrapApp = function (mayDefer) { 228 var vaadinDir = getConfig('vaadinDir'); 229 230 var versionInfo = getConfig('versionInfo'); 231 232 var themeUri = vaadinDir + 'themes/' + getConfig('theme'); 233 loadTheme(themeUri, versionInfo && versionInfo['vaadinVersion']); 234 235 var widgetset = getConfig('widgetset'); 236 var widgetsetUrl = getConfig('widgetsetUrl'); 237 if (!widgetsetUrl) { 238 widgetsetUrl = vaadinDir + 'widgetsets/' + widgetset + "/"
238+ widgetset + ".nocache.js?" + new Date().getTime(); 239 } 240 var widgetsetReady = getConfig('widgetsetReady'); 241 loadWidgetset(widgetsetUrl, widgetset, widgetsetReady); 242 243 if (getConfig('uidl') === undefined) { 244 if (mayDefer) { 245 fetchRootConfig(); 246 } else { 247 throw "May not defer bootstrap any more"; 248 } 249 } else { 250 if (widgetsets[widgetset].callback) { 251 log("Starting from bootstrap", appId); 252 widgetsets[widgetset].callback(appId); 253 } else { 254 log("Setting pending startup", appId); 255 widgetsets[widgetset].pendingApps.push(appId); 256 } 257 } 258 }; 259 bootstrapApp(true); 260 261 if (getConfig("debug")) { 262 // TODO debug state is now global for the entire page, but should somehow only be set for the current application 263 window.vaadin.debug = true; 264 } 265 266 return app; 267 }, 268 clients: {}, 269 getAppIds: function () { 270 var ids = []; 271 for (var id in apps) { 272 if (apps.hasOwnProperty(id)) { 273 ids.push(id); 274 } 275 } 276 return ids; 277 }, 278 getApp: function (appId) { 279 return apps[appId]; 280 }, 281 loadTheme: loadTheme, 282 registerWidgetset: function (widgetset, callback) { 283 log("Widgetset registered", widgetset); 284 var ws = widgetsets[widgetset]; 285 if (ws && ws.pendingApps) { 286 ws.callback = callback; 287 for (var i = 0; i < ws.pendingApps.length; i++) { 288 var appId = ws.pendingApps[i]; 289 log("Starting from register widgetset", appId); 290 callback(appId); 291 } 292 ws.pendingApps = null; 293 } 294 }, 295 getBrowserDetailsParameters: function (parentElementId, sendUrlsAsParameters) { 296 // Screen height and width 297 var params = 'v-sh=' + window.screen.height; 298 params += '&v-sw=' + window.screen.width; 299
300 // Window height and width 301 var cw = 0; 302 var ch = 0; 303 if (typeof(window.innerWidth) == 'number') { 304 // Modern browsers 305 cw = window.innerWidth; 306 ch = window.innerHeight; 307 } else { 308 // IE 8 309 cw = document.documentElement.clientWidth; 310 ch = document.documentElement.clientHeight; 311 } 312 params += '&v-cw=' + cw + '&v-ch=' + ch; 313 314 315 var d = new Date(); 316 317 params += '&v-curdate=' + d.getTime(); 318 319 var tzo1 = d.getTimezoneOffset(); // current offset 320 var dstDiff = 0; 321 var rtzo = tzo1; 322 323 for (var m = 12; m > 0; m--) { 324 d.setUTCMonth(m); 325 var tzo2 = d.getTimezoneOffset(); 326 if (tzo1 != tzo2) { 327 dstDiff = (tzo1 > tzo2 ? tzo1 - tzo2 : tzo2 - tzo1); // offset w/o DST 328 rtzo = (tzo1 > tzo2 ? tzo1 : tzo2); // offset w/o DST 329 break; 330 } 331 } 332 333 // Time zone offset 334 params += '&v-tzo=' + tzo1; 335 336 // DST difference 337 params += '&v-dstd=' + dstDiff; 338 339 // Raw time zone offset 340 params += '&v-rtzo=' + rtzo; 341 342 // DST in effect? 343 params += '&v-dston=' + (tzo1 != rtzo); 344 345 // Time zone id (if available) 346 try { 347 params += '&v-tzid=' + encodeURIComponent(Intl.DateTimeFormat().resolvedOptions().timeZone); 348 } catch (err) { 349 350 } 351 352 var pe = document.getElementById(parentElementId); 353 if (pe) { 354 params += '&v-vw=' + pe.offsetWidth; 355 params += '&v-vh=' + pe.offsetHeight; 356 } 357 358 // Location 359 if (sendUrlsAsParameters !== false) { 360 params += '&v-loc=' + encodeURIComponent(location.href); 361 } 362
363 // Window name 364 if (window.name) { 365 params += '&v-wn=' + encodeURIComponent(window.name); 366 } 367 368 // This parameter is used in multiplatform-runtime as a key for 369 // storing the MPR UI content in the session 370 if (window.mprUiId) { 371 params += '&v-mui=' + encodeURIComponent(window.mprUiId); 372 } 373 374 // Detect touch device support 375 var supportsTouch = false; 376 try { 377 document.createEvent("TouchEvent"); 378 supportsTouch = true; 379 } catch (e) { 380 // Chrome and IE10 touch detection 381 supportsTouch = 'ontouchstart' in window 382 || navigator.msMaxTouchPoints; 383 } 384 385 if (supportsTouch) { 386 params += "&v-td=1"; 387 } 388 389 return params; 390 } 391 }; 392 393 log('Vaadin bootstrap loaded'); 394})();
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.