|
|
@@ -2,8 +2,8 @@ |
|
|
|
var apps = {}; |
|
|
|
var themesLoaded = {}; |
|
|
|
var widgetsets = {}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var log; |
|
|
|
if (typeof console === "undefined" || !window.location.search.match(/[&?]debug(&|$)/)) { |
|
|
|
//If no console.log present, just use a no-op |
|
|
@@ -17,30 +17,35 @@ |
|
|
|
//In IE, its a native function for which apply is not defined, but it works without a proper 'this' reference |
|
|
|
log = console.log; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var loadTheme = function(url, version) { |
|
|
|
if(!themesLoaded[url]) { |
|
|
|
log("loadTheme", url, version); |
|
|
|
|
|
|
|
|
|
|
|
var href = url + '/styles.css'; |
|
|
|
if (version) { |
|
|
|
href += '?v=' + version; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var stylesheet = document.createElement('link'); |
|
|
|
stylesheet.setAttribute('rel', 'stylesheet'); |
|
|
|
stylesheet.setAttribute('type', 'text/css'); |
|
|
|
stylesheet.setAttribute('href', href); |
|
|
|
document.getElementsByTagName('head')[0].appendChild(stylesheet); |
|
|
|
themesLoaded[url] = true; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
var isWidgetsetLoaded = function(widgetset) { |
|
|
|
|
|
|
|
var getCookie = function (cname) { |
|
|
|
var b = document.cookie.match('(^|;)\\s*' + cname + '\\s*=\\s*([^;]+)'); |
|
|
|
return b ? b.pop() : ''; |
|
|
|
}; |
|
|
|
|
|
|
|
var isWidgetsetLoaded = function(widgetset) { |
|
|
|
var className = widgetset.replace(/\./g, "_"); |
|
|
|
return (typeof window[className]) != "undefined"; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var loadWidgetset = function(url, widgetset, ready) { |
|
|
|
if (widgetsets[widgetset]) { |
|
|
|
return; |
|
|
@@ -60,12 +65,12 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
}, 15000); |
|
|
|
|
|
|
|
|
|
|
|
var scriptTag = document.createElement('script'); |
|
|
|
scriptTag.setAttribute('type', 'text/javascript'); |
|
|
|
scriptTag.setAttribute('src', url); |
|
|
|
document.getElementsByTagName('head')[0].appendChild(scriptTag); |
|
|
|
|
|
|
|
|
|
|
|
widgetsets[widgetset] = { |
|
|
|
pendingApps: [] |
|
|
|
}; |
|
|
@@ -79,7 +84,7 @@ |
|
|
|
for ( var i = 0; i < appDiv.childElementCount; i++) { |
|
|
|
var className = appDiv.childNodes[i].className; |
|
|
|
// If the app div contains a child with the class |
|
|
|
// "v-app-loading" we have only received the HTML |
|
|
|
// "v-app-loading" we have only received the HTML |
|
|
|
// but not yet started the widget set |
|
|
|
// (UIConnector removes the v-app-loading div). |
|
|
|
if (className && className.indexOf("v-app-loading") != -1) { |
|
|
@@ -92,7 +97,7 @@ |
|
|
|
window.vaadin = window.vaadin || { |
|
|
|
initApplication: function(appId, config) { |
|
|
|
var testbenchId = appId.replace(/-\d+$/, ''); |
|
|
|
|
|
|
|
|
|
|
|
if (apps[appId]) { |
|
|
|
if (window.vaadin && window.vaadin.clients && window.vaadin.clients[testbenchId] && window.vaadin.clients[testbenchId].initializing) { |
|
|
|
throw "Application " + appId + " is already being initialized"; |
|
|
@@ -103,19 +108,19 @@ |
|
|
|
} |
|
|
|
|
|
|
|
log("init application", appId, config); |
|
|
|
|
|
|
|
|
|
|
|
window.vaadin.clients[testbenchId] = { |
|
|
|
isActive: function() { |
|
|
|
return true; |
|
|
|
}, |
|
|
|
initializing: true |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var getConfig = function(name) { |
|
|
|
var value = config[name]; |
|
|
|
return value; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var fetchRootConfig = function(callback) { |
|
|
|
log('Fetching root config'); |
|
|
|
var url = getConfig('browserDetailsUrl'); |
|
|
@@ -124,8 +129,8 @@ |
|
|
|
url = window.location.href.replace(/#.*/,''); |
|
|
|
} |
|
|
|
// Timestamp to avoid caching |
|
|
|
url += ((/\?/).test(url) ? "&" : "?") + "v-" + (new Date()).getTime(); |
|
|
|
|
|
|
|
url += ((/\?/).test(url) ? "&" : "?") + "v-" + (new Date()).getTime(); |
|
|
|
|
|
|
|
var params = "v-browserDetails=1"; |
|
|
|
var rootId = getConfig("v-rootId"); |
|
|
|
if (rootId !== undefined) { |
|
|
@@ -137,16 +142,16 @@ |
|
|
|
if (theme !== undefined) { |
|
|
|
params += '&theme=' + encodeURIComponent(theme); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
params += "&v-appId=" + appId; |
|
|
|
|
|
|
|
|
|
|
|
var extraParams = getConfig('extraParams') |
|
|
|
if (extraParams !== undefined) { |
|
|
|
params += extraParams; |
|
|
|
} |
|
|
|
|
|
|
|
params += '&' + vaadin.getBrowserDetailsParameters(appId, getConfig('sendUrlsAsParameters')); |
|
|
|
|
|
|
|
|
|
|
|
params += '&' + vaadin.getBrowserDetailsParameters(appId, getConfig('sendUrlsAsParameters')); |
|
|
|
|
|
|
|
var r; |
|
|
|
try { |
|
|
|
r = new XMLHttpRequest(); |
|
|
@@ -154,7 +159,7 @@ |
|
|
|
r = new ActiveXObject("MSXML2.XMLHTTP.3.0"); |
|
|
|
} |
|
|
|
r.open('POST', url, true); |
|
|
|
r.onreadystatechange = function (aEvt) { |
|
|
|
r.onreadystatechange = function (aEvt) { |
|
|
|
if (r.readyState == 4) { |
|
|
|
// Save responseStatus so as Offline Applications know what happened |
|
|
|
// when loading root configuration from server, and depending on the |
|
|
@@ -166,91 +171,94 @@ |
|
|
|
if (r.status == 200){ |
|
|
|
log("Got root config response", text); |
|
|
|
var updatedConfig = JSON.parse(text); |
|
|
|
|
|
|
|
|
|
|
|
// Copy new properties to the config object |
|
|
|
for (var property in updatedConfig) { |
|
|
|
if (updatedConfig.hasOwnProperty(property)) { |
|
|
|
config[property] = updatedConfig[property]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Try bootstrapping again, this time without fetching missing info |
|
|
|
bootstrapApp(false); |
|
|
|
} else { |
|
|
|
log('Error', r.statusText, text); |
|
|
|
|
|
|
|
|
|
|
|
//Let TB waitForVaadin work again |
|
|
|
delete window.vaadin.clients[testbenchId]; |
|
|
|
|
|
|
|
|
|
|
|
// Show the error in the app's div |
|
|
|
var appDiv = document.getElementById(appId); |
|
|
|
appDiv.innerHTML = text; |
|
|
|
appDiv.style['overflow'] = 'auto'; |
|
|
|
} |
|
|
|
|
|
|
|
// Run the fetchRootConfig callback if present. |
|
|
|
callback && callback(r); |
|
|
|
} |
|
|
|
}; |
|
|
|
// send parameters as POST data |
|
|
|
r.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); |
|
|
|
r.send(params); |
|
|
|
|
|
|
|
log('sending request to ', url); |
|
|
|
}; |
|
|
|
|
|
|
|
//Export public data |
|
|
|
var app = { |
|
|
|
getConfig: getConfig, |
|
|
|
// Used when the app was started in offline, so as it is possible |
|
|
|
// to defer root configuration loading until network is available. |
|
|
|
fetchRootConfig: fetchRootConfig |
|
|
|
}; |
|
|
|
apps[appId] = app; |
|
|
|
|
|
|
|
if (!window.name) { |
|
|
|
window.name = appId + '-' + Math.random(); |
|
|
|
} |
|
|
|
|
|
|
|
var bootstrapApp = function(mayDefer) { |
|
|
|
var vaadinDir = getConfig('vaadinDir'); |
|
|
|
|
|
|
|
var versionInfo = getConfig('versionInfo'); |
|
|
|
|
|
|
|
var themeUri = vaadinDir + 'themes/' + getConfig('theme'); |
|
|
|
loadTheme(themeUri, versionInfo && versionInfo['vaadinVersion']); |
|
|
|
|
|
|
|
var widgetset = getConfig('widgetset'); |
|
|
|
var widgetsetUrl = getConfig('widgetsetUrl'); |
|
|
|
if (!widgetsetUrl) { |
|
|
|
widgetsetUrl = vaadinDir + 'widgetsets/' + widgetset + "/" + widgetset + ".nocache.js?" + new Date().getTime(); |
|
|
|
} |
|
|
|
var widgetsetReady = getConfig('widgetsetReady'); |
|
|
|
loadWidgetset(widgetsetUrl, widgetset, widgetsetReady); |
|
|
|
|
|
|
|
if (getConfig('uidl') === undefined) { |
|
|
|
if (mayDefer) { |
|
|
|
fetchRootConfig(); |
|
|
|
} else { |
|
|
|
throw "May not defer bootstrap any more"; |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (widgetsets[widgetset].callback) { |
|
|
|
log("Starting from bootstrap", appId); |
|
|
|
widgetsets[widgetset].callback(appId); |
|
|
|
} else { |
|
|
|
log("Setting pending startup", appId); |
|
|
|
widgetsets[widgetset].pendingApps.push(appId); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
bootstrapApp(true); |
|
|
|
// Run the fetchRootConfig callback if present. |
|
|
|
callback && callback(r); |
|
|
|
} |
|
|
|
}; |
|
|
|
// send parameters as POST data |
|
|
|
r.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); |
|
|
|
var xsrfToken = getCookie("XSRF-TOKEN"); |
|
|
|
if (xsrfToken && xsrfToken.length > 0) { |
|
|
|
r.setRequestHeader("X-XSRF-TOKEN", xsrfToken); |
|
|
|
}r.send(params); |
|
|
|
|
|
|
|
log('sending request to ', url); |
|
|
|
}; |
|
|
|
|
|
|
|
//Export public data |
|
|
|
var app = { |
|
|
|
getConfig: getConfig, |
|
|
|
// Used when the app was started in offline, so as it is possible |
|
|
|
// to defer root configuration loading until network is available. |
|
|
|
fetchRootConfig: fetchRootConfig |
|
|
|
}; |
|
|
|
apps[appId] = app; |
|
|
|
|
|
|
|
if (!window.name) { |
|
|
|
window.name = appId + '-' + Math.random(); |
|
|
|
} |
|
|
|
|
|
|
|
var bootstrapApp = function (mayDefer) { |
|
|
|
var vaadinDir = getConfig('vaadinDir'); |
|
|
|
|
|
|
|
var versionInfo = getConfig('versionInfo'); |
|
|
|
|
|
|
|
var themeUri = vaadinDir + 'themes/' + getConfig('theme'); |
|
|
|
loadTheme(themeUri, versionInfo && versionInfo['vaadinVersion']); |
|
|
|
|
|
|
|
var widgetset = getConfig('widgetset'); |
|
|
|
var widgetsetUrl = getConfig('widgetsetUrl'); |
|
|
|
if (!widgetsetUrl) { |
|
|
|
widgetsetUrl = vaadinDir + 'widgetsets/' + widgetset + "/" + widgetset + ".nocache.js?" + new Date().getTime(); |
|
|
|
} |
|
|
|
var widgetsetReady = getConfig('widgetsetReady'); |
|
|
|
loadWidgetset(widgetsetUrl, widgetset, widgetsetReady); |
|
|
|
|
|
|
|
if (getConfig('uidl') === undefined) { |
|
|
|
if (mayDefer) { |
|
|
|
fetchRootConfig(); |
|
|
|
} else { |
|
|
|
throw "May not defer bootstrap any more"; |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (widgetsets[widgetset].callback) { |
|
|
|
log("Starting from bootstrap", appId); |
|
|
|
widgetsets[widgetset].callback(appId); |
|
|
|
} else { |
|
|
|
log("Setting pending startup", appId); |
|
|
|
widgetsets[widgetset].pendingApps.push(appId); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
bootstrapApp(true); |
|
|
|
|
|
|
|
if (getConfig("debug")) { |
|
|
|
// TODO debug state is now global for the entire page, but should somehow only be set for the current application |
|
|
|
// TODO debug state is now global for the entire page, but should somehow only be set for the current application |
|
|
|
window.vaadin.debug = true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return app; |
|
|
|
}, |
|
|
|
clients: {}, |
|
|
@@ -284,7 +292,7 @@ |
|
|
|
// Screen height and width |
|
|
|
var params = 'v-sh=' + window.screen.height; |
|
|
|
params += '&v-sw=' + window.screen.width; |
|
|
|
|
|
|
|
|
|
|
|
// Window height and width |
|
|
|
var cw = 0; |
|
|
|
var ch = 0; |
|
|
@@ -298,16 +306,16 @@ |
|
|
|
ch = document.documentElement.clientHeight; |
|
|
|
} |
|
|
|
params += '&v-cw=' + cw + '&v-ch=' + ch; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var d = new Date(); |
|
|
|
|
|
|
|
|
|
|
|
params += '&v-curdate=' + d.getTime(); |
|
|
|
|
|
|
|
|
|
|
|
var tzo1 = d.getTimezoneOffset(); // current offset |
|
|
|
var dstDiff = 0; |
|
|
|
var rtzo = tzo1; |
|
|
|
|
|
|
|
|
|
|
|
for (var m=12;m>0;m--) { |
|
|
|
d.setUTCMonth(m); |
|
|
|
var tzo2 = d.getTimezoneOffset(); |
|
|
@@ -320,22 +328,22 @@ |
|
|
|
|
|
|
|
// Time zone offset |
|
|
|
params += '&v-tzo=' + tzo1; |
|
|
|
|
|
|
|
|
|
|
|
// DST difference |
|
|
|
params += '&v-dstd=' + dstDiff; |
|
|
|
|
|
|
|
|
|
|
|
// Raw time zone offset |
|
|
|
params += '&v-rtzo=' + rtzo; |
|
|
|
|
|
|
|
|
|
|
|
// DST in effect? |
|
|
|
params += '&v-dston=' + (tzo1 != rtzo); |
|
|
|
|
|
|
|
|
|
|
|
var pe = document.getElementById(parentElementId); |
|
|
|
if (pe) { |
|
|
|
params += '&v-vw=' + pe.offsetWidth; |
|
|
|
params += '&v-vh=' + pe.offsetHeight; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Location |
|
|
|
if (sendUrlsAsParameters !== false) { |
|
|
|
params += '&v-loc=' + encodeURIComponent(location.href); |
|
|
@@ -345,7 +353,7 @@ |
|
|
|
if (window.name) { |
|
|
|
params += '&v-wn=' + encodeURIComponent(window.name); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Detect touch device support |
|
|
|
var supportsTouch = false; |
|
|
|
try { |
|
|
@@ -360,10 +368,10 @@ |
|
|
|
if (supportsTouch) { |
|
|
|
params += "&v-td=1"; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return params; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
log('Vaadin bootstrap loaded'); |
|
|
|
})(); |