thresholdMgr.js 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. // Licensed Materials - Property of IBM
  2. //
  3. // IBM Cognos Products: cogadmin
  4. //
  5. // (C) Copyright IBM Corp. 2005, 2014
  6. //
  7. // US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  8. //
  9. //
  10. // Copyright (C) 2008 Cognos ULC, an IBM Company. All rights reserved.
  11. // Cognos (R) is a trademark of Cognos ULC, (formerly Cognos Incorporated).
  12. /*******************************************************************************
  13. * Cognos Generic Threshold Manager Library Description: A library to facilitate
  14. * the creation of a Cognos standard threshold editor with customizable editors
  15. ******************************************************************************/
  16. var TYPE_HIGH_POSITIVE = "high";
  17. var TYPE_MIDDLE_POSITIVE = "middle";
  18. var TYPE_LOW_POSITIVE = "low";
  19. var TYPE_NONE = "none";
  20. var THRESHOLD_EXCEED_MAX = -2;
  21. var THRESHOLD_NO_MATCH = -3;
  22. var THRESHOLD_NOT_A_NUMBER = -4;
  23. var HEALTHS = ["Good","Average","Poor"];
  24. /*
  25. * The data for a particular editor
  26. */
  27. function ThresholdModel(value, exclusive, attrName, exAttrName, upperSide) {
  28. var orig = "" + value + exclusive;
  29. this.value = value;
  30. this.exclusive = exclusive;
  31. this.attrName = attrName; // the name of the "value" attribute used to
  32. // post to the server (eg. "UpperSidePoor")
  33. this.exAttrName = exAttrName; // the name of the "exclusive" attribute
  34. // used to post to the server (eg.
  35. // "UpperPoorEx")
  36. this.upperSide = upperSide; // boolean to store whether the threshold lies
  37. // on the upper or lower side of the scale
  38. this.errorCode = 0;
  39. this.setErrorCode = function(value) {
  40. this.errorCode = parseFloat(value);
  41. }
  42. this.getErrorCode = function() {
  43. return this.errorCode;
  44. }
  45. this.clearErrorCode = function() {
  46. this.errorCode = 0;
  47. }
  48. this.setValue = function(value) {
  49. this.value = value;
  50. }
  51. this.setExclusive = function(isExclusive) {
  52. this.exclusive = isExclusive;
  53. }
  54. this.hasChanged = function() {
  55. return ("" + this.value + this.exclusive) != orig;
  56. }
  57. this.getValue = function() {
  58. return this.value;
  59. }
  60. this.isExclusive = function() {
  61. return this.exclusive;
  62. }
  63. this.isUpperSide = function() {
  64. return this.upperSide;
  65. }
  66. }
  67. /*
  68. * The view for an editor consisting of 2 editors. 1 editor for the top and 1
  69. * for the bottom. The view is designed to allow an editor to "jump" into a
  70. * higher or lower view when the "up" or "down" icons are respectively.
  71. */
  72. function ThresholdView(dialog, health, label, topEditor, botEditor, imagesURL) {
  73. var tr = document.createElement("tr");
  74. var td = document.createElement("td");
  75. tr.appendChild(td);
  76. td.style.cssText = "border:0pt none;margin:0pt;padding:0pt;white-space:nowrap;";
  77. td.align = "right";
  78. var imgTop = document.createElement("input");
  79. imgTop.setAttribute("type", "image");
  80. imgTop.setAttribute("src", imagesURL + "rangestyle_up_normal.gif");
  81. imgTop.setAttribute("alt", "");
  82. var editorParentTop = document.createElement("span");
  83. td.appendChild(editorParentTop);
  84. if (topEditor) {
  85. editorParentTop.appendChild(topEditor.isUpperSide ? topEditor.exclusive
  86. : topEditor.inclusive);
  87. if (topEditor.isUpperSide) {
  88. topEditor.imgExclusive = imgTop;
  89. } else {
  90. topEditor.imgInclusive = imgTop;
  91. }
  92. }
  93. imgTop.style.visibility = "hidden";
  94. imgTop.disabled = true;
  95. td.appendChild(imgTop);
  96. td.appendChild(document.createElement("div"));
  97. if (topEditor && topEditor.model) {
  98. imgTop.onclick = function() {
  99. topEditor.update(true, false);
  100. initTabStops(dialog,true);
  101. };
  102. imgTop.alt = "";
  103. imgTop.onmouseover = function() {
  104. this.src = imagesURL + 'rangestyle_up_rollover.gif'
  105. };
  106. imgTop.onmouseout = function() {
  107. this.src = imagesURL + 'rangestyle_up_normal.gif'
  108. };
  109. }
  110. var imgBot = document.createElement("input");
  111. imgBot.setAttribute("type", "image");
  112. var editorParentBot = document.createElement("span");
  113. td.appendChild(editorParentBot);
  114. if (botEditor) {
  115. editorParentBot.appendChild(botEditor.isUpperSide ? botEditor.inclusive
  116. : botEditor.exclusive);
  117. if (botEditor.isUpperSide) {
  118. botEditor.imgInclusive = imgBot;
  119. } else {
  120. botEditor.imgExclusive = imgBot;
  121. }
  122. }
  123. imgBot.style.visibility = "hidden";
  124. imgBot.disabled = true;
  125. imgBot.setAttribute("src", imagesURL + "rangestyle_down_normal.gif");
  126. imgBot.setAttribute("alt", "");
  127. imgBot.style.verticalAlign = "bottom";
  128. td.appendChild(imgBot);
  129. if (botEditor && botEditor.model) {
  130. imgBot.onclick = function() {
  131. botEditor.update(true, false);
  132. initTabStops(dialog, true);
  133. };
  134. imgBot.onmouseover = function() {
  135. this.src = imagesURL + "rangestyle_down_rollover.gif"
  136. };
  137. imgBot.onmouseout = function() {
  138. this.src = imagesURL + "rangestyle_down_normal.gif"
  139. };
  140. }
  141. var tdScale = document.createElement("td");
  142. tr.appendChild(tdScale);
  143. tdScale.innerHTML += '<img width="23" alt="" height="3" border="0" style="border: 0pt none ; margin: 0pt; padding: 0pt; display: block;" src="'
  144. + imagesURL + 'range_top.gif"/>';
  145. tdScale.innerHTML += '<img width="23" alt="" height="16" border="0" style="border: 0pt none ; margin: 0pt; padding: 0pt; display: block;" src="'
  146. + imagesURL + 'range_resize.gif"/>';
  147. tdScale.innerHTML += '<img width="23" alt="" border="0" style="border: 0pt none ; margin: 0pt; padding: 0pt; display: block;" src="'
  148. + imagesURL + 'range_middle.gif"/>';
  149. tdScale.innerHTML += '<img width="23" alt="" height="16" border="0" style="border: 0pt none ; margin: 0pt; padding: 0pt; display: block;" src="'
  150. + imagesURL + 'range_resize.gif"/>';
  151. tdScale.innerHTML += '<img width="23" alt="" height="3" border="0" style="border: 0pt none ; margin: 0px; padding: 0px; display: block;" src="'
  152. + imagesURL + 'range_bottom.gif"/>';
  153. var tdHealth = document.createElement("td");
  154. tr.appendChild(tdHealth);
  155. tdHealth.innerHTML += '<img alt="' + label
  156. + '" style="display:inline;margin-right:100px" border="0" title="'
  157. + label + '" src="' + imagesURL + 'icon_' + health
  158. + '_traffic32.gif"/>';
  159. if (botEditor) {
  160. botEditor.update();
  161. }
  162. if (topEditor) {
  163. topEditor.update();
  164. }
  165. return tr;
  166. }
  167. ThresholdView.getEditorLabel = function(model, i18n, units, range) {
  168. var labelTemplate = i18n.labelTemplate;
  169. var coreLabel = ThresholdView.getLabel(model, i18n, false);
  170. return labelTemplate.replace('#LABEL#',coreLabel).replace('#UNITS#',units).replace('#RANGE#',range);
  171. }
  172. ThresholdView.getEditorToggleLabel = function(model, i18n) {
  173. return ThresholdView.getLabel(model, i18n, true);
  174. }
  175. ThresholdView.getLabel = function(model, i18n, isToggleButton) {
  176. var tokens = model.exAttrName.split(/(?=[A-Z])/); //Each upper case letter
  177. var upperLower = tokens[0]
  178. var health = tokens[1];
  179. if ((isToggleButton && !model.exclusive) || (!isToggleButton && model.exclusive)) {
  180. health = HEALTHS[HEALTHS.indexOf(health)-1];
  181. } else {
  182. upperLower = upperLower == "Lower" ? "Upper" : "Lower";
  183. }
  184. var labelKey = upperLower+health+"Label";
  185. var label = i18n[labelKey];
  186. return label;
  187. }
  188. /*
  189. * A 'controller' object for an editor which renders the supplied editor based
  190. * on the state of it's supplied model
  191. */
  192. function EditorManager(model, editor, isUpperSide, inputModel) {
  193. this.model = model;
  194. this.isUpperSide = isUpperSide;
  195. this.editor = editor;
  196. this.inputModel = inputModel;
  197. if (model && model.isExclusive()) {
  198. this.exclusive = editor.element;
  199. this.inclusive = editor.element.cloneNode(true); // placeholder
  200. } else {
  201. this.inclusive = editor.element;
  202. this.exclusive = editor.element.cloneNode(true); // placeholder
  203. }
  204. this.imgInclusive = null;
  205. this.imgExclusive = null;
  206. this.updateElement = function(element, hide) {
  207. element.style.visibility = hide ? "hidden" : "visible";
  208. element.disabled = hide;
  209. var inputs = element.getElementsByTagName('input');
  210. for ( var i = 0; i < inputs.length; i++) {
  211. inputs[i].disabled = hide;
  212. }
  213. }
  214. this.updateElements = function() {
  215. var isExclusive = this.model ? this.model.isExclusive() : true;
  216. this.updateElement(this.inclusive, isExclusive);
  217. this.updateElement(this.exclusive, !isExclusive);
  218. editor.update();
  219. }
  220. this.update = function(switchEx, needUpdate) {
  221. if (needUpdate == undefined)
  222. needUpdate = true;
  223. if (model) {
  224. if (switchEx) {
  225. model.setExclusive(!model.exclusive);
  226. var exclusiveParent = this.exclusive.parentNode;
  227. var inclusiveParent = this.inclusive.parentNode;
  228. var i = null
  229. var e = null;
  230. if (exclusiveParent) {
  231. e = exclusiveParent.removeChild(exclusiveParent.lastChild);
  232. }
  233. if (inclusiveParent) {
  234. i = inclusiveParent.removeChild(inclusiveParent.lastChild);
  235. }
  236. if (exclusiveParent && i) {
  237. exclusiveParent.appendChild(i);
  238. this.exclusive = i;
  239. }
  240. if (inclusiveParent && e) {
  241. inclusiveParent.appendChild(e);
  242. this.inclusive = e;
  243. }
  244. }
  245. this.updateElements();
  246. if (this.imgExclusive) {
  247. this.imgExclusive.style.visibility = model.isExclusive() ? "visible"
  248. : "hidden";
  249. this.imgExclusive.disabled = !model.isExclusive();
  250. setToggleLabel(model, this.imgExclusive, this.inputModel);
  251. }
  252. if (this.imgInclusive) {
  253. this.imgInclusive.style.visibility = model.isExclusive() ? "hidden"
  254. : "visible";
  255. this.imgInclusive.disabled = model.isExclusive();
  256. setToggleLabel(model, this.imgInclusive, this.inputModel);
  257. }
  258. if (model.value >= 0 && needUpdate)
  259. this.editor.update();
  260. } else {
  261. this.updateElements();
  262. if (this.imgExclusive) {
  263. this.imgExclusive.style.visibility = "visible";
  264. this.imgExclusive.disabled = false;
  265. }
  266. if (this.imgInclusive) {
  267. this.imgInclusive.style.visibility = "hidden";
  268. this.imgInclusive.disabled = true;
  269. }
  270. }
  271. }
  272. setToggleLabel = function(model, toggleButton, inputModel) {
  273. var toggleLabel = inputModel.i18n.toggleLabel;
  274. toggleLabel = toggleLabel.replace('#TARGET#',ThresholdView.getEditorToggleLabel(model, inputModel.i18n));
  275. toggleButton.setAttribute('title', toggleLabel);
  276. toggleButton.setAttribute('alt', toggleLabel);
  277. }
  278. }
  279. /*
  280. * Encapsulates the Threshold Manager Widget
  281. */
  282. function ThresholdsManager(parentElt, inputModel) {
  283. var lowerSeparator = null;
  284. this.models = new Array();
  285. this.createSeparator = function(label, valign) {
  286. var tr = document.createElement("tr");
  287. var td = document.createElement("td");
  288. tr.appendChild(td);
  289. td.align = "right";
  290. td.style.cssText = "border: 0pt none ; margin: 0pt; padding: 0pt; display: block;";
  291. if (label != null) {
  292. td.innerHTML += '<span class="formText">' + label + '</span>';
  293. }
  294. var td2 = document.createElement("td");
  295. td2.style.cssText = "border:0pt none;margin:0pt;padding:0pt";
  296. td2.innerHTML += '<img alt="" width="23" border="0" style="border: 0pt none ; margin: 0pt; padding: 0pt; display: block;" src="'
  297. + inputModel.imagesURL
  298. + 'range_tic'
  299. + ((label == null) ? '_mid' : '') + '.gif"/>';
  300. if (valign) {
  301. td2.setAttribute("valign", valign);
  302. }
  303. tr.appendChild(td2);
  304. return tr;
  305. }
  306. this.addView = function(view, model) {
  307. if (tbody.childNodes.length > 2) {
  308. tbody.insertBefore(this.createSeparator(), lowerSeparator);
  309. }
  310. tbody.insertBefore(view, lowerSeparator);
  311. if (model) {
  312. this.models[this.models.length] = model;
  313. }
  314. }
  315. this.getModels = function() {
  316. return this.models;
  317. }
  318. var table = document.createElement("table");
  319. table.className = "cctable"
  320. table.setAttribute("width", "100%");
  321. table.setAttribute("role", "presentation");
  322. while (parentElt.childNodes.length > 0) {
  323. parentElt.removeChild(parentElt.firstChild);
  324. }
  325. var theader = document.createElement("thead");
  326. theader.className = "cogstyle-table-header";
  327. var tbody = document.createElement("tbody");
  328. if (inputModel.type == "none") {
  329. table.style["filter"] = "alpha(opacity=50)";
  330. table.style["-moz-opacity"] = .5;
  331. table.style["opacity"] = .5;
  332. }
  333. table.appendChild(theader);
  334. table.appendChild(tbody);
  335. var trHeader = document.createElement("tr");
  336. trHeader.className = "cogstyle-form-label";
  337. theader.appendChild(trHeader);
  338. var tdValuesHeader = document.createElement("td");
  339. tdValuesHeader.align = "left";
  340. tdValuesHeader.innerHTML += inputModel.i18n.valuesHeaderLabel;
  341. tdValuesHeader.colSpan = 2;
  342. var parentWidth = parseInt(parentElt.style.width);
  343. trHeader.appendChild(tdValuesHeader);
  344. var tdScoreHeader = document.createElement("td");
  345. tdScoreHeader.align = "left";
  346. tdScoreHeader.innerHTML += inputModel.i18n.scoreHeaderLabel;
  347. trHeader.appendChild(tdScoreHeader);
  348. tbody.appendChild(this.createSeparator(inputModel.i18n.maxLabel, 'bottom'));
  349. lowerSeparator = this.createSeparator(inputModel.i18n.minLabel, 'top');
  350. tbody.appendChild(lowerSeparator);
  351. parentElt.appendChild(table);
  352. }
  353. /*
  354. * Default Threshold Editor consisting of 1 HTML textual input element.
  355. */
  356. function DefaultEditor(model, inputModel) {
  357. var patternRegExp = /^\d{0,14}$/;
  358. this.input = document.createElement("input");
  359. this.input.className = "cogstyle-threshold-default-input";
  360. var range = "1 - 99999999999999";
  361. var self = this.input;
  362. xAddEventListener(self, "keypress", thresholdNoLetters, false);
  363. xAddEventListener(self, "keyup", function(event) {
  364. thresholdCheck(model, self, inputModel.maxValue, patternRegExp);
  365. }, false);
  366. xAddEventListener(self, "blur", function(event) {
  367. var dValue = thresholdCheck(model, self, inputModel.maxValue,
  368. patternRegExp);
  369. if (dValue !== null) {
  370. model.setValue(dValue);
  371. }
  372. }, false);
  373. this.input.setAttribute("autocomplete", "OFF");
  374. this.input.setAttribute("maxlength", inputModel.maxValue.toString().length);
  375. this.input.maxLength = inputModel.maxValue.toString().length;
  376. this.input.disabled = inputModel.type == TYPE_NONE;
  377. // Editor interface "this.update" implementation
  378. this.update = function() {
  379. this.input.value = model.getValue();
  380. var label = ThresholdView.getEditorLabel(model, inputModel.i18n, '', range);
  381. this.input.setAttribute("alt", label);
  382. this.input.setAttribute("title", label);
  383. }
  384. this.element = this.input;
  385. }
  386. /*
  387. * Percentage Threshold Editor consisting of 1 HTML textual input element.
  388. */
  389. function PercentageEditor(model, inputModel) {
  390. var container = document.createElement("span");
  391. var patternRegExp = /^\d{0,2}(\.)?\d{0,2}$/;
  392. this.input = document.createElement("input");
  393. this.input.className = "cogstyle-threshold-duration-input";
  394. var range = "0.01 - 99.99";
  395. var self = this.input;
  396. xAddEventListener(self, "keypress", thresholdNoLetters, false);
  397. xAddEventListener(self, "keyup", function(event) {
  398. thresholdCheck(model, self, inputModel.maxValue, patternRegExp);
  399. }, false);
  400. xAddEventListener(self, "blur", function(event) {
  401. var dValue = thresholdCheck(model, self, inputModel.maxValue,
  402. patternRegExp);
  403. if (dValue !== null) {
  404. model.setValue(floatMath(dValue, 0.01, "*"));
  405. }
  406. }, false);
  407. this.input.setAttribute("autocomplete", "OFF");
  408. this.input.setAttribute("maxlength", inputModel.maxValue.toString().length);
  409. this.input.maxLength = inputModel.maxValue.toString().length;
  410. this.input.disabled = inputModel.type == TYPE_NONE;
  411. // Editor interface "this.update" implementation
  412. this.update = function() {
  413. var value = model.getValue();
  414. if (value) {
  415. this.input.value = parseFloat(100 * value).toFixed(2);
  416. }
  417. var label = ThresholdView.getEditorLabel(model, inputModel.i18n,'',range);
  418. this.input.setAttribute("title", label);
  419. this.input.setAttribute("alt", label);
  420. }
  421. container.appendChild(this.input);
  422. var labelContainer = document.createElement("span");
  423. labelContainer.className = "cogstyle-form-label";
  424. labelContainer.style.cssText = "padding:2px";
  425. labelContainer.innerHTML += "%";
  426. container.appendChild(labelContainer);
  427. this.element = container;
  428. }
  429. /*
  430. * Duration utility class
  431. */
  432. function Duration(milliseconds) {
  433. var mSeconds = milliseconds;
  434. this.hours = Math.floor(milliseconds / 1000 / 60 / 60);
  435. milliseconds = milliseconds - this.hours * 1000 * 60 * 60
  436. this.minutes = Math.floor(milliseconds / 1000 / 60);
  437. milliseconds = milliseconds - this.minutes * 1000 * 60
  438. this.seconds = (milliseconds % 1000 == 0) ? Math.round(milliseconds / 1000)
  439. : milliseconds / 1000;
  440. this.toString = function(inputModel) {
  441. if (inputModel && inputModel.i18n) {
  442. var s = "";
  443. if (this.hours > 0) {
  444. s += this.hours + inputModel.i18n.hoursLabelAbbr;
  445. }
  446. if (this.minutes > 0) {
  447. s += " " + this.minutes + inputModel.i18n.minutesLabelAbbr;
  448. }
  449. s += " " + this.seconds + inputModel.i18n.secondsLabelAbbr;
  450. return s;
  451. } else {
  452. return "" + mSeconds;
  453. }
  454. }
  455. }
  456. /*
  457. * mask of the input value of threshold, garantee the input is an integer and
  458. * less then upperBound @para obj: target object to be checked @para uBound: the
  459. * maxValue (include) allowed
  460. */
  461. thresholdCheck = function(model, obj, uBound, pattern) {
  462. function styleSwitcher(obj, withError) {
  463. if (withError) {
  464. if (obj.className.search(/-error$/i) == -1) {
  465. obj.className = obj.className + "-error";
  466. }
  467. } else {
  468. obj.className = obj.className.replace(/-error$/i, "");
  469. }
  470. }
  471. var retValue = obj.value;
  472. // get rid of the leading or tail space, try to avoid flashing at the same
  473. // time.
  474. if (trim(retValue).length < retValue.length) {
  475. retValue = trim(retValue);
  476. }
  477. if (isNaN(retValue) || retValue < 0) {
  478. obj.setAttribute("cogErrorType", THRESHOLD_NOT_A_NUMBER);
  479. styleSwitcher(obj, true);
  480. model.setErrorCode(THRESHOLD_NOT_A_NUMBER);
  481. return null;
  482. }
  483. if (parseFloat(retValue) > parseFloat(uBound)) {
  484. obj.setAttribute("cogErrorType", THRESHOLD_EXCEED_MAX);
  485. styleSwitcher(obj, true);
  486. model.setErrorCode(THRESHOLD_EXCEED_MAX);
  487. return null;
  488. }
  489. if (!retValue.match(pattern)) {
  490. obj.setAttribute("cogErrorType", THRESHOLD_NO_MATCH);
  491. styleSwitcher(obj, true);
  492. model.setErrorCode(THRESHOLD_NO_MATCH);
  493. return null;
  494. }
  495. styleSwitcher(obj, false);
  496. obj.setAttribute("cogErrorType", 0);
  497. model.clearErrorCode();
  498. return retValue ? parseFloat(retValue) : 0;
  499. }
  500. // event handler for threshold onkeypress, prevent the letter and space from
  501. // input
  502. thresholdNoLetters = function(event) {
  503. // Get the event object and character code in a portable way
  504. var e = event || window.event; // Key event object
  505. var code = e.charCode || e.keyCode; // What key was pressed
  506. // If this keystroke is a function key of any kind, do not filter it
  507. if (e.charCode == 0)
  508. return true; // Function key (Firefox only)
  509. if (e.ctrlKey || e.altKey)
  510. return true; // Ctrl or Alt held down
  511. if (code < 32)
  512. return true; // ASCII control character
  513. // Convert the character code to a character
  514. var c = String.fromCharCode(code);
  515. var pattern = /\d|[\.]/;
  516. if (pattern.test(c)) {
  517. return true;
  518. } else {
  519. // And reject this keypress event
  520. if (e.preventDefault)
  521. e.preventDefault();
  522. if (e.returnValue)
  523. e.returnValue = false;
  524. return false;
  525. }
  526. }
  527. /*
  528. * Duration Threshold editor consisting of 3 HTML textual input elements for
  529. * "Hours","Minutes","Seconds"
  530. */
  531. function DurationEditor(model, inputModel) {
  532. var container = document.createElement("span");
  533. var hours = createInput(inputModel.i18n.hoursLabelAbbr, 999, /^\d{0,3}$/);
  534. var mins = createInput(inputModel.i18n.minutesLabelAbbr, 59, /^\d{0,2}$/);
  535. var secs = createInput(inputModel.i18n.secondsLabelAbbr, 59.999,
  536. /^\d{0,2}(\.)?\d{0,3}$/, 0.001);
  537. var self = this;
  538. function createInput(label, upperBound, pattern, lowerBound) {
  539. this.lowerBound = lowerBound;
  540. this.upperBound = upperBound;
  541. var lb = lowerBound || 0;
  542. var input = document.createElement("input");
  543. input.className = "cogstyle-threshold-duration-input";
  544. xAddEventListener(input, "keypress", thresholdNoLetters, false);
  545. xAddEventListener(input, "keyup", function(event) {
  546. thresholdCheck(model, input, upperBound, pattern);
  547. }, false);
  548. xAddEventListener(input, "blur", function(event) {
  549. var dValue = thresholdCheck(model, input, upperBound, pattern);
  550. input.setAttribute("retValue", dValue);
  551. var finalValue = self.getValue();
  552. if (finalValue !== null) {
  553. model.setValue(finalValue);
  554. }
  555. }, false);
  556. input.setAttribute("autocomplete", "OFF");
  557. input.setAttribute("maxlength", upperBound.toString().length);
  558. input.maxLength = upperBound.toString().length;
  559. input.upperBound = upperBound;
  560. input.disabled = inputModel.type == TYPE_NONE;
  561. container.appendChild(input);
  562. var labelContainer = document.createElement("span");
  563. labelContainer.className = "cogstyle-form-label";
  564. labelContainer.style.cssText = "padding:2px";
  565. labelContainer.innerHTML += label;
  566. container.appendChild(labelContainer);
  567. return input;
  568. }
  569. this.getValue = function() {
  570. var ihours = hours.getAttribute("retValue") || 0;
  571. var imins = mins.getAttribute("retValue") || 0;
  572. var isecs = secs.getAttribute("retValue") || 0;
  573. if (hours.getAttribute("cogErrorType")
  574. && hours.getAttribute("cogErrorType") < 0) {
  575. model.setErrorCode(hours.getAttribute("cogErrorType"));
  576. return;
  577. } else if (mins.getAttribute("cogErrorType")
  578. && mins.getAttribute("cogErrorType") < 0) {
  579. model.setErrorCode(mins.getAttribute("cogErrorType"));
  580. return;
  581. } else if (secs.getAttribute("cogErrorType")
  582. && secs.getAttribute("cogErrorType") < 0) {
  583. model.setErrorCode(secs.getAttribute("cogErrorType"));
  584. return;
  585. } else if (!ihours && !imins && !isecs) {
  586. model.setErrorCode(THRESHOLD_NOT_A_NUMBER);
  587. return;
  588. } else {
  589. return (ihours * 1000 * 60 * 60) + (imins * 1000 * 60)
  590. + (isecs * 1000);
  591. }
  592. }
  593. // Editor interface "this.update" implementation
  594. this.update = function() {
  595. var duration = new Duration(model.getValue());
  596. if (duration > 0) {
  597. hours.value = duration.hours;
  598. hours.setAttribute("retValue", duration.hours);
  599. mins.value = duration.minutes;
  600. mins.setAttribute("retValue", duration.minutes);
  601. secs.value = duration.seconds;
  602. secs.setAttribute("retValue", duration.seconds);
  603. }
  604. var hoursLabel = ThresholdView.getEditorLabel(model, inputModel.i18n, inputModel.i18n.hoursLabel, hours.upperBound);
  605. hours.setAttribute("alt", hoursLabel);
  606. hours.setAttribute("title", hoursLabel);
  607. var minsLabel = ThresholdView.getEditorLabel(model, inputModel.i18n, inputModel.i18n.minutesLabel, mins.upperBound);
  608. mins.setAttribute("alt", minsLabel);
  609. mins.setAttribute("title", minsLabel);
  610. var secsLabel = ThresholdView.getEditorLabel(model, inputModel.i18n, inputModel.i18n.secondsLabel, secs.upperBound);
  611. secs.setAttribute("alt", secsLabel);
  612. secs.setAttribute("title", secsLabel);
  613. }
  614. this.element = container;
  615. }
  616. /*
  617. * Encapsulates the Threshold Tooltip Widget
  618. */
  619. function ThresholdsTooltip(inputModel) {
  620. var container = document.getElementById(inputModel.container);
  621. while (container.childNodes && (container.childNodes.length > 0)) {
  622. container.removeChild(container.firstChild);
  623. }
  624. var table = document.createElement("table");
  625. table.setAttribute("role", "presentation");
  626. container.appendChild(table);
  627. var tbody = document.createElement("tbody");
  628. table.appendChild(tbody);
  629. container.appendChild(table);
  630. var upperSideAvgModel = null;
  631. var lowerSideAvgModel = null;
  632. if (inputModel.type != TYPE_HIGH_POSITIVE) {
  633. var upperSidePoorModel = new ThresholdModel(
  634. inputModel.upperSidePoorValue, inputModel.upperSidePoorEx,
  635. "UpperSidePoor", "UpperPoorEx", true, inputModel.i18n);
  636. addView(upperSidePoorModel, null, "poor", inputModel.i18n.poorLabel);
  637. upperSideAvgModel = new ThresholdModel(inputModel.upperSideAvgValue,
  638. inputModel.upperSideAvgEx, "UpperSideAverage",
  639. "UpperAverageEx", true, inputModel.i18n);
  640. addView(upperSidePoorModel, upperSideAvgModel, "average",
  641. inputModel.i18n.avgLabel);
  642. }
  643. if (inputModel.type != TYPE_LOW_POSITIVE) {
  644. lowerSideAvgModel = new ThresholdModel(inputModel.lowerSideAvgValue,
  645. inputModel.lowerSideAvgEx, "LowerSideAverage",
  646. "LowerAverageEx", false, inputModel.i18n);
  647. }
  648. if (inputModel.type == TYPE_LOW_POSITIVE) {
  649. addView(null, upperSideAvgModel, "good", inputModel.i18n.goodLabel);
  650. } else if (inputModel.type == TYPE_HIGH_POSITIVE) {
  651. addView(lowerSideAvgModel, null, "good", inputModel.i18n.goodLabel);
  652. } else {
  653. addView(upperSideAvgModel, lowerSideAvgModel, "good",
  654. inputModel.i18n.goodLabel);
  655. }
  656. if (inputModel.type != TYPE_LOW_POSITIVE) {
  657. var lowerSidePoorModel = new ThresholdModel(
  658. inputModel.lowerSidePoorValue, inputModel.lowerSidePoorEx,
  659. "LowerSidePoor", "LowerPoorEx", false, inputModel.i18n);
  660. addView(lowerSideAvgModel, lowerSidePoorModel, "average",
  661. inputModel.i18n.avgLabel);
  662. addView(null, lowerSidePoorModel, "poor", inputModel.i18n.poorLabel);
  663. }
  664. function addView(topModel, botModel, health, healthLabel) {
  665. var tr = document.createElement("tr");
  666. tbody.appendChild(tr);
  667. var tdHealth = document.createElement("td");
  668. tr.appendChild(tdHealth);
  669. tdHealth.setAttribute("valign", "middle");
  670. tdHealth.innerHTML += '<img border="0" title="' + healthLabel
  671. + '" alt="' + healthLabel + '" src="' + inputModel.imagesURL
  672. + 'icon_' + health + '_traffic.gif"/>';
  673. tdRange = document.createElement("td");
  674. tr.appendChild(tdRange);
  675. if (topModel && botModel) {
  676. var base = inputModel.valueBase || 1;
  677. var botValue = parseFloat(botModel.value);
  678. var topValue = parseFloat(topModel.value);
  679. var offSetTop = 0;
  680. var offSetBot = 0;
  681. var isConsecutive = floatMath(topValue, -botValue) == base;
  682. var arrConsecutive = [];
  683. var botText = "";
  684. var topText = "";
  685. if (botModel.isUpperSide() && topModel.isUpperSide()) {
  686. if (!topModel.isExclusive()) {
  687. offSetTop = -base;
  688. }
  689. if (botModel.isExclusive()) {
  690. offSetBot = base;
  691. }
  692. } else if ((!botModel.isUpperSide()) && (!topModel.isUpperSide())) {
  693. if (topModel.isExclusive()) {
  694. offSetTop = -base;
  695. }
  696. if (!botModel.isExclusive()) {
  697. offSetBot = base;
  698. }
  699. } else if (topModel.isUpperSide) {
  700. if (!topModel.isExclusive()) {
  701. offSetTop = -base;
  702. }
  703. if (!botModel.isExclusive()) {
  704. offSetBot = base;
  705. }
  706. }
  707. if (botText = getToolTipText(botValue, offSetBot, isConsecutive))
  708. arrConsecutive.push(botText);
  709. if (topText = getToolTipText(topValue, offSetTop, isConsecutive))
  710. // to avoid the duplicated value
  711. if (botText != topText)
  712. arrConsecutive.push(topText);
  713. tdRange.innerHTML = "= " + arrConsecutive.join(" - ");
  714. } else if (topModel) {
  715. tdRange.innerHTML = ">"
  716. + ((!topModel.isExclusive() && topModel.isUpperSide())
  717. || (topModel.isExclusive() && !topModel
  718. .isUpperSide()) ? "= " : " ")
  719. + getToolTipText(parseFloat(topModel.value));
  720. } else if (botModel) {
  721. tdRange.innerHTML = "<"
  722. + ((!botModel.isExclusive() && !botModel.isUpperSide())
  723. || (botModel.isExclusive() && botModel
  724. .isUpperSide()) ? "= " : " ")
  725. + getToolTipText(parseFloat(botModel.value));
  726. }
  727. tbody.appendChild(tr);
  728. }
  729. function getToolTipText(value, offSet, isConsecutive) {
  730. var isConsecutive = isConsecutive || false;
  731. var tOffSet = offSet ? offSet : 0;
  732. if (isConsecutive && offSet != 0)
  733. return "";
  734. if (inputModel.propertyType == "xs:duration") {
  735. var duration = new Duration(value + tOffSet);
  736. return duration.toString(inputModel);
  737. } else if (inputModel.propertyType == "cdm:percentage") {
  738. return (100 * floatMath(value, tOffSet)).toFixed(2) + "%";
  739. } else {
  740. return value + tOffSet;
  741. }
  742. }
  743. }
  744. /*******************************************************************************
  745. * End of Cognos Generic Threshold Manager Library
  746. ******************************************************************************/
  747. /*******************************************************************************
  748. * CogAdmin specific implementation of Cognos Threshold Manager
  749. ******************************************************************************/
  750. function CogAdminThresholdManager(inputModel, targetDiv, dialog) {
  751. var targetDiv = $(targetDiv);
  752. var initialType = inputModel.type;
  753. var manager = null;
  754. var self = this;
  755. this.thresholdContainer = document.getElementById('thresholdsContainer');
  756. this.dialog = dialog;
  757. /* for the change of nextGen *****************begin******************* */
  758. this.addPatternItem = function(type, lbl) {
  759. var patternItem = xCreateElement("div");
  760. var itemId = "pattern_" + type;
  761. var isChecked = false;
  762. if (inputModel.type == type)
  763. isChecked = true;
  764. if (document.all && !window.opera && document.createElement) {
  765. // MSIE 6 for browser does not support DOM-insertion of radio
  766. // buttons. The following code works around that lack of support.
  767. var patternInput = document
  768. .createElement("<input type='radio' name='pattern' id='"
  769. + itemId + "' value='" + type + "' "
  770. + (isChecked ? "checked" : "") + ">");
  771. } else if (document.createElement && document.createTextNode) {
  772. // other DOM compilable browsers
  773. var patternInput = xCreateElement("input");
  774. patternInput.id = itemId;
  775. patternInput.type = "radio";
  776. patternInput.name = "pattern"
  777. patternInput.value = type
  778. patternInput.checked = isChecked;
  779. } else {
  780. return;
  781. }
  782. var patternLabel = xCreateElement("label");
  783. patternLabel.htmlFor = itemId;
  784. patternLabel.appendChild(document.createTextNode(lbl));
  785. xAddEventListener(patternInput, "click", function(event) {
  786. self.update(type)
  787. }, false);
  788. patternItem.appendChild(patternInput);
  789. patternItem.appendChild(patternLabel);
  790. return patternItem;
  791. }
  792. if (targetDiv) {
  793. while (targetDiv.childNodes.length > 0) {
  794. targetDiv.removeChild(targetDiv.firstChild);
  795. }
  796. var Desc = xCreateElement("div");
  797. Desc.style.marginBottom = "5px";
  798. Desc.className = "dialogHeaderText";
  799. Desc.appendChild(document
  800. .createTextNode(ADM.THR.IDS_ADMNEW_THR_DIALOG_TIP));
  801. var fieldSet = xCreateElement("fieldset");
  802. fieldSet.style.border = "none";
  803. fieldSet.style.padding = "0";
  804. var legend = xCreateElement("legend");
  805. legend.className = "cogstyle-form-label";
  806. legend.appendChild(document
  807. .createTextNode(ADM.THR.IDS_ADMNEW_THR_PERF_PATTERN));
  808. var thresholdTitle = xCreateElement("div");
  809. thresholdTitle.style.marginTop = "5px";
  810. thresholdTitle.style.marginBottom = "5px";
  811. thresholdTitle.className = "cogstyle-form-label";
  812. thresholdTitle.appendChild(document
  813. .createTextNode(ADM.THR.IDS_ADMNEW_THR_SCORE_CALC));
  814. var patternDiv = xCreateElement("div");
  815. patternDiv.appendChild(Desc);
  816. patternDiv.appendChild(fieldSet);
  817. fieldSet.appendChild(legend);
  818. fieldSet.appendChild(this.addPatternItem("none",
  819. ADM.THR.IDS_ADMNEW_THR_NONE));
  820. fieldSet.appendChild(this.addPatternItem("high",
  821. ADM.THR.IDS_ADMNEW_THR_HIGH_VALUE));
  822. fieldSet.appendChild(this.addPatternItem("middle",
  823. ADM.THR.IDS_ADMNEW_THR_MIDDLE_VALUE));
  824. fieldSet.appendChild(this.addPatternItem("low",
  825. ADM.THR.IDS_ADMNEW_THR_LOW_VALUE));
  826. patternDiv.appendChild(thresholdTitle);
  827. targetDiv.appendChild(patternDiv);
  828. this.thresholdContainer = xCreateElement("div");
  829. this.thresholdContainer.id = "thresholdsContainer";
  830. this.thresholdContainer.style.cssText = "border:1px solid;overflow:auto;height:235px;width:400px;margin-bottom:10px;";
  831. targetDiv.appendChild(this.thresholdContainer);
  832. }
  833. /* for the change of nextGen *****************end******************* */
  834. this.update = function(type) {
  835. if (type) {
  836. inputModel.type = type;
  837. }
  838. manager = new ThresholdsManager(this.thresholdContainer, inputModel);
  839. var upperSidePoorModel = new ThresholdModel(
  840. inputModel.upperSidePoorValue, inputModel.upperSidePoorEx,
  841. "UpperSidePoor", "UpperPoorEx", false, inputModel.i18n);
  842. var upperSidePoorEditor = new EditorManager(
  843. inputModel.type != TYPE_NONE ? upperSidePoorModel : null,
  844. new inputModel.editorClass(upperSidePoorModel, inputModel),
  845. true, inputModel);
  846. var upperSideAvgModel = new ThresholdModel(
  847. inputModel.upperSideAvgValue, inputModel.upperSideAvgEx,
  848. "UpperSideAverage", "UpperAverageEx", false, inputModel.i18n);
  849. var upperSideAvgEditor = new EditorManager(
  850. inputModel.type != TYPE_NONE ? upperSideAvgModel : null,
  851. new inputModel.editorClass(upperSideAvgModel, inputModel), true, inputModel);
  852. var lowerSideAvgModel = new ThresholdModel(
  853. inputModel.lowerSideAvgValue, inputModel.lowerSideAvgEx,
  854. "LowerSideAverage", "LowerAverageEx",false, inputModel.i18n);
  855. var lowerSideAvgEditor = new EditorManager(lowerSideAvgModel,
  856. new inputModel.editorClass(lowerSideAvgModel, inputModel),
  857. false, inputModel);
  858. var lowerSidePoorModel = new ThresholdModel(
  859. inputModel.lowerSidePoorValue, inputModel.lowerSidePoorEx,
  860. "LowerSidePoor", "LowerPoorEx",false, inputModel.i18n);
  861. var lowerSidePoorEditor = new EditorManager(lowerSidePoorModel,
  862. new inputModel.editorClass(lowerSidePoorModel, inputModel),
  863. false, inputModel);
  864. var thresholds = new Array();
  865. if (inputModel.type != TYPE_HIGH_POSITIVE) {
  866. var upperSidePoorView = new ThresholdView(dialog, "poor",
  867. inputModel.i18n.poorLabel, null, upperSidePoorEditor,
  868. inputModel.imagesURL);
  869. manager.addView(upperSidePoorView, upperSidePoorModel);
  870. var upperSideAvgView = new ThresholdView(dialog, "average",
  871. inputModel.i18n.avgLabel, upperSidePoorEditor,
  872. upperSideAvgEditor, inputModel.imagesURL);
  873. manager.addView(upperSideAvgView, upperSideAvgModel);
  874. }
  875. var goodView = new ThresholdView(
  876. dialog,
  877. "good",
  878. inputModel.i18n.goodLabel,
  879. (inputModel.type == TYPE_LOW_POSITIVE || inputModel.type == TYPE_MIDDLE_POSITIVE) ? upperSideAvgEditor
  880. : null,
  881. (inputModel.type == TYPE_HIGH_POSITIVE || inputModel.type == TYPE_MIDDLE_POSITIVE) ? lowerSideAvgEditor
  882. : null, inputModel.imagesURL);
  883. manager.addView(goodView);
  884. if (inputModel.type == TYPE_HIGH_POSITIVE
  885. || inputModel.type == TYPE_MIDDLE_POSITIVE) {
  886. var lowerSideAvgView = new ThresholdView(dialog, "average",
  887. inputModel.i18n.avgLabel, lowerSideAvgEditor,
  888. lowerSidePoorEditor, inputModel.imagesURL);
  889. manager.addView(lowerSideAvgView, lowerSideAvgModel);
  890. var lowerSidePoorView = new ThresholdView(dialog, "poor",
  891. inputModel.i18n.poorLabel, lowerSidePoorEditor, null,
  892. inputModel.imagesURL);
  893. manager.addView(lowerSidePoorView, lowerSidePoorModel);
  894. }
  895. initTabStops(dialog,true);
  896. }
  897. this.hasChanged = function() {
  898. var thresholds = manager.getModels();
  899. for ( var i = 0; i < thresholds.length; i++) {
  900. if (thresholds[i].hasChanged()) {
  901. return true;
  902. }
  903. }
  904. return initialType != inputModel.type;
  905. }
  906. this.getSubmitString = function() {
  907. var queryString = "processRequest=true&thresholdPropertyName="
  908. + inputModel.thresholdPropertyName + "&thresholdResourceID="
  909. + inputModel.thresholdResourceID;
  910. if (inputModel.type != TYPE_NONE) {
  911. var thresholds = manager.getModels();
  912. for ( var i = 0; i < thresholds.length; i++) {
  913. queryString += "&"
  914. + (thresholds[i].attrName + "="
  915. + thresholds[i].getValue() + "&"
  916. + thresholds[i].exAttrName + "=" + thresholds[i]
  917. .isExclusive());
  918. }
  919. }
  920. queryString += "&deleteThreshold=" + (inputModel.type == TYPE_NONE);
  921. return queryString;
  922. }
  923. this.validate = function(maxValue) {
  924. if (!maxValue)
  925. maxValue = inputModel.maxValue;
  926. if (inputModel.type != TYPE_NONE) {
  927. var models = manager.getModels();
  928. for ( var i = 0; i < models.length; i++) {
  929. // if have a error code, validate it first, since the value
  930. // might be empty.
  931. switch (models[i].getErrorCode()) {
  932. case THRESHOLD_EXCEED_MAX:
  933. alert(inputModel.i18n.validateMsgExceedMax);
  934. return false;
  935. break;
  936. case THRESHOLD_NO_MATCH:
  937. alert(inputModel.i18n.validateMsgBadFormat);
  938. return false;
  939. break;
  940. case THRESHOLD_NOT_A_NUMBER:
  941. alert(inputModel.i18n.validateMsgNotNumeric);
  942. return false;
  943. break;
  944. default:
  945. }
  946. // editor's default value is "", in case of clicking "ok" button
  947. // without touching the input.
  948. if (models[i].value == 0 || models[i].value == ""
  949. || isNaN(models[i].value)) {
  950. alert(inputModel.i18n.validateMsgNotNumeric);
  951. return false;
  952. }
  953. // range logic
  954. if ((i > 0)
  955. && (parseFloat(models[i].value) >= parseFloat(models[i - 1].value))) {
  956. alert(inputModel.i18n.validateMsgInvalidRange);
  957. return false;
  958. }
  959. models[i].value = Math.abs(models[i].value);
  960. }
  961. }
  962. return true;
  963. }
  964. this.update();
  965. }
  966. editThreshold = function(thresholdFragId, grpCaption, objCaption, name, type, resourceID) {
  967. var thresholdFrag = createFragment(thresholdFragId, null,
  968. '/cogadmin/controls/threshold.xts');
  969. var params = 'thresholdGroupName=' + grpCaption
  970. + '&thresholdPropertyCaption=' + objCaption
  971. + '&thresholdPropertyName=' + name + '&thresholdResourceID='
  972. + resourceID + '&propertyType=' + type + '&style=dialog';
  973. thresholdFrag.retrieve(params);
  974. }
  975. initTabStops = function(dialog, skipFocus) {
  976. var dialogEle = document.getElementById(dialog.id);
  977. var inputs = dialogEle.getElementsByTagName('input');
  978. for (var i=0; i < inputs.length; i++) {
  979. inputs[i].tabIndex = "1";
  980. }
  981. dialog.initTabStops(skipFocus);
  982. }