cvContentView.js 79 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288
  1. /*
  2. IBM Confidential
  3. OCO Source Materials
  4. IBM Cognos Products: authoring
  5. (C) Copyright IBM Corp. 2015, 2022
  6. The source code for this program is not published or otherwise divested
  7. of its trade secrets, irrespective of what has been deposited with the
  8. U.S. Copyright Office.
  9. */
  10. define( [
  11. 'bi/glass/app/ContentView',
  12. 'jquery',
  13. 'q',
  14. 'bi/classicviewer/nls/StringResource',
  15. 'bi/commons/utils/Utils',
  16. 'bi/authoring/utils/pat/rsLaunchParameters',
  17. 'bi/authoring/utils/pat/rsPromptParameters',
  18. 'bi/authoring/utils/rsPerformance',
  19. 'bi/authoring/utils/rsCommon',
  20. 'bi/authoring/utils/rsOpenHelper',
  21. 'bi/authoring/utils/rsShareHelper',
  22. 'bi/authoring/utils/rsPromptHandler',
  23. 'bi/admin/common/utils/parameters/ParameterValues'],
  24. function(ContentView, $, Q, StringResource, Utils, rsLaunchParameters, rsPromptParameters, rsPerformance, rsCommon, rsOpenHelper, rsShareHelper, rsPromptHandler, ParameterValues)
  25. {
  26. 'use strict';
  27. var classicViewerGatewaySuffix = "v1/disp";
  28. var promptPageEndpoint = "/rds/promptPage/report/";
  29. var cvFormFields = [
  30. "cv.navlinks",
  31. "cv.header",
  32. "cv.toolbar",
  33. "cv.selection",
  34. "cv.drill",
  35. "cv.contextInfo",
  36. "cv.contextmenu",
  37. "cv.id",
  38. "cv.responseFormat",
  39. "cv.rsProfile",
  40. "cv.showFaultPage",
  41. "cv.useAjax",
  42. "cv.reuseConversation",
  43. "cv.promptForDownload",
  44. "cv.gateway",
  45. "cv.webcontent",
  46. "cv.keepWindowOpen",
  47. "ui.action",
  48. "ui.cafcontextid",
  49. "ui.conversation",
  50. "ui.spec",
  51. "ui.errURL",
  52. "ui.routingServerGroup",
  53. "ui.name",
  54. "ui.object",
  55. "run.outputFormat",
  56. "run.outputLocale",
  57. "run.outputPageDefinition",
  58. "run.outputPageOrientation",
  59. "run.verticalElements",
  60. "run.horizontalElements",
  61. "run.prompt",
  62. "run.xslURL",
  63. "run.data",
  64. "specification.editSpecification",
  65. "modelPath",
  66. "m_tracking",
  67. "parameterValues",
  68. "reuseResults",
  69. "keepIterators",
  70. "rs_aliases",
  71. "authenticitytoken",
  72. "specificationType",
  73. "system.http://developer.cognos.com/ceba/constants/systemOptionEnum#accessibilityFeatures",
  74. "biDirectional.http://developer.cognos.com/ceba/constants/biDirectionalOptionEnum#biDirectionalFeaturesEnabled",
  75. "generic.anyURI.runOptionEnum#globalParameters",
  76. "isTitan",
  77. "IncludePerformance"
  78. ];
  79. // Pattern to extract search path from defaultOutput method
  80. var g_reDefaultOutput = /^defaultOutput\((.*),\s*'[^']*'\s*,\s*'[^']*'\s*\)/;
  81. var cvContentView = ContentView.extend({
  82. init: function(options, appView) {
  83. rsCommon.decodeAndMoveCMProperties(options);
  84. rsCommon.convertStringQSToValues(options, options.glassContext);
  85. rsCommon.decodeAndMoveRSOptions(options);
  86. // After the following call, every member of options is now a member of this
  87. cvContentView.inherited('init', this, arguments);
  88. this.m_sTitle = StringResource.get('classicviewer_welcome');
  89. this.m_oAppView = appView;
  90. try
  91. {
  92. // to open a report passed on the URL and pass parameters, we need access to the
  93. // launch parameters stored in the calling window's Application object
  94. var v_oLaunchParameters = rsLaunchParameters.Retrieve(this.launchParametersKey);
  95. if (!v_oLaunchParameters && window.opener && !window.opener.closed && window.opener.RSParameters)
  96. {
  97. var v_sLaunchParametersKey = window.opener.RSParameters.launchParametersKey;
  98. var v_oLaunchParameters = rsLaunchParameters.Retrieve(v_sLaunchParametersKey);
  99. }
  100. else if (window.parent && options.launchParametersRef && window.parent[options.launchParametersRef])
  101. {
  102. this.m_oPromptContext = window.parent[options.launchParametersRef].promptContext;
  103. }
  104. if (v_oLaunchParameters)
  105. {
  106. // merge options with the values pointed to by the key
  107. // the options from the object pointed to by the key take precedence
  108. $.extend(true, this, v_oLaunchParameters);
  109. }
  110. }
  111. catch(e)
  112. {
  113. console.log("cvContentView.init() - Call to window.opener failed, assume it doesn't exist");
  114. }
  115. // console.log("end: cvContentView.init" );
  116. this.m_bFullyInitialized = false;
  117. // Name of the classic viewer creation callback method
  118. this.m_sCreateCallback = "cvCreateCallback" + Date.now();
  119. },
  120. _postInit: function() {
  121. if (this.m_bFullyInitialized) {
  122. return;
  123. }
  124. this.m_bFullyInitialized = true;
  125. var options = this;
  126. if (options.type == 'output' && options.cmProperties && options.cmProperties.parent && options.cmProperties.parent[0] && options.cmProperties.parent[0].parent) {
  127. // If processing an output object and we have ancestor information, generate the saved output name.
  128. var v_sReportName = options.cmProperties.parent[0].parent[0].defaultName;
  129. this.m_sTitle = v_sReportName + " - " + options.cmProperties.modificationTime.substring(0, 10)+ " - " + options.cmProperties.format;
  130. }
  131. else if (options.cmProperties && options.cmProperties.defaultName)
  132. {
  133. this.m_sTitle = options.cmProperties.defaultName;
  134. }
  135. else if (options.defaultName)
  136. {
  137. this.m_sTitle = options.defaultName;
  138. }
  139. if (options.rsFinalRunOptions) {
  140. if (typeof options.rsFinalRunOptions.format != 'undefined')
  141. {
  142. options.format = options.rsFinalRunOptions.format;
  143. }
  144. if (typeof options.rsFinalRunOptions.locale != 'undefined')
  145. {
  146. // test how used
  147. options.locale = options.rsFinalRunOptions.locale;
  148. }
  149. if ( typeof options.rsFinalRunOptions.prompt !== 'undefined')
  150. {
  151. options.prompt = options.rsFinalRunOptions.prompt;
  152. }
  153. if (typeof options.rsFinalRunOptions.a11y != 'undefined')
  154. {
  155. options.a11y = options.rsFinalRunOptions.a11y;
  156. }
  157. if (typeof options.rsFinalRunOptions.bidi != 'undefined')
  158. {
  159. options.bidi = options.rsFinalRunOptions.bidi;
  160. }
  161. if (typeof options.rsFinalRunOptions.editSpecification != 'undefined')
  162. {
  163. options.editSpecification = options.rsFinalRunOptions.editSpecification;
  164. }
  165. delete options.rsFinalRunOptions;
  166. }
  167. // let create a form to submit to the classicviewer
  168. // TODO....change m_oRVFormParamters to something more meaningful like m_oClassicViewerForm?
  169. this.m_oRVFormParameters = {};
  170. // Transfer all options.xxx fields where xxx is a recognised form field name to m_oRVFormParameters
  171. cvFormFields.forEach(function(v_sFormField){
  172. if (typeof options[v_sFormField] != 'undefined') {
  173. this.m_oRVFormParameters[v_sFormField] = options[v_sFormField];
  174. }
  175. }, this);
  176. if (options.format && !this.m_oRVFormParameters['run.outputFormat']) {
  177. this.m_oRVFormParameters['run.outputFormat'] = options.format;
  178. }
  179. if (options.contentLocale) {
  180. this.m_oRVFormParameters['run.outputLocale'] = options.contentLocale;
  181. }
  182. if (typeof options.prompt != 'undefined') {
  183. this.m_oRVFormParameters['run.prompt'] = (typeof options.prompt === "string") ? (options.prompt == "true") : !!options.prompt;
  184. }
  185. else
  186. { // for classical report running from RS, we treated undefined as true
  187. this.m_oRVFormParameters['run.prompt'] = true;
  188. }
  189. if (typeof options.a11y != 'undefined') {
  190. this.m_oRVFormParameters["system.http://developer.cognos.com/ceba/constants/systemOptionEnum#accessibilityFeatures"] = !!(options.a11y);
  191. }
  192. if (typeof options.bidi != 'undefined') {
  193. this.m_oRVFormParameters["biDirectional.http://developer.cognos.com/ceba/constants/biDirectionalOptionEnum#biDirectionalFeaturesEnabled"] = !!(options.bidi);
  194. }
  195. if (typeof options.editSpecification != 'undefined') {
  196. // This option is an XML string so only set it if we actually have something
  197. this.m_oRVFormParameters["specification.editSpecification"] = options.editSpecification;
  198. }
  199. // Ensure viewer renders the client side viewer in the response.
  200. // By default, PDF with accessibility enabled produces a page with PDF only and no viewer
  201. this.m_oRVFormParameters["ui.reuseWindow"] = true;
  202. this.m_oRVFormParameters["cv.createCallback"] = this.m_sCreateCallback;
  203. if (options.parameterValuesJSON)
  204. {
  205. this.m_oRVFormParameters["parameterValues"] = rsPromptParameters.rsBuildPromptParameters(null, options.parameterValuesJSON);
  206. }
  207. else if (options.parameterValuesXML) {
  208. this.m_oRVFormParameters["parameterValues"] = options.parameterValuesXML;
  209. }
  210. //Prompt parameters simple format
  211. this.m_aPromptParameters = [];
  212. for(var v_sKey in options)
  213. {
  214. if (options.hasOwnProperty(v_sKey) && v_sKey.indexOf('p_') == 0 && options[v_sKey])
  215. {
  216. this.m_aPromptParameters.push({name: v_sKey, value: options[v_sKey]});
  217. }
  218. }
  219. //Prompt parameters defined in json
  220. this.m_aPromptParametersComplex = [];
  221. if (options["promptParameters"])
  222. {
  223. this.m_aPromptParametersComplex = Array.isArray(options["promptParameters"]) ? options["promptParameters"] : [options["promptParameters"]];
  224. }
  225. var v_sSearchPath = this.getSearchPath();
  226. var v_sStoreId = this.cmProperties && this.cmProperties.id;
  227. // Prefer search path over store ID since external lineage expects a standard search path
  228. var v_sReportSearchPath = v_sSearchPath || (v_sStoreId ? 'storeID("' + v_sStoreId + '")': "");
  229. this.m_oRVFormParameters['ui.object'] = v_sReportSearchPath;
  230. if (!this.m_oRVFormParameters['ui.object']) {
  231. this.m_oRVFormParameters['cv.id'] = 'RS';
  232. // this.m_oRVFormParameters['ui.errURL'] = 'javascript:window.close()';
  233. }
  234. if (this.type == 'output')
  235. {
  236. this.m_oRVFormParameters['ui.action'] = 'view';
  237. // Remove "run." parameters since we are viewing
  238. // Some of these override the ui.action=view and cause a run instead which is not what we want.
  239. for (var v_sProp in this.m_oRVFormParameters)
  240. {
  241. if (v_sProp.substring(0, 4) == "run.")
  242. {
  243. delete this.m_oRVFormParameters[v_sProp];
  244. }
  245. }
  246. }
  247. else
  248. {
  249. // deletions are to ensure empty form fields are
  250. // not passed to viewer to avoid CAF rejecting them.
  251. if (this.m_oRVFormParameters['ui.object']) {
  252. this.m_oRVFormParameters['ui.action'] = 'run';
  253. delete this.m_oRVFormParameters['ui.spec'];
  254. }
  255. else if (this.m_oRVFormParameters['ui.spec']) {
  256. this.m_oRVFormParameters['ui.action'] = 'runSpecification';
  257. delete this.m_oRVFormParameters['ui.object'];
  258. }
  259. else {
  260. delete this.m_oRVFormParameters['ui.action'];
  261. delete this.m_oRVFormParameters['ui.spec'];
  262. delete this.m_oRVFormParameters['ui.object'];
  263. this.glassContext.showToast(StringResource.get('invalid_refresh'), {type:'error'});
  264. }
  265. }
  266. // We want to explicitly turn off the header (which says Cognos Viewer) as well as the toolbars
  267. this.m_oRVFormParameters["cv.header"] = false;
  268. this.m_oRVFormParameters["cv.toolbar"] = false;
  269. this.m_oRVFormParameters["cv.keepWindowOpen"]=true;
  270. this.m_oRVFormParameters["isTitan"] = true;
  271. if (this.glassContext &&
  272. this.glassContext.services &&
  273. this.glassContext.services.userProfile &&
  274. this.glassContext.services.userProfile.userProfileSettings &&
  275. this.glassContext.services.userProfile.userProfileSettings.parameter_values)
  276. {
  277. this.m_oRVFormParameters["generic.anyURI.runOptionEnum#globalParameters"] = ParameterValues.toXML(this.glassContext.services.userProfile.userProfileSettings.parameter_values);
  278. }
  279. },
  280. showWaitIndicator: function() {
  281. this.m_elDivViewerContainer.style.visibility = "hidden";
  282. this.m_elDivStartUp.style.visibility = "visible";
  283. },
  284. hideWaitIndicator: function() {
  285. this.m_elDivStartUp.style.visibility = "hidden";
  286. this.m_elDivViewerContainer.style.visibility = "visible";
  287. },
  288. _getNameFromViewer: function () {
  289. var v_oViewer = this.getCognosViewer();
  290. return v_oViewer && v_oViewer.envParams && v_oViewer.envParams['ui.name'];
  291. },
  292. getTitle: function() {
  293. // console.log("In cvContentView.getTitle\n");
  294. return this.m_sTitle;
  295. },
  296. getIcon: function() {
  297. //console.log("In cvContentView.getIcon\n");
  298. return 'common-report';
  299. },
  300. getIconTooltip: function() {
  301. //console.log("In cvContentView.getIconTooltip\n");
  302. return StringResource.get('classicviewer_welcome');
  303. },
  304. /**
  305. * Get the store ID of the underlying report object
  306. */
  307. getReportStoreId: function() {
  308. if (rsCommon.isObjectOfType(this.cmProperties, 'output')) {
  309. return this.cmProperties.parent[0].parent[0].id;
  310. }
  311. return this.cmProperties && this.cmProperties.id;
  312. },
  313. /**
  314. * Get the search path of the underlying report object
  315. */
  316. getSearchPath: function() {
  317. return this.cmProperties && this.cmProperties.searchPath;
  318. },
  319. getType: function() {
  320. var v_sType = this.cmProperties && this.cmProperties.type;
  321. if (!v_sType)
  322. {
  323. //When a classic report is launched from shared URL, we will not have cmPromperties, nor the type, we need to get the type from the viewer itself.
  324. var v_oCV = this.getCognosViewer();
  325. v_sType = v_oCV && v_oCV.envParams["ui.objectClass"];
  326. }
  327. return v_sType;
  328. },
  329. getTimeStamp: function() {
  330. //console.log("In cvContentView.getTimeStamp\n");
  331. return new Date().toUTCString();
  332. },
  333. updateButtons: function() {
  334. // Determine if readable. Assume readable if permissions not provided.
  335. var v_bRead = true;
  336. if (this.cmProperties && this.cmProperties.permissions && this.cmProperties.permissions.indexOf("read") == -1) {
  337. v_bRead = false;
  338. }
  339. var v_bShowEdit = false;
  340. //StoreId will be null if Authoring has launched classic viewer (because we are doing a runspec)
  341. if (this.glassContext.hasCapability("canUseReportStudio") && this.getReportStoreId() && v_bRead)
  342. {
  343. v_bShowEdit = true;
  344. }
  345. if (this.cmProperties && this.cmProperties.type == 'reportView')
  346. {
  347. // Don't allow edit on report views
  348. v_bShowEdit = false;
  349. }
  350. else if (this.cmProperties && this.cmProperties.type == 'report'
  351. && this.cmProperties.metadataModelPackage && this.cmProperties.metadataModelPackage[0] && this.cmProperties.metadataModelPackage[0].effectiveUserCapabilities)
  352. {
  353. if (this.cmProperties.metadataModelPackage[0].effectiveUserCapabilities.indexOf('canUseReportStudio') === -1 )
  354. {
  355. v_bShowEdit = false;
  356. }
  357. }
  358. if (this.type == "output" || (this.cmProperties && this.cmProperties.type == "output"))
  359. {
  360. var v_bRun = this.cmProperties.permissions.indexOf("execute") != -1;
  361. this._setDisplayForPlugins(v_bRun, ["com.ibm.bi.classicviewer.outputBtn"]);
  362. this._setDisplayForPlugins(false, ["com.ibm.bi.classicviewer.saveBtn",
  363. "com.ibm.bi.classicviewer.editBtn",
  364. "com.ibm.bi.classicviewer.runMenu",
  365. "com.ibm.bi.classicviewer.previousReportBtn"]);
  366. }
  367. else
  368. {
  369. var v_bHasStoreId = !!this.getReportStoreId();
  370. var v_sPluginId = "com.ibm.bi.classicviewer.editBtn";
  371. this._setDisplayForPlugins(v_bShowEdit, [v_sPluginId]);
  372. this._setDisplayForPlugins(v_bHasStoreId, ["com.ibm.bi.classicviewer.saveBtn"]);
  373. this._setDisplayForPlugins(v_bHasStoreId, ["com.ibm.bi.classicviewer.runMenu"]);
  374. this._setDisplayForPlugins(false, ["com.ibm.bi.classicviewer.previousReportBtn","com.ibm.bi.classicviewer.outputBtn"]);
  375. }
  376. },
  377. /**
  378. * Make the viewer iframe visible and hide the 'wait' indicator.
  379. */
  380. _showViewer: function() {
  381. this.hideWaitIndicator();
  382. this.updateButtons();
  383. delete window.OnErrorPage;
  384. //console.log("end: cvContentView._showViewer\n");
  385. },
  386. show: function()
  387. {
  388. this.m_bDeactivated = undefined;
  389. cvContentView.inherited('show', this, arguments);
  390. if (this.m_aFnCallbacks)
  391. { // show saved plugings status
  392. var fnCallback;
  393. while (this.m_aFnCallbacks.length > 0)
  394. {
  395. fnCallback = this.m_aFnCallbacks.shift();
  396. fnCallback();
  397. }
  398. }
  399. },
  400. _setEnabledForPlugins: function(v_bEnabled, v_aPluginIds)
  401. {
  402. v_aPluginIds.forEach(function(v_sPluginId)
  403. {
  404. var v_oPlugin = this.findPlugin(v_sPluginId);
  405. if (v_oPlugin)
  406. {
  407. if (v_bEnabled)
  408. {
  409. // console.log('%s show', v_sPluginId);
  410. v_oPlugin.enable();
  411. }
  412. else
  413. {
  414. // console.log('%s hide', v_sPluginId);
  415. v_oPlugin.disable();
  416. }
  417. }
  418. else
  419. {
  420. console.log('could not find plugin: %s', v_sPluginId);
  421. }
  422. }, this.glassContext);
  423. },
  424. _setDisplayForPlugins: function(v_bShow, v_aPluginIds) {
  425. //console.group("cvContentView._setDisplayForPlugins");
  426. //console.log("v_bShow:%s", v_bShow);
  427. v_aPluginIds.forEach(
  428. function(v_sPluginId) {
  429. var v_oPlugin = this.findPlugin(v_sPluginId);
  430. if ( v_oPlugin )
  431. {
  432. if (v_bShow)
  433. {
  434. // console.log('%s show', v_sPluginId);
  435. v_oPlugin.show();
  436. }
  437. else
  438. {
  439. // console.log('%s hide', v_sPluginId);
  440. v_oPlugin.hide();
  441. }
  442. }
  443. else
  444. {
  445. console.log('could not find plugin: %s', v_sPluginId);
  446. }
  447. },
  448. this.glassContext );
  449. //console.groupEnd();
  450. },
  451. _isInternetExplorer: function()
  452. {
  453. var v_sAgent = navigator.userAgent.toLowerCase();
  454. var v_fIEVersion = ( v_sAgent.search(/trident\/([0-9]+\.[0-9]+)/) != -1 ) ? parseFloat( RegExp.$1 ) : 0;
  455. return (v_fIEVersion >= 7.0);
  456. },
  457. removePdfClass: function()
  458. {
  459. if (this._isInternetExplorer())
  460. {
  461. this.m_elDivViewerContainer.classList.remove('PdfViewer');
  462. }
  463. },
  464. addPdfClass: function()
  465. {
  466. if (this._isInternetExplorer())
  467. {
  468. //console.log("Setting PdfViewer class for IE");
  469. this.m_elDivViewerContainer.classList.add('PdfViewer');
  470. }
  471. },
  472. onReportStatusComplete: function() {
  473. rsPerformance.mark('cvContentView.onReportStatusComplete');
  474. console.timeEnd('rsperf: render->reportStatusComplete');
  475. if (!!this.getReportStoreId())
  476. {
  477. this._setEnabledForPluginsLazily(true, ["com.ibm.bi.classicviewer.saveBtn", "com.ibm.bi.classicviewer.runMenu"]);
  478. }
  479. // did we do something that changed the title?
  480. //if (this.m_sTitle)
  481. //{
  482. // var v_sViewerName = this._getNameFromViewer();
  483. // if (v_sViewerName && this.m_sTitle != v_sViewerName)
  484. // {
  485. // this.m_sTitle = v_sViewerName;
  486. // this.trigger('change:title', {'value': this.m_sTitle});
  487. // }
  488. //}
  489. var v_oCognosViewer = this.getCognosViewer();
  490. if (v_oCognosViewer && v_oCognosViewer.outputFormat == "PDF")
  491. {
  492. this.addPdfClass();
  493. // Get PDF iframe
  494. this.m_iFramePDF = this.m_iframeClassicViewer.contentDocument.querySelector("iframe");
  495. }
  496. else {
  497. this.removePdfClass();
  498. delete this.m_iFramePDF;
  499. }
  500. },
  501. onReportStatusPrompting: function() {
  502. if (!!this.getReportStoreId())
  503. {
  504. this._setEnabledForPluginsLazily(false, ["com.ibm.bi.classicviewer.saveBtn", "com.ibm.bi.classicviewer.runMenu"]);
  505. // NOTE : Setting focus on the window did not work, but setting focus to the control did.
  506. // Not sure why. If you can think of a better way...great.
  507. // Change at your own risk.
  508. // get a node list of all the prompting control widgets
  509. var v_sCSSSelectors = ".clsTextWidget, .clsSelectDateEditBox, .clsSelectDateYearEditBox, .clsSelectDateEditBox, .clsSelectDateYearEditBox";
  510. var v_nlPromptingControl = this.m_iframeClassicViewer.contentDocument.querySelectorAll(v_sCSSSelectors);
  511. // classnames of all the prompting control widgets including the prompt buttons
  512. var v_sCSSAllSelectors = v_sCSSSelectors + ", .bp";
  513. if (v_nlPromptingControl.length > 0)
  514. {
  515. var v_aSelectors = v_sCSSAllSelectors.split(", ");
  516. // Check the active element matches one of the desired classname
  517. var bFound = v_aSelectors.includes("." + this.m_iframeClassicViewer.contentDocument.activeElement.className);
  518. // if none of them has a focus, set focus to the first non-button one.
  519. if (bFound == false) {
  520. v_nlPromptingControl[0].focus();
  521. }
  522. }
  523. }
  524. },
  525. _setEnabledForPluginsLazily: function(v_bEnabled, v_aPluginIds)
  526. {
  527. if (this.m_bDeactivated)
  528. {
  529. /**
  530. * this is for a long run report. when the running report's appView is hided behind and the report finish running,
  531. * this.findPlugin() function could find any plugin correctly, because glass always try to find plugin from current appView
  532. * which is not the long run report belong's to. so here, keep those status and do them when user switch the long run report's appView back to active
  533. */
  534. if (!this.m_aFnCallbacks)
  535. {
  536. this.m_aFnCallbacks = [];
  537. }
  538. this.m_aFnCallbacks.push(function() {
  539. this._setEnabledForPlugins(v_bEnabled, v_aPluginIds);
  540. }.bind(this));
  541. }
  542. else
  543. {
  544. this._setEnabledForPlugins(v_bEnabled, v_aPluginIds);
  545. }
  546. },
  547. getViewerConfiguration: function() {
  548. console.timeEnd('rsperf: render->getViewerConfiguration');
  549. rsPerformance.mark('cvContentView.getViewerConfiguration');
  550. return {
  551. httpRequestCallbacks: {
  552. reportStatus: {
  553. complete: this.onReportStatusComplete.bind(this),
  554. prompting: this.onReportStatusPrompting.bind(this)
  555. }
  556. }
  557. };
  558. },
  559. render: function() {
  560. if (this.rsResolved) {
  561. // urlMap already fully resolved so proceed with rendering
  562. return this._render();
  563. }
  564. // Perspective was launched directly without going through rsOpenHelper
  565. // Complete open resolution then proceed with render.
  566. if (!this.cmProperties && this.objRef) {
  567. // Create cmProperties from available information so resolution has something to work with
  568. this.cmProperties = {
  569. id: this.objRef,
  570. type: this.type // may or not be available but that is OK
  571. };
  572. }
  573. var v_oOpenSpec = {
  574. cmProperties: this.cmProperties,
  575. glassContext: this.glassContext,
  576. urlMap: this
  577. };
  578. return rsOpenHelper.resolveUrlMap(v_oOpenSpec).then(function(v_oResolvedOpenSpec) {
  579. // Merge resolved urlMap back into this instance and proceed with rendering
  580. $.extend(this, v_oResolvedOpenSpec.urlMap);
  581. return this._render();
  582. }.bind(this));
  583. },
  584. _cleanPromptContext: function() {
  585. delete window.OnReportOutput;
  586. delete window.OnErrorPage;
  587. delete window.FinishCollectPrompts;
  588. this.m_oPromptContext.promptOpener.close();
  589. },
  590. _render: function() {
  591. // Perform any final initialization now that urlMap is fully resolved
  592. this._postInit();
  593. // Update the buttons before we display the view in order to prevent flicker (REPORT-11732)
  594. this.updateButtons();
  595. // This method returns a promise whose resolution signals the glass that our content view is done drawing.
  596. // Our view adds an iframe to the document and we use the onload event to trigger further processing to avoid race conditions.
  597. // The problem is the onload is called when the iframe is added to the document but also when the glass processes the promise resolution.
  598. // We need to defer our onload processing to the second call because any work done on the first load will get erased by the second load
  599. // (iframe src is about:blank).
  600. // One wrinkle in this is that under Edge, the iframe is not loaded when the glass promise is resolved so it must process things slightly differently.
  601. var deferred = $.Deferred();
  602. console.timeEnd('rsperf: onSelectItem->render');
  603. console.time('rsperf: render->loadIframe');
  604. rsPerformance.mark('cvContentView.render');
  605. this.$el.empty();
  606. // Create wait indicator
  607. var v_aWaiting = document.getElementsByClassName("loadingIndicatorContainer");
  608. var v_oWaiting = (v_aWaiting && v_aWaiting.length > 0) ? v_aWaiting.item(0) : null;
  609. this.m_elDivStartUp = document.createElement('div');
  610. this.m_elDivStartUp.innerHTML = v_oWaiting ? v_oWaiting.outerHTML : "";
  611. this.$el.append(this.m_elDivStartUp);
  612. // Create viewer div
  613. this.m_elDivViewerContainer = document.createElement('div');
  614. this.m_elDivViewerContainer.style.width = "100%";
  615. this.m_elDivViewerContainer.style.height = "100%";
  616. this.m_elDivViewerContainer.style.position = "absolute";
  617. this.m_elDivViewerContainer.style.visibility = "hidden";
  618. this.$el.append(this.m_elDivViewerContainer);
  619. // Create viewer iframe
  620. this.m_iframeClassicViewer = document.createElement('iframe');
  621. this.m_iframeClassicViewer.name = this.m_iframeClassicViewer.title = this.id || '_classicViewer';
  622. this.m_iframeClassicViewer.src = "about:blank";
  623. this.m_iframeClassicViewer.style.border = "none";
  624. this.m_iframeClassicViewer.style.width = "100%";
  625. this.m_iframeClassicViewer.style.height = "100%";
  626. this.m_iframeClassicViewer.style.position = "absolute";
  627. // HACK: the Glass doesn't have an API to squish the sidebar
  628. this.m_oAppView.$('.navbar').addClass('narrow');
  629. console.time('rsperf: render->getViewerConfiguration');
  630. window.getViewerConfiguration = this.getViewerConfiguration.bind(this);
  631. console.time('rsperf: render->reportStatusComplete');
  632. // prompting for collectParameterValues in classical viewer
  633. if (this.m_oPromptContext && this.m_oPromptContext.promptOpener && this.getReportStoreId())
  634. {
  635. // The following callback is invoked from prompt pages.
  636. // If a report has no parameters then no prompt page is rendered so we never
  637. // show the window - this is what we want. If we do show the window when there a no prompt pages, then
  638. // when we close the window in FinishCollectPrompts (see above), this terminates the java script which prevents
  639. // the caller from displaying the correct toasts.
  640. window.OnReportOutput = function() {
  641. // show prompting window if we have not already done so
  642. if (!this.m_oPromptContext.promptOpenerShown)
  643. {
  644. this._showViewer();
  645. this.m_oPromptContext.promptOpener.show();
  646. this.m_oPromptContext.promptOpenerShown = true;
  647. }
  648. }.bind(this);
  649. // Callback from classic error page
  650. window.OnErrorPage = function( code, message, details ) {
  651. if (this.m_oPromptContext.promptFnErrorCallback) {
  652. var error = {
  653. "code": code,
  654. "message": message,
  655. "details": details
  656. };
  657. this.m_oPromptContext.promptFnErrorCallback( error );
  658. }
  659. else if (this.m_oPromptContext.promptFnCancelCallback) {
  660. this.m_oPromptContext.promptFnCancelCallback();
  661. }
  662. this._cleanPromptContext();
  663. }.bind(this);
  664. // classical API function, this is called when finishing prompting
  665. window.FinishCollectPrompts = function(success) {
  666. if (success) {
  667. if (this.m_oPromptContext.promptFnOkCallback1)
  668. {
  669. console.log("promptContext.promptFnOkCallback1");
  670. // This version of the OK callback will invoke the prompting service to retrieve the results.
  671. // This resolves a strange behavior in IE (see APAR 14584 which applies to reports as well as QS)
  672. this.m_oPromptContext.promptFnOkCallback1();
  673. this._cleanPromptContext();
  674. }
  675. else
  676. {
  677. console.log("promptContext.promptFnOkCallback");
  678. this.glassContext.getSvc('.Prompting').then(function(promptingSvc) {
  679. promptingSvc.getPromptAnswers(this.m_oPromptContext.promptRDSId).then( function(values) {
  680. this.m_oPromptContext.promptFnOkCallback(values);
  681. this._cleanPromptContext();
  682. }.bind(this));
  683. }.bind(this));
  684. }
  685. }
  686. else
  687. {
  688. if (this.m_oPromptContext.promptFnCancelCallback) {
  689. this.m_oPromptContext.promptFnCancelCallback();
  690. }
  691. this._cleanPromptContext();
  692. }
  693. }.bind(this);
  694. // RDS request for prompt ID
  695. this.glassContext.services.ajax.ajax({
  696. url: classicViewerGatewaySuffix + promptPageEndpoint + this.getReportStoreId(),
  697. type: 'GET',
  698. dataType: 'xml'
  699. }).done(function(xmlDoc, status, jqXHR) {
  700. this.m_oPromptContext.promptRDSId = xmlDoc.getElementsByTagNameNS('http://developer.cognos.com/schemas/rds/types/2', 'promptID').item(0).textContent;
  701. this.m_oPromptContext.promptOpener.id = this.m_oPromptContext.promptRDSId;
  702. // Store any parameter values provided by the caller in the runTimeState object which is created by the
  703. // call to the promptPageEndpoint above.
  704. // The promting XTS pages look for initial parameter values in this runTimeState object.
  705. var v_sParameterValues = rsPromptParameters.rsBuildPromptParameters( null, this.m_oPromptContext.parameters );
  706. this.glassContext.services.ajax.ajax({
  707. type: 'PUT',
  708. url: 'v1/objects/' + this.m_oPromptContext.promptRDSId,
  709. data: JSON.stringify(
  710. {
  711. type: 'runTimeState',
  712. state: v_sParameterValues
  713. }),
  714. headers: {
  715. 'Accept': 'application/json',
  716. 'Content-Type': 'application/json'
  717. }
  718. }).done(function(){
  719. // submit collectParameterValues request based on report id and prompt id
  720. this._createAndSubmitCollectParameterValuesForm(this.getReportStoreId(), xmlDoc.getElementsByTagNameNS('http://developer.cognos.com/schemas/rds/types/2', 'url').item(0).textContent);
  721. deferred.resolve(this.$el);
  722. }.bind(this));
  723. }.bind(this));
  724. }
  725. else
  726. {
  727. // onload must be specified before iframe is attached to the document because Chrome will trigger the load immediately
  728. this.m_iframeClassicViewer.onload = this._onLoad.bind(this);
  729. this.loadClassicViewer();
  730. // This is the "early" resolve - show the StartUp div right away
  731. deferred.resolve(this.$el);
  732. }
  733. // On Chrome, adding the iframe to the document triggers the onload event immediately whereas other browsers load the iframe
  734. // when the current js call stack finishes. We must delay adding the iframe until all work is done in this method to ensure
  735. // all callbacks are properly configured before the ifrmae loads so this is the last thing we do.
  736. this.m_elDivViewerContainer.appendChild(this.m_iframeClassicViewer);
  737. return deferred.promise();
  738. },
  739. /**
  740. * This method is called by the classic viewer right after the classic viewer object is created but before the page finishes loading.
  741. * The timing is important because it lets us know about the classic viewer before any iframes are processed which may trigger a download.
  742. * The div containing the classic viewer is hidden until we are notified the classic viewer exists so this must happen before download is initiated.
  743. * @param v_sCV Name of the classic viewer object
  744. */
  745. _onClassicViewerCreated: function( v_sCV )
  746. {
  747. //console.log("CV create callback");
  748. // Get the classic viewer object
  749. if (this.m_iframeClassicViewer && this.m_iframeClassicViewer.contentWindow) {
  750. // Ensure getClassicViewer returns the the classic viewer without having to look for it
  751. this.m_oCognosViewer = this.m_iframeClassicViewer.contentWindow[v_sCV];
  752. }
  753. this._onClassicViewerLoaded();
  754. },
  755. /**
  756. * Hook up the classic viewer to the cvContentView
  757. * and display the viewer iframe
  758. */
  759. _onClassicViewerLoaded: function()
  760. {
  761. console.timeEnd('rsperf: render->loadIframe');
  762. console.timeEnd('rsperf: total_RunReport');
  763. rsPerformance.mark('cvContentView._onClassicViewerLoaded');
  764. rsPerformance.mark('authoring-selectItemAndDraw-stop');
  765. //console.log("cvContentView._onClassicViewerLoaded(). ");
  766. if (this.isViewerLoaded())
  767. {
  768. // Either classic viewer or RDS prompt page is loaded
  769. var v_oCognosViewer = this.getCognosViewer();
  770. if (v_oCognosViewer)
  771. {
  772. this.m_iframeClassicViewer.contentWindow.onunload = this._release.bind(this);
  773. // get a reference to the original executeBackURL method...just in case we need to call it
  774. this.original_executeBackURL = this.m_iframeClassicViewer.contentWindow.executeBackURL;
  775. // point the existing method to our method
  776. this.m_iframeClassicViewer.contentWindow.executeBackURL = this.executeBackURL.bind(this);
  777. // get a reference to the original doSingleDrill method...we need to call it later
  778. this.original_doSingleDrill = this.m_iframeClassicViewer.contentWindow.doSingleDrill;
  779. // point the existing method to our method
  780. this.m_iframeClassicViewer.contentWindow.doSingleDrill = this.doSingleDrill.bind(this);
  781. // Define goto page handler
  782. this.m_iframeClassicViewer.contentWindow.rsGoToHandler = this.gotoHandler.bind(this);
  783. // Prevent old PDF drill logic from trying to restore PDF using browser history (see viewer drill-from-pdf.xts)
  784. this.m_iframeClassicViewer.contentWindow.f_restorePDF = this.f_restorePDF.bind(this);
  785. // get a reference to the original addDrillEnvironmentFormFields method...we need to call it later
  786. this.original_addDrillEnvironmentFormFields = this.m_iframeClassicViewer.contentWindow.addDrillEnvironmentFormFields;
  787. // point the existing method to our method
  788. this.m_iframeClassicViewer.contentWindow.addDrillEnvironmentFormFields = this.addDrillEnvironmentFormFields.bind(this);
  789. if (this.glassContext && this.glassContext.isDevInstall && this.glassContext.isDevInstall())
  790. {
  791. rsPerformance.summarizeClassicViewerRun( this );
  792. }
  793. if (v_oCognosViewer.updateNewBrowserWindow && this.m_iframeClassicViewer.contentWindow.getFormWarpRequest)
  794. {
  795. var form = this.m_iframeClassicViewer.contentWindow.getFormWarpRequest();
  796. var v_sBackURL = v_oCognosViewer.m_bIgnoreCloseWindow ? "" : (form ? form["ui.backURL"].value : "");
  797. if (v_sBackURL == "javascript:window.close();")
  798. {
  799. v_oCognosViewer.updateNewBrowserWindow = function()
  800. {
  801. this.glassContext.closeAppView("classicviewer", this.id);
  802. }.bind(this);
  803. }
  804. }
  805. /**
  806. * inject a function to classical viewer, when keyboard conbination ctrl-shift-1 is hit,
  807. * this function will be called to fucus to Appbar
  808. */
  809. v_oCognosViewer.focusBackToContent = function(evt) {
  810. this.glassContext.accessibilityController.setFocusToAppbar();
  811. }.bind(this);
  812. /**
  813. * inject a function to classical viewer, when keyboard conbination ctrl-shift-2 is hit,
  814. * this function will be called to fucus to MainContent
  815. */
  816. v_oCognosViewer.focusBackToMainContent = function(evt) {
  817. this.setFocus();
  818. }.bind(this);
  819. }
  820. this._showViewer();
  821. }
  822. // Stop processing load event
  823. this.m_iframeClassicViewer.onload = null;
  824. },
  825. createLaunchSpec : function(v_oCmObject, format, method, locale, sPrompt)
  826. {
  827. // Convert HTML-like formats to HTML to ensure perspective resolution works
  828. // Viewer will handle specifying the actual format that it really wants.
  829. format = format.indexOf('HTML') != -1 ? 'HTML' : format;
  830. var v_oLaunchSpec = {
  831. // string of output format
  832. // one of HTML, PDF, xlsxData, CSV, spreadsheetML, layoutDataXML, rawXML, singleXLS, HTMLFragment
  833. format: format,
  834. objRef: v_oCmObject.id,
  835. type: v_oCmObject.type,
  836. contentLocale: locale,
  837. };
  838. switch (method)
  839. {
  840. case "execute":
  841. case "run":
  842. v_oLaunchSpec.action = "run";
  843. break;
  844. case "view":
  845. case "viewOutput":
  846. v_oLaunchSpec.action = "viewOutput";
  847. break;
  848. case "edit":
  849. v_oLaunchSpec.action = "edit";
  850. break;
  851. }
  852. switch (sPrompt)
  853. {
  854. case "yes":
  855. case "true":
  856. v_oLaunchSpec.prompt = true;
  857. break;
  858. case "no":
  859. case "false":
  860. v_oLaunchSpec.prompt = false;
  861. break;
  862. }
  863. return v_oLaunchSpec;
  864. },
  865. // we are hijacking the viewer's copy of this method so that we can
  866. // add a form field to the form before being submitted
  867. addDrillEnvironmentFormFields : function(drillForm, oCV)
  868. {
  869. // call the original viewer method
  870. this.original_addDrillEnvironmentFormFields (drillForm, oCV);
  871. // append the cv.keepWindowOpen field to the form
  872. // we probably do not need to check to see if the "createFormField" method exists, but
  873. // I would rather make sure before I called it.
  874. if (this.m_iframeClassicViewer && this.m_iframeClassicViewer.contentWindow && this.m_iframeClassicViewer.contentWindow.createFormField)
  875. {
  876. drillForm.appendChild(this.m_iframeClassicViewer.contentWindow.createFormField("cv.keepWindowOpen", "true"));
  877. }
  878. },
  879. /**
  880. * Handler called from goto page for authored drill.
  881. * @param drillType Indicates what kind of drill is being performed
  882. * @param drill drill information specific to drill type
  883. */
  884. gotoHandler : function(drillType, drill) {
  885. if (drillType == 'authoredDrillthru') {
  886. this._authoredDrillHandler(drill);
  887. }
  888. else {
  889. this._packageDrillHandler(drill);
  890. }
  891. },
  892. /**
  893. * Submit form described by drill as AJAX request after adding option
  894. * to make request return results of calling drill service on package drill object.
  895. */
  896. _packageDrillHandler : function(drillForm) {
  897. this._sendDrillThroughRequest( {packageDrill: true}, drillForm );
  898. },
  899. /**
  900. * Perform authored drill. Converts the drill information into the parameters expected by the doSingleDrill method
  901. * and then calls said method. As a result, authored drill from goto page behaves the same
  902. * as single authored drill.
  903. */
  904. _authoredDrillHandler : function(drill) {
  905. var target, args, method, format, locale, bookmark, sourceContext, objectPaths, cvId, sPrompt, dynamicDrill;
  906. var v_aObj = [];
  907. var v_aParams = [];
  908. var v_oDrillDoc = this.parseXML(drill);
  909. var v_nDrillNode = v_oDrillDoc && v_oDrillDoc.documentElement.firstChild;
  910. while (v_nDrillNode) {
  911. switch (v_nDrillNode.nodeName) {
  912. case 'param':
  913. switch (v_nDrillNode.getAttribute('name')) {
  914. case 'action':
  915. method = this.getNodeText(v_nDrillNode);
  916. break;
  917. case 'format':
  918. format = this.getNodeText(v_nDrillNode);
  919. break;
  920. case 'locale':
  921. locale = this.getNodeText(v_nDrillNode);
  922. break;
  923. case 'target':
  924. var v_sTarget = this.getNodeText(v_nDrillNode);
  925. // When action on drill is view, the target search path provided from the goto page
  926. // is based on the defaultOutput( path, format, locale ) CM search path function.
  927. // Use a pattern to extract the path parameter.
  928. var v_aMatch = v_sTarget.match(g_reDefaultOutput);
  929. if (v_aMatch && v_aMatch.length > 1) {
  930. v_sTarget = v_aMatch[1];
  931. }
  932. v_aObj.push('obj');
  933. v_aObj.push(v_sTarget);
  934. break;
  935. case 'prompt':
  936. sPrompt = this.getNodeText(v_nDrillNode);
  937. break;
  938. case 'dynamicDrill':
  939. dynamicDrill = this.getNodeText(v_nDrillNode);
  940. break;
  941. case 'showInNewWindow':
  942. target = (this.getNodeText(v_nDrillNode) == 'false') ? '' : '_blank';
  943. break;
  944. case 'executionParameters':
  945. break;
  946. case 'metadataModel':
  947. break;
  948. case 'sourceContext':
  949. sourceContext = this.getNodeText(v_nDrillNode);
  950. break;
  951. case 'bookmark':
  952. bookmark = this.getNodeText(v_nDrillNode);
  953. break;
  954. case 'objectPaths':
  955. objectPaths = this.getNodeText(v_nDrillNode);
  956. break;
  957. }
  958. break;
  959. case 'drillParameters':
  960. var v_nParamNode = v_nDrillNode.firstChild;
  961. while (v_nParamNode) {
  962. if (v_nParamNode.nodeName == 'param') {
  963. var v_sName = v_nParamNode.getAttribute('name');
  964. var v_sValue = this.getNodeText(v_nParamNode);
  965. v_aParams.push([v_sName, v_sValue]);
  966. }
  967. v_nParamNode = v_nParamNode.nextSibling;
  968. }
  969. break;
  970. }
  971. v_nDrillNode = v_nDrillNode.nextSibling;
  972. }
  973. args = [v_aObj];
  974. cvId = this.getCognosViewer().getId();
  975. this.doSingleDrill(target, args.concat(v_aParams), method, format, locale, bookmark, sourceContext, objectPaths, cvId, sPrompt, dynamicDrill );
  976. },
  977. doSingleDrill : function(target,args,method,format,locale,bookmark,sourceContext,objectPaths,cvId,sPrompt,dynamicDrill) {
  978. // This method is called by the classic viewer when doing a single drill. The viewer first determines whether or
  979. // not a drill to self should be done. If not, then it calls this method. We need to take over processing
  980. // so that we can determine which perspective should be used on the target.
  981. // But first, we use the classic viewer to call the drill service.
  982. var v_oArguments = {
  983. target: target,
  984. args: args,
  985. method: method,
  986. format: format,
  987. locale: locale,
  988. bookmark: bookmark,
  989. sourceContext: sourceContext,
  990. objectPaths: objectPaths,
  991. cvId: cvId,
  992. sPrompt: sPrompt,
  993. dynamicDrill: dynamicDrill
  994. };
  995. this.showWaitIndicator();
  996. // Override how classic viewer issues it's drill request and call original drill method
  997. this.getCognosViewer().sendDrillThroughRequest = this._sendDrillThroughRequest.bind(this, v_oArguments);
  998. this.original_doSingleDrill(target,args,method,format,locale,bookmark,sourceContext,objectPaths,cvId,sPrompt,dynamicDrill);
  999. },
  1000. _htmlDecode: function (v_sText) {
  1001. var v_oDoc = new DOMParser().parseFromString('<div>' + v_sText + '</div>', "text/html");
  1002. return v_oDoc.documentElement.textContent;
  1003. },
  1004. _sendDrillThroughRequest: function(v_oDrillArguments, v_elViewerDrillForm)
  1005. {
  1006. // Convert classic viewer drill form into an AJAX request
  1007. var v_sAction = v_elViewerDrillForm.action;
  1008. var v_iIdx = v_sAction.indexOf("?");
  1009. var v_sURL = v_iIdx > 0 ? v_sAction.substring(0, v_iIdx) : v_sAction;
  1010. var v_aData = [];
  1011. var v_nlInputs = v_elViewerDrillForm.elements;
  1012. for (var idx = 0; idx < v_nlInputs.length; ++idx) {
  1013. var v_nInput = v_nlInputs[idx];
  1014. if (v_nInput.nodeName === 'INPUT') {
  1015. v_aData.push(v_nInput.name + '=' + encodeURIComponent(v_nInput.value) );
  1016. }
  1017. }
  1018. // Force viewer to only perform drill service call
  1019. v_aData.push('cv.drillServiceOnly=true');
  1020. var v_oRequest = {
  1021. type : 'POST',
  1022. url : v_sAction,
  1023. dataType: 'xml',
  1024. data : v_aData.join('&')
  1025. };
  1026. this.glassContext.services.ajax.ajax(v_oRequest)
  1027. .fail(function(x,http,z) {
  1028. var v_sMsg = null;
  1029. if (http && typeof http.getResponseHeader == 'function' && http.getResponseHeader('Content-Type').indexOf('text/html') == 0)
  1030. {
  1031. // We appear to have an error page since we were expecting a SOAP response but we got html
  1032. var v_aMatch = http.responseText.match(/<ERROR_CODE>(.*)<\/ERROR_CODE><ERROR_MSG>(.*)<\/ERROR_MSG>/);
  1033. if (v_aMatch && v_aMatch.length >= 3)
  1034. {
  1035. v_sMsg = this._htmlDecode(v_aMatch[2]);
  1036. console.error("cvContentView._sendDrillThroughRequest " + v_aMatch[1] + ":" + v_sMsg);
  1037. }
  1038. }
  1039. this.hideWaitIndicator();
  1040. this.glassContext.showToast(v_sMsg || "Unexpected error on drill request", {type:'error'});
  1041. }.bind(this))
  1042. .then(this._drillServiceResponse.bind(this, v_oDrillArguments, v_sURL));
  1043. },
  1044. getOutputPages: function(v_nDrillServiceResponse)
  1045. {
  1046. var v_nDetails = v_nDrillServiceResponse.querySelector('Envelope>Body result>details');
  1047. var v_aElements = this._getChildElementsByXsiType( v_nDetails, 'bus:asynchDetailReportOutput' );
  1048. var v_nOutputPages = v_aElements.length > 0 ? v_aElements[0] : null; // should only be 0 or 1
  1049. var v_nPage = v_nOutputPages.querySelector('item');
  1050. return v_nPage ? v_nPage.textContent : '';
  1051. },
  1052. F_SetPromptCallbackResponse: function(v_sResponse, v_oAttachments)
  1053. {
  1054. if (v_sResponse)
  1055. {
  1056. var v_nResponse = this.parseXML(v_sResponse);
  1057. if (this._promptDeferred)
  1058. {
  1059. this._promptDeferred.resolve(v_nResponse);
  1060. }
  1061. }
  1062. else
  1063. {
  1064. this._promptDeferred.reject({"state": "Cancel"});
  1065. }
  1066. },
  1067. _drillServiceResponse: function(v_oDrillArguments, v_sUrl, v_oResponseData, v_sStatus, v_oXHR)
  1068. {
  1069. // Handle drill service response which might require
  1070. // - issuing a wait request if status=working
  1071. // - display prompt page is status=prompting
  1072. var v_nDrillServiceResponse = v_oResponseData;
  1073. var v_nStatus = v_nDrillServiceResponse.querySelector('Envelope>Body result>status');
  1074. var v_sStatus = v_nStatus && v_nStatus.textContent;
  1075. if (v_sStatus == 'working' || v_sStatus == 'stillWorking') {
  1076. this._wait( v_nDrillServiceResponse, v_sUrl )
  1077. .fail(function() {
  1078. console.error("cvContentView._drillServiceResponse wait failed");
  1079. this.hideWaitIndicator();
  1080. this.glassContext.showToast("Unexpected error on drill request", {type:'error'});
  1081. }.bind(this))
  1082. .then(this._drillServiceResponse.bind(this, v_oDrillArguments, v_sUrl));
  1083. return;
  1084. }
  1085. var v_nDetails = v_nDrillServiceResponse.querySelector('Envelope>Body result>details');
  1086. var v_aElements = this._getChildElementsByXsiType( v_nDetails, 'bus:asynchDetailReportStatus' );
  1087. var v_nReportStatus = v_aElements.length > 0 ? v_aElements[0] : null; // should only be 0 or 1
  1088. v_nStatus = v_nReportStatus ? v_nReportStatus.querySelector('status') : null;
  1089. v_sStatus = v_nStatus && v_nStatus.textContent;
  1090. if (v_sStatus == 'prompting') {
  1091. this._prompt( v_nDrillServiceResponse )
  1092. .fail(function(err) {
  1093. this.hideWaitIndicator();
  1094. if (!err || err.state != "Cancel")
  1095. {
  1096. console.error("cvContentView._drillServiceResponse prompt failed");
  1097. this.glassContext.showToast(err.message, {type:'error'});
  1098. }
  1099. }.bind(this))
  1100. .then(
  1101. // Process the drill response now that prompts have been satisfied
  1102. this._drillServiceResponse.bind(this, v_oDrillArguments, v_sUrl)
  1103. );
  1104. return;
  1105. }
  1106. // Invoke target
  1107. this._doDrill(v_oDrillArguments, v_nDrillServiceResponse);
  1108. },
  1109. _wait : function( v_nDrillServiceResponse, v_sUrl ) {
  1110. var v_nBody = v_nDrillServiceResponse.querySelector('Envelope>Body');
  1111. var v_nResponse = v_nBody.querySelector('runSpecificationResponse,runResponse,waitResponse');
  1112. if (v_nResponse)
  1113. {
  1114. v_nBody.removeChild(v_nResponse);
  1115. }
  1116. var v_nWait = v_nDrillServiceResponse.createElementNS("http://developer.cognos.com/schemas/reportService/1", "rs:wait");
  1117. v_nBody.appendChild(v_nWait);
  1118. this._addCafContextID(v_nDrillServiceResponse);
  1119. var v_nDocElem = v_nDrillServiceResponse.documentElement;
  1120. // IE doesn't have outerHTML
  1121. var v_sWait = v_nDocElem.outerHTML || ( new XMLSerializer() ).serializeToString(v_nDocElem);
  1122. var v_oRequest = {
  1123. type : 'POST',
  1124. url : v_sUrl,
  1125. dataType: 'xml',
  1126. contentType: 'text/xml; charset=UTF-8',
  1127. headers: {SOAPAction: 'http://www.ibm.com/xmlns/prod/cognos/reportService/201712/.absolute' },
  1128. data : v_sWait
  1129. };
  1130. return this.glassContext.services.ajax.ajax(v_oRequest);
  1131. },
  1132. _addCafContextID : function( v_nSoapRequest ) {
  1133. var v_oCognosViewer = this.getCognosViewer();
  1134. if (v_oCognosViewer) {
  1135. var v_sCAF = v_oCognosViewer.getCAFContext();
  1136. if (v_sCAF) {
  1137. var v_nBiBusHeader = v_nSoapRequest.querySelector('Envelope>Header>biBusHeader');
  1138. if (v_nBiBusHeader) {
  1139. var v_nCAF = v_nBiBusHeader.querySelector('CAF');
  1140. if (!v_nCAF) {
  1141. // no CAF node, create it
  1142. v_nCAF = v_nSoapRequest.createElement('bus:CAF');
  1143. v_nCAF.setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'xsi:type', 'bus:CAF');
  1144. v_nBiBusHeader.appendChild(v_nCAF);
  1145. }
  1146. var v_nContextID = v_nCAF.querySelector('contextID');
  1147. if (!v_nContextID) {
  1148. // no contextID node, create it
  1149. v_nContextID = v_nSoapRequest.createElement('bus:contextID');
  1150. v_nContextID.setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'xsi:type', 'xs:string');
  1151. v_nCAF.appendChild(v_nContextID);
  1152. }
  1153. // set contextID
  1154. v_nContextID.textContent = v_sCAF;
  1155. }
  1156. }
  1157. }
  1158. },
  1159. _prompt : function( v_nDrillServiceResponse ) {
  1160. // This method should display the prompt page and when the prompting sequence is complete
  1161. // return the resulting SOAP response as the promise resolution so that the drill through can proceed.
  1162. // Until this logic is implemented, we force a failure instead.
  1163. this._promptDeferred = $.Deferred();
  1164. rsPromptHandler.F_DoPrompting(this, v_nDrillServiceResponse, this.glassContext);
  1165. return this._promptDeferred.promise();
  1166. },
  1167. _extractOption : function( v_nDrillThroughDetails, v_sType, v_sName )
  1168. {
  1169. var v_oValue;
  1170. var v_nOptions = v_nDrillThroughDetails && v_nDrillThroughDetails.querySelector('options');
  1171. var v_aXMLOptions = this._getChildElementsByXsiType( v_nOptions, v_sType );
  1172. for (var idx = 0; idx < v_aXMLOptions.length; ++idx) {
  1173. var v_nOption = v_aXMLOptions[idx];
  1174. var v_nName = v_nOption.querySelector('name');
  1175. if (v_nName && v_nName.textContent == v_sName) {
  1176. var v_nValue = v_nOption.querySelector('value');
  1177. if (v_nValue) {
  1178. if (v_nValue.getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'type') == 'SOAP-ENC:Array') {
  1179. v_oValue = [];
  1180. var v_nChildren = v_nValue.childNodes;
  1181. for (var idx = 0; idx < v_nChildren.length; ++idx) {
  1182. var v_nChild = v_nChildren.item(idx);
  1183. if (v_nChild.nodeType == Node.ELEMENT_NODE) {
  1184. v_oValue.push( v_nChild.textContent );
  1185. }
  1186. }
  1187. }
  1188. else {
  1189. v_oValue = v_nValue.textContent;
  1190. }
  1191. }
  1192. break;
  1193. }
  1194. }
  1195. return v_oValue;
  1196. },
  1197. /**
  1198. * Extract information from SOAP asynchDetailDrillThroughRequest response of a run package drill object request.
  1199. * Convert information into a form as an authored drill was being processed.
  1200. * @param v_oDrillArguments Extracted drill information
  1201. * @param v_nDrillThroughDetails The asynchDetailDrillThroughRequest from the SOAP response
  1202. */
  1203. _extractPackageDrillArguments : function(v_oDrillArguments, v_nDrillThroughDetails) {
  1204. /* bookmark not provided in drill response */
  1205. v_oDrillArguments.args = [];
  1206. // Extract target report search path
  1207. var v_nNode = v_nDrillThroughDetails.querySelector('target');
  1208. var v_sNode = v_nNode ? v_nNode.textContent : "";
  1209. v_oDrillArguments.args.push(['obj', v_sNode]);
  1210. // Extract drill in new window
  1211. v_oDrillArguments.target = ''; // no way to specify open in new window on package drill
  1212. // Extract drill format
  1213. var v_aFormat = this._extractOption( v_nDrillThroughDetails, 'bus:runOptionStringArray', 'outputFormat' );
  1214. v_oDrillArguments.format = v_aFormat && v_aFormat.length > 0 ? v_aFormat[0] : '';
  1215. // Extract drill action
  1216. v_nNode = v_nDrillThroughDetails.querySelector('action');
  1217. var v_sNode = v_nNode ? v_nNode.textContent : "";
  1218. v_oDrillArguments.method = v_sNode;
  1219. // Package drill does not provide content locale so use this instance's value
  1220. // If viewing saved output, use output locale else use current locale
  1221. v_oDrillArguments.locale = this.cmProperties && this.cmProperties.type == 'output' ? this.cmProperties.locale : (this.contentLocale || '');
  1222. // Extract drill prompt
  1223. v_oDrillArguments.sPrompt = this._extractOption( v_nDrillThroughDetails, 'bus:runOptionBoolean', 'prompt' );
  1224. },
  1225. _doDrill : function(v_oDrillArguments, v_nDrillServiceResponse) {
  1226. // Get the asynchDetailDrillThroughRequest element from the drill service SOAP response
  1227. var v_nDetails = v_nDrillServiceResponse.querySelector('Envelope>Body result>details');
  1228. // IE does not appear to support query selectors on attribute values with namespace qualified attributes i.e. xsi:type
  1229. // so we do it the 'hard' way
  1230. var v_aElements = this._getChildElementsByXsiType( v_nDetails, 'bus:asynchDetailDrillThroughRequest' );
  1231. var v_nDrillThroughDetails = v_aElements.length > 0 ? v_aElements[0] : null; // should only be 0 or 1
  1232. if (v_oDrillArguments.packageDrill && v_nDrillThroughDetails) {
  1233. this._extractPackageDrillArguments(v_oDrillArguments, v_nDrillThroughDetails);
  1234. }
  1235. /*bookmark,*/
  1236. var v_bDrillThoughNewWindow = v_oDrillArguments.target == "_blank" ? true : false;
  1237. var v_sSearchPath = v_oDrillArguments.args[0][1];
  1238. var v_oCurrentThisContext = this;
  1239. this._getCMInfo(v_sSearchPath).then(function(v_oCmObject)
  1240. {
  1241. var v_sDrillTargetId = v_oCmObject.id;
  1242. var v_oLaunchSpec = this.createLaunchSpec(v_oCmObject, v_oDrillArguments.format, v_oDrillArguments.method, v_oDrillArguments.locale, v_oDrillArguments.sPrompt);
  1243. var v_oDrillContext = {};
  1244. // Extract edit specification option value and add to 'large' options
  1245. var v_sEditSpecification = this._extractOption( v_nDrillThroughDetails, 'bus:specificationOptionXMLEncodedXML', 'editSpecification' );
  1246. if (v_sEditSpecification && v_sEditSpecification.length > 0) {
  1247. v_oDrillContext.editSpecification = v_sEditSpecification;
  1248. }
  1249. // Extract parameter values and add to 'large' options
  1250. var v_nParameters = v_nDrillThroughDetails && v_nDrillThroughDetails.querySelector('parameters');
  1251. if (v_nParameters) {
  1252. var v_sParameterXML = ( new XMLSerializer() ).serializeToString( v_nParameters );
  1253. if (v_sParameterXML && v_sParameterXML.length > 0) {
  1254. v_oDrillContext.parameterValuesXML = v_sParameterXML;
  1255. }
  1256. }
  1257. var v_oGlass = this.glassContext;
  1258. var v_oGlassSettings = rsCommon.extractGlassSettings( this );
  1259. if (v_bDrillThoughNewWindow) {
  1260. v_oLaunchSpec.launchParametersKey = rsLaunchParameters.Store(v_oDrillContext);
  1261. // Encode options as a JSON string to avoid unexpected changes to parameters
  1262. var v_oUrlMap = {
  1263. objRef: v_sDrillTargetId,
  1264. rsEncodedOptions: JSON.stringify(v_oLaunchSpec)
  1265. };
  1266. // Transfer any glass settings that we are aware of
  1267. v_oUrlMap = $.extend( v_oUrlMap, v_oGlassSettings );
  1268. v_oUrlMap.closeWindowOnLastView = true;
  1269. v_oUrlMap.prefetchsvc = "disabled"; // this an optimization for the new window - it tells the glass to load less stuff
  1270. var v_sUrl = this.glassContext.getUrl( { urlMap: v_oUrlMap } );
  1271. var newWindow = window.open(v_sUrl, "_blank");
  1272. if (newWindow)
  1273. {
  1274. newWindow.focus();
  1275. }
  1276. this.f_restorePDF();
  1277. this.hideWaitIndicator();
  1278. }
  1279. else {
  1280. v_oLaunchSpec = $.extend(v_oLaunchSpec, v_oDrillContext);
  1281. // Transfer any glass settings that we are aware of
  1282. v_oLaunchSpec = $.extend( v_oLaunchSpec, v_oGlassSettings );
  1283. // close the authoring perspective with the drill target id (if exists)
  1284. v_oGlass.closeAppView("authoring", v_sDrillTargetId)
  1285. // close the classicviewer perspective with the drill target id (if exists)
  1286. .then(v_oGlass.closeAppView.bind(v_oGlass, "classicviewer", v_sDrillTargetId))
  1287. // open a classicviewer perspective with the drill target id
  1288. .then(v_oGlass.openAppView.bind(v_oGlass, undefined, {content: v_oLaunchSpec}))
  1289. .then(function(targetAppView) {
  1290. // wait for the appView to be created
  1291. return targetAppView.onViewRendered();
  1292. })
  1293. .then(function() {
  1294. this.f_restorePDF();
  1295. this.hideWaitIndicator();
  1296. }.bind(this));
  1297. }
  1298. }.bind(this))
  1299. .catch(function(err){
  1300. var v_sSearchPath = err.message;
  1301. var v_sMessage = "Content Manager did not return information for '" + v_sSearchPath + "'";
  1302. v_oCurrentThisContext.glassContext.showToast(v_sMessage, {type:'error'});
  1303. console.warn('cvContentView.sendDrillThroughRequest could NOT load: %s', err);
  1304. }).bind(this);
  1305. },
  1306. _getChildElementsByXsiType : function ( v_nNode, v_sXsiType )
  1307. {
  1308. var v_aResult = [];
  1309. if (v_nNode) {
  1310. var v_nChildren = v_nNode.childNodes;
  1311. for (var idx = 0; idx < v_nChildren.length; ++idx) {
  1312. var v_nChild = v_nChildren.item(idx);
  1313. if (v_nChild.nodeType == Node.ELEMENT_NODE && v_nChild.getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'type') == v_sXsiType) {
  1314. v_aResult.push( v_nChild );
  1315. }
  1316. }
  1317. }
  1318. return v_aResult;
  1319. },
  1320. // This function's existence is checked in Viewer's drill-from-pdf.xts
  1321. f_restorePDF : function ()
  1322. {
  1323. if (this.m_iFramePDF)
  1324. {
  1325. // refresh the PDF iframe
  1326. var src = this.m_iFramePDF.src;
  1327. this.m_iFramePDF.src = src;
  1328. }
  1329. },
  1330. f_convertParametersfromXmlToJsonStr : function (v_nParameters)
  1331. {
  1332. // the node comes in as
  1333. // <drillParameters>
  1334. // <param name="p_ProdLine">&lt;selectChoices&gt;&lt;selectOption useValue=&quot;Outdoor Protection&quot; displayValue=&quot;Outdoor Protection&quot;/&gt;&lt;/selectChoices&gt;</param>
  1335. // </drillParameters>
  1336. var v_aParameters = [];
  1337. // walk through all the child nodes
  1338. var v_nChildNode = v_nParameters.firstChild;
  1339. while (v_nChildNode)
  1340. {
  1341. var v_oParameter = {};
  1342. if (v_nChildNode.nodeName === "param")
  1343. {
  1344. // populate the name field with the v_nChildNode's name attribute and
  1345. // strip off the p_
  1346. v_oParameter.name = v_nChildNode.getAttribute("name");
  1347. v_oParameter.name = v_oParameter.name.slice(2);
  1348. v_oParameter.value = [];
  1349. //
  1350. // the textContent of the param node needs to be converted from string
  1351. // &lt;selectChoices&gt;&lt;selectOption useValue=&quot;Outdoor Protection&quot; displayValue=&quot;Outdoor Protection&quot;/&gt;&lt;/selectChoices&gt;
  1352. // to an XML doc
  1353. // <selectChoices>
  1354. // <selectOption useValue="Outdoor Protection" displayValue="Outdoor Protection">
  1355. // </selectChoices>
  1356. // so that is can be parsed
  1357. var v_nSelectDoc = this.parseXML(v_nChildNode.textContent);
  1358. // create a v_oParameter.value entry for each selectOption node
  1359. var v_aSelectOptionNodes = v_nSelectDoc.getElementsByTagName("selectOption");
  1360. for (var i = 0; i < v_aSelectOptionNodes.length; i++)
  1361. {
  1362. var v_oValue = {};
  1363. if (v_aSelectOptionNodes[i].hasAttribute("displayValue"))
  1364. {
  1365. v_oValue.display = v_aSelectOptionNodes[i].getAttribute("displayValue");
  1366. }
  1367. v_oValue.use = v_aSelectOptionNodes[i].getAttribute("useValue");
  1368. v_oParameter.value.push(v_oValue);
  1369. }
  1370. v_nChildNode = v_nChildNode.nextSibling;
  1371. v_aParameters.push(v_oParameter);
  1372. }
  1373. }
  1374. return JSON.stringify(v_aParameters);
  1375. },
  1376. _getCMInfo: function (v_sSearchPath) {
  1377. var v_sSearchPathUrl = "v1/search_path?searchPath=" +
  1378. encodeURIComponent(v_sSearchPath) +
  1379. "&fields=id,type";
  1380. return this.glassContext.services.fetch.get(v_sSearchPathUrl)
  1381. .then( function(v_oCmInfoResponse) {
  1382. return v_oCmInfoResponse.data.data[0];
  1383. })
  1384. .catch(function(v_oErr){
  1385. console.log('cvContentView.getCMInfo FAILED for "%s"', v_sSearchPathUrl);
  1386. throw new Error(v_sSearchPath);
  1387. });
  1388. },
  1389. _extractCmPathTermFromCmPathUrl: function(v_sCmPathUrl) {
  1390. // Extract the "path" query-value from the path url
  1391. // /bi/v1/path?path=.public_folders%2Fbugs%2Fcv-apar120836_pi88512-rtc200676-drillparams
  1392. var v_sQuery = v_sCmPathUrl.split("?", 2)[1];
  1393. var v_aFields = v_sQuery.split("&");
  1394. for(var i=0; i < v_aFields.length; ++i)
  1395. {
  1396. var v_aNameValue = v_aFields[i].split("=", 2);
  1397. var v_sName = v_aNameValue[0], v_sValue = v_aNameValue[1];
  1398. if (v_sName == "path")
  1399. {
  1400. return decodeURIComponent(v_sValue);
  1401. }
  1402. }
  1403. },
  1404. executeBackURL: function (s_CVId) {
  1405. // get the cognos viewer
  1406. var v_oCognosViewer = this.getCognosViewer();
  1407. var form = this.m_iframeClassicViewer.contentDocument.getElementById("formWarpRequest" + (s_CVId ? s_CVId : ""));
  1408. var v_sBackURL = v_oCognosViewer.m_bIgnoreCloseWindow ? "" : form["ui.backURL"].value;
  1409. // see if there is a "CMODAL_FRAME" in the authoring document
  1410. var v_nClassicViewerDialogFrame = this.m_iframeClassicViewer.contentDocument.getElementById("CMODAL_FRAME");
  1411. // if there is a modal shown and the CModal class is available, hide the dialog box
  1412. if (v_oCognosViewer.modalShown && v_nClassicViewerDialogFrame && v_nClassicViewerDialogFrame.CModal)
  1413. {
  1414. // hide the dialog
  1415. v_nClassicViewerDialogFrame.CModal.hide();
  1416. // reset the flag
  1417. v_oCognosViewer.modalShown = false;
  1418. }
  1419. // the perspective is in an iframe, so we can not use window.close.
  1420. // instead, we will call the class to close the current app view (which is us)
  1421. if (v_sBackURL == "javascript:window.close();")
  1422. {
  1423. this.glassContext.closeAppView("classicviewer", this.id);
  1424. }
  1425. // otherwise call the original execBackURL method
  1426. else {
  1427. this.original_executeBackURL(s_CVId);
  1428. }
  1429. v_oCognosViewer.m_bIgnoreCloseWindow = undefined;
  1430. },
  1431. _createAndSubmitCollectParameterValuesForm: function(v_sStoreId, v_sUrl) {
  1432. v_sUrl = decodeURIComponent(v_sUrl);
  1433. var v_sParameters = v_sUrl.slice(v_sUrl.indexOf("?"));
  1434. var v_elForm = document.createElement("form");
  1435. v_elForm.target = this.m_iframeClassicViewer.name;
  1436. v_elForm.method = "post";
  1437. v_elForm.action = classicViewerGatewaySuffix + v_sParameters;
  1438. v_elForm.style.display = "none";
  1439. document.body.appendChild(v_elForm);
  1440. v_elForm.submit();
  1441. document.body.removeChild(v_elForm);
  1442. },
  1443. /**
  1444. * onload handler for classic viewer iframe
  1445. */
  1446. _onLoad: function() {
  1447. //console.log( "_onLoad");
  1448. if (this.isViewerLoaded())
  1449. {
  1450. //console.log( "_onLoad viewer loaded");
  1451. // Classic viewer exists so the viewer form post result was loaded
  1452. this._onClassicViewerLoaded();
  1453. }
  1454. else if (this.m_fOnLoadHandler)
  1455. {
  1456. //console.log( "_onLoad launch viewer");
  1457. // Call the classic viewer now that the iframe has been loaded by the glass
  1458. this.m_fOnLoadHandler();
  1459. // Ensure form is posted only once in case things go bad
  1460. this.m_fOnLoadHandler = null;
  1461. }
  1462. else
  1463. {
  1464. //console.log( "_onLoad show viewer");
  1465. // If we get here, something unexpected occurred. Most likely, the viewer returned something
  1466. // (error page) that does not signal cvContentView that it is there via window.OnErrorPage or
  1467. // the classic viewer creation callback.
  1468. // Show the viewer div in case there is something there.
  1469. this._showViewer();
  1470. }
  1471. },
  1472. _createAndSubmitNewForm: function() {
  1473. //console.log( "_createAndSubmitNewForm");
  1474. // APAR 120836 REPORT FAILS TO RUN IN IE11 IF THE DRILL-THROUGH PROMPTPARAMETER VALUES ARE LARGER THAN 2,083 CHAR LIMIT
  1475. // Use a POST with form instead of GET request
  1476. var v_elForm = document.createElement("form");
  1477. v_elForm.target = this.m_iframeClassicViewer.name;
  1478. v_elForm.method = "post";
  1479. v_elForm.action = classicViewerGatewaySuffix;
  1480. v_elForm.style.display = "none";
  1481. var v_elInput = v_elForm.appendChild( document.createElement("input") );
  1482. v_elInput.type = "hidden";
  1483. v_elInput.name = "b_action";
  1484. v_elInput.value = "cognosViewer";
  1485. Object.keys(this.m_oRVFormParameters).forEach( function(key){
  1486. var v_elInput = v_elForm.appendChild( document.createElement("input") );
  1487. v_elInput.type = "hidden";
  1488. v_elInput.name = key;
  1489. v_elInput.value = this.m_oRVFormParameters[key];
  1490. },
  1491. this);
  1492. rsPromptParameters.cvAddPromptParameters(v_elForm, this.m_aPromptParameters, this.m_aPromptParametersComplex);
  1493. document.body.appendChild(v_elForm);
  1494. // if include performance details is selected, create an xml http request
  1495. // and manually pass the X-CA-IPA header.
  1496. if (this.m_oRVFormParameters.IncludePerformance == "true")
  1497. {
  1498. // concatenate the name and values into an array of name=values
  1499. var v_saFormData = [];
  1500. for (var i = 0; i < v_elForm.elements.length; i++)
  1501. {
  1502. var v_sElementName = v_elForm.elements[i].name;
  1503. var v_sElementValue = v_elForm.elements[i].value;
  1504. v_saFormData.push(encodeURIComponent(v_sElementName) + '=' + encodeURIComponent(v_sElementValue));
  1505. }
  1506. // encode formData elements into one string
  1507. var v_sPostData = v_saFormData.join('&').replace(/%20/g, '+');
  1508. var v_http = new XMLHttpRequest();
  1509. var v_sBaseURI = v_elForm.action;
  1510. v_http.onreadystatechange = function() {
  1511. // insert server response into the classic viewer iFrame
  1512. if (this.readyState == 4 && this.status == 200) {
  1513. var v_nClassicViewerIframe = document.getElementsByName("_classicViewer")[0];
  1514. var v_nIframeDocument = v_nClassicViewerIframe.contentDocument;
  1515. var v_sHeadWithBase = '<head><base href="' + v_sBaseURI + '">';
  1516. var v_sHtmlText = v_http.responseText.replace(/<head>/, v_sHeadWithBase);
  1517. v_nIframeDocument.open();
  1518. v_nIframeDocument.write(v_sHtmlText);
  1519. v_nIframeDocument.close();
  1520. }
  1521. };
  1522. v_http.open(v_elForm.method, v_elForm.action);
  1523. v_http.setRequestHeader('Cache-Control', 'max-age=0');
  1524. v_http.setRequestHeader('Upgrade-Insecure-Requests', '1');
  1525. v_http.setRequestHeader('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8');
  1526. v_http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  1527. v_http.setRequestHeader('X-CA-IPA', '1');
  1528. v_http.send(v_sPostData);
  1529. } else {
  1530. v_elForm.submit();
  1531. }
  1532. document.body.removeChild(v_elForm);
  1533. },
  1534. _setLocalSessionData : function (key, data) {
  1535. if (typeof(Storage) !== "undefined") {
  1536. localStorage.setItem(key, data);
  1537. }
  1538. else
  1539. {
  1540. console.log("Sorry! No Web Storage support...");
  1541. }
  1542. },
  1543. loadClassicViewer: function () {
  1544. //console.log("begin: cvContentView.loadClassicViewer" );
  1545. this.m_fOnLoadHandler = this._createAndSubmitNewForm.bind(this);
  1546. // If the viewer responds with an error page then the _onLoad will not find the viewer object
  1547. // so the div visibility won't be adjusted.
  1548. // Use the error page OnErrorPage callback to detect this and ensure the error page is displayed.
  1549. window.OnErrorPage = function() {
  1550. this._showViewer();
  1551. }.bind(this);
  1552. window[this.m_sCreateCallback] = this._onClassicViewerCreated.bind(this);
  1553. var v_oMRU;
  1554. if (this.getType() == "output")
  1555. {
  1556. if (this.reportProperties)
  1557. {
  1558. v_oMRU = $.extend(true, {}, this.reportProperties);
  1559. }
  1560. }
  1561. else
  1562. {
  1563. if (this.cmProperties)
  1564. {
  1565. v_oMRU = $.extend(true, {}, this.cmProperties);
  1566. }
  1567. }
  1568. if (v_oMRU)
  1569. {
  1570. console.log('add to MRU');
  1571. this.glassContext.getSvc('.Content').then(function(contentSvc) {
  1572. contentSvc.addToMRU(v_oMRU);
  1573. });
  1574. }
  1575. // Instrumentation wants specific terms
  1576. // Some glass actions won't be instrumented
  1577. var v_oGlassActionToInstrumentationEventType = {
  1578. 'run' : 'Ran Process',
  1579. 'viewOutput': 'Read Object',
  1580. };
  1581. var v_sInstrumentationType = v_oGlassActionToInstrumentationEventType[ this.action ];
  1582. if (v_sInstrumentationType && this.glassContext)
  1583. {
  1584. var v_oInstrumentationService = this.glassContext.getCoreSvc('.Instrumentation');
  1585. if (v_oInstrumentationService && v_oInstrumentationService.enabled)
  1586. {
  1587. var v_sType;
  1588. var v_sId;
  1589. if (this.type == 'output' && this.cmProperties)
  1590. {
  1591. // our opener code should fill in the parent chain
  1592. // cmProperties.parent[0] is the reportVersion object
  1593. // cmProperties.parent[0].parent[0] is the object that has output versions
  1594. var v_oVersionedAncestor = this.cmProperties.parent[0].parent[0];
  1595. v_oVersionedAncestor = v_oVersionedAncestor.base || v_oVersionedAncestor;
  1596. v_sType = v_oVersionedAncestor.type;
  1597. v_sId = v_oVersionedAncestor.id;
  1598. }
  1599. else
  1600. {
  1601. v_sType = this.type;
  1602. v_sId = this.id;
  1603. }
  1604. var v_oEvent = {
  1605. type: v_sInstrumentationType,
  1606. objectType: v_sType,
  1607. object: v_sId,
  1608. 'custom.viewer' : 'classic',
  1609. 'custom.outputFormat' : this.format,
  1610. milestoneName: v_sInstrumentationType + '_' + v_sType
  1611. };
  1612. if (v_sInstrumentationType === v_oGlassActionToInstrumentationEventType.run)
  1613. {
  1614. v_oEvent['processType'] = 'Run a Report';
  1615. }
  1616. v_oInstrumentationService.track( v_oEvent );
  1617. }
  1618. }
  1619. //console.log("end: cvContentView.loadClassicViewer" );
  1620. },
  1621. getCognosViewer: function() {
  1622. if (this.m_oCognosViewer)
  1623. {
  1624. return this.m_oCognosViewer;
  1625. }
  1626. var v_oViewer = null;
  1627. if (this.m_iframeClassicViewer && this.m_iframeClassicViewer.contentWindow) {
  1628. v_oViewer = this.m_iframeClassicViewer.contentWindow.oCV_NS_ || this.m_iframeClassicViewer.contentWindow.oCVRS || this.m_iframeClassicViewer.contentWindow.oCV_THIS_;
  1629. if (v_oViewer)
  1630. {
  1631. this.m_oCognosViewer = v_oViewer;
  1632. }
  1633. }
  1634. return v_oViewer;
  1635. },
  1636. /**
  1637. * Return whether or not a classic viewer or an RDS prompt page is loaded.
  1638. * This method is needed because the RDS prompt page used by collect parameter values does not have a real classic viewer so
  1639. * getCognosViewer returns null in this scenario but we still need to know if a prompt page was loaded.
  1640. */
  1641. isViewerLoaded: function() {
  1642. return this.getCognosViewer() || (this.m_iframeClassicViewer && this.m_iframeClassicViewer.contentWindow && this.m_iframeClassicViewer.contentWindow.oCV);
  1643. },
  1644. /*
  1645. Get content is called by the SHARE team. See RTC #82310
  1646. they expect:
  1647. .application {
  1648. .storeID, // Store ID in the CM, null if report not saved
  1649. .cmSearthPath, // Search Path in the CM of the report, null if report not saved
  1650. .reportName, // report name
  1651. .isModified // whether the report has beeen modified. Set to false.
  1652. }
  1653. .promptParameters{
  1654. .name,
  1655. .value {
  1656. inclusive, // true | false,
  1657. use, // true | false,
  1658. display, // "Run report with data",
  1659. type // "simpleParmValueItem"
  1660. }
  1661. }
  1662. As per RTC #82310, the json format depends on the type of parameter:
  1663. // range (bound and unbound)
  1664. parameters: [
  1665. {
  1666. name: "string",
  1667. value: [
  1668. {
  1669. inclusive: boolean,
  1670. type,
  1671. start: {
  1672. inclusive: boolean,
  1673. use: "string",
  1674. display: "string",
  1675. },
  1676. end: {
  1677. inclusive: boolean,
  1678. use: "string",
  1679. display: "string",
  1680. }
  1681. }
  1682. ]
  1683. }
  1684. ]
  1685. */
  1686. /*
  1687. Story 86638
  1688. Note: You will know glass is making this type of getContent(options) request when the passed in options contains
  1689. {mode:'bookmark'}. If the options argument is missing or does not contain "mode":"bookmark", you can interpret it as a "Full state" request.
  1690. It's ok for both calls to return the same state. It's completely up to you and your implementation.
  1691. */
  1692. getContent: function(options) {
  1693. //console.log("cvContentView.getContent" );
  1694. return rsCommon.getContent( options, this, rsShareHelper );
  1695. },
  1696. getApplicationContent: function( v_oContent, v_oCmProperties )
  1697. {
  1698. var application = {};
  1699. application.storeID = this.cmProperties && this.cmProperties.id;
  1700. application.cmSearchPath = !rsCommon.isObjectOfType(this.cmProperties, 'output') && this.getSearchPath();
  1701. application.reportName = this.getTitle();
  1702. application.isModified = false;
  1703. application.type = (this.cmProperties && this.cmProperties.type) || undefined;
  1704. return application;
  1705. },
  1706. parseXML: function(v_sXML)
  1707. {
  1708. if (window.DOMParser)
  1709. {
  1710. return (new window.DOMParser()).parseFromString(v_sXML, "text/xml");
  1711. }
  1712. else if (typeof window.ActiveXObject != "undefined" && new window.ActiveXObject("Microsoft.XMLDOM"))
  1713. {
  1714. var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
  1715. xmlDoc.async = "false";
  1716. xmlDoc.loadXML(v_sXML);
  1717. return xmlDoc;
  1718. }
  1719. return null;
  1720. },
  1721. getParametersFromViewer: function()
  1722. {
  1723. var v_aGlassParameters = [];
  1724. try
  1725. {
  1726. if (this.getCognosViewer())
  1727. {
  1728. var v_sXMLParameters = this.getCognosViewer().getExecutionParameters();
  1729. //console.log("Parameters = %s", v_sXMLParameters);
  1730. var v_oDoc = this.parseXML(v_sXMLParameters);
  1731. // get all the children nodes
  1732. var v_nChildNode = v_oDoc.documentElement.firstChild;
  1733. while (v_nChildNode)
  1734. {
  1735. // we are interested in the item nodes
  1736. if (v_nChildNode.nodeName == "item")
  1737. {
  1738. var v_oGlassParamStruct = {
  1739. name: "",
  1740. value: []
  1741. };
  1742. // walk through the child nodes..looking for bus:name and bus:value
  1743. var v_nItemChildNode = v_nChildNode.firstChild;
  1744. while (v_nItemChildNode)
  1745. {
  1746. switch(v_nItemChildNode.nodeName)
  1747. {
  1748. // bus:name contains the parameter name
  1749. case "bus:name" :
  1750. v_oGlassParamStruct.name = this.getNodeText(v_nItemChildNode);
  1751. break;
  1752. // bus:value contains type, inclusive, display, and use
  1753. case "bus:value":
  1754. var v_nValueNode = v_nItemChildNode.firstChild;
  1755. while (v_nValueNode)
  1756. {
  1757. // we are interested in the item nodes
  1758. if (v_nValueNode.nodeName == "item")
  1759. {
  1760. var v_oGlassParamValue = this.getValuesFromBusValueNode(v_nValueNode.getAttribute("xsi:type"), v_nValueNode.childNodes);
  1761. v_oGlassParamStruct.value.push(v_oGlassParamValue);
  1762. }
  1763. v_nValueNode = v_nValueNode.nextSibling;
  1764. }
  1765. break;
  1766. }
  1767. v_nItemChildNode = v_nItemChildNode.nextSibling;
  1768. }
  1769. v_aGlassParameters.push(v_oGlassParamStruct);
  1770. }
  1771. v_nChildNode = v_nChildNode.nextSibling;
  1772. }
  1773. }
  1774. }
  1775. catch (err)
  1776. {
  1777. console.log("cvContentView.getParametersFromViewer failed (%s) ", err.message);
  1778. }
  1779. //console.log("GlassParameters = ", v_aGlassParameters);
  1780. return v_aGlassParameters;
  1781. },
  1782. /**
  1783. * This method gets the parameters from the application
  1784. * This is a public method used by other components and as such
  1785. * must be defined in both rs and cv content views.
  1786. */
  1787. getParameterValues : function( bStripCredentials ) {
  1788. var v_aParameterValues = this.getParametersFromViewer();
  1789. if (bStripCredentials && v_aParameterValues)
  1790. {
  1791. var v_aParameters = [];
  1792. if (v_aParameterValues.length > 0) {
  1793. v_aParameterValues.forEach( function(v_oParameter) {
  1794. if (!bStripCredentials || !v_oParameter || !v_oParameter.name || v_oParameter.name.indexOf("credential:") != 0) {
  1795. v_aParameters.push( v_oParameter );
  1796. }
  1797. });
  1798. v_aParameterValues = v_aParameters;
  1799. }
  1800. }
  1801. return v_aParameterValues;
  1802. },
  1803. getValuesFromBusValueNode: function(v_sType, v_nlNodeList)
  1804. {
  1805. var v_oGlassParamValue = {};
  1806. var v_oStartEnd = {};
  1807. // strip off the bus: portion
  1808. v_oGlassParamValue.type = v_sType.substring(4);
  1809. for ( var j = 0; j < v_nlNodeList.length; j++ )
  1810. {
  1811. var v_nNode = v_nlNodeList[ j ];
  1812. var v_bStart = false;
  1813. v_oStartEnd = {}; // empty
  1814. switch(v_nNode.nodeName)
  1815. {
  1816. case "bus:start":
  1817. v_bStart = true;
  1818. // continue
  1819. case "bus:end":
  1820. // get all the children nodes
  1821. var v_nChildNode = v_nNode.firstChild;
  1822. while (v_nChildNode)
  1823. {
  1824. switch(v_nChildNode.nodeName)
  1825. {
  1826. case "bus:inclusive" :
  1827. v_oStartEnd.inclusive = (this.getNodeText (v_nChildNode) == "true") ? true : false;
  1828. break;
  1829. case "bus:display" :
  1830. v_oStartEnd.display = this.getNodeText (v_nChildNode);
  1831. break;
  1832. case "bus:use" :
  1833. v_oStartEnd.use = this.getNodeText (v_nChildNode);
  1834. break;
  1835. }
  1836. v_nChildNode = v_nChildNode.nextSibling;
  1837. };
  1838. // set start or end in the v_oGlassParamValue
  1839. if (v_bStart)
  1840. {
  1841. v_oGlassParamValue.start = v_oStartEnd;
  1842. }
  1843. else
  1844. {
  1845. v_oGlassParamValue.end = v_oStartEnd;
  1846. }
  1847. break;
  1848. case "bus:inclusive" :
  1849. v_oGlassParamValue.inclusive = (this.getNodeText (v_nNode) == "true") ? true : false;
  1850. break;
  1851. case "bus:display" :
  1852. v_oGlassParamValue.display = this.getNodeText (v_nNode);
  1853. break;
  1854. case "bus:use" :
  1855. v_oGlassParamValue.use = this.getNodeText (v_nNode);
  1856. break;
  1857. }
  1858. }
  1859. // Share is looking for "inclusive" for a range value, as per OM. If missing (seems to always be missing), just add a inclusive=true
  1860. if ( v_oGlassParamValue.inclusive === undefined &&
  1861. (v_oGlassParamValue.start !== undefined || v_oGlassParamValue.end !== undefined) )
  1862. {
  1863. v_oGlassParamValue.inclusive = true;
  1864. }
  1865. return v_oGlassParamValue;
  1866. },
  1867. getNodeText: function(v_nNode)
  1868. {
  1869. var ATTRIBUTE_NODE = 2;
  1870. return v_nNode && (v_nNode.nodeType == ATTRIBUTE_NODE ? v_nNode.nodeValue : v_nNode.textContent);
  1871. },
  1872. deactivate: function() {
  1873. this.m_bDeactivated = true;
  1874. this.glassContext.unlockGlass();
  1875. //console.log("cvContentView.deactivate()");
  1876. },
  1877. /**
  1878. * This method is called from the iframe onunload event.
  1879. * The problem is that the viewer release method results in a synchronous XMLHttpRequest which browsers complain about.
  1880. * Ideally we should be using the glass remove() method instead. But when glass calls remove, they have already
  1881. * removed the content view div which means our iframe has already been unloaded so there is no longer a viewer
  1882. * on which we can call release().
  1883. */
  1884. _release: function() {
  1885. var v_oViewer = this.getCognosViewer();
  1886. if (v_oViewer)
  1887. {
  1888. // Once viewer releases it's conversation, it is no longer functional
  1889. // so ensure we can no longer talk to it.
  1890. this.m_oCognosViewer = null;
  1891. try {
  1892. // only call release if the viewer isn't keeping the session alive
  1893. if( !v_oViewer.getKeepSessionAlive() ) {
  1894. v_oViewer.release();
  1895. delete window[this.m_sCreateCallback];
  1896. }
  1897. } catch(e) {
  1898. }
  1899. }
  1900. this.m_oAppView = null;
  1901. },
  1902. canRun: function() {
  1903. // this perspective is only used when a report is run
  1904. return true;
  1905. },
  1906. /**
  1907. * Called by global parameter flyout to determine what parameters are used by the currently active view.
  1908. * @return Array of parameter names currently in use by the report.
  1909. */
  1910. getParameters: function() {
  1911. var v_aParameters = this.getParametersFromViewer();
  1912. return rsPromptParameters.convertParameterArrayToObject(v_aParameters);
  1913. },
  1914. /**
  1915. * Called by global parameter flyout to let content view know what global parameters have changed.
  1916. * The method determines if any of the modified global parameters are used by the report and if so
  1917. * the report is refreshed.
  1918. * @param v_oGlobalParameters The global parameters that have been modified.
  1919. * @param glassContext The glass context used to access complete global parameters.
  1920. */
  1921. updateGlobalParameters: function( v_oNewGlobalParameters, v_oGlassContext ) {
  1922. var v_oCognosViewer = this.getCognosViewer();
  1923. if (v_oCognosViewer && v_oCognosViewer.updateGlobalParameters && v_oNewGlobalParameters)
  1924. {
  1925. var v_aGlobalParametersDelta = rsCommon.convertToArray( v_oNewGlobalParameters );
  1926. v_oCognosViewer.updateGlobalParameters( JSON.stringify( v_aGlobalParametersDelta ) );
  1927. }
  1928. },
  1929. /**
  1930. * Called by Collaboration to retrieve the DOM node for screen capturing and report's name.
  1931. * @returns {array} Array of objects containing the DOM element and the name.
  1932. */
  1933. getShareableItemsForCollaboration: function() {
  1934. // console.log('cvContentView.getShareableItemsForCollaboration');
  1935. if (this.m_bFullyInitialized && this.m_iframeClassicViewer)
  1936. {
  1937. var doc = this.m_iframeClassicViewer.contentDocument;
  1938. var body = doc.body;
  1939. return [{
  1940. el: body,
  1941. label: this.m_sTitle
  1942. }];
  1943. }
  1944. return [];
  1945. },
  1946. /**
  1947. * setFocus will be called whenever glass want to put focus inside contentView.
  1948. * here, the code will check if clasical viewer is loaded then focus inside report viewer
  1949. */
  1950. setFocus: function setFocus()
  1951. {
  1952. if (this.isViewerLoaded())
  1953. {
  1954. var doc = this.m_iframeClassicViewer.contentWindow.document;
  1955. var rvContent = doc.getElementById("RVContent" + this.getCognosViewer().getId());
  1956. if (rvContent)
  1957. {
  1958. var el = this.getFirstFocus(rvContent);
  1959. if (el) {
  1960. el.focus();
  1961. }
  1962. }
  1963. }
  1964. else
  1965. {
  1966. cvContentView.inherited('setFocus', this, arguments);
  1967. }
  1968. },
  1969. getFirstFocus:function(v_elTop, v_elParent)
  1970. {
  1971. var v_elParent = v_elParent || v_elTop;
  1972. var v_elFocus;
  1973. var v_iLength = v_elParent.childNodes.length;
  1974. for ( var i = 0; i < v_iLength && !v_elFocus; i++ )
  1975. {
  1976. var v_elChild = v_elParent.childNodes[i];
  1977. var v_bDisabled = ( v_elChild.disabled ||
  1978. ( v_elChild.getAttribute && ( v_elChild.getAttribute( "disabled" ) == "true" || v_elChild.getAttribute( "aria-disabled" ) == "true" ) )
  1979. );
  1980. if ( ( !v_bDisabled || this.isToolbarButton( v_elChild ) ) && v_elChild.style && v_elChild.style.visibility != "hidden" && v_elChild.style.display != "none" )
  1981. {
  1982. if ( v_elChild.nodeName == "INPUT" && v_elChild.type == "radio" )
  1983. {
  1984. v_elFocus = this.getCheckedOrFirstRadioButtonInGroup( v_elTop, v_elChild.getAttribute( "name" ) );
  1985. }
  1986. else if ( this.isOKToFocus( v_elChild ) )
  1987. {
  1988. v_elFocus = v_elChild;
  1989. }
  1990. else
  1991. {
  1992. v_elFocus = this.getFirstFocus( v_elTop, v_elChild );
  1993. }
  1994. }
  1995. }
  1996. return v_elFocus;
  1997. },
  1998. isToolbarButton: function( el ) {
  1999. if ( el.getAttribute )
  2000. {
  2001. var v_sRole = el.getAttribute( "role" );
  2002. if ( v_sRole == "button" || v_sRole == "combobox" )
  2003. {
  2004. for ( ; el; el = el.parentNode )
  2005. {
  2006. if ( el.getAttribute && el.getAttribute( "role" ) == "toolbar" )
  2007. {
  2008. return true;
  2009. }
  2010. }
  2011. }
  2012. }
  2013. return false;
  2014. },
  2015. getCheckedOrFirstRadioButtonInGroup: function( v_elContainer, v_sRadioGroupName )
  2016. {
  2017. var v_elRadioChecked;
  2018. var v_elFirstRadio;
  2019. var nl = v_elContainer.getElementsByTagName( "INPUT" );
  2020. var v_iLength = nl.length;
  2021. for ( var i = 0; i < v_iLength; i++ )
  2022. {
  2023. var v_el = nl.item( i );
  2024. if ( v_el.type == "radio" && v_el.name == v_sRadioGroupName )
  2025. {
  2026. if ( !v_elFirstRadio )
  2027. {
  2028. v_elFirstRadio = v_el;
  2029. }
  2030. if ( v_el.checked == true )
  2031. {
  2032. v_elRadioChecked = v_el;
  2033. break;
  2034. }
  2035. }
  2036. }
  2037. return v_elRadioChecked || v_elFirstRadio;
  2038. },
  2039. isOKToFocus: function( v_el )
  2040. {
  2041. var v_iTabindex = parseInt( v_el.getAttribute( "tabIndex" ) );
  2042. return ( v_iTabindex >= 0 ||
  2043. ( ( v_el.nodeName == "INPUT" || v_el.nodeName == "BUTTON" || v_el.nodeName == "TEXTAREA" ) && v_iTabindex != -1 ) );
  2044. }
  2045. });
  2046. return cvContentView;
  2047. });