You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vaadinBootstrap.js 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. (function() {
  2. var apps = {};
  3. var themesLoaded = {};
  4. var widgetsets = {};
  5. var log;
  6. if (typeof console === "undefined" || !window.location.search.match(/[&?]debug(&|$)/)) {
  7. //If no console.log present, just use a no-op
  8. log = function() {};
  9. } else if (typeof console.log === "function") {
  10. //If it's a function, use it with apply
  11. log = function() {
  12. console.log.apply(console, arguments);
  13. };
  14. } else {
  15. //In IE, its a native function for which apply is not defined, but it works without a proper 'this' reference
  16. log = console.log;
  17. }
  18. var loadTheme = function(url) {
  19. if(!themesLoaded[url]) {
  20. log("loadTheme", url);
  21. var stylesheet = document.createElement('link');
  22. stylesheet.setAttribute('rel', 'stylesheet');
  23. stylesheet.setAttribute('type', 'text/css');
  24. stylesheet.setAttribute('href', url + "/styles.css");
  25. document.getElementsByTagName('head')[0].appendChild(stylesheet);
  26. themesLoaded[url] = true;
  27. }
  28. };
  29. var isWidgetsetLoaded = function(widgetset) {
  30. var className = widgetset.replace(/\./g, "_");
  31. return (typeof window[className]) != "undefined";
  32. };
  33. var loadWidgetset = function(url, widgetset) {
  34. if (widgetsets[widgetset]) {
  35. return;
  36. }
  37. log("load widgetset", url, widgetset);
  38. setTimeout(function() {
  39. if (!isWidgetsetLoaded(widgetset)) {
  40. alert("Failed to load the widgetset: " + url);
  41. }
  42. }, 15000);
  43. var scriptTag = document.createElement('script');
  44. scriptTag.setAttribute('type', 'text/javascript');
  45. scriptTag.setAttribute('src', url);
  46. document.getElementsByTagName('head')[0].appendChild(scriptTag);
  47. widgetsets[widgetset] = {
  48. pendingApps: []
  49. };
  50. };
  51. var isInitializedInDom = function(appId) {
  52. var appDiv = document.getElementById(appId);
  53. if (!appDiv) {
  54. return false;
  55. }
  56. for ( var i = 0; i < appDiv.childElementCount; i++) {
  57. var className = appDiv.childNodes[i].className;
  58. // If the app div contains a child with the class
  59. // "v-app-loading" we have only received the HTML
  60. // but not yet started the widget set
  61. // (UIConnector removes the v-app-loading div).
  62. if (className && className.contains("v-app-loading")) {
  63. return false;
  64. }
  65. }
  66. return true;
  67. };
  68. window.vaadin = window.vaadin || {
  69. initApplication: function(appId, config) {
  70. var testbenchId = appId.replace(/-\d+$/, '');
  71. if (apps[appId]) {
  72. if (window.vaadin && window.vaadin.clients && window.vaadin.clients[testbenchId] && window.vaadin.clients[testbenchId].initializing) {
  73. throw "Application " + appId + " is already being initialized";
  74. }
  75. if (isInitializedInDom(appId)) {
  76. throw "Application " + appId + " already initialized";
  77. }
  78. }
  79. log("init application", appId, config);
  80. window.vaadin.clients[testbenchId] = {
  81. isActive: function() {
  82. return true;
  83. },
  84. initializing: true
  85. };
  86. var getConfig = function(name) {
  87. var value = config[name];
  88. return value;
  89. };
  90. var fetchRootConfig = function() {
  91. log('Fetching root config');
  92. var url = getConfig('browserDetailsUrl');
  93. if (!url) {
  94. // No special url defined, use the same URL that loaded this page (without the fragment)
  95. url = window.location.href.replace(/#.*/,'');
  96. }
  97. url += ((/\?/).test(url) ? "&" : "?") + "v-browserDetails=1";
  98. var rootId = getConfig("v-rootId");
  99. if (rootId !== undefined) {
  100. url += "&v-rootId=" + rootId;
  101. }
  102. // Tell the UI what theme it is configured to use
  103. var theme = getConfig('theme');
  104. if (theme !== undefined) {
  105. url += '&theme=' + encodeURIComponent(theme);
  106. }
  107. // Tell the UI what pushMode it is configured to use
  108. var pushMode = getConfig('pushMode');
  109. if (pushMode !== undefined) {
  110. url += '&v-pushMode=' + encodeURIComponent(pushMode);
  111. }
  112. var extraParams = getConfig('extraParams')
  113. if (extraParams !== undefined) {
  114. url += extraParams;
  115. }
  116. url += '&' + vaadin.getBrowserDetailsParameters(appId);
  117. // Timestamp to avoid caching
  118. url += '&v-' + (new Date()).getTime();
  119. var r;
  120. try {
  121. r = new XMLHttpRequest();
  122. } catch (e) {
  123. r = new ActiveXObject("MSXML2.XMLHTTP.3.0");
  124. }
  125. r.open('POST', url, true);
  126. r.onreadystatechange = function (aEvt) {
  127. if (r.readyState == 4) {
  128. var text = r.responseText;
  129. if (r.status == 200){
  130. log("Got root config response", text);
  131. var updatedConfig = JSON.parse(text);
  132. // Copy new properties to the config object
  133. for (var property in updatedConfig) {
  134. if (updatedConfig.hasOwnProperty(property)) {
  135. config[property] = updatedConfig[property];
  136. }
  137. }
  138. // Try bootstrapping again, this time without fetching missing info
  139. bootstrapApp(false);
  140. } else {
  141. log('Error', r.statusText, text);
  142. //Let TB waitForVaadin work again
  143. delete window.vaadin.clients[testbenchId];
  144. // Show the error in the app's div
  145. var appDiv = document.getElementById(appId);
  146. appDiv.innerHTML = text;
  147. appDiv.style['overflow'] = 'auto';
  148. }
  149. }
  150. };
  151. r.send(null);
  152. log('sending request to ', url);
  153. };
  154. //Export public data
  155. var app = {
  156. 'getConfig': getConfig
  157. };
  158. apps[appId] = app;
  159. if (!window.name) {
  160. window.name = appId + '-' + Math.random();
  161. }
  162. var bootstrapApp = function(mayDefer) {
  163. var vaadinDir = getConfig('vaadinDir');
  164. var themeUri = vaadinDir + 'themes/' + getConfig('theme');
  165. loadTheme(themeUri);
  166. var widgetset = getConfig('widgetset');
  167. var widgetsetUrl = getConfig('widgetsetUrl');
  168. if (!widgetsetUrl) {
  169. widgetsetUrl = vaadinDir + 'widgetsets/' + widgetset + "/" + widgetset + ".nocache.js?" + new Date().getTime();
  170. }
  171. loadWidgetset(widgetsetUrl, widgetset);
  172. if (getConfig('uidl') === undefined) {
  173. if (mayDefer) {
  174. fetchRootConfig();
  175. } else {
  176. throw "May not defer bootstrap any more";
  177. }
  178. } else {
  179. if (widgetsets[widgetset].callback) {
  180. log("Starting from bootstrap", appId);
  181. widgetsets[widgetset].callback(appId);
  182. } else {
  183. log("Setting pending startup", appId);
  184. widgetsets[widgetset].pendingApps.push(appId);
  185. }
  186. }
  187. };
  188. bootstrapApp(true);
  189. if (getConfig("debug")) {
  190. // TODO debug state is now global for the entire page, but should somehow only be set for the current application
  191. window.vaadin.debug = true;
  192. }
  193. return app;
  194. },
  195. clients: {},
  196. getApp: function(appId) {
  197. var app = apps[appId];
  198. return app;
  199. },
  200. loadTheme: loadTheme,
  201. registerWidgetset: function(widgetset, callback) {
  202. log("Widgetset registered", widgetset);
  203. widgetsets[widgetset].callback = callback;
  204. for(var i = 0; i < widgetsets[widgetset].pendingApps.length; i++) {
  205. var appId = widgetsets[widgetset].pendingApps[i];
  206. log("Starting from register widgetset", appId);
  207. callback(appId);
  208. }
  209. widgetsets[widgetset].pendingApps = null;
  210. },
  211. getBrowserDetailsParameters: function(parentElementId) {
  212. // Screen height and width
  213. var url = 'v-sh=' + window.screen.height;
  214. url += '&v-sw=' + window.screen.width;
  215. // Window height and width
  216. var cw = 0;
  217. var ch = 0;
  218. if(typeof(window.innerWidth) == 'number') {
  219. // Modern browsers
  220. cw = window.innerWidth;
  221. ch = window.innerHeight;
  222. } else {
  223. // IE 8
  224. cw = document.documentElement.clientWidth;
  225. ch = document.documentElement.clientHeight;
  226. }
  227. url += '&v-cw=' + cw + '&v-ch=' + ch;
  228. var d = new Date();
  229. url += '&v-curdate=' + d.getTime();
  230. var tzo1 = d.getTimezoneOffset(); // current offset
  231. var dstDiff = 0;
  232. var rtzo = tzo1;
  233. for (var m=12;m>0;m--) {
  234. d.setUTCMonth(m);
  235. var tzo2 = d.getTimezoneOffset();
  236. if (tzo1 != tzo2) {
  237. dstDiff = (tzo1 > tzo2 ? tzo1-tzo2 : tzo2-tzo1); // offset w/o DST
  238. rtzo = (tzo1 > tzo2 ? tzo1 : tzo2); // offset w/o DST
  239. break;
  240. }
  241. }
  242. // Time zone offset
  243. url += '&v-tzo=' + tzo1;
  244. // DST difference
  245. url += '&v-dstd=' + dstDiff;
  246. // Raw time zone offset
  247. url += '&v-rtzo=' + rtzo;
  248. // DST in effect?
  249. url += '&v-dston=' + (tzo1 != rtzo);
  250. var pe = document.getElementById(parentElementId);
  251. if (pe) {
  252. url += '&v-vw=' + pe.offsetWidth;
  253. url += '&v-vh=' + pe.offsetHeight;
  254. }
  255. // Location
  256. url += '&v-loc=' + encodeURIComponent(location.href);
  257. // Window name
  258. if (window.name) {
  259. url += '&v-wn=' + encodeURIComponent(window.name);
  260. }
  261. // Detect touch device support
  262. var supportsTouch = false;
  263. try {
  264. document.createEvent("TouchEvent");
  265. supportsTouch = true;
  266. } catch (e) {
  267. // Chrome and IE10 touch detection
  268. supportsTouch = 'ontouchstart' in window
  269. || navigator.msMaxTouchPoints;
  270. }
  271. if (supportsTouch) {
  272. url += "&v-td=1";
  273. }
  274. return url;
  275. }
  276. };
  277. log('Vaadin bootstrap loaded');
  278. })();