portletapi.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. // Licensed Materials - Property of IBM
  2. //
  3. // IBM Cognos Products: cpscrn
  4. //
  5. // (C) Copyright IBM Corp. 2013, 2014
  6. //
  7. // US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  8. //
  9. //
  10. (function() {
  11. // define namespace
  12. if (!window.com_ibm_cognos_cps){
  13. com_ibm_cognos_cps = {}
  14. }
  15. if (com_ibm_cognos_cps.ApplicationContext){
  16. // Stop if the ApplicationContext is already defined.
  17. return;
  18. }
  19. var _F_Array =
  20. {
  21. indexOf: function(array, value, begin, strict)
  22. {
  23. for (var i = +begin || 0, l = array.length; i < l; i++) {
  24. if (array[i] === value || strict && array[i] == value) {
  25. return i;
  26. }
  27. }
  28. return -1;
  29. },
  30. unique: function (array, strict)
  31. {
  32. var a = [], i, l = array.length;
  33. for (i = 0; i < l; i++) {
  34. if (this.indexOf(a, array[i], 0, strict) < 0) {
  35. a.push(array[i]);
  36. }
  37. }
  38. return a;
  39. },
  40. forEach: function(array, func, thisArg)
  41. {
  42. if (typeof func == "function") {
  43. var i, v, l = array.length;
  44. if (thisArg === undefined) {
  45. for (i = 0; i < l; i++) {
  46. func(array[i]);
  47. }
  48. } else {
  49. for (i = 0; i < l; i++) {
  50. func.call(thisArg, array[i]);
  51. }
  52. }
  53. }
  54. },
  55. insert: function(array, i, obj)
  56. {
  57. if (i !== undefined && obj !==undefined) {
  58. array.splice(i, 0, obj);
  59. }
  60. },
  61. remove: function(array, obj)
  62. {
  63. if (obj !== undefined)
  64. {
  65. var i = this.indexOf(array, obj);
  66. if (i >= 0)
  67. {
  68. array.splice(i, 1);
  69. return obj;
  70. }
  71. }
  72. return null;
  73. },
  74. removeAt: function(array, i)
  75. {
  76. if (i !== undefined) {
  77. array.splice(i, 1);
  78. }
  79. }
  80. };
  81. // Helper object used to create the xmlHttpRequest based on the current browser
  82. var CPSConfig = {
  83. browser: 'unknown',
  84. browserVersion: 'unknown',
  85. OS: 'unknown',
  86. xmlHttpDefault: null,
  87. emptyFunction:function(){},
  88. initialize: function()
  89. {
  90. this.browser = this.lookup(this.browsers).toLowerCase() || 'unknown';
  91. this.browserVersion = this.parseVersion(navigator.userAgent) || this.parseVersion(navigator.appVersion) || 'unknown';
  92. this.OS = this.lookup(this.systems) || 'unknown';
  93. this.xmlHttpDefault = this.findXMLHttpActiveXVersion();
  94. },
  95. lookup: function(data)
  96. {
  97. var i, l = data.length;
  98. for (i = 0; i < l; i++)
  99. {
  100. this.versionKey = data[i].partialKey || data[i].identity;
  101. var agent = data[i].agent;
  102. if (agent)
  103. {
  104. if (agent.indexOf(data[i].key) != -1)
  105. return data[i].identity;
  106. }
  107. else if (data[i].prop)
  108. return data[i].identity;
  109. }
  110. },
  111. parseVersion: function(s)
  112. {
  113. var index = s.indexOf(this.versionKey);
  114. if (index == -1)
  115. return;
  116. return parseFloat(s.substring(index + this.versionKey.length + 1).replace(/[^\d\.\-\+]/g, '_')); //sanitize before parse to avoid XSS vulnerability!
  117. },
  118. findXMLHttpActiveXVersion: function()
  119. {
  120. if (window.ActiveXObject)
  121. {
  122. var i, l = this.xmlHttpVersions.length;
  123. for (i = 0; i < l; i++)
  124. {
  125. try
  126. {
  127. // Try and create the ActiveXObject for Internet Explorer, if it doesn't work, try again.
  128. var xmlhttp = new ActiveXObject(this.xmlHttpVersions[i]);
  129. if (xmlhttp)
  130. return this.xmlHttpVersions[i];
  131. }
  132. catch (e)
  133. {
  134. // this ActiveX is not there, continue with next one in list
  135. }
  136. }
  137. }
  138. return null;
  139. },
  140. browsers: [
  141. { agent: navigator.userAgent, key: 'MSIE', identity: 'Explorer', partialKey: 'MSIE' },
  142. { agent: navigator.userAgent, key: 'Firefox', identity: 'Firefox' },
  143. { agent: navigator.userAgent, key: 'Gecko', identity: 'Mozilla', partialKey: 'rv' },
  144. { agent: navigator.userAgent, key: 'Mozilla', identity: 'Netscape', partialKey: 'Mozilla' },
  145. { agent: navigator.userAgent, key: 'Netscape', identity: 'Netscape' },
  146. { prop: window.opera, identity: 'Opera' },
  147. { agent: navigator.vendor, key: 'Apple', identity: 'Safari' }
  148. ],
  149. systems: [
  150. { agent: navigator.platform, key: 'Win', identity: 'Windows' },
  151. { agent: navigator.platform, key: 'Mac', identity: 'Mac' },
  152. { agent: navigator.platform, key: 'Linux', identity: 'Linux' }
  153. ],
  154. xmlHttpVersions: [
  155. 'Msxml2.XMLHTTP.6.0',
  156. 'Msxml2.XMLHTTP.3.0',
  157. 'Msxml2.XMLHTTP',
  158. 'Microsoft.XMLHTTP'
  159. ]
  160. }
  161. CPSConfig.initialize();
  162. /*
  163. Helper DOM utils.
  164. */
  165. com_ibm_cognos_cps._F_DOM =
  166. {
  167. addEventListener: function (node, type, callback, capture)
  168. {
  169. type = type.toLowerCase();
  170. if (node.addEventListener) {
  171. node.addEventListener(type, callback, capture);
  172. } else if (node.attachEvent) {
  173. node.attachEvent('on' + type, callback);
  174. } else {
  175. node['on' + type] = callback;
  176. }
  177. },
  178. selectNodes: function(node, xpath)
  179. {
  180. if (document.all)
  181. {
  182. var arr = new Array();
  183. var nodes = node.selectNodes(xpath);
  184. var i, l = nodes.length;
  185. for (i=0; i<l; i++)
  186. {
  187. arr.push(nodes.item(i));
  188. }
  189. return arr;
  190. }
  191. else
  192. {
  193. var doc = (node.ownerDocument) ? node.ownerDocument : node;
  194. var results = doc.evaluate(xpath, node, doc.createNSResolver(doc.documentElement), XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
  195. if (results)
  196. {
  197. var arr = new Array();
  198. var node = results.iterateNext();
  199. while (node != null)
  200. {
  201. arr.push(node);
  202. node = results.iterateNext();
  203. }
  204. return arr;
  205. }
  206. return null;
  207. }
  208. },
  209. selectSingleNode: function (node, xpath)
  210. {
  211. if (document.all)
  212. {
  213. return node.selectSingleNode(xpath);
  214. }
  215. else
  216. {
  217. var doc = (node.ownerDocument) ? node.ownerDocument : node;
  218. var results = doc.evaluate(xpath, node, doc.createNSResolver(doc.documentElement), XPathResult.FIRST_ORDERED_NODE_TYPE, null);
  219. if (results && results.singleNodeValue)
  220. return results.singleNodeValue;
  221. return null;
  222. }
  223. },
  224. getAttribute: function(node, name)
  225. {
  226. return node.getAttribute(name);
  227. },
  228. text: function(node)
  229. {
  230. function deepScanText(node)
  231. {
  232. var v = '';
  233. var n = node.firstChild;
  234. while (n != null)
  235. {
  236. if (n.nodeType == 3)
  237. v += n.nodeValue;
  238. else if (n.nodeType == 4)
  239. v += n.data;
  240. else if (n.nodeType == 1)
  241. v += deepScanText(n);
  242. n = n.nextSibling;
  243. }
  244. return v;
  245. }
  246. if (node == null || node === undefined)
  247. return '';
  248. if (document.all)
  249. return node.text;
  250. else if (node.nodeValue)
  251. return node.nodeValue;
  252. return deepScanText(node);
  253. },
  254. parseXml: function(xmlString)
  255. {
  256. var xmlDoc = null;
  257. if (window.ActiveXObject){
  258. xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
  259. xmlDoc.async="false";
  260. xmlDoc.loadXML(xmlString);
  261. }
  262. if (xmlDoc == null){
  263. var parser = new DOMParser();
  264. xmlDoc = parser.parseFromString(xmlString,"text/xml");
  265. }
  266. return xmlDoc;
  267. }
  268. }
  269. /*
  270. This class provides the APS that enables our content to work in enterprise portals.
  271. getWebContentResource: return an absolute url that will be used to retrieve a webcontent resource
  272. getGatewayResource: return an absolute url that will be used to retrieve a gateway resource
  273. getProxiedResource: return a url that can be used to do ajax request without running into cross domain issues
  274. getXHR: creates an xmlHttpRequest object.
  275. */
  276. CPSWebApplication = com_ibm_cognos_cps.ApplicationContext = function(spec){
  277. if (spec){
  278. this.initialize(spec);
  279. }
  280. }
  281. //013 Create event handler map
  282. CPSWebApplication.eventHandler = {};
  283. CPSWebApplication.prototype = com_ibm_cognos_cps.ApplicationContext.prototype = {
  284. /*
  285. * Sets the configuration object
  286. */
  287. initialize: function(spec){
  288. if (this.initialized){
  289. return;
  290. }
  291. this.eventSubscriptions = {};
  292. this.properties = {}; //deprecated
  293. this.id = spec.namespacePrefix ? spec.namespacePrefix : '';
  294. this.userpreferences = spec.userPreferences;
  295. if (!this.userprefjson){
  296. this.userprefjson = {};
  297. }
  298. this.settings = spec.applicationSettings;
  299. if (!this.settings){
  300. this.settings = {};
  301. }
  302. this.cssmapping = spec.cssMapping;
  303. if (!this.cssmapping){
  304. this.cssmapping = {};
  305. }
  306. this.events = spec.events;
  307. if (!this.events){
  308. this.events = {listen:[], publish:[]};
  309. }
  310. this.navstate = spec.navigationState;
  311. if (!this.navstate){
  312. this.navstate = {};
  313. }
  314. this.navstatedirty = false;
  315. this.webcontent = spec.webcontent;
  316. this.gateway = spec.gateway;
  317. this.getProperty = function(name){
  318. if (spec[name]){
  319. return spec[name];
  320. }else{
  321. return this.properties[name]; //deprecated
  322. }
  323. }
  324. if (!com_ibm_cognos_cps.ApplicationContext.instances){
  325. com_ibm_cognos_cps.ApplicationContext.instances = [];
  326. }
  327. this.instanceIndex = com_ibm_cognos_cps.ApplicationContext.instances.length;
  328. com_ibm_cognos_cps.ApplicationContext.instances.push(this);
  329. // Check if we need to do a client login
  330. var features = this.getProperty('features');
  331. if (features && features.indexOf('BrowserLogin') != -1){
  332. this.login();
  333. }
  334. this.initialized = true;
  335. },
  336. /*
  337. * Return the portlet's unique ID, ex. "p134677430"
  338. * This is prepended to all element ids in the portlet's html, and changes each page load
  339. */
  340. getID: function(){
  341. return this.id;
  342. },
  343. /*
  344. * Get the URI root for web content, ex. "http://exampleserver/cognos/"
  345. */
  346. getWebContentURI:function(){
  347. return this.webcontent;
  348. },
  349. setWebContentURI:function(value){
  350. this.webcontent=value;
  351. },
  352. /*
  353. * get the URI for the gateway, ex. "http://exampleserver/cognos/cgi-bin/cognos.cgi"
  354. */
  355. getGatewayURI:function(){
  356. return this.gateway;
  357. },
  358. setGatewayURI:function(value){
  359. this.gateway=value;
  360. },
  361. /*
  362. * Get the value of the named setting.
  363. * Settings include things such as the portlet alias, and any settings the user can set from the portlet config page.
  364. */
  365. getSetting:function(name){
  366. var value = this.settings[name];
  367. if (value === undefined){
  368. // The legacy sdk portlet appends 'sdk_' to the custom properties
  369. if (name.indexOf('sdk_') != 0) {
  370. name = 'sdk_' + name;
  371. }
  372. value=this.settings[name];
  373. }
  374. if(value && (typeof value == 'object') && value.length != undefined){
  375. value = value[0];
  376. }
  377. return value;
  378. },
  379. getMessage:function(resourceID) {
  380. var message = eval(resourceID);
  381. return message;
  382. },
  383. getSettingValues:function(name){
  384. var value = this.settings[name];
  385. if (value === undefined){
  386. // The legacy sdk portlet appends 'sdk_' to the custom properties
  387. if (name.indexOf('sdk_') != 0) {
  388. name = 'sdk_' + name;
  389. }
  390. value=this.settings[name];
  391. }
  392. if(value && (typeof value == 'string')){
  393. var arr = [];
  394. arr.push(value);
  395. value = arr;
  396. }
  397. return value;
  398. },
  399. /*
  400. * get css mappings, used to change css classes
  401. */
  402. getCssMapping:function(origialCss){
  403. return this.cssmapping[origialCss];
  404. },
  405. /*
  406. * get user preferences, which are set from the containing portal
  407. */
  408. getUserPreference:function(name){
  409. return this.userpreferences[name];
  410. },
  411. /*
  412. * Retrieve a value from the navigational state of the portlet.
  413. */
  414. getNavState:function(name){
  415. return this.navstate[name];
  416. },
  417. /*
  418. * Add key=value type information to the navigational state of the portlet,
  419. * This allows state to be kept across page loads within the user session.
  420. * Both key and value must be string type data.
  421. * May cause delays when unloading the page, to write the changed state back
  422. */
  423. setNavState:function(name, value){
  424. this.navstate[name] = value;
  425. if (! this.navstatedirty){
  426. this.navstatedirty = true;
  427. document.body.onbeforeunload = this._hitch(this, this._writeNavState);
  428. }
  429. },
  430. /*
  431. * This removes the key=value pair from the navigational state of the portlet.
  432. * Keys removed in this manner will no longer appear in the user session.
  433. * May cause delays when unloading the page, to write the changed state back
  434. */
  435. delNavState:function(name){
  436. delete this.navstate[name];
  437. if (! this.navstatedirty){
  438. this.navstatedirty = true;
  439. document.body.onbeforeunload = this._hitch(this, this._writeNavState);
  440. }
  441. },
  442. /*
  443. * private helper function for setNavState() and delNavState()
  444. */
  445. _writeNavState:function(){
  446. var query = [];
  447. for (key in this.navstate) {
  448. query.push(encodeURIComponent(key) + '=' + encodeURIComponent(this.navstate[key]));
  449. }
  450. var url = this._getActionURI(query.join('&'));
  451. var xhr = this._getXHR();
  452. xhr.open('GET', url, false);
  453. xhr.send();
  454. },
  455. subscribe: function(name, func){
  456. this.eventSubscriptions[name] = func;
  457. },
  458. publish: function(name, data){
  459. var invoked = false;
  460. for (var i = 0 ; i < com_ibm_cognos_cps.ApplicationContext.instances.length; i++){
  461. var c = com_ibm_cognos_cps.ApplicationContext.instances[i];
  462. if (c != this && c.eventSubscriptions[name]){
  463. c.eventSubscriptions[name](data);
  464. invoked = true;
  465. }
  466. }
  467. return invoked;
  468. },
  469. /*
  470. *Adds an event handler to the handler map //013
  471. */
  472. addListener: function(event, handler) {
  473. if (_F_Array.indexOf(this.events.listen, event) > -1) {
  474. if (CPSWebApplication.eventHandler[event]) {
  475. _F_Array.insert(CPSWebApplication.eventHandler[event], 0, handler);
  476. }
  477. else {
  478. CPSWebApplication.eventHandler[event] = new Array(handler);
  479. }
  480. }
  481. else {
  482. throw "This application does not listen for event: " + event;
  483. }
  484. },
  485. publishEvent: function(event, payload) {
  486. if(_F_Array.indexOf(this.events.publish, event) > -1) {
  487. var handlerArray = CPSWebApplication.eventHandler[event]
  488. if (handlerArray) {
  489. for (var i = 0; i < handlerArray.length; i++) {
  490. var handler = handlerArray[i];
  491. if (handler) {
  492. handler(payload);
  493. }
  494. }
  495. }
  496. else {
  497. throw "No listeners present for event: " + event;
  498. }
  499. }
  500. else {
  501. throw "This application does not publish event: " + event;
  502. }
  503. },
  504. /*
  505. * makes an absolute url from a base and a url which maybe absolute or relative.
  506. */
  507. makeAbsolute: function(base, url){
  508. if(url.indexOf(base) !== 0){
  509. var index = base.indexOf('://');
  510. if (index !== -1){
  511. index = base.indexOf('/', index + 3);
  512. if (index !== -1){
  513. return base.substring(0, index) + (url.charAt(0) === '/' ? '' : '/' ) + url;
  514. }
  515. }
  516. }
  517. return url;
  518. },
  519. /*
  520. * Return a URI which will be proxied by the portal, so as to avoid cross site request issues
  521. */
  522. getProxiedURI:function(url){
  523. var proxyTemplate = this.getProperty('proxyTemplate');
  524. // no proxying in CC
  525. if (proxyTemplate && !('cognos' == this.getProperty('portalAgent'))){
  526. return this._cpsresourceurl(this.getProperty('proxyTemplate'), url);
  527. }
  528. return url;
  529. },
  530. /*
  531. * Save the setting in the given form as portlet settings.
  532. */
  533. saveSettings: function(form){
  534. var saveForm = document[this.getProperty('scope')+'_editSaveForm'];
  535. if (saveForm){
  536. for (var i = 0 ; i < form.elements.length; i++){
  537. if (form.elements[i].type != 'button'){
  538. var input = document.createElement("input");
  539. input.name = "p_" + form.elements[i].name;
  540. input.type = form.elements[i].type;
  541. input.value = form.elements[i].value;
  542. input.checked = form.elements[i].checked;
  543. saveForm.appendChild(input);
  544. }
  545. }
  546. saveForm.submit();
  547. }
  548. },
  549. /*
  550. * Reset the settings of a portlet.
  551. */
  552. resetSettings: function(form){
  553. if (this.getProperty('editResetTemplate')) {
  554. document.location.href = this.getProperty('editResetTemplate');
  555. }
  556. },
  557. /*
  558. * Cancel the editing of the setting and go back to view the app
  559. */
  560. cancelSettings: function(){
  561. if (this.getProperty('editCancelTemplate')) {
  562. document.location.href = this.getProperty('editCancelTemplate');
  563. }
  564. },
  565. getPortalAgent: function(){
  566. return this.getProperty('portalAgent');
  567. },
  568. /*
  569. * Helper function that returns a url that will store the query to the nav state when accessed
  570. */
  571. _getActionURI:function(query){
  572. var actionTemplate = this.getProperty('actionTemplate');
  573. if (actionTemplate){
  574. return this._cpsactionurl(this.getProperty('actionTemplate'), query);
  575. }
  576. return null;
  577. },
  578. /*
  579. * This will log into the gateway, then call the callback.
  580. * It may be called by many different portlets simultaneously
  581. */
  582. login : function(callback){
  583. var passport = this.getProperty('camPassport');
  584. if (passport) {
  585. if (CPSWebApplication.loadState == 'unloaded') {
  586. CPSWebApplication.loadState = 'loading';
  587. if (callback){
  588. CPSWebApplication.pendingCallbacks.push(callback);
  589. }
  590. var div = document.createElement("div");
  591. div.style.display='none';
  592. var fr = document.createElement("iframe");
  593. fr.src = this.gateway + "?b_action=xts.run&m=/cps4/common/sso.xts&m_passportID=" + encodeURIComponent(passport);
  594. fr.onload = window.parent.CPSWebApplication.postLogin();
  595. div.appendChild(fr);
  596. document.body.appendChild(div);
  597. } else if (CPSWebApplication.loadState == 'loading' && callback) {
  598. CPSWebApplication.pendingCallbacks.push(callback);
  599. } else if (CPSWebApplication.loadState == 'loaded' && callback) {
  600. callback();
  601. }
  602. } else if(callback){
  603. callback();
  604. }
  605. },
  606. /*
  607. * helper function for getProxiedURI(),
  608. */
  609. _cpsresourceurl: function(resourceTemplate, target){
  610. var begin = resourceTemplate.indexOf('_cpsresourceurl');
  611. if (begin != -1){
  612. var endMarker='cpsendmarker_';
  613. var end = resourceTemplate.indexOf(endMarker, begin);
  614. if (end != -1){
  615. var marker = resourceTemplate.substring(begin, end + endMarker.length);
  616. var decodeCount = 0;
  617. var decodedMarker = marker;
  618. while(decodedMarker != '_cpsresourceurl:cpsendmarker_' && decodeCount ++ < 10){
  619. decodedMarker = decodeURIComponent(decodedMarker);
  620. }
  621. if (decodeCount < 10){
  622. var encodedTarget = target;
  623. for (i =0; i < decodeCount ; i++){
  624. encodedTarget = encodeURIComponent(encodedTarget);
  625. }
  626. target = resourceTemplate.replace(marker, encodedTarget);
  627. }
  628. }
  629. }
  630. // Plumtree portletIds.. so we can synchronize passports.
  631. if (window.cognosPortletIds){
  632. if(target.indexOf('?') != -1)
  633. target += '&';
  634. else
  635. target += '?';
  636. target += 'cognosPortletIds='+encodeURIComponent(cognosPortletIds.join('_'));
  637. }
  638. return target;
  639. },
  640. /*
  641. * helper function for _getActionURI()
  642. */
  643. _cpsactionurl: function(resourceTemplate, target){
  644. var begin = resourceTemplate.indexOf('_cpsparamsurl');
  645. if (begin != -1){
  646. var endMarker='cpsendmarker_';
  647. var end = resourceTemplate.indexOf(endMarker, begin);
  648. if (end != -1){
  649. var marker = resourceTemplate.substring(begin, end + endMarker.length);
  650. var decodeCount = 0;
  651. var decodedMarker = marker;
  652. while(decodedMarker != '_cpsparamsurl=cpsendmarker_' && decodeCount ++ < 10){
  653. decodedMarker = decodeURIComponent(decodedMarker);
  654. }
  655. if (decodeCount < 10){
  656. var encodedTarget = target;
  657. for (i =0; i < decodeCount ; i++){
  658. encodedTarget = encodeURIComponent(encodedTarget);
  659. }
  660. target = resourceTemplate.replace(marker, encodedTarget);
  661. }
  662. }
  663. }
  664. // Plumtree portletIds.. so we can synchronize passports.
  665. if (window.cognosPortletIds){
  666. if(target.indexOf('?') != -1)
  667. target += '&';
  668. else
  669. target += '?';
  670. target += 'cognosPortletIds='+encodeURIComponent(cognosPortletIds.join('_'));
  671. }
  672. return target;
  673. },
  674. /*
  675. * returns an XHR request in a cross-browser fashion
  676. */
  677. _getXHR: function(options){
  678. var obj;
  679. // plumtree xhr (knows how to handle timeouts ..)
  680. if (window.CustomPTHttpRequest !== undefined){
  681. obj = new CustomPTHttpRequest();
  682. }
  683. if (CPSConfig.xmlHttpDefault != null) {
  684. obj = new ActiveXObject(CPSConfig.xmlHttpDefault);
  685. }
  686. // Well if there is no ActiveXObject available it must be firefox, opera, or something else
  687. if (typeof XMLHttpRequest != 'undefined')
  688. {
  689. obj = new XMLHttpRequest();
  690. }
  691. if (!obj){
  692. throw 'No XMLHttpRequest object is available';
  693. }
  694. if (options){
  695. obj.onreadystatechange = function()
  696. {
  697. try
  698. {
  699. if (obj.readyState == 4)
  700. {
  701. if (obj.status >= 200 && obj.status < 300)
  702. {
  703. if (typeof options.onSuccess == "function") {
  704. options.onSuccess(obj);
  705. }
  706. }
  707. else
  708. {
  709. if (typeof options.onFailure == "function") {
  710. options.onFailure(obj);
  711. }
  712. }
  713. // fix for IE memory leak
  714. _self.transport.onreadystatechange = CPSConfig.emptyFunction;
  715. }
  716. }
  717. catch (e)
  718. {
  719. try
  720. {
  721. if (typeof options.onException == "function") {
  722. if (this.status !== 0) {
  723. options.onException(e);
  724. }
  725. }
  726. }
  727. catch (e1)
  728. {
  729. console.log('e1:' + e1);
  730. }
  731. }
  732. }; // of function
  733. }
  734. return obj;
  735. },
  736. /*
  737. * returns a function that will be called with the object as its scope
  738. */
  739. _hitch:function(obj, func){
  740. return function(){
  741. func.apply(obj);
  742. };
  743. },
  744. /*
  745. * This can be called to load a library in such a way that it will only be loaded once on the page.
  746. */
  747. loadLibrary: function(href, callback, conditionFunction)
  748. {
  749. if (conditionFunction && !conditionFunction()){
  750. if (callback){
  751. callback(false);
  752. }
  753. return false;
  754. }
  755. if (!window.CognosCPSLoadedLibMap){
  756. window.CognosCPSLoadedLibMap = {};
  757. }
  758. if ( !window.CognosCPSLoadedLibMap[href])
  759. {
  760. CognosCPSLoadedLibMap[href] = true;
  761. var callbacks = [];
  762. CPSWebApplication.loadingCallbacks[href] = callbacks;
  763. callbacks.push(callback);
  764. var head = document.getElementsByTagName('HEAD').item(0);
  765. var node = document.createElement('SCRIPT');
  766. var _self = this;
  767. node.onload = node.onreadystatechange = function()
  768. {
  769. if (this.readyState && this.readyState != 'loaded' && this.readyState != 'complete') {
  770. return;
  771. }
  772. var callbacks = CPSWebApplication.loadingCallbacks[href];
  773. for (var i = 0 ; i < callbacks.length; i++){
  774. callbacks[i](true);
  775. }
  776. delete CPSWebApplication.loadingCallbacks[href];
  777. };
  778. node.type = 'text/javascript';
  779. node.src = href;
  780. head.appendChild(node);
  781. return true;
  782. }
  783. if (callback){
  784. var callbacks = CPSWebApplication.loadingCallbacks[href];
  785. if (callbacks){
  786. callbacks.push(callback);
  787. }else {
  788. callback();
  789. }
  790. }
  791. return false;
  792. }
  793. }
  794. /*
  795. * helper function for login()
  796. */
  797. CPSWebApplication.postLogin = function() {
  798. CPSWebApplication.loadState = 'loaded';
  799. for (var i = 0; i < CPSWebApplication.pendingCallbacks.length; i++) {
  800. CPSWebApplication.pendingCallbacks[i]();
  801. }
  802. }
  803. CPSWebApplication.loadState = 'unloaded';
  804. CPSWebApplication.pendingCallbacks = [];
  805. CPSWebApplication.loadingCallbacks = {};
  806. })();
  807. window.CognosConnect = new CPSWebApplication();