util.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. /********************************************************************************************************************************
  2. * Licensed Materials - Property of IBM *
  3. * *
  4. * IBM Cognos Products: AGS *
  5. * *
  6. * (C) Copyright IBM Corp. 2005, 2010 *
  7. * *
  8. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *
  9. *********************************************************************************************************************************/
  10. //grab all tags from this or subordinate frames
  11. FormUtils.prototype.getElementsFromFrameByTagName = function(aFrame, tag){
  12. if(!aFrame.document){
  13. return new Array();
  14. }
  15. // find the elements
  16. var theTags = getArray(aFrame.document.getElementsByTagName(tag));
  17. // check all the subframes
  18. for (var i = 0; i < aFrame.frames.length; ++i) {
  19. theTags = theTags.concat(getArray(this.getElementsFromFrameByTagName(aFrame.frames[i], tag)));
  20. }
  21. return theTags;
  22. }
  23. //domII implementation returns non Array collections
  24. function getArray(aCollection){
  25. var anArray = new Array();
  26. for(var i = 0; i < aCollection.length; i++){
  27. anArray.push(aCollection[i]);
  28. }
  29. return anArray;
  30. }
  31. FormUtils.prototype.setVisibilityOnElementsFromFrameByTagName = function(aFrame, tag, bVis){
  32. var selects = agsFormUtils.getElementsFromFrameByTagName(aFrame, tag);
  33. for(var i = 0; i < selects.length; i++){
  34. if(!selects[i] || !selects[i].offsetParent){
  35. continue;
  36. }
  37. selects[i].style.visibility=bVis ? "visible" : "hidden";
  38. }
  39. }
  40. // handy form manipulation util
  41. //usefull function i nicked from ddh... and enhanced?
  42. FormUtils.prototype.getElementByIdOrName = function(id){
  43. return this.getElementFromFrame(window, id);
  44. }
  45. //usefull function i nicked and made recursive
  46. FormUtils.prototype.getElementFromFrame = function(aFrame, id){
  47. // find the element ang register all the handlers that we need
  48. var srcElem = aFrame.document.getElementById(id);
  49. if (srcElem == null) {
  50. // try finding it by name
  51. var elementNames = aFrame.document.getElementsByName(id);
  52. if (elementNames != null && elementNames.length == 1) {
  53. srcElem = elementNames[0];
  54. }
  55. }
  56. if (srcElem == null) {
  57. // check all the subframes
  58. for (var i = 0; i < aFrame.frames.length && srcElem == null; ++i) {
  59. srcElem = this.getElementFromFrame(aFrame.frames[i], id);
  60. }
  61. }
  62. return srcElem;
  63. }
  64. //retrieve a single frame
  65. FormUtils.prototype.getFrame = function(startFrame, targetFrameId){
  66. if(startFrame.name = targetFrameId){
  67. return startFrame;
  68. }
  69. var foundFrame;
  70. // check all the subframes
  71. for (var i = 0; i < startFrame.frames.length && !foundFrame; ++i) {
  72. foundFrame = this.getFrame(startFrame.frames[i], targetFrameId);
  73. }
  74. return foundFrame;
  75. }
  76. /*
  77. * Get the event source in a browser agnostic way
  78. */
  79. FormUtils.prototype.getEventId = function(event) {
  80. var id = null;
  81. var srcElem = (cf.browserCheck.isIE5Up() ? event.srcElement : event.currentTarget);
  82. while (id == null) {
  83. id = srcElem.id;
  84. if (id == null || id.length == 0) {
  85. id = srcElem.name;
  86. }
  87. if (id != null && id.length == 0) {
  88. id = null;
  89. }
  90. if (id == null) {
  91. srcElem = srcElem.parentNode;
  92. }
  93. }
  94. return id;
  95. }
  96. function FormUtils(){
  97. }
  98. var agsFormUtils = new FormUtils();
  99. // -----------------------------------------------------------------------------
  100. //
  101. // --- Data utilities functions ---
  102. //
  103. // -----------------------------------------------------------------------------
  104. function isNumeric(idx) {
  105. return (getDataType(idx) == 0);
  106. }
  107. function isOldTypeNumeric(idx) {
  108. if (!cfgGetAt("IsFakeMeasure", idx))
  109. return false;
  110. return (getDataTypeFromArray(idx, "ColOldType") == 0);
  111. }
  112. function isString(idx) {
  113. return (getDataType(idx) == 5);
  114. }
  115. //returns true for date, time, datetime and timeInterval
  116. function isDateTime(idx) {
  117. var type = getDataType(idx);
  118. return (type > 0 && type < 5);
  119. }
  120. function isOldTypeDateTime(idx) {
  121. if (!cfgGetAt("IsFakeMeasure", idx))
  122. return false;
  123. var type = getDataTypeFromArray(idx, "ColOldType");
  124. return (type > 0 && type < 5);
  125. }
  126. function isDate(idx) {
  127. var type = getDataType(idx);
  128. return (type == 1);
  129. }
  130. function isTime(idx) {
  131. var type = getDataType(idx);
  132. return (type == 2);
  133. }
  134. function isInterval(idx) {
  135. var type = getDataType(idx);
  136. return (type == 4);
  137. }
  138. function isBlob(idx) {
  139. return (getDataType(idx) == 6);
  140. }
  141. function isCalc(idx) {
  142. if (cfgGetAt("calcOp", idx) != "")
  143. return true;
  144. return false;
  145. }
  146. function getCalcType(idx) {
  147. var calcOp = cfgGetAt("calcOp", idx);
  148. if (calcOp != "")
  149. {
  150. switch (calcOp)
  151. {
  152. //numerical calcs
  153. case "sum":
  154. case "difference":
  155. case "division":
  156. case "product":
  157. case "average":
  158. case "maximum":
  159. case "minimum":
  160. case "percent":
  161. case "percentDifference":
  162. case "percentTotal":
  163. case "percentile":
  164. case "rank":
  165. case "quartile":
  166. case "quantile":
  167. case "number":
  168. case "round":
  169. case "round down":
  170. case "absolute":
  171. case "sqrt":
  172. case "power":
  173. //datetime calcs
  174. case "yearDateTime":
  175. case "monthYearDateTime":
  176. case "hourDateTime":
  177. case "minuteDateTime":
  178. case "secondDateTime":
  179. case "dayWeekDateTime":
  180. case "dayMonthDateTime":
  181. case "dayYearDateTime":
  182. /* case "weekDateTime": not used */
  183. //time calcs
  184. case "hourTime":
  185. case "minuteTime":
  186. case "secondTime":
  187. case "yearDate":
  188. //date calcs
  189. case "monthYearDate":
  190. case "dayWeekDate":
  191. case "dayMonthDate":
  192. case "dayYearDate":
  193. //interval calcs
  194. case "rankInterval": //currently represented as "rank" since rankInterval cannot be used on the cpp side
  195. case "daysInterval":
  196. case "daysBetweenDate":
  197. case "monthsBetweenDate":
  198. case "yearsBetweenDate":
  199. case "daysBetweenDateTime":
  200. case "monthsBetweenDateTime":
  201. case "yearsBetweenDateTime":
  202. /* case "weekDate": not used */
  203. return "number";
  204. //custom range calcs
  205. case "rangeString":
  206. case "rangeNumber":
  207. case "rangeDate":
  208. case "rangeTime":
  209. case "rangeInterval":
  210. case "rangeDateTime":
  211. return "range";
  212. //custom group calcs
  213. case "groupString":
  214. case "groupNumber":
  215. return "group";
  216. //string calcs
  217. case "left":
  218. case "right":
  219. case "trim":
  220. //date calcs
  221. case "monthNameDate":
  222. case "dayFirstDate":
  223. case "dayLastDate":
  224. case "dayNameDate":
  225. //datetime calcs
  226. case "monthNameDateTime":
  227. case "dayNameDateTime":
  228. case "dayFirstDateTime":
  229. case "dayLastDateTime":
  230. //concatenation calcs
  231. case "concatString":
  232. case "concatNumber":
  233. case "concatInterval":
  234. case "concatDatetime":
  235. case "concatDefault":
  236. return "string";
  237. //date calcs
  238. case "maxDate":
  239. case "minDate":
  240. return "date";
  241. //time calcs
  242. case "maxTime":
  243. case "minTime":
  244. return "time";
  245. //datetime calcs
  246. case "maxDateTime":
  247. case "minDateTime":
  248. return "datetime";
  249. //interval calcs
  250. case "sumInterval":
  251. case "differenceDateTime":
  252. case "differenceInterval":
  253. case "minInterval":
  254. case "maxInterval":
  255. return "interval";
  256. //model calcs
  257. case "model":
  258. return "model";
  259. }
  260. }
  261. return "unknown";
  262. }
  263. function getDataType(idx) {
  264. return getDataTypeFromArray(idx, "ColType");
  265. }
  266. function getDataTypeFromArray(idx, arrayName)
  267. {
  268. var nDatatype = cfgGetAt(arrayName, idx);
  269. if (nDatatype == "reportExpression")
  270. return 7;
  271. else
  272. {
  273. switch (parseInt(nDatatype))
  274. {
  275. case 2: // dtInt
  276. case 3: // dtDouble
  277. case 10: // kDataTypeInt16
  278. case 11: // kDataTypeInt32
  279. case 12: // kDataTypeInt64
  280. case 20: // kDataTypeDecimal
  281. case 21: // kDataTypeNumeric
  282. case 30: // kDataTypeFloat
  283. case 31: // kDataTypeFloat32
  284. case 32: // kDataTypeFloat64
  285. case 40: // kDataTypeBinary
  286. case 41: // kDataTypeBinaryLength16
  287. return 0; //number
  288. case 50: // "kDataTypeDate"
  289. return 1; //date
  290. case 51: // "kDataTypeTime"
  291. return 2; //time
  292. case 52: // "kDataTypeDateTime"
  293. return 3; //datetime
  294. case 53: // "kDataTypeTimeInterval"
  295. return 4; //timeinterval
  296. case 60: // kDataTypeCharacter
  297. case 61: // kDataTypeCharacterLength16
  298. case 62: // kDataTypeCharacterLength32
  299. case 80: // kDataTypeDatabaseKey
  300. return 5; //string
  301. case 70: // "kDataTypeBlob"
  302. case 71: // "kDataTypeTextBlob"
  303. case 72: // "kDataTypeBlobArray"
  304. case 40: // "kDataTypeBinary"
  305. case 41: // "kDataTypeBinaryLength16"
  306. return 6; //blob
  307. default:
  308. break;
  309. }
  310. }
  311. return -1;
  312. }
  313. function getSelectionsDataType()
  314. {
  315. var numSel = cfgSize("SelColumns");
  316. if (numSel < 1)
  317. return -1;
  318. var dataType = getDataType(cfgGetAt("SelColumns", 0));
  319. for (var i = 1; i < numSel; i++)
  320. {
  321. if (dataType != getDataType(cfgGetAt("SelColumns", i)))
  322. return -1;
  323. }
  324. return dataType;
  325. }
  326. /*
  327. * General DOM utils
  328. */
  329. function DOMUtils(){
  330. }
  331. var agsDomUtils = new DOMUtils();
  332. /*
  333. * cross browser toggle function, to show/hide an element such as a DIV
  334. */
  335. DOMUtils.prototype.toggle = function(name){
  336. if(document.getElementById(name).style.display == 'none')
  337. {
  338. this.show(name);
  339. }
  340. else
  341. {
  342. this.hide(name);
  343. }
  344. }
  345. /*
  346. * cross browser function to show an element such as a DIV
  347. */
  348. DOMUtils.prototype.show = function(name){
  349. document.getElementById(name).style.display='';
  350. }
  351. /*
  352. * cross browser function to hide an element such as a DIV
  353. */
  354. DOMUtils.prototype.hide = function(name){
  355. document.getElementById(name).style.display='none';
  356. }
  357. function AgsConditionParameterValue(name, parameterValue){
  358. this.parameterValue = parameterValue;
  359. this.name = name;
  360. }
  361. AgsConditionParameterValue.prototype.getValue = function(){
  362. return this.parameterValue;
  363. }
  364. AgsConditionParameterValue.prototype.getName = function(){
  365. return this.name;
  366. }
  367. AgsConditionParameterValue.prototype.getValue = function(){
  368. return this.parameterValue;
  369. }
  370. AgsConditionParameterValue.prototype.getName = function(){
  371. return this.name;
  372. }
  373. ////////////////////////////////
  374. //read and write px or % numbers
  375. ////////////////////////////////
  376. function SizeParser(sizeString){
  377. this.isPercent = isPercent;
  378. this.leq = leq;
  379. this.toString = toString;
  380. sizeString = new String(sizeString);
  381. var numberMatch = /^([0-9]+)$/
  382. var percentMatch = /^([0-9]+)%$/;
  383. var pixelMatch = /^([0-9]+)px$/;
  384. //default to px
  385. this.unit = "px";
  386. this.number = 0;
  387. var aMatch;
  388. if(!sizeString){
  389. return;
  390. }else if(aMatch = sizeString.match(numberMatch)){
  391. }else if(aMatch = sizeString.match(pixelMatch)){
  392. }else if(aMatch = sizeString.match(percentMatch)){
  393. this.unit = "%"
  394. }else{
  395. return;
  396. }
  397. this.number = aMatch[1] ? aMatch[1] : 0;
  398. //does the parsed number represent a percentage or a unit?
  399. function isPercent(){
  400. return this.unit == "%";
  401. }
  402. //determine if the parsed number is less than or equal to 'num'
  403. function leq(num){
  404. return this.number <= num;
  405. }
  406. function toString(){
  407. return "" + this.number + this.unit;
  408. }
  409. function equals(anObject){
  410. var isEqual = anObject instanceof SizeParser;
  411. return isEqual && (this.unit ==anObject.unit && this.number == anObject.number);
  412. }
  413. }
  414. /*
  415. this takes an input object and checks the maxLength attribute and trucs the
  416. value of the input if it goes over
  417. */
  418. function checkMaxLength(anInput){
  419. var mlength=anInput.getAttribute ? parseInt(anInput.getAttribute("maxlength")) : ""
  420. if (anInput.getAttribute && anInput.value.length > mlength){
  421. anInput.value=anInput.value.substring(0, mlength)
  422. }
  423. }
  424. // this is an XML decode function
  425. function decode(text)
  426. {
  427. // seeing as this is come from XML - and it could hold anything - unescape
  428. // any dodgy characters
  429. var amp_re = /&amp;/g;
  430. var lt_re = /&lt;/g;
  431. var gt_re = /&gt;/g;
  432. var apos_re = /&apos;/g;
  433. var quot_re = /&quot;/g;
  434. // Decode stuff which has been encoded/escaped out.
  435. text = text.replace(lt_re, "<");
  436. text = text.replace(gt_re, ">");
  437. text = text.replace(apos_re, "'");
  438. text = text.replace(quot_re, "\"");
  439. // IMPORTANT - the amp_re has to come last otherwise double encoded values are decoded
  440. // as well. If this is at the beginning &amp;lt; -> < in one go which is not good
  441. text = text.replace(amp_re, "&");
  442. return text;
  443. }
  444. /******************************************************************************
  445. * MISC FUNCTIONS
  446. ******************************************************************************/
  447. /*
  448. * Get the expression locale, if not available then assign the content locale
  449. * this function will update the config variable 'expressionLocale'
  450. */
  451. function getExpressionLocale() {
  452. var el=getConfigFrame().cfgGet("expressionLocale");
  453. var cl = getConfigFrame().cfgGet("contentLocale");
  454. //if we have an expression locale then assign it
  455. if (!el || el == '') {
  456. el = cl;
  457. //update the expression locale
  458. getConfigFrame().cfgSet("expressionLocale",el);
  459. }
  460. return el;
  461. }
  462. function resetExpressionLocale() {
  463. var cl = getConfigFrame().cfgGet("contentLocale");
  464. getConfigFrame().cfgSet("expressionLocale",cl);
  465. }
  466. function getLocales(contentLocaleKey, productLocaleKey){
  467. var locales = new Object();
  468. // extract contentLocale from the cookie
  469. var cookieValues = document.cookie.split(";");
  470. for (var i = 0; i < cookieValues.length; i++)
  471. {
  472. if (cookieValues[i].match(/^\s*CRN=/i))
  473. {
  474. var aLocales = decodeURIComponent(decodeURIComponent(cookieValues[i].split("=")[1])).split("&");
  475. for (var j = 0; j < aLocales.length; j++)
  476. {
  477. if (aLocales[j].match(/^contentLocale=/i))
  478. locales[contentLocaleKey] = aLocales[j].split("=")[1];
  479. if (aLocales[j].match(/^productLocale=/i))
  480. locales[productLocaleKey] = aLocales[j].split("=")[1];
  481. }
  482. }
  483. if (locales[contentLocaleKey] && locales[productLocaleKey])
  484. break;
  485. }
  486. if (locales[contentLocaleKey] == "")
  487. locales[contentLocaleKey] = cfgGet("contentLocale");
  488. if (locales[productLocaleKey] == "")
  489. locales[productLocaleKey] = cfgGet("productLocale");
  490. return locales;
  491. }
  492. function DefectMessage(message, severity, location){
  493. this.location = location;
  494. this.severity = new Severity(severity);
  495. this.message = htmlEncode(message);
  496. }
  497. DefectMessage.prototype.toString = function(){
  498. return this.message;
  499. }
  500. function SeverityEnum(){
  501. this.WARN = 3;
  502. this.FATAL = 1;
  503. this.ERROR = 2;
  504. this.INFO = 4;
  505. this.severity = new Object();
  506. this.severity["fatal"] = new Array(1, "../ps/portal/images/msg_fatal_16.gif");
  507. this.severity["warn"] = new Array(3, "../ps/portal/images/msg_warning_16.gif");
  508. this.severity["error"] = new Array(2, "../ps/portal/images/msg_error_16.gif");
  509. this.severity["info"] = new Array(4, "../ps/portal/images/msg_information_16.gif");
  510. }
  511. var ags_severity_enum = new SeverityEnum();
  512. function Severity(severityText){
  513. var si = ags_severity_enum.severity[severityText];
  514. if(si){
  515. this.level = si[0];
  516. this.img_src = si[1];
  517. }else{
  518. this.level = 5;
  519. this.img_src = "../ps/images/space.gif";
  520. }
  521. this.text = severityText;
  522. }
  523. function DefectMessages(messages){
  524. this.messages = new Array();
  525. this.allMessages = new Array();
  526. for(var i = 0; messages && i < messages.length; i++){
  527. this.addMessage(messages[i]);
  528. }
  529. this.maxSeverity;
  530. this.process();
  531. }
  532. DefectMessages.prototype.addMessage = function(defectMessage){
  533. if(defectMessage instanceof DefectMessage && defectMessage.message){
  534. this.allMessages.push(defectMessage);
  535. }
  536. this.process();
  537. }
  538. DefectMessages.prototype.addMessages = function(defectMessageArray){
  539. this.allMessages = this.allMessages.concat(defectMessageArray);
  540. this.process();
  541. }
  542. DefectMessages.prototype.process = function(){
  543. this.messagesBySeverity = new Object();
  544. for(var i = 0; i < this.allMessages.length; i++){
  545. var levelMessages = this.messagesBySeverity[this.allMessages[i].severity.text];
  546. if(!levelMessages){
  547. levelMessages = this.messagesBySeverity[this.allMessages[i].severity.text] = new Array();
  548. }
  549. levelMessages.push(this.allMessages[i]);
  550. if(this.allMessages[i].severity.level && this.maxSeverity < this.allMessages[i].severity.level){
  551. this.maxSeverity = this.allMessages[i].severity.level;
  552. }
  553. }
  554. }
  555. DefectMessages.prototype.isEmpty = function(){
  556. return !this.allMessages || this.allMessages.length == 0;
  557. }
  558. /*
  559. this looks for the validate header messages and emboldens, and removes icons from all the rest
  560. CNC-SDS-0400 - <b style="color:red">
  561. CNC-SDS-0401 - <b style="color:blue">
  562. CNC-SDS-0403 - <b style="color:green">
  563. */
  564. DefectMessages.prototype.sortMessagesForValidate = function(){
  565. var warnings = this.messagesBySeverity['warn'];
  566. for(var i = 0; warnings && i < warnings.length; i++){
  567. if(warnings[i].message.match("CNC-SDS-0401")){
  568. warnings[i].message = "<b style='color:blue'>" + warnings[i].message + "</b>";
  569. }else if(i != 0){
  570. //this prevents the icon displaying
  571. warnings[i].severity = new Severity("none");
  572. }
  573. }
  574. var errors = this.messagesBySeverity['error'];
  575. for(var i = 0; errors && i < errors.length; i++){
  576. if(errors[i].message.match("CNC-SDS-0400")){
  577. errors[i].message = "<b style='color:red'>" + errors[i].message + "</b>";
  578. }else if(i != 0){
  579. //this prevents the icon displaying
  580. errors[i].severity = new Severity("none");
  581. }
  582. }
  583. var infos = this.messagesBySeverity['info'];
  584. for(var i = 0; infos && i < infos.length; i++){
  585. if(infos[i].message.match("CNC-SDS-0403")){
  586. infos[i].message = "<b style='color:green'>" + infos[i].message + "</b>";
  587. }else if(i != 0){
  588. //this prevents the icon displaying
  589. infos[i].severity = new Severity("none");
  590. }
  591. }
  592. }
  593. DefectMessages.prototype.getMessagesForSeverity = function(severity){
  594. var messages;
  595. if(severity instanceof Severity){
  596. messages = this.messagesBySeverity[severity.text];
  597. }else{
  598. messages = this.messagesBySeverity[severity];
  599. }
  600. return messages;
  601. }
  602. DefectMessages.prototype.getMaximumSeverity = function(){
  603. return this.maxSeverity;
  604. }
  605. function BrowserCheck() {
  606. this.config = new BrowserConfig();
  607. }
  608. BrowserCheck.prototype = {
  609. isFirefox: function () {
  610. return this.config.browser=='firefox';
  611. },
  612. isFF3Up: function () {
  613. return this.config.browser=='firefox' && this.config.browserVersion >= 3;
  614. }
  615. ,
  616. isIE: function() {
  617. return this.config.browser=='explorer' && !this.config.browser!='opera';
  618. },
  619. isIE5Up: function() {
  620. return this.config.browser=='explorer' && this.config.browserVersion >= 5;
  621. },
  622. isIE5dot5Up: function() {
  623. return this.config.browser=='explorer' && this.config.browserVersion >= 5.5;
  624. },
  625. isIE5dot5: function() {
  626. return this.config.browser=='explorer' && this.config.browserVersion == 5.5;
  627. },
  628. /*
  629. * This will return non IE browsers. Typically the following:
  630. * Firefox, Netscape, Safari, Mozilla, AOL, Konqueror, Chrome
  631. */
  632. isNav6Up : function() {
  633. return navigator.userAgent.indexOf('Mozilla/5.0') != -1;
  634. },
  635. getBrowser: function() {
  636. return this.config.browser;
  637. },
  638. getBrowserVersion: function() {
  639. this.config.browserVersion;
  640. }
  641. }
  642. /**
  643. * Browser config
  644. */
  645. function BrowserConfig() {
  646. this.initialize();
  647. }
  648. BrowserConfig.prototype =
  649. {
  650. browser: "unknown",
  651. browserVersion: "unknown",
  652. initialize: function()
  653. {
  654. this.browser = this.lookup(this.browsers).toLowerCase() || "unknown";
  655. this.browserVersion = this.parseVersion(navigator.userAgent) || this.parseVersion(navigator.appVersion) || "unknown";
  656. },
  657. lookup: function(data)
  658. {
  659. var i, l = data.length;
  660. for (i = 0; i < l; i++)
  661. {
  662. this.versionKey = data[i].partialKey || data[i].identity;
  663. var agent = data[i].agent;
  664. if (agent)
  665. {
  666. if (agent.indexOf(data[i].key) != -1)
  667. return data[i].identity;
  668. }
  669. else if (data[i].prop)
  670. return data[i].identity;
  671. }
  672. },
  673. parseVersion: function(s)
  674. {
  675. var index = s.indexOf(this.versionKey);
  676. if (index == -1)
  677. return;
  678. return parseFloat(s.substring(index + this.versionKey.length + 1));
  679. },
  680. browsers: [
  681. { agent: navigator.userAgent, key: "MSIE", identity: "Explorer", partialKey: "MSIE" },
  682. { agent: navigator.userAgent, key: "Firefox", identity: "Firefox" },
  683. { agent: navigator.userAgent, key: "Chrome", identity: "Chrome" },
  684. { agent: navigator.vendor, key: "Apple", identity: "Safari" },
  685. { agent: navigator.userAgent, key: "Gecko", identity: "Mozilla", partialKey: "rv" },
  686. { agent: navigator.userAgent, key: "Mozilla", identity: "Netscape", partialKey: "Mozilla" },
  687. { agent: navigator.userAgent, key: "Netscape", identity: "Netscape" },
  688. { prop: window.opera, identity: "Opera" }
  689. ]
  690. }