rsIFrameManager.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. IBM Confidential
  3. OCO Source Materials
  4. IBM Cognos Products: rs
  5. (C) Copyright IBM Corp. 2018, 2020
  6. The source code for this program is not published or otherwise divested of its trade secrets, irrespective of what has been deposited with the U.S. Copyright Office.
  7. */
  8. define([
  9. 'jquery',
  10. 'q',
  11. 'bi/authoring/utils/rsCommon'
  12. ],
  13. function($, Q, rsCommon){
  14. 'use strict';
  15. function isMyParentTheTopWindow(w)
  16. {
  17. try
  18. {
  19. return Boolean(w.parent == w.top);
  20. }
  21. catch(e)
  22. {
  23. return false;
  24. }
  25. }
  26. var rsIFrameManager = {};
  27. rsIFrameManager.m_iNewFrameId = 1;
  28. rsIFrameManager.F_LaunchRS = function(v_oParameters, v_oGlassContext, v_oLaunchParameters)
  29. {
  30. console.info('rsperf: rsIFrameManager.F_LaunchRS ...');
  31. this.m_oLaunchParameters = v_oLaunchParameters ? v_oLaunchParameters : null;
  32. var v_bPrelaunchTest = false;
  33. if (v_bPrelaunchTest)
  34. {
  35. this.F_PreLaunch(v_oGlassContext);
  36. }
  37. // Do not use prelaunch version is only for viewing or editing reports, do not use if creating or editing a data set
  38. if (this.m_oPrelaunchRSPromise && (v_oGlassContext.currentAppView.currentContentView.perspective !== 'datasets'))
  39. {
  40. console.time('rsIFrameManager.F_LaunchRS->f_relaunchRSIFrameInView');
  41. var v_oIFramePromise = this.m_oPrelaunchRSPromise;
  42. this.m_oPrelaunchRSPromise = null;
  43. console.time("rsperf: Waiting for RS relaunch");
  44. if (v_oIFramePromise.isFulfilled())
  45. {
  46. // avoiding using done for performance reason because the done is called in a setTimeout which allows all sorts of other processing to happen
  47. // normally, this promise will always be resolved by this point
  48. return this.f_relaunchRSIFrameInView(v_oParameters, v_oLaunchParameters, v_oIFramePromise.inspect().value);
  49. }
  50. var v_oRelaunchDeferred = Q.defer();
  51. v_oIFramePromise
  52. .then( this.f_relaunchRSIFrameInView.bind(this, v_oParameters, v_oLaunchParameters))
  53. .done(function(v_idIFrameAuthoring){
  54. v_oRelaunchDeferred.resolve(v_idIFrameAuthoring);
  55. });
  56. return v_oRelaunchDeferred.promise;
  57. }
  58. console.time("rsperf: Launch RS->OnRSApplicationReadyForObservers");
  59. var v_oLaunchDeferred = Q.defer();
  60. this.f_launchRS( v_oGlassContext, v_oParameters,
  61. this.f_onLaunchReadyForObservers.bind(this, v_oGlassContext, v_oLaunchDeferred),
  62. v_oLaunchDeferred.reject.bind(v_oLaunchDeferred, new Error("rsIFrameManager: error during f_launchRS") ) );
  63. return v_oLaunchDeferred.promise;
  64. };
  65. rsIFrameManager.f_relaunchRSIFrameInView = function(v_oParameters, v_oLaunchParameters, v_iframeAuthoring)
  66. {
  67. console.timeEnd('rsIFrameManager.F_LaunchRS->f_relaunchRSIFrameInView');
  68. var v_oIFrameLaunchedDeferred = Q.defer();
  69. console.timeEnd("rsperf: Waiting for RS relaunch");
  70. console.time("rsperf: Launch from prelaunch RS->OnRSApplicationReadyForObservers");
  71. v_iframeAuthoring.OnRSApplicationReadyForObservers = function() {
  72. v_oIFrameLaunchedDeferred.resolve(v_iframeAuthoring.id);
  73. console.timeEnd("rsperf: Launch from prelaunch RS->OnRSApplicationReadyForObservers");
  74. }.bind(this);
  75. var v_oRsParameters = JSON.parse(v_oParameters.rsParameters);
  76. v_iframeAuthoring.contentWindow.Application.Relaunch(v_oRsParameters, v_oLaunchParameters);
  77. return v_oIFrameLaunchedDeferred.promise;
  78. };
  79. rsIFrameManager.f_getBodyRect = function(el)
  80. {
  81. // in the glass the scrollable element is the HTML element not the body as one would expect.
  82. var v_elScrollable = document.documentElement;
  83. var v_oRect = el.getBoundingClientRect();
  84. var v_oBodyRect = document.body.getBoundingClientRect();
  85. return {
  86. top : v_oRect.top - v_oBodyRect.top + (v_elScrollable.scrollTop ? v_elScrollable.scrollTop : 0),
  87. left : v_oRect.left - v_oBodyRect.left + (v_elScrollable.scrollLeft ? v_elScrollable.scrollLeft : 0),
  88. width : v_oRect.width,
  89. height : v_oRect.height
  90. };
  91. };
  92. rsIFrameManager.F_PositionAndSizeIFrame = function($elContainer, v_iframeAuthoring)
  93. {
  94. function f_getZIndex( v_el )
  95. {
  96. var v_elCur = v_el;
  97. while(v_elCur && v_elCur.nodeName != "#document")
  98. {
  99. var v_oStyle = v_elCur.ownerDocument.defaultView.getComputedStyle( v_elCur, null );
  100. var v_iValue = parseInt( v_oStyle.zIndex, 10 );
  101. if (!isNaN(v_iValue) && v_iValue !== 0)
  102. {
  103. return v_iValue;
  104. }
  105. v_elCur = v_elCur.parentNode;
  106. }
  107. return 0;
  108. }
  109. var v_oRect = this.f_getBodyRect($elContainer.get(0));
  110. v_iframeAuthoring.style.top = v_oRect.top + "px";
  111. v_iframeAuthoring.style.left = v_oRect.left + "px";
  112. v_iframeAuthoring.style.width = v_oRect.width + "px";
  113. v_iframeAuthoring.style.height = v_oRect.height + "px";
  114. v_iframeAuthoring.style.zIndex = f_getZIndex($elContainer.get(0)) + 1;
  115. v_iframeAuthoring.style.visibility = "visible";
  116. //console.log("F_PositionAndSizeIFrame: " + v_iframeAuthoring.style.left + "," + v_iframeAuthoring.style.top + " " + v_iframeAuthoring.style.width + "," + v_iframeAuthoring.style.height);
  117. };
  118. rsIFrameManager.F_HideIFrame = function(v_iframeAuthoring)
  119. {
  120. // since the iframe is still taking space in the flow, position it somewhere that doesn't cause scrollbars in glass window
  121. v_iframeAuthoring.style.top = "-5000px";
  122. v_iframeAuthoring.style.left = "-5000px";
  123. v_iframeAuthoring.style.zIndex = -1;
  124. v_iframeAuthoring.style.visibility = "hidden";
  125. };
  126. rsIFrameManager.F_DetachIFrame = function(v_iframeAuthoring)
  127. {
  128. var v_oApplication = v_iframeAuthoring.contentWindow.Application;
  129. if (v_oApplication)
  130. {
  131. v_oApplication.DetachFromGlass();
  132. }
  133. this.m_divRSFrameHolder.removeChild(v_iframeAuthoring);
  134. };
  135. rsIFrameManager.f_createRSIFrame = function(v_oParameters)
  136. {
  137. var v_aHTML = [];
  138. // Added the title to resolve the accessibility issue.
  139. v_aHTML.push('<iframe title="RSIframe" src="');
  140. if (isMyParentTheTopWindow(window))
  141. {
  142. // our parent is the top so
  143. // we can't be nested in another rasp.htm so
  144. // we don't need to add a unique id to our url
  145. v_aHTML.push(v_oParameters.rsUrl);
  146. }
  147. else
  148. {
  149. // both IE does not allow nested iframes for the same URL, so adding a random version to allow the nesting
  150. // other browser all prevent nesting more then 2 levels deep
  151. v_aHTML.push(v_oParameters.rsUrl + "?v=" + Math.random());
  152. }
  153. // ensure iframe has dimensions so that panes don't get sized to their minimums
  154. v_aHTML.push('" style="border:none;top:-5000px;left:-5000px;width:1024px;height:768px;position:absolute;visibility:hidden" data-rsparameters="');
  155. v_aHTML.push(this.f_HTMLAttributeEncode(v_oParameters.rsParameters));
  156. v_aHTML.push('" allowfullscreen="true"/>');
  157. return v_aHTML.join("");
  158. };
  159. rsIFrameManager.f_onLaunchReadyForObservers = function(v_oGlassContext, v_oDeferred, v_iframeAuthoring)
  160. {
  161. console.timeEnd("rsperf: Launch RS->OnRSApplicationReadyForObservers");
  162. var v_oApplication = v_iframeAuthoring.contentWindow.Application;
  163. // RS will need a glass context while launching
  164. v_oApplication.GlassContext = v_oGlassContext;
  165. v_oApplication.LaunchParameters = this.m_oLaunchParameters;
  166. v_oDeferred.resolve(v_iframeAuthoring.id);
  167. };
  168. rsIFrameManager.f_HTMLEncode = function(s)
  169. {
  170. return s.replace( /&/g, "&amp;" ).replace( /</g, "&lt;" ).replace( />/g, "&gt;" );
  171. };
  172. rsIFrameManager.f_HTMLAttributeEncode = function(s)
  173. {
  174. return this.f_HTMLEncode(s).replace( /'/g, "&#39;" ).replace( /"/g, "&quot;" );
  175. };
  176. rsIFrameManager.f_prelaunchRS = function(v_oGlassContext, v_fnOnLaunched, v_fnOnLaunchError)
  177. {
  178. console.time("rsperf: prelaunch RS");
  179. var v_oRsParameters = rsCommon.createRSParameters( {}, v_oGlassContext );
  180. v_oRsParameters.prelaunchRS = true;
  181. this.f_launchRS(v_oGlassContext, rsCommon.createTemplateParameters(v_oRsParameters), this.f_onPrelaunchRSReadyForObservers.bind(this, v_oGlassContext, v_fnOnLaunched), v_fnOnLaunchError);
  182. };
  183. rsIFrameManager.f_launchRS = function(v_oGlassContext, v_oParameters, v_fnOnLaunched, v_fnOnLaunchError)
  184. {
  185. if (!this.m_divRSFrameHolder)
  186. {
  187. $("body").prepend('<div style="position:absolute;top:0px;left:0px;visibility:hidden"></div>');
  188. this.m_divRSFrameHolder = $("body").find("div").get(0);
  189. }
  190. var $divRSFrameHolder = $(this.m_divRSFrameHolder);
  191. $divRSFrameHolder.prepend(this.f_createRSIFrame(v_oParameters));
  192. var v_iframeAuthoring = $divRSFrameHolder.find("iframe").get(0);
  193. v_iframeAuthoring.id = "rsIFrameManager_" + this.m_iNewFrameId++;
  194. v_iframeAuthoring.OnRSApplicationReadyForObservers = v_fnOnLaunched.bind(null, v_iframeAuthoring);
  195. v_iframeAuthoring.onerror = v_fnOnLaunchError;
  196. };
  197. rsIFrameManager.f_onPrelaunchRSReadyForObservers = function(v_oGlassContext, v_fnOnLaunched, v_iframeAuthoring)
  198. {
  199. var v_oApplication = v_iframeAuthoring.contentWindow.Application;
  200. v_oApplication.GlassContext = v_oGlassContext;
  201. v_oApplication.LaunchParameters = this.m_oLaunchParameters;
  202. if ( v_oApplication.SharedState.Get("isAppLoaded") )
  203. {
  204. this.f_onPrelaunchAppLoaded(v_iframeAuthoring, v_fnOnLaunched);
  205. }
  206. else
  207. {
  208. v_oApplication.SharedState.AddObserver("rsIFrameManager", "isAppLoaded", this.f_onPrelaunchAppLoaded.bind(this, v_iframeAuthoring, v_fnOnLaunched, true) );
  209. }
  210. };
  211. rsIFrameManager.f_onPrelaunchAppLoaded = function(v_iframeAuthoring, v_fnOnLaunched, v_bRemoveObserver)
  212. {
  213. console.timeEnd("rsperf: prelaunch RS");
  214. if (v_bRemoveObserver)
  215. {
  216. var v_oApplication = v_iframeAuthoring.contentWindow.Application;
  217. v_oApplication.SharedState.RemoveObserver("rsIFrameManager", "isAppLoaded");
  218. }
  219. setTimeout(v_fnOnLaunched.bind(null, v_iframeAuthoring), 0);
  220. };
  221. rsIFrameManager.F_PreLaunch = function(v_oGlassContext)
  222. {
  223. if (this.m_oPrelaunchRSPromise)
  224. {
  225. return;
  226. }
  227. var v_oDefer = Q.defer();
  228. this.m_oPrelaunchRSPromise = v_oDefer.promise;
  229. this.f_prelaunchRS(v_oGlassContext, function(v_idIFrameAuthoring) {
  230. v_oDefer.resolve(v_idIFrameAuthoring);
  231. }.bind(this), v_oDefer.resolve.bind(v_oDefer, null));
  232. };
  233. return rsIFrameManager;
  234. });