extensions/net.sf.basedb.meludi/trunk/resources/meludi-2.js

Code
Comments
Other
Rev Date Author Line
2933 14 Nov 14 olle 1
2933 14 Nov 14 olle 2 var Meludi = function()
2933 14 Nov 14 olle 3 {
2933 14 Nov 14 olle 4   var meludi = {};
2933 14 Nov 14 olle 5   var internal = {};
2933 14 Nov 14 olle 6
3210 26 Mar 15 olle 7   meludi.TITLE = 'MeLuDI';
6805 24 Aug 22 olle 8   meludi.VERSION = '1.6.0';
2933 14 Nov 14 olle 9
2933 14 Nov 14 olle 10   var WELL_ALPHA = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
2933 14 Nov 14 olle 11
2933 14 Nov 14 olle 12   var GENERIC_STRATAGENE_NAME = 'Stratagene.r';
2933 14 Nov 14 olle 13   var EXTERNAL_RNA_NAME = 'External.r';
2933 14 Nov 14 olle 14   
2933 14 Nov 14 olle 15   var CASENAME_WITH_SUFFIX = /^\d{7}(C|D)?$/;
2933 14 Nov 14 olle 16   var CASENAME = /^\d{7}$/;
2933 14 Nov 14 olle 17   
2933 14 Nov 14 olle 18   var RCCID_WITH_SUFFIX = /^\d{10}(B|C|D){1}$/;
2933 14 Nov 14 olle 19   
2933 14 Nov 14 olle 20   var currentDirectory;
2933 14 Nov 14 olle 21   
2933 14 Nov 14 olle 22   /*
4215 08 Nov 16 olle 23     Verify that the 'case' name equals itemNamePrefix + itemNumDigits digits
4215 08 Nov 16 olle 24   */
4215 08 Nov 16 olle 25   meludi.isValidCaseName2 = function isValidCaseName(caseName, itemNamePrefix, itemNumDigits)
4215 08 Nov 16 olle 26   {
4215 08 Nov 16 olle 27 /*
4215 08 Nov 16 olle 28     var regex = /^ML\d{5}$/;
4215 08 Nov 16 olle 29 */
4215 08 Nov 16 olle 30     var regex = new RegExp('^' + itemNamePrefix + '\\d{' + itemNumDigits + '}$', '');
4215 08 Nov 16 olle 31     return caseName.match(regex);
4215 08 Nov 16 olle 32   }
4215 08 Nov 16 olle 33
4215 08 Nov 16 olle 34   /*
4142 30 Sep 16 olle 35     Verify that the 'case' name equals itemNamePrefix + 5 digits
2933 14 Nov 14 olle 36   */
4142 30 Sep 16 olle 37   meludi.isValidCaseName = function isValidCaseName(caseName, itemNamePrefix)
2933 14 Nov 14 olle 38   {
4142 30 Sep 16 olle 39 /*
2933 14 Nov 14 olle 40     var regex = /^ML\d{5}$/;
4142 30 Sep 16 olle 41 */
4142 30 Sep 16 olle 42     var regex = new RegExp('^' + itemNamePrefix + '\\d{5}$', '');
2933 14 Nov 14 olle 43     return caseName.match(regex);
2933 14 Nov 14 olle 44   }
2933 14 Nov 14 olle 45
2933 14 Nov 14 olle 46   /*
2933 14 Nov 14 olle 47     Verify that the 'case' name is a 7-digit value + optional C/D suffix
2933 14 Nov 14 olle 48   */
2933 14 Nov 14 olle 49 /*
2933 14 Nov 14 olle 50   meludi.isValidCaseName = function isValidCaseName(caseName, allowSuffix)
2933 14 Nov 14 olle 51   {
2933 14 Nov 14 olle 52     return caseName.match(allowSuffix ? CASENAME_WITH_SUFFIX : CASENAME);
2933 14 Nov 14 olle 53   }
2933 14 Nov 14 olle 54 */
2933 14 Nov 14 olle 55   
2933 14 Nov 14 olle 56   /*
2933 14 Nov 14 olle 57     Verify that the RCCID number is a 10-digit value + 'B', 'C', or 'D' suffix
2933 14 Nov 14 olle 58    */
2933 14 Nov 14 olle 59   meludi.isValidRccidNumber = function(rccidNumber)
2933 14 Nov 14 olle 60   {
2933 14 Nov 14 olle 61     return rccidNumber.match(RCCID_WITH_SUFFIX);
2933 14 Nov 14 olle 62   }
2933 14 Nov 14 olle 63
2933 14 Nov 14 olle 64   /**
2933 14 Nov 14 olle 65     Check the control digit of the given personal number.
2933 14 Nov 14 olle 66     @pnr The 10-digit personal number in the form YYMMDDXXXX
2933 14 Nov 14 olle 67   */
2933 14 Nov 14 olle 68   meludi.personalNumberControlDigitCheck = function(pnr)
2933 14 Nov 14 olle 69   {
2933 14 Nov 14 olle 70     var sum = 0;
2933 14 Nov 14 olle 71     var factor = 2;
2933 14 Nov 14 olle 72     for (var i = 0; i < 9; i++)
2933 14 Nov 14 olle 73     {
2933 14 Nov 14 olle 74       var digit = parseInt(pnr.substr(i, 1), 10);
2933 14 Nov 14 olle 75       var tmp = factor * digit;
2933 14 Nov 14 olle 76       sum += tmp >= 10 ? tmp - 9: tmp;
2933 14 Nov 14 olle 77       factor = factor == 2 ? 1 : 2;
2933 14 Nov 14 olle 78     }
2933 14 Nov 14 olle 79     
2933 14 Nov 14 olle 80     var control = 10 - (sum % 10);
2933 14 Nov 14 olle 81     if (control == 10) control = 0;
2933 14 Nov 14 olle 82     return (control == parseInt(pnr.substr(9, 1), 10))
2933 14 Nov 14 olle 83   }
2933 14 Nov 14 olle 84   
2933 14 Nov 14 olle 85   /**
2933 14 Nov 14 olle 86     Autofill a date-string.
2933 14 Nov 14 olle 87     The supplemented date-string will have the format yyyyMMdd when it's returned.
2933 14 Nov 14 olle 88     If the short-date in format MMdd is larger the current date, the year before will be used.
2933 14 Nov 14 olle 89     
2933 14 Nov 14 olle 90     @param shortDate Date in format 'MMdd' or in 'yyMMdd'
2933 14 Nov 14 olle 91     @param allowSixDigitDates Boolean Flag indicating if 6-digit dates should be auto-filled (default = false).
2933 14 Nov 14 olle 92   */
2933 14 Nov 14 olle 93   meludi.autoFillDate = function(shortDate, allowSixDigitDates)
2933 14 Nov 14 olle 94   {
2933 14 Nov 14 olle 95     shortDate = shortDate.replace("-","");
2933 14 Nov 14 olle 96     var fullDate = shortDate;
2933 14 Nov 14 olle 97   
2933 14 Nov 14 olle 98     var currentDate = new Date();
2933 14 Nov 14 olle 99     var currentYear = currentDate.getFullYear();
2933 14 Nov 14 olle 100     var currentMonth = currentDate.getMonth()+1;
2933 14 Nov 14 olle 101     
2933 14 Nov 14 olle 102     if (shortDate.length == 4 && Dates.isDate(shortDate, 'MMdd'))
2933 14 Nov 14 olle 103     {
2933 14 Nov 14 olle 104       var month = parseInt(shortDate.substring(0, 2), 10);
2933 14 Nov 14 olle 105       var day = parseInt(shortDate.substring(2), 10);
2933 14 Nov 14 olle 106       if ((month > currentMonth) || (month == currentMonth && day > currentDate.getDate())) 
2933 14 Nov 14 olle 107       {
2933 14 Nov 14 olle 108         currentYear--;
2933 14 Nov 14 olle 109       }
2933 14 Nov 14 olle 110       fullDate = currentYear+shortDate;
2933 14 Nov 14 olle 111     }
2933 14 Nov 14 olle 112     else if (allowSixDigitDates && shortDate.length == 6 && Dates.isDate(shortDate, 'yyMMdd'))
2933 14 Nov 14 olle 113     {
2933 14 Nov 14 olle 114       var year = parseInt(shortDate.substring(0,2), 10);    
2933 14 Nov 14 olle 115       fullDate = ((2000+year) > currentYear ? "19" : "20") + fullDate;
2933 14 Nov 14 olle 116     }  
2933 14 Nov 14 olle 117     return fullDate;  
2933 14 Nov 14 olle 118   }
2933 14 Nov 14 olle 119   
2933 14 Nov 14 olle 120   meludi.autoFillTime = function(shortTime)
2933 14 Nov 14 olle 121   {
2933 14 Nov 14 olle 122     var fullTimeString = shortTime;
2933 14 Nov 14 olle 123     if (shortTime.length==3)
2933 14 Nov 14 olle 124     {
2933 14 Nov 14 olle 125       fullTimeString = "0"+shortTime;
2933 14 Nov 14 olle 126     }
2933 14 Nov 14 olle 127     return fullTimeString;
2933 14 Nov 14 olle 128   }
2933 14 Nov 14 olle 129
2933 14 Nov 14 olle 130   /**
2933 14 Nov 14 olle 131     Convert a 2-digit year to a 4-digit year. Assuming
2933 14 Nov 14 olle 132     that the short year is between 1 and 100 years old. 
2933 14 Nov 14 olle 133   */
2933 14 Nov 14 olle 134   meludi.fullYear = function(shortYear)
2933 14 Nov 14 olle 135   {
2933 14 Nov 14 olle 136     var thisYear = new Date().getFullYear();
2933 14 Nov 14 olle 137     var fullYear = shortYear + 100*Math.floor((thisYear - shortYear - 1) / 100);
2933 14 Nov 14 olle 138     return fullYear;
2933 14 Nov 14 olle 139   }
2933 14 Nov 14 olle 140   
2933 14 Nov 14 olle 141   meludi.formatNumber = function(number, unit, baseDecimals)
2933 14 Nov 14 olle 142   {
2933 14 Nov 14 olle 143     if (number == null) return '';
2933 14 Nov 14 olle 144     
2933 14 Nov 14 olle 145     var numDecimals;
2933 14 Nov 14 olle 146     if (!baseDecimals) baseDecimals = 3;
2933 14 Nov 14 olle 147     if (number < 10)
2933 14 Nov 14 olle 148     {
2933 14 Nov 14 olle 149       numDecimals = baseDecimals;
2933 14 Nov 14 olle 150     }
2933 14 Nov 14 olle 151     else if (number < 100)
2933 14 Nov 14 olle 152     {
2933 14 Nov 14 olle 153       numDecimals = baseDecimals-1;
2933 14 Nov 14 olle 154     }
2933 14 Nov 14 olle 155     else
2933 14 Nov 14 olle 156     {
2933 14 Nov 14 olle 157       numDecimals = baseDecimals-2;
2933 14 Nov 14 olle 158     }
2933 14 Nov 14 olle 159
2933 14 Nov 14 olle 160     var result = number.toFixed(numDecimals);
2933 14 Nov 14 olle 161     if (unit) result += unit;
2933 14 Nov 14 olle 162     return result;
2933 14 Nov 14 olle 163   }
2933 14 Nov 14 olle 164
2933 14 Nov 14 olle 165   /**
2933 14 Nov 14 olle 166     Reformat a date string in YYYYMMDD or YYYYMMDD HHMM format
2933 14 Nov 14 olle 167     to YYYY-MM-DD HH:MM
2933 14 Nov 14 olle 168   */
2933 14 Nov 14 olle 169   meludi.reformatDate = function(value, defaultValue)
2933 14 Nov 14 olle 170   {
2933 14 Nov 14 olle 171     if (!value) return defaultValue || '';
2933 14 Nov 14 olle 172     if (value.length == 8)
2933 14 Nov 14 olle 173     {
2933 14 Nov 14 olle 174       // YYYYMMDD
2933 14 Nov 14 olle 175       value = value.substr(0, 4) + '-' + value.substr(4, 2) + '-' + value.substr(6, 2);
2933 14 Nov 14 olle 176     }
2933 14 Nov 14 olle 177     else if (value.length == 13)
2933 14 Nov 14 olle 178     {
2933 14 Nov 14 olle 179       // YYYYMMDD HHMM
2933 14 Nov 14 olle 180       value = value.substr(0, 4) + '-' + value.substr(4, 2) + '-' + value.substr(6, 2) + ' ' + value.substr(9, 2) + ':' + value.substr(11, 2);
2933 14 Nov 14 olle 181     }
2933 14 Nov 14 olle 182     return value;
2933 14 Nov 14 olle 183   }
2933 14 Nov 14 olle 184
2933 14 Nov 14 olle 185   
2933 14 Nov 14 olle 186   /**
2933 14 Nov 14 olle 187     Get subtype information.
2933 14 Nov 14 olle 188   */
2933 14 Nov 14 olle 189   meludi.getSubtypeInfo = function(subtype)
2933 14 Nov 14 olle 190   {
2933 14 Nov 14 olle 191     var url = '../Subtype.servlet?ID='+App.getSessionId();
2933 14 Nov 14 olle 192     url += '&cmd=GetSubtypeInfo&name='+subtype;
2933 14 Nov 14 olle 193     var response = Wizard.syncJsonRequest(url);
2933 14 Nov 14 olle 194     return response ? response.subtype : null;
2933 14 Nov 14 olle 195   }
2933 14 Nov 14 olle 196   
2933 14 Nov 14 olle 197   meludi.setCurrentDirectory = function(path)
2933 14 Nov 14 olle 198   {
2933 14 Nov 14 olle 199     if (path == currentDirectory) return;
2933 14 Nov 14 olle 200     var url = '../Session.servlet?ID='+App.getSessionId();
2933 14 Nov 14 olle 201     url += '&cmd=SetCurrentDirectory&path='+encodeURIComponent(path);
2933 14 Nov 14 olle 202     Wizard.syncJsonRequest(url);
2933 14 Nov 14 olle 203     currentDirectory = path;
2933 14 Nov 14 olle 204   }
2933 14 Nov 14 olle 205   
2933 14 Nov 14 olle 206   /**
2933 14 Nov 14 olle 207     Load protocols of the given subtype and add them
2933 14 Nov 14 olle 208     to a selection list. This method submits an
2933 14 Nov 14 olle 209     async request to the server and then returns
2933 14 Nov 14 olle 210     immediately.
2933 14 Nov 14 olle 211   */
2933 14 Nov 14 olle 212   meludi.loadProtocols = function(subtype, list, annotations)
2933 14 Nov 14 olle 213   {
2933 14 Nov 14 olle 214     list = Doc.element(list);
2933 14 Nov 14 olle 215     list.length=0;
2933 14 Nov 14 olle 216     list[0] = new Option('loading...', '');
2933 14 Nov 14 olle 217     Doc.addClass(list, 'list-loading');
2933 14 Nov 14 olle 218     var url = '../Protocol.servlet?ID='+App.getSessionId();
2933 14 Nov 14 olle 219     url += '&cmd=GetProtocols&subtype='+subtype;
2933 14 Nov 14 olle 220     Wizard.asyncJsonRequest(url, 
2933 14 Nov 14 olle 221       function(response)
2933 14 Nov 14 olle 222       {
2933 14 Nov 14 olle 223         internal.fillList(response.protocols, list, true);
2933 14 Nov 14 olle 224       }
2933 14 Nov 14 olle 225     );
2933 14 Nov 14 olle 226   }
2933 14 Nov 14 olle 227   
2933 14 Nov 14 olle 228   /**
2933 14 Nov 14 olle 229     Load software of the given subtype and add them
2933 14 Nov 14 olle 230     to a selection list. This method submits an
2933 14 Nov 14 olle 231     async request to the server and then returns
2933 14 Nov 14 olle 232     immediately.
2933 14 Nov 14 olle 233   */
2933 14 Nov 14 olle 234   meludi.loadSoftware = function(subtype, list)
2933 14 Nov 14 olle 235   {
2933 14 Nov 14 olle 236     list = Doc.element(list);
2933 14 Nov 14 olle 237     list.length=0;
2933 14 Nov 14 olle 238     list[0] = new Option('loading...', '');
2933 14 Nov 14 olle 239     Doc.addClass(list, 'list-loading');
2933 14 Nov 14 olle 240     var url = '../Software.servlet?ID='+App.getSessionId();
2933 14 Nov 14 olle 241     url += '&cmd=GetSoftware&subtype='+subtype;
2933 14 Nov 14 olle 242     Wizard.asyncJsonRequest(url, 
2933 14 Nov 14 olle 243       function(response)
2933 14 Nov 14 olle 244       {
2933 14 Nov 14 olle 245         internal.fillList(response.software, list, true);
2933 14 Nov 14 olle 246       }
2933 14 Nov 14 olle 247     );
2933 14 Nov 14 olle 248   }
2933 14 Nov 14 olle 249   
2933 14 Nov 14 olle 250   /**
2933 14 Nov 14 olle 251     Load hardware of the given subtype and add them
2933 14 Nov 14 olle 252     to a selection list. This method submits an
2933 14 Nov 14 olle 253     async request to the server and then returns
2933 14 Nov 14 olle 254     immediately.
2933 14 Nov 14 olle 255   */
2933 14 Nov 14 olle 256   meludi.loadHardware = function(subtype, list, annotations)
2933 14 Nov 14 olle 257   {
2933 14 Nov 14 olle 258     list = Doc.element(list);
2933 14 Nov 14 olle 259     list.length=0;
2933 14 Nov 14 olle 260     list[0] = new Option('loading...', '');
2933 14 Nov 14 olle 261     Doc.addClass(list, 'list-loading');
2933 14 Nov 14 olle 262     var url = '../Hardware.servlet?ID='+App.getSessionId();
2933 14 Nov 14 olle 263     url += '&cmd=GetHardware&subtype='+subtype;
2933 14 Nov 14 olle 264     if (annotations)
2933 14 Nov 14 olle 265     {
2933 14 Nov 14 olle 266       url += '&annotations='+annotations;
2933 14 Nov 14 olle 267     }
2933 14 Nov 14 olle 268     Wizard.asyncJsonRequest(url, 
2933 14 Nov 14 olle 269       function(response)
2933 14 Nov 14 olle 270       {
2933 14 Nov 14 olle 271         internal.fillList(response.hardware, list, true);
2933 14 Nov 14 olle 272       }
2933 14 Nov 14 olle 273     );
2933 14 Nov 14 olle 274   }
2933 14 Nov 14 olle 275
2933 14 Nov 14 olle 276   // Fills a selection list with items
2933 14 Nov 14 olle 277   internal.fillList = function(items, list, addNoneOption)
2933 14 Nov 14 olle 278   {
2933 14 Nov 14 olle 279     Doc.removeClass(list, 'list-loading');
2933 14 Nov 14 olle 280     list.length = 0;
2933 14 Nov 14 olle 281     for (var i = 0; i < items.length; i++)
2933 14 Nov 14 olle 282     {
2933 14 Nov 14 olle 283       var item = items[i];
2933 14 Nov 14 olle 284       var option = new Option(item.name, item.id, item.isDefault);
2933 14 Nov 14 olle 285       option.item = item;
2933 14 Nov 14 olle 286       list[list.length] = option;
2933 14 Nov 14 olle 287     }
2933 14 Nov 14 olle 288     if (list.length > 0) Wizard.setInputStatus(list.id, 'valid');
2933 14 Nov 14 olle 289     if (addNoneOption)
2933 14 Nov 14 olle 290     {
2933 14 Nov 14 olle 291       list[list.length] = new Option('- none -', '');
2933 14 Nov 14 olle 292     }
2933 14 Nov 14 olle 293   }
2933 14 Nov 14 olle 294   
2933 14 Nov 14 olle 295   meludi.isStratagene = function(sampleName)
2933 14 Nov 14 olle 296   {
2933 14 Nov 14 olle 297     return sampleName.indexOf(GENERIC_STRATAGENE_NAME) == 0;
2933 14 Nov 14 olle 298   }
2933 14 Nov 14 olle 299
2933 14 Nov 14 olle 300   meludi.isExternal = function(sampleName)
2933 14 Nov 14 olle 301   {
2933 14 Nov 14 olle 302     return sampleName.indexOf(EXTERNAL_RNA_NAME) == 0;
2933 14 Nov 14 olle 303   }
2933 14 Nov 14 olle 304
2933 14 Nov 14 olle 305   meludi.wellToAlpha = function(wellNo)
2933 14 Nov 14 olle 306   {
2933 14 Nov 14 olle 307     return wellNo >=0 && wellNo < WELL_ALPHA.length ? WELL_ALPHA[wellNo] : '?';
2933 14 Nov 14 olle 308   }
2933 14 Nov 14 olle 309   
2933 14 Nov 14 olle 310   meludi.alphaToWell = function(wellAlpha)
2933 14 Nov 14 olle 311   {
2933 14 Nov 14 olle 312     return WELL_ALPHA.indexOf(wellAlpha.toUpperCase());
2933 14 Nov 14 olle 313   }
2933 14 Nov 14 olle 314   
2933 14 Nov 14 olle 315   /**
2933 14 Nov 14 olle 316     Open a popup window and copy a part of the current window to the popup
2933 14 Nov 14 olle 317     and make it suitable for printin.
2933 14 Nov 14 olle 318   
2933 14 Nov 14 olle 319     @param printElementId The id of a html tag in the current page that should
2933 14 Nov 14 olle 320       be copied to the print window
2933 14 Nov 14 olle 321     @param pageTitle The title of the print window
2933 14 Nov 14 olle 322     @param pageOrientation 'landscape' or 'portrait' (default)
2933 14 Nov 14 olle 323     @param printNote Optional note intended to include instructions how to configure
2933 14 Nov 14 olle 324       the browser for optimal printing (eg. set to landscape and scale to 75%)
2933 14 Nov 14 olle 325   */
2933 14 Nov 14 olle 326   meludi.openPrintWindow = function(printElementId, pageTitle, pageOrientation, printNote, meludiRoot, extraStyles)
2933 14 Nov 14 olle 327   {
2933 14 Nov 14 olle 328     // Default width/height is for 'portrait' orientation
2933 14 Nov 14 olle 329     var width = 900;
2933 14 Nov 14 olle 330     var height = 900;
2933 14 Nov 14 olle 331     if (pageOrientation == 'landscape')
2933 14 Nov 14 olle 332     {
2933 14 Nov 14 olle 333       width = 1300;
2933 14 Nov 14 olle 334       height = 700;
2933 14 Nov 14 olle 335     }
2933 14 Nov 14 olle 336     
2933 14 Nov 14 olle 337     var url = 'print_template.jsp?ID='+App.getSessionId();
2933 14 Nov 14 olle 338     if (extraStyles) url += '&extraStyles='+extraStyles;
2933 14 Nov 14 olle 339     if (meludiRoot) url = meludiRoot+url;
2933 14 Nov 14 olle 340     // Open the print-window 
2933 14 Nov 14 olle 341     internal.printOptions = {
2933 14 Nov 14 olle 342       'printElementId': printElementId,
2933 14 Nov 14 olle 343       'pageTitle': pageTitle, 
2933 14 Nov 14 olle 344       'pageOrientation': pageOrientation, 
2933 14 Nov 14 olle 345       'printNote': printNote
2933 14 Nov 14 olle 346     };
2933 14 Nov 14 olle 347     var printWin = window.open(url, 'PrintWindow', 'width='+width+',height='+height+',toolbar=yes,location=no,directories=no,status=no,menubar=yes,scrollbars=yes,resizable=yes');
2933 14 Nov 14 olle 348   }
2933 14 Nov 14 olle 349
2933 14 Nov 14 olle 350   meludi.finalizePrint = function(printWin)
2933 14 Nov 14 olle 351   {
2933 14 Nov 14 olle 352     // Set page title...
2933 14 Nov 14 olle 353     if (internal.printOptions.pageTitle) 
2933 14 Nov 14 olle 354     {
2933 14 Nov 14 olle 355       printWin.document.title = internal.printOptions.pageTitle;
2933 14 Nov 14 olle 356     }
2933 14 Nov 14 olle 357   
2933 14 Nov 14 olle 358     // ...orientation...
2933 14 Nov 14 olle 359     if (internal.printOptions.pageOrientation)
2933 14 Nov 14 olle 360     {
2933 14 Nov 14 olle 361       var paper = printWin.document.getElementById('paper');
2933 14 Nov 14 olle 362       paper.className += ' ' + internal.printOptions.pageOrientation;
2933 14 Nov 14 olle 363     }
2933 14 Nov 14 olle 364     
2933 14 Nov 14 olle 365     // ... and print note
2933 14 Nov 14 olle 366     if (internal.printOptions.printNote)
2933 14 Nov 14 olle 367     {
2933 14 Nov 14 olle 368       var note = printWin.document.getElementById('printNote');
2933 14 Nov 14 olle 369       note.innerHTML = internal.printOptions.printNote;
2933 14 Nov 14 olle 370     }
2933 14 Nov 14 olle 371     
2933 14 Nov 14 olle 372     // Get the HTML from the <div> tag to be printed
2933 14 Nov 14 olle 373     var printElement = Doc.element(internal.printOptions.printElementId);
2933 14 Nov 14 olle 374     var printHtml = printElement.innerHTML;
2933 14 Nov 14 olle 375     // Replace all <canvas> elements with <img>
2933 14 Nov 14 olle 376     // since that seems the only way to make things work in IE
2933 14 Nov 14 olle 377     printHtml = printHtml.replace(/\<canvas.*?\<\/canvas\>/g, '<img class="canvas-copy">');
2933 14 Nov 14 olle 378   
2933 14 Nov 14 olle 379     // Copy the HTML to the print-area in the print-window
2933 14 Nov 14 olle 380     var printArea = printWin.document.getElementById('printarea');
2933 14 Nov 14 olle 381     printArea.innerHTML = printHtml;
2933 14 Nov 14 olle 382   
2933 14 Nov 14 olle 383     // Copy the <canvas> elements as images to the <img> elements
2933 14 Nov 14 olle 384     // using toDataURL()
2933 14 Nov 14 olle 385     var srcCanvas = printElement.getElementsByTagName('canvas');
2933 14 Nov 14 olle 386     var printImg = printArea.getElementsByClassName('canvas-copy');
2933 14 Nov 14 olle 387     for (var i = 0; i < srcCanvas.length; i++)
2933 14 Nov 14 olle 388     {
2933 14 Nov 14 olle 389       printImg[i].src = srcCanvas[i].toDataURL();
2933 14 Nov 14 olle 390     }
2933 14 Nov 14 olle 391     
2933 14 Nov 14 olle 392   }
2933 14 Nov 14 olle 393   
2933 14 Nov 14 olle 394   return meludi;
2933 14 Nov 14 olle 395 }();
2933 14 Nov 14 olle 396
2933 14 Nov 14 olle 397
2933 14 Nov 14 olle 398
2933 14 Nov 14 olle 399
2933 14 Nov 14 olle 400 var Wizard = function()
2933 14 Nov 14 olle 401 {
2933 14 Nov 14 olle 402   var wizard = {};
2933 14 Nov 14 olle 403   var internal = {};
3185 18 Mar 15 olle 404   var debug = 0;
2933 14 Nov 14 olle 405   
2933 14 Nov 14 olle 406   var currentStep = 1;
2933 14 Nov 14 olle 407   var numLiveAsyncRequests = 0;
2933 14 Nov 14 olle 408   var hasSentRegistration = false;
2933 14 Nov 14 olle 409   var forceConfirm = false;
2933 14 Nov 14 olle 410   var noConfirmOnFirstStep = true;
2933 14 Nov 14 olle 411   var hasFatalError = false;
2933 14 Nov 14 olle 412   
2933 14 Nov 14 olle 413   /**
2933 14 Nov 14 olle 414     Validate the 'date'-input field that is the target of this event
2933 14 Nov 14 olle 415     The date is optional unless 'required' is part if it's className.
2933 14 Nov 14 olle 416     Dates should be either 4 or 8 digits with month+day or year+month+day.
2933 14 Nov 14 olle 417     If 'data-allow-six-digits' is set on the target element, the year
2933 14 Nov 14 olle 418     is allowed to be only 2 digits.
2933 14 Nov 14 olle 419     
2933 14 Nov 14 olle 420     4-digit (and 6-digit) dates auto-padded to 8 digits.
2933 14 Nov 14 olle 421     
2933 14 Nov 14 olle 422     The 'data-valid' attribute is set to 1 or 0 depending on the outcome,
2933 14 Nov 14 olle 423     and 'data-warning' is set if the date is missing on non-required fields.
2933 14 Nov 14 olle 424   */
2933 14 Nov 14 olle 425   wizard.validateDate = function(event)
2933 14 Nov 14 olle 426   {
2933 14 Nov 14 olle 427     var target = event.currentTarget;
2933 14 Nov 14 olle 428     var isValid = false;
2933 14 Nov 14 olle 429     var isWarning = false;
2933 14 Nov 14 olle 430     
2933 14 Nov 14 olle 431     // Reset current status
2933 14 Nov 14 olle 432     wizard.setInputStatus(target);
2933 14 Nov 14 olle 433     
2933 14 Nov 14 olle 434     var date = target.value;
2933 14 Nov 14 olle 435     if (date == '')
2933 14 Nov 14 olle 436     {
2933 14 Nov 14 olle 437       // No date, is this an error or a warning?
2933 14 Nov 14 olle 438       var optional = target.className.indexOf('required') == -1;
2933 14 Nov 14 olle 439       wizard.setInputStatus(target, optional ? 'warning' : 'invalid', 'Missing');
2933 14 Nov 14 olle 440       isValid = optional;
2933 14 Nov 14 olle 441       isWarning = optional;
2933 14 Nov 14 olle 442     }
2933 14 Nov 14 olle 443     else
2933 14 Nov 14 olle 444     {
2933 14 Nov 14 olle 445       var allowSixDigits = Data.int(target, 'allow-six-digits');
2933 14 Nov 14 olle 446       date = Meludi.autoFillDate(date, allowSixDigits);
2933 14 Nov 14 olle 447       target.value = date;
2933 14 Nov 14 olle 448       
2933 14 Nov 14 olle 449       var d = Dates.parseString(date, 'yyyyMMdd');
2933 14 Nov 14 olle 450       if (d == null)
2933 14 Nov 14 olle 451       {
2933 14 Nov 14 olle 452         Wizard.setInputStatus(target, 'invalid', 'Not a valid date');
2933 14 Nov 14 olle 453       }
2933 14 Nov 14 olle 454       else
2933 14 Nov 14 olle 455       {
2933 14 Nov 14 olle 456         var disallowFutureDate = Data.int(target, 'disallow-future-date');
2933 14 Nov 14 olle 457         var today = new Date();
2933 14 Nov 14 olle 458         if (disallowFutureDate && (d.getTime() > today.getTime()))
2933 14 Nov 14 olle 459         {
2933 14 Nov 14 olle 460           Wizard.setInputStatus(target, 'invalid', 'Future dates are not valid');
2933 14 Nov 14 olle 461         }
2933 14 Nov 14 olle 462         else
2933 14 Nov 14 olle 463         {
2933 14 Nov 14 olle 464           Wizard.setInputStatus(target, 'valid');
2933 14 Nov 14 olle 465           isValid = true;
2933 14 Nov 14 olle 466         }
2933 14 Nov 14 olle 467       }
2933 14 Nov 14 olle 468     }
2933 14 Nov 14 olle 469
2933 14 Nov 14 olle 470     Data.set(target, 'valid', isValid ? 1 : 0);
2933 14 Nov 14 olle 471     Data.set(target, 'warning', isWarning ? 1 : 0);
2933 14 Nov 14 olle 472     
2933 14 Nov 14 olle 473     if (!isValid && target.focus) target.focus();
2933 14 Nov 14 olle 474     return isValid;
2933 14 Nov 14 olle 475   }
2933 14 Nov 14 olle 476
2933 14 Nov 14 olle 477   
2933 14 Nov 14 olle 478   wizard.isValid = function(element)
2933 14 Nov 14 olle 479   {
2933 14 Nov 14 olle 480     return Data.int(element, 'valid', 1);
2933 14 Nov 14 olle 481   }
2933 14 Nov 14 olle 482
2933 14 Nov 14 olle 483
2933 14 Nov 14 olle 484   wizard.initFileSelectionField = function(element)
2933 14 Nov 14 olle 485   {
2933 14 Nov 14 olle 486     element = Doc.element(element);
2933 14 Nov 14 olle 487     
2933 14 Nov 14 olle 488     var subtype = Data.get(element, 'subtype');
2933 14 Nov 14 olle 489     if (subtype)
2933 14 Nov 14 olle 490     {
5149 28 Nov 18 olle 491       element.subtype = Meludi.getSubtypeInfo(subtype);
2933 14 Nov 14 olle 492     }
2933 14 Nov 14 olle 493     
2933 14 Nov 14 olle 494     Buttons.addClickHandler(element.id + '.btn', wizard.browseOnClick, { 'file-field': element.id });
2933 14 Nov 14 olle 495     Events.doOnEnter(element, wizard.browseOnClick);
2933 14 Nov 14 olle 496     
2933 14 Nov 14 olle 497     Events.addEventHandler(element, 'base-selected', wizard.fileSelected);
2933 14 Nov 14 olle 498     Events.addEventHandler(element, 'change', wizard.fileChanged);
2933 14 Nov 14 olle 499     Events.sendChangeEvent(element);
2933 14 Nov 14 olle 500   }
2933 14 Nov 14 olle 501   
2933 14 Nov 14 olle 502   wizard.browseOnClick = function(event)
2933 14 Nov 14 olle 503   {
2933 14 Nov 14 olle 504     var fileField = Doc.element(Data.get(event.currentTarget, 'file-field', event.currentTarget.id));
2933 14 Nov 14 olle 505
2933 14 Nov 14 olle 506     var url = '&resetTemporary=1';
2933 14 Nov 14 olle 507     var nameFilter = Data.get(fileField, 'name-filter');
2933 14 Nov 14 olle 508     if (nameFilter)
2933 14 Nov 14 olle 509     {
2933 14 Nov 14 olle 510       url += '&tmpfilter:STRING:name='+encodeURIComponent(nameFilter);
2933 14 Nov 14 olle 511     }
2933 14 Nov 14 olle 512
2933 14 Nov 14 olle 513     var subtype = fileField.subtype;
2933 14 Nov 14 olle 514     if (subtype)
2933 14 Nov 14 olle 515     {
2933 14 Nov 14 olle 516       url += '&tmpfilter:INT:itemSubtype='+subtype.id;
2933 14 Nov 14 olle 517     }
2933 14 Nov 14 olle 518     
2933 14 Nov 14 olle 519     var directory = Data.get(fileField, 'directory');
2933 14 Nov 14 olle 520     if (directory && !Data.get(fileField, 'has-browsed'))
2933 14 Nov 14 olle 521     {
2933 14 Nov 14 olle 522       Meludi.setCurrentDirectory(directory);
2933 14 Nov 14 olle 523       Data.set(fileField, 'has-browsed', 1);
2933 14 Nov 14 olle 524     }
2933 14 Nov 14 olle 525     
2933 14 Nov 14 olle 526     Dialogs.selectItem('FILE', fileField, 0, url);
2933 14 Nov 14 olle 527   }
2933 14 Nov 14 olle 528   
2933 14 Nov 14 olle 529   wizard.fileSelected = function(event)
2933 14 Nov 14 olle 530   {
2933 14 Nov 14 olle 531     event.currentTarget.value = event.detail.name;
2933 14 Nov 14 olle 532     Events.sendChangeEvent(event.currentTarget);
2933 14 Nov 14 olle 533   }
2933 14 Nov 14 olle 534   
2933 14 Nov 14 olle 535   wizard.fileChanged = function(event)
2933 14 Nov 14 olle 536   {
2933 14 Nov 14 olle 537     var target = event.currentTarget;
2933 14 Nov 14 olle 538     
2933 14 Nov 14 olle 539     var isValid = false;
2933 14 Nov 14 olle 540     var isWarning = false;
2933 14 Nov 14 olle 541     
2933 14 Nov 14 olle 542     // Reset current status
2933 14 Nov 14 olle 543     wizard.setInputStatus(target);
2933 14 Nov 14 olle 544     
2933 14 Nov 14 olle 545     var path = target.value;
2933 14 Nov 14 olle 546     if (path == '')
2933 14 Nov 14 olle 547     {
2933 14 Nov 14 olle 548       // No file, is this an error or a warning?
2933 14 Nov 14 olle 549       var optional = target.className.indexOf('required') == -1;
2933 14 Nov 14 olle 550       wizard.setInputStatus(target, optional ? 'warning' : 'invalid', 'Missing');
2933 14 Nov 14 olle 551       isValid = optional;
2933 14 Nov 14 olle 552       isWarning = optional;
2933 14 Nov 14 olle 553     }
2933 14 Nov 14 olle 554     else
2933 14 Nov 14 olle 555     {
2933 14 Nov 14 olle 556       Wizard.setInputStatus(target, 'valid');
2933 14 Nov 14 olle 557       isValid = true;
2933 14 Nov 14 olle 558     }
2933 14 Nov 14 olle 559     
2933 14 Nov 14 olle 560     Data.set(target, 'valid', isValid ? 1 : 0);
2933 14 Nov 14 olle 561     Data.set(target, 'warning', isWarning ? 1 : 0);
2933 14 Nov 14 olle 562     
2933 14 Nov 14 olle 563     if (!isValid && target.focus) target.focus();
2933 14 Nov 14 olle 564   }
2933 14 Nov 14 olle 565   
2933 14 Nov 14 olle 566   
2933 14 Nov 14 olle 567   /**
5149 28 Nov 18 olle 568     Get subtype information.
5149 28 Nov 18 olle 569   */
5149 28 Nov 18 olle 570   wizard.getSubtypeInfo = function(subtype)
5149 28 Nov 18 olle 571   {
5149 28 Nov 18 olle 572     var url = '../Subtype.servlet?ID='+App.getSessionId();
5149 28 Nov 18 olle 573     url += '&cmd=GetSubtypeInfo&name='+subtype;
5149 28 Nov 18 olle 574     var response = Wizard.syncJsonRequest(url);
5149 28 Nov 18 olle 575     return response ? response.subtype : null;
5149 28 Nov 18 olle 576   }
5149 28 Nov 18 olle 577   
5149 28 Nov 18 olle 578   /**
5149 28 Nov 18 olle 579     Get data file type information.
5149 28 Nov 18 olle 580   */
5149 28 Nov 18 olle 581   wizard.getDataFileTypeInfo = function(filetype)
5149 28 Nov 18 olle 582   {
5149 28 Nov 18 olle 583     var url = '../Subtype.servlet?ID='+App.getSessionId();
5149 28 Nov 18 olle 584     url += '&cmd=GetDataFileTypeInfo&name='+filetype;
5149 28 Nov 18 olle 585     var response = Wizard.syncJsonRequest(url);
5149 28 Nov 18 olle 586     return response ? response.fileType : null;
5149 28 Nov 18 olle 587   }
5149 28 Nov 18 olle 588   
5149 28 Nov 18 olle 589   wizard.setCurrentDirectory = function(path)
5149 28 Nov 18 olle 590   {
5149 28 Nov 18 olle 591     if (path == currentDirectory) return;
5149 28 Nov 18 olle 592     var url = '../Session.servlet?ID='+App.getSessionId();
5149 28 Nov 18 olle 593     url += '&cmd=SetCurrentDirectory&path='+encodeURIComponent(path);
5149 28 Nov 18 olle 594     Wizard.syncJsonRequest(url);
5149 28 Nov 18 olle 595     currentDirectory = path;
5149 28 Nov 18 olle 596   }
5149 28 Nov 18 olle 597   
5149 28 Nov 18 olle 598   /**
2933 14 Nov 14 olle 599     Change display status for an input field.
2933 14 Nov 14 olle 600     @param prefix ID prefix to locate tags
2933 14 Nov 14 olle 601     @param clazz The message clazz (valid, invalid, warning) or empty
2933 14 Nov 14 olle 602     @param message The message (may be empty)
2933 14 Nov 14 olle 603   */
2933 14 Nov 14 olle 604   wizard.setInputStatus = function(prefix, clazz, message)
2933 14 Nov 14 olle 605   {
2933 14 Nov 14 olle 606     if (prefix.id) prefix = prefix.id;
2933 14 Nov 14 olle 607     
2933 14 Nov 14 olle 608     var statusTag = Doc.element(prefix + '.status');
2933 14 Nov 14 olle 609     statusTag.className = 'status ' + (clazz || '');
2933 14 Nov 14 olle 610     
2933 14 Nov 14 olle 611     var trTag = statusTag.parentNode;
2933 14 Nov 14 olle 612     var trClass = Data.get(trTag, 'original-class');
2933 14 Nov 14 olle 613     if (!trClass)
2933 14 Nov 14 olle 614     {
2933 14 Nov 14 olle 615       trClass = trTag.className || 'foo';
2933 14 Nov 14 olle 616       Data.set(trTag, 'original-class', trClass);
2933 14 Nov 14 olle 617     }
2933 14 Nov 14 olle 618     trTag.className = trClass + ' ' + (clazz || '');
2933 14 Nov 14 olle 619     
2933 14 Nov 14 olle 620     var msgTag = Doc.element(prefix + '.message');
2933 14 Nov 14 olle 621     if (msgTag)
2933 14 Nov 14 olle 622     {
2933 14 Nov 14 olle 623       if (message)
2933 14 Nov 14 olle 624       {
2933 14 Nov 14 olle 625         msgTag.innerHTML = message;
2933 14 Nov 14 olle 626         Doc.show(msgTag, Data.get(msgTag, 'display', 'inline'));
2933 14 Nov 14 olle 627       }
2933 14 Nov 14 olle 628       else
2933 14 Nov 14 olle 629       {
2933 14 Nov 14 olle 630         msgTag.innerHTML = message;
2933 14 Nov 14 olle 631         Doc.hide(msgTag);
2933 14 Nov 14 olle 632       }
2933 14 Nov 14 olle 633     }
2933 14 Nov 14 olle 634     else
2933 14 Nov 14 olle 635     {
2933 14 Nov 14 olle 636       statusTag.title = message || '';
2933 14 Nov 14 olle 637     }
2933 14 Nov 14 olle 638   }
2933 14 Nov 14 olle 639
2933 14 Nov 14 olle 640   
2933 14 Nov 14 olle 641   /**
2933 14 Nov 14 olle 642     Event handler for input fields, that go to the
2933 14 Nov 14 olle 643     next wizard step if TAB or ENTER key is pressed.
2933 14 Nov 14 olle 644     A short delay is used to allow other event handler
2933 14 Nov 14 olle 645     to run first (eg. for validation).
2933 14 Nov 14 olle 646   */
2933 14 Nov 14 olle 647   wizard.goNextOnTabOrEnter = function(event)
2933 14 Nov 14 olle 648   {
2933 14 Nov 14 olle 649     if (event.keyCode == 9 || event.keyCode == 13) 
2933 14 Nov 14 olle 650     {
2933 14 Nov 14 olle 651       setTimeout(function() { wizard.goNext(true) }, 200);
2933 14 Nov 14 olle 652     }
2933 14 Nov 14 olle 653   }
2933 14 Nov 14 olle 654   
2933 14 Nov 14 olle 655   /**
2933 14 Nov 14 olle 656     Event handler for input fields, that go to the
2933 14 Nov 14 olle 657     next wizard step if TAB key is pressed.
2933 14 Nov 14 olle 658     A short delay is used to allow other event handler
2933 14 Nov 14 olle 659     to run first (eg. for validation).
2933 14 Nov 14 olle 660   */
2933 14 Nov 14 olle 661   wizard.goNextOnTab = function(event)
2933 14 Nov 14 olle 662   {
2933 14 Nov 14 olle 663     if (event.keyCode == 9) 
2933 14 Nov 14 olle 664     {
2933 14 Nov 14 olle 665       setTimeout(function() { wizard.goNext(true) }, 200);
2933 14 Nov 14 olle 666     }
2933 14 Nov 14 olle 667   }
2933 14 Nov 14 olle 668   
2933 14 Nov 14 olle 669   /**
2933 14 Nov 14 olle 670     Event handler for input fields, that changes
2933 14 Nov 14 olle 671     focus to the next element. The next element
2933 14 Nov 14 olle 672     should be defined by 'data-next-focus' attribute.
2933 14 Nov 14 olle 673     It is recommended that this is consisistent with TAB.
2933 14 Nov 14 olle 674   */
2933 14 Nov 14 olle 675   wizard.focusOnEnter = function(event)
2933 14 Nov 14 olle 676   {
2933 14 Nov 14 olle 677     if (event.keyCode == 13)
2933 14 Nov 14 olle 678     {
2933 14 Nov 14 olle 679       var nextFocus = Doc.element(Data.get(event.currentTarget, 'next-focus'));
2933 14 Nov 14 olle 680       if (nextFocus && nextFocus.focus) nextFocus.focus();
2933 14 Nov 14 olle 681     }
2933 14 Nov 14 olle 682   }
2933 14 Nov 14 olle 683   
2933 14 Nov 14 olle 684   // Event handler for the 'Next' navigation button
2933 14 Nov 14 olle 685   wizard.goNextOnClick = function(event)
2933 14 Nov 14 olle 686   {
2933 14 Nov 14 olle 687     wizard.goNext(false);
2933 14 Nov 14 olle 688   }
2933 14 Nov 14 olle 689   
2933 14 Nov 14 olle 690   /**
2933 14 Nov 14 olle 691     Go to the next step in the wizard. This method will first
2933 14 Nov 14 olle 692     submit 'wizard-validate' event to the current step. If at 
2933 14 Nov 14 olle 693     least one event handler calls 'Event.preventDefault()' the 
2933 14 Nov 14 olle 694     processing is aborted. 
2933 14 Nov 14 olle 695     
2933 14 Nov 14 olle 696     Otherwise, the current step is disabled and the 'wizard-initialize' 
2933 14 Nov 14 olle 697     event is sent to the next step. The event handler is responsible
2933 14 Nov 14 olle 698     for calling 'Wizard.setCurrentStep' to display the next step.
2933 14 Nov 14 olle 699   */
2933 14 Nov 14 olle 700   wizard.goNext = function(auto)
2933 14 Nov 14 olle 701   {
2933 14 Nov 14 olle 702     var verify = Doc.element('verifyGoNext');
2933 14 Nov 14 olle 703     if (verify && !verify.checked) return;
2933 14 Nov 14 olle 704     
2933 14 Nov 14 olle 705     var details = { 'auto': auto };
2933 14 Nov 14 olle 706     
2933 14 Nov 14 olle 707     // Send 'wizard-validate' event to current step
2933 14 Nov 14 olle 708     var step = Doc.element('step-'+currentStep);
2933 14 Nov 14 olle 709     var evt = document.createEvent('CustomEvent');
2933 14 Nov 14 olle 710     evt.initCustomEvent('wizard-validate', true, true, details);
2933 14 Nov 14 olle 711     if (!step.dispatchEvent(evt)) 
2933 14 Nov 14 olle 712     {
2933 14 Nov 14 olle 713       wizard.notifyError();
2933 14 Nov 14 olle 714       return;
2933 14 Nov 14 olle 715     }
2933 14 Nov 14 olle 716
2933 14 Nov 14 olle 717     // Hide all navigation buttons and disable form controls in current step
2933 14 Nov 14 olle 718     internal.hideButtons('navigation');
2933 14 Nov 14 olle 719     internal.disableStep(step);
2933 14 Nov 14 olle 720     
2933 14 Nov 14 olle 721     // Send 'wizard-initialize' to the next step
2933 14 Nov 14 olle 722     var nextStep = Doc.element('step-'+(currentStep+1));
2933 14 Nov 14 olle 723     var evt = document.createEvent('CustomEvent');
2933 14 Nov 14 olle 724     evt.initCustomEvent('wizard-initialize', true, true, details);
2933 14 Nov 14 olle 725     nextStep.dispatchEvent(evt);
2933 14 Nov 14 olle 726   }
2933 14 Nov 14 olle 727   
2933 14 Nov 14 olle 728   wizard.notifyError = function()
2933 14 Nov 14 olle 729   {
2933 14 Nov 14 olle 730     Doc.addClass('wizard', 'flash-error');
2933 14 Nov 14 olle 731     setTimeout(internal.stopFlashing, 2000);
2933 14 Nov 14 olle 732   }
2933 14 Nov 14 olle 733   
2933 14 Nov 14 olle 734   internal.stopFlashing = function()
2933 14 Nov 14 olle 735   {
2933 14 Nov 14 olle 736     Doc.removeClass('wizard', 'flash-error');
2933 14 Nov 14 olle 737   }
2933 14 Nov 14 olle 738   
2933 14 Nov 14 olle 739   /**
2933 14 Nov 14 olle 740     Finalize the registration of the wizard. This method will
2933 14 Nov 14 olle 741     first submit 'wizard-validate' to the current step. If at 
2933 14 Nov 14 olle 742     least one event handler calls 'Event.preventDefault()' the 
2933 14 Nov 14 olle 743     processing is aborted.
2933 14 Nov 14 olle 744     
2933 14 Nov 14 olle 745     Otherwise, the current step is disabled and the 'wizard-submit' 
2933 14 Nov 14 olle 746     event is sent to the 'wizard'. The event handler is responsible
2933 14 Nov 14 olle 747     for finalizing the registration and displaying a proper
2933 14 Nov 14 olle 748     message, for example, by calling Wizard.showFinalMessage()
2933 14 Nov 14 olle 749   */
2933 14 Nov 14 olle 750   wizard.goRegister = function()
2933 14 Nov 14 olle 751   {
2933 14 Nov 14 olle 752     // Check if verification is enabled
2933 14 Nov 14 olle 753     var verify = Doc.element('verifyGoNext');
2933 14 Nov 14 olle 754     if (verify && !verify.checked) return;
2933 14 Nov 14 olle 755     
2933 14 Nov 14 olle 756     // Send 'wizard-validate' event to current step
2933 14 Nov 14 olle 757     var step = Doc.element('step-'+currentStep);
2933 14 Nov 14 olle 758     var evt = document.createEvent('Event');
2933 14 Nov 14 olle 759     evt.initEvent('wizard-validate', false, true);
2933 14 Nov 14 olle 760     if (!step.dispatchEvent(evt)) 
2933 14 Nov 14 olle 761     {
2933 14 Nov 14 olle 762       wizard.notifyError();
2933 14 Nov 14 olle 763       return;
2933 14 Nov 14 olle 764     }
2933 14 Nov 14 olle 765
2933 14 Nov 14 olle 766     internal.hideButtons('navigation');
2933 14 Nov 14 olle 767     internal.disableStep(step);
2933 14 Nov 14 olle 768     
2933 14 Nov 14 olle 769     // Send 'wizard-submit' to the next step
2933 14 Nov 14 olle 770     var wiz = Doc.element('wizard');
2933 14 Nov 14 olle 771     hasSentRegistration = true;
2933 14 Nov 14 olle 772     var evt = document.createEvent('Event');
2933 14 Nov 14 olle 773     evt.initEvent('wizard-submit', false, true);
2933 14 Nov 14 olle 774     wiz.dispatchEvent(evt);
2933 14 Nov 14 olle 775   }
2933 14 Nov 14 olle 776   
2933 14 Nov 14 olle 777   wizard.setNoConfirmOnFirstStep = function(cf)
2933 14 Nov 14 olle 778   {
2933 14 Nov 14 olle 779     noConfirmOnFirstStep = cf;
2933 14 Nov 14 olle 780   }
2933 14 Nov 14 olle 781   
2933 14 Nov 14 olle 782   // Ask the user for confirmation and then restart the wizard
2933 14 Nov 14 olle 783   wizard.cancelWizard = function()
2933 14 Nov 14 olle 784   {
2933 14 Nov 14 olle 785     forceConfirm = true;
2933 14 Nov 14 olle 786     wizard.restartWizard();
2933 14 Nov 14 olle 787   }
2933 14 Nov 14 olle 788   
2933 14 Nov 14 olle 789   // Restart the wizard without asking the user for confirmation
2933 14 Nov 14 olle 790   wizard.restartWizard = function()
2933 14 Nov 14 olle 791   {
2933 14 Nov 14 olle 792     var url = location.href;
2933 14 Nov 14 olle 793     if (url.indexOf('&restart=1') == -1) url += '&restart=1';
2933 14 Nov 14 olle 794     location.href = url;
2933 14 Nov 14 olle 795   }
2933 14 Nov 14 olle 796   
2933 14 Nov 14 olle 797   wizard.goPrint = function()
2933 14 Nov 14 olle 798   {
2933 14 Nov 14 olle 799     window.print();
2933 14 Nov 14 olle 800   }
2933 14 Nov 14 olle 801   
2933 14 Nov 14 olle 802   wizard.setCurrentStep = function(stepNo)
2933 14 Nov 14 olle 803   {
2933 14 Nov 14 olle 804     currentStep = stepNo;
2933 14 Nov 14 olle 805     internal.enableStep(Doc.element('step-'+currentStep));
2933 14 Nov 14 olle 806   }
2933 14 Nov 14 olle 807
2933 14 Nov 14 olle 808   internal.disableStep = function(step)
2933 14 Nov 14 olle 809   {
2933 14 Nov 14 olle 810     step = Doc.element(step);
2933 14 Nov 14 olle 811     internal.disableAllFormElements(step);
2933 14 Nov 14 olle 812     Doc.addClass(step, 'disabled');
2933 14 Nov 14 olle 813     Doc.hide('gonext-message');
2933 14 Nov 14 olle 814     var stepNo = step.getElementsByClassName('step-no')[0];
2933 14 Nov 14 olle 815     Events.addEventHandler(stepNo, 'click', internal.togglePastStep, {'step-id': step.id});
2933 14 Nov 14 olle 816     stepNo.title = 'Show/hide this section';
2933 14 Nov 14 olle 817   }
2933 14 Nov 14 olle 818   
2933 14 Nov 14 olle 819   internal.enableStep = function(step)
2933 14 Nov 14 olle 820   {
2933 14 Nov 14 olle 821     step = Doc.element(step);
2933 14 Nov 14 olle 822     Doc.removeClass(step, 'disabled');
2933 14 Nov 14 olle 823     Doc.show(step);
2933 14 Nov 14 olle 824   }
2933 14 Nov 14 olle 825
2933 14 Nov 14 olle 826   // Toggle visibility of a past step
2933 14 Nov 14 olle 827   // The step is hidden if the 'auto-hide' class is present
2933 14 Nov 14 olle 828   internal.togglePastStep = function(event)
2933 14 Nov 14 olle 829   {
2933 14 Nov 14 olle 830     var step = Data.get(event.currentTarget, 'step-id');
2933 14 Nov 14 olle 831     Doc.addOrRemoveClass(step, 'auto-hide');
2933 14 Nov 14 olle 832   }
2933 14 Nov 14 olle 833   
2933 14 Nov 14 olle 834   wizard.syncJsonRequest = function(url, method, postdata)
2933 14 Nov 14 olle 835   {
2933 14 Nov 14 olle 836     if (debug)
2933 14 Nov 14 olle 837     {
2933 14 Nov 14 olle 838       App.debug((method || 'GET') + ': ' + url);
2933 14 Nov 14 olle 839       if (postdata) App.debug(postdata);
2933 14 Nov 14 olle 840     }
2933 14 Nov 14 olle 841     var request = Ajax.getXmlHttpRequest();
2933 14 Nov 14 olle 842     request.open(method || 'GET', url, false);
2933 14 Nov 14 olle 843     if (postdata) 
2933 14 Nov 14 olle 844     {
2933 14 Nov 14 olle 845       request.setRequestHeader("Content-Type", "application/json");
2933 14 Nov 14 olle 846     }
2933 14 Nov 14 olle 847     request.send(postdata || null);
2933 14 Nov 14 olle 848     
2933 14 Nov 14 olle 849     if (debug) App.debug(request.responseText);
2933 14 Nov 14 olle 850     if (!hasFatalError) Wizard.hideWizardStatus();
2933 14 Nov 14 olle 851
2933 14 Nov 14 olle 852     var response = null;
2933 14 Nov 14 olle 853     var errorMsg = null;
2933 14 Nov 14 olle 854     try
2933 14 Nov 14 olle 855     {
2933 14 Nov 14 olle 856       response = JSON.parse(request.responseText);
2933 14 Nov 14 olle 857       if (response.status != 'ok')
2933 14 Nov 14 olle 858       {
2933 14 Nov 14 olle 859         errorMsg = response.message;
2933 14 Nov 14 olle 860       }
2933 14 Nov 14 olle 861     }
2933 14 Nov 14 olle 862     catch (err)
2933 14 Nov 14 olle 863     {
2933 14 Nov 14 olle 864       errorMsg = err.toString ? err.toString() : err;
2933 14 Nov 14 olle 865     }
2933 14 Nov 14 olle 866     
2933 14 Nov 14 olle 867     if (errorMsg)
2933 14 Nov 14 olle 868     {
2933 14 Nov 14 olle 869       Wizard.setFatalError(errorMsg);
2933 14 Nov 14 olle 870       return null;
2933 14 Nov 14 olle 871     }
2933 14 Nov 14 olle 872     else
2933 14 Nov 14 olle 873     {
2933 14 Nov 14 olle 874       return response;
2933 14 Nov 14 olle 875     }
2933 14 Nov 14 olle 876   }
2933 14 Nov 14 olle 877   
2933 14 Nov 14 olle 878   /**
2933 14 Nov 14 olle 879     Submit an ansynchronous request for JSON data. 'GET' method
2933 14 Nov 14 olle 880     is used if 'method' parameter is not set.
2933 14 Nov 14 olle 881     The 'callback' should be a method accepting a single
2933 14 Nov 14 olle 882     JSON parameter object. If the 'status' of the response
2933 14 Nov 14 olle 883     is not 'ok' this method will call setFatalError and
2933 14 Nov 14 olle 884     without calling the callback method.
2933 14 Nov 14 olle 885   */
2933 14 Nov 14 olle 886   wizard.asyncJsonRequest = function(url, callback, method, postdata)
2933 14 Nov 14 olle 887   {
2933 14 Nov 14 olle 888     if (debug)
2933 14 Nov 14 olle 889     {
2933 14 Nov 14 olle 890       App.debug((method || 'GET') + ': ' + url);
2933 14 Nov 14 olle 891       if (postdata) App.debug(postdata);
2933 14 Nov 14 olle 892     }
2933 14 Nov 14 olle 893     var request = Ajax.getXmlHttpRequest();
2933 14 Nov 14 olle 894     request.jsonCallback = callback;
2933 14 Nov 14 olle 895     request.open(method || 'GET', url, true);
2933 14 Nov 14 olle 896     if (postdata) 
2933 14 Nov 14 olle 897     {
2933 14 Nov 14 olle 898       request.setRequestHeader("Content-Type", "application/json");
2933 14 Nov 14 olle 899     }
2933 14 Nov 14 olle 900     Ajax.setReadyStateHandler(request, internal.asyncCallbackWrapper, internal.asyncCallbackWrapper);
2933 14 Nov 14 olle 901     numLiveAsyncRequests++;
2933 14 Nov 14 olle 902     request.send(postdata || null);
2933 14 Nov 14 olle 903   }
2933 14 Nov 14 olle 904   
2933 14 Nov 14 olle 905   /**
2933 14 Nov 14 olle 906     Callback wrapper for ansynchronous requests.
2933 14 Nov 14 olle 907   */
2933 14 Nov 14 olle 908   internal.asyncCallbackWrapper = function(request)
2933 14 Nov 14 olle 909   {
2933 14 Nov 14 olle 910     numLiveAsyncRequests--;
2933 14 Nov 14 olle 911     if (debug) App.debug(request.responseText);
2933 14 Nov 14 olle 912     if (!hasFatalError) Wizard.hideWizardStatus();
2933 14 Nov 14 olle 913
2933 14 Nov 14 olle 914     var response = null;
2933 14 Nov 14 olle 915     var messages = null;
2933 14 Nov 14 olle 916     try
2933 14 Nov 14 olle 917     {
2933 14 Nov 14 olle 918       if (request.status != 200)
2933 14 Nov 14 olle 919       {
2933 14 Nov 14 olle 920         throw new Error(request.responseText);
2933 14 Nov 14 olle 921       }
2933 14 Nov 14 olle 922       else
2933 14 Nov 14 olle 923       {
2933 14 Nov 14 olle 924         if (request.getResponseHeader('Content-Type').indexOf('json') != -1)
2933 14 Nov 14 olle 925         {
2933 14 Nov 14 olle 926           response = JSON.parse(request.responseText);
2933 14 Nov 14 olle 927           messages = response.messages;
2933 14 Nov 14 olle 928           if (response.status != 'ok')
2933 14 Nov 14 olle 929           {
2933 14 Nov 14 olle 930             throw new Error(response.message || response.stacktrace);
2933 14 Nov 14 olle 931           }
2933 14 Nov 14 olle 932         }
2933 14 Nov 14 olle 933         else
2933 14 Nov 14 olle 934         {
2933 14 Nov 14 olle 935           response = request.responseText;
2933 14 Nov 14 olle 936         }
2933 14 Nov 14 olle 937         if (request.jsonCallback && request.jsonCallback.call)
2933 14 Nov 14 olle 938         {
2933 14 Nov 14 olle 939           request.jsonCallback.call(null, response);
2933 14 Nov 14 olle 940         }
2933 14 Nov 14 olle 941       }
2933 14 Nov 14 olle 942     }
2933 14 Nov 14 olle 943     catch (err)
2933 14 Nov 14 olle 944     {
2933 14 Nov 14 olle 945       Wizard.setFatalError(err, messages);
2933 14 Nov 14 olle 946     }
2933 14 Nov 14 olle 947   }
2933 14 Nov 14 olle 948
2933 14 Nov 14 olle 949   
2933 14 Nov 14 olle 950   /**
2933 14 Nov 14 olle 951     A fatal error has occurred and the wizard will not be able to continue.
2933 14 Nov 14 olle 952     This method will display the error message, disable all form input fields
2933 14 Nov 14 olle 953     and buttons (except the 'Restart' button).
2933 14 Nov 14 olle 954   */
2933 14 Nov 14 olle 955   wizard.setFatalError = function(err, messages)
2933 14 Nov 14 olle 956   {
2933 14 Nov 14 olle 957     hasFatalError = true;
2933 14 Nov 14 olle 958     var msg = err;
2933 14 Nov 14 olle 959     if (err.toString)
2933 14 Nov 14 olle 960     {
2933 14 Nov 14 olle 961       App.debug(err.toString());
2933 14 Nov 14 olle 962       msg = Strings.encodeTags(err.toString());
2933 14 Nov 14 olle 963       if (err.stack && !messages)
2933 14 Nov 14 olle 964       {
2933 14 Nov 14 olle 965         App.debug(err.stack);
2933 14 Nov 14 olle 966         msg += '<br><pre>'+Strings.encodeTags(err.stack)+'</pre>';
2933 14 Nov 14 olle 967       }
2933 14 Nov 14 olle 968     }
2933 14 Nov 14 olle 969     else
2933 14 Nov 14 olle 970     {
2933 14 Nov 14 olle 971       App.debug(msg);
2933 14 Nov 14 olle 972     }
2933 14 Nov 14 olle 973     
2933 14 Nov 14 olle 974     if (messages) 
2933 14 Nov 14 olle 975     {
2933 14 Nov 14 olle 976       msg = '<div class="messagecontainer error">'+msg+'</div>'+internal.generateMessageList(messages).html;
2933 14 Nov 14 olle 977       wizard.setWizardStatus('success', msg);
2933 14 Nov 14 olle 978     }
2933 14 Nov 14 olle 979     else
2933 14 Nov 14 olle 980     {
2933 14 Nov 14 olle 981       wizard.setWizardStatus('messagecontainer error', msg || 'Unexpected failure!');
2933 14 Nov 14 olle 982     }
2933 14 Nov 14 olle 983     
2933 14 Nov 14 olle 984     Doc.addClass('wizard', 'disabled');
2933 14 Nov 14 olle 985     internal.disableAllFormElements('wizard', true);
2933 14 Nov 14 olle 986     Doc.show('gorestart');
2933 14 Nov 14 olle 987   }
2933 14 Nov 14 olle 988
2933 14 Nov 14 olle 989   
2933 14 Nov 14 olle 990   /**
2933 14 Nov 14 olle 991     Display a 'loading' global wizard-status message.
2933 14 Nov 14 olle 992   */
2933 14 Nov 14 olle 993   wizard.showLoadingAnimation = function(msg)
2933 14 Nov 14 olle 994   {
2933 14 Nov 14 olle 995     wizard.setWizardStatus('loading', msg  || 'Working, please wait...');
2933 14 Nov 14 olle 996   }
2933 14 Nov 14 olle 997
2933 14 Nov 14 olle 998   wizard.showStatusMessage = function(msg)
2933 14 Nov 14 olle 999   {
2933 14 Nov 14 olle 1000     App.debug(msg);
2933 14 Nov 14 olle 1001     wizard.setWizardStatus('messagecontainer note', msg);
2933 14 Nov 14 olle 1002   }
2933 14 Nov 14 olle 1003   
2933 14 Nov 14 olle 1004   wizard.showGoNextConfirmation = function(verify, msg)
2933 14 Nov 14 olle 1005   {
2933 14 Nov 14 olle 1006     var check = '';
2933 14 Nov 14 olle 1007     if (verify)
2933 14 Nov 14 olle 1008     {
2933 14 Nov 14 olle 1009       check = '<input type="checkbox" name="verifyGoNext" id="verifyGoNext">';
2933 14 Nov 14 olle 1010       Doc.addClass('gonext', 'disabled');
2933 14 Nov 14 olle 1011       Doc.addClass('goregister', 'disabled');
2933 14 Nov 14 olle 1012     }
2933 14 Nov 14 olle 1013     
2933 14 Nov 14 olle 1014     var gonext = Doc.element('gonext-message');
2933 14 Nov 14 olle 1015     gonext.innerHTML = check + msg;
2933 14 Nov 14 olle 1016     Doc.show(gonext);
2933 14 Nov 14 olle 1017     
2933 14 Nov 14 olle 1018     if (verify)
2933 14 Nov 14 olle 1019     {
2933 14 Nov 14 olle 1020       Events.addEventHandler('verifyGoNext', 'click', internal.verifyInternalOnClick);
2933 14 Nov 14 olle 1021     }
2933 14 Nov 14 olle 1022   }
2933 14 Nov 14 olle 1023   
2933 14 Nov 14 olle 1024   wizard.hideGoNextConfirmation = function()
2933 14 Nov 14 olle 1025   {
2933 14 Nov 14 olle 1026     var gonext = Doc.element('gonext-message');
2933 14 Nov 14 olle 1027     gonext.innerHTML = '';
2933 14 Nov 14 olle 1028     Doc.hide(gonext);
2933 14 Nov 14 olle 1029     Doc.removeClass('gonext', 'disabled');
2933 14 Nov 14 olle 1030     Doc.removeClass('goregister', 'disabled');
2933 14 Nov 14 olle 1031   }
2933 14 Nov 14 olle 1032   
2933 14 Nov 14 olle 1033   internal.verifyInternalOnClick = function(event)
2933 14 Nov 14 olle 1034   {
2933 14 Nov 14 olle 1035     var frm = document.forms['meludi'];
2933 14 Nov 14 olle 1036     var checked = event.currentTarget.checked;
2933 14 Nov 14 olle 1037     Doc.addOrRemoveClass('goregister', 'disabled', !checked);
2933 14 Nov 14 olle 1038     Doc.addOrRemoveClass('gonext', 'disabled', !checked);
2933 14 Nov 14 olle 1039   }
2933 14 Nov 14 olle 1040   
2933 14 Nov 14 olle 1041   /**
2933 14 Nov 14 olle 1042     Show final registration messages in a list.
2933 14 Nov 14 olle 1043   */
2933 14 Nov 14 olle 1044   wizard.showFinalMessage = function(messages)
2933 14 Nov 14 olle 1045   {
2933 14 Nov 14 olle 1046     var msg = internal.generateMessageList(messages);
2933 14 Nov 14 olle 1047     wizard.setWizardStatus('success', msg.html);
2933 14 Nov 14 olle 1048     return { 'errors': msg.errors, 'warnings': msg.warnings };
2933 14 Nov 14 olle 1049   }
2933 14 Nov 14 olle 1050   
2933 14 Nov 14 olle 1051   
2933 14 Nov 14 olle 1052   /*
2933 14 Nov 14 olle 1053     Call this method once to start a repeating timer that will submit
2933 14 Nov 14 olle 1054     an Ajax request at regular intervals in order to keep the current login
2933 14 Nov 14 olle 1055     session alive. Once started there is no way to stop the timer except
2933 14 Nov 14 olle 1056     navigating away from the page.
2933 14 Nov 14 olle 1057     @param meludiRoot Optional relative path to the root of the MeLuDi installation (for pages in a subdirectory)
2933 14 Nov 14 olle 1058   */
2933 14 Nov 14 olle 1059   wizard.keepSessionAlive = function()
2933 14 Nov 14 olle 1060   {
2933 14 Nov 14 olle 1061     if (debug)
2933 14 Nov 14 olle 1062     {
2933 14 Nov 14 olle 1063       // Create a 'simulate timeout' checkbox
2933 14 Nov 14 olle 1064       var div = document.createElement('div');
2933 14 Nov 14 olle 1065       div.id = 'simulateTimeoutDiv';
2933 14 Nov 14 olle 1066       div.style.textAlign = 'center';
2933 14 Nov 14 olle 1067       div.innerHTML = '<label><input type="checkbox" id="simulateTimeout">Simulate session timeout</label>';
2933 14 Nov 14 olle 1068       var frm = document.forms['meludi'];
2933 14 Nov 14 olle 1069       frm.appendChild(div);
2933 14 Nov 14 olle 1070     }
2933 14 Nov 14 olle 1071     
2933 14 Nov 14 olle 1072     internal.scheduleKeepAlive();
2933 14 Nov 14 olle 1073   }
2933 14 Nov 14 olle 1074   
2933 14 Nov 14 olle 1075   // Schedule a keep-alive request
2933 14 Nov 14 olle 1076   internal.scheduleKeepAlive = function()
2933 14 Nov 14 olle 1077   {
2933 14 Nov 14 olle 1078     setTimeout(internal.sendKeepAlive, debug ? 5000 : 30000);
2933 14 Nov 14 olle 1079   }
2933 14 Nov 14 olle 1080
2933 14 Nov 14 olle 1081   // Send a keep-alive request
2933 14 Nov 14 olle 1082   internal.sendKeepAlive = function()
2933 14 Nov 14 olle 1083   {
2933 14 Nov 14 olle 1084     if (hasSentRegistration || hasFatalError) 
2933 14 Nov 14 olle 1085     {
2933 14 Nov 14 olle 1086       if (debug) Doc.hide('simulateTimeoutDiv');
2933 14 Nov 14 olle 1087       return;
2933 14 Nov 14 olle 1088     }
2933 14 Nov 14 olle 1089     var simulateTimeout = false;
2933 14 Nov 14 olle 1090     if (debug) 
2933 14 Nov 14 olle 1091     {
2933 14 Nov 14 olle 1092       var msg = 'Checking if session '+App.getSessionId() + ' is alive';
2933 14 Nov 14 olle 1093       var timeoutDiv = Doc.element('simulateTimeout');
2933 14 Nov 14 olle 1094       if (timeoutDiv && timeoutDiv.checked)
2933 14 Nov 14 olle 1095       {
2933 14 Nov 14 olle 1096         simulateTimeout = true;
2933 14 Nov 14 olle 1097         timeoutDiv.checked = false;
2933 14 Nov 14 olle 1098         msg += ' (simulating a session timeout)'
2933 14 Nov 14 olle 1099       }
2933 14 Nov 14 olle 1100       App.debug(msg);
2933 14 Nov 14 olle 1101     }
2933 14 Nov 14 olle 1102     
2933 14 Nov 14 olle 1103     var url = '../Session.servlet?ID='+App.getSessionId();
2933 14 Nov 14 olle 1104     url += '&cmd=CheckSession';
2933 14 Nov 14 olle 1105     if (simulateTimeout) url += '&simulateTimeout=1';
2933 14 Nov 14 olle 1106     
2933 14 Nov 14 olle 1107     wizard.asyncJsonRequest(url, internal.onKeepAliveResponse);
2933 14 Nov 14 olle 1108   }
2933 14 Nov 14 olle 1109
2933 14 Nov 14 olle 1110   
2933 14 Nov 14 olle 1111   internal.onKeepAliveResponse = function(response)
2933 14 Nov 14 olle 1112   {
2933 14 Nov 14 olle 1113     if (!response.session)
2933 14 Nov 14 olle 1114     {
2933 14 Nov 14 olle 1115       // Hide navigation buttons
2933 14 Nov 14 olle 1116       Doc.hide('navigation');
2933 14 Nov 14 olle 1117       Doc.addClass('wizard', 'disabled');
2933 14 Nov 14 olle 1118       
2933 14 Nov 14 olle 1119       // Show message
2933 14 Nov 14 olle 1120       var div = Doc.element('timeoutMessage');
2933 14 Nov 14 olle 1121       if (!div)
2933 14 Nov 14 olle 1122       {
2933 14 Nov 14 olle 1123         div = document.createElement('div');
2933 14 Nov 14 olle 1124         div.id = 'timeoutMessage';
2933 14 Nov 14 olle 1125         div.className = 'messagecontainer error link';
2933 14 Nov 14 olle 1126         div.innerHTML = 'You have been logged out due to inactivity or unstable internet connection. Click HERE to login again!';
2933 14 Nov 14 olle 1127         div.addEventListener('click', internal.openLoginWindow, false);
2933 14 Nov 14 olle 1128         div.addEventListener('logged-in', internal.loggedInAgain, false);
2933 14 Nov 14 olle 1129         var frm = document.forms['meludi'];
2933 14 Nov 14 olle 1130         frm.appendChild(div);
2933 14 Nov 14 olle 1131       }
2933 14 Nov 14 olle 1132       Doc.show(div);
2933 14 Nov 14 olle 1133     }
2933 14 Nov 14 olle 1134     else
2933 14 Nov 14 olle 1135     {
2933 14 Nov 14 olle 1136       internal.scheduleKeepAlive();
2933 14 Nov 14 olle 1137     }
2933 14 Nov 14 olle 1138   }
2933 14 Nov 14 olle 1139
2933 14 Nov 14 olle 1140   // Open popup window for logging in again
2933 14 Nov 14 olle 1141   internal.openLoginWindow = function()
2933 14 Nov 14 olle 1142   {
2933 14 Nov 14 olle 1143     if (debug) App.debug('Need to login again!');
2933 14 Nov 14 olle 1144     var url = '../keep_session_alive.jsp?ID='+App.getSessionId();
2933 14 Nov 14 olle 1145     Dialogs.openPopup(url, 'KeepSessionAlive', 800, 600);
2933 14 Nov 14 olle 1146   }
2933 14 Nov 14 olle 1147
2933 14 Nov 14 olle 1148   // Callback when the user has been successfully logged in
2933 14 Nov 14 olle 1149   internal.loggedInAgain = function()
2933 14 Nov 14 olle 1150   {
2933 14 Nov 14 olle 1151     if (debug) App.debug('Logged in again!');
2933 14 Nov 14 olle 1152     Doc.removeClass('wizard', 'disabled');
2933 14 Nov 14 olle 1153     Doc.hide('timeoutMessage');
2933 14 Nov 14 olle 1154     Doc.show('navigation');
2933 14 Nov 14 olle 1155     internal.scheduleKeepAlive();
2933 14 Nov 14 olle 1156   }
2933 14 Nov 14 olle 1157
2933 14 Nov 14 olle 1158   internal.generateMessageList = function(messages)
2933 14 Nov 14 olle 1159   {
2933 14 Nov 14 olle 1160     var msg = '<ul>';
2933 14 Nov 14 olle 1161     var numWarnings = 0;
2933 14 Nov 14 olle 1162     var numErrors = 0;
2933 14 Nov 14 olle 1163     for (var i = 0; i < messages.length; i++)
2933 14 Nov 14 olle 1164     {
2933 14 Nov 14 olle 1165       var msgLine = messages[i];
2933 14 Nov 14 olle 1166       if (msgLine.indexOf('[Warning]') >= 0)
2933 14 Nov 14 olle 1167       {
2933 14 Nov 14 olle 1168         msg += '<li class="warning">' + Strings.encodeTags(msgLine.replace('[Warning]', ''));
2933 14 Nov 14 olle 1169         numWarnings++;
2933 14 Nov 14 olle 1170       }
2933 14 Nov 14 olle 1171       else if (msgLine.indexOf('[Error]') >= 0)
2933 14 Nov 14 olle 1172       {
2933 14 Nov 14 olle 1173         msg += '<li class="error">' + Strings.encodeTags(msgLine.replace('[Error]', ''));
2933 14 Nov 14 olle 1174         numErrors++;
2933 14 Nov 14 olle 1175       }
2933 14 Nov 14 olle 1176       else
2933 14 Nov 14 olle 1177       {
2933 14 Nov 14 olle 1178         msg += '<li class="ok">' + Strings.encodeTags(msgLine);
2933 14 Nov 14 olle 1179       }
2933 14 Nov 14 olle 1180     }
2933 14 Nov 14 olle 1181     msg += '</ul>';
2933 14 Nov 14 olle 1182     return { 'html': msg, 'errors': numErrors, 'warnings': numWarnings };
2933 14 Nov 14 olle 1183   }
2933 14 Nov 14 olle 1184   
2933 14 Nov 14 olle 1185   /**
2933 14 Nov 14 olle 1186     Hide the current global wizard-status message.
2933 14 Nov 14 olle 1187   */
2933 14 Nov 14 olle 1188   wizard.hideWizardStatus = function()
2933 14 Nov 14 olle 1189   {
2933 14 Nov 14 olle 1190     Doc.hide('wizard-status');
2933 14 Nov 14 olle 1191   }
2933 14 Nov 14 olle 1192     
2933 14 Nov 14 olle 1193   /**
2933 14 Nov 14 olle 1194     Initialize the wizard:
2933 14 Nov 14 olle 1195     
2933 14 Nov 14 olle 1196     * Check that a project is active
2933 14 Nov 14 olle 1197   */
2933 14 Nov 14 olle 1198   internal.initWizard = function()
2933 14 Nov 14 olle 1199   {
2933 14 Nov 14 olle 1200     // Check if project is enabled
2933 14 Nov 14 olle 1201     var wiz = Doc.element('wizard');
2933 14 Nov 14 olle 1202     if (wiz)
2933 14 Nov 14 olle 1203     {
2933 14 Nov 14 olle 1204       if (!App.getActiveProjectId())
2933 14 Nov 14 olle 1205       {
2933 14 Nov 14 olle 1206         wizard.setFatalError('No project has been selected.');
2933 14 Nov 14 olle 1207       }
2933 14 Nov 14 olle 1208       window.addEventListener('beforeunload', internal.confirmLeaveWizard);
2933 14 Nov 14 olle 1209     }
2933 14 Nov 14 olle 1210     
2933 14 Nov 14 olle 1211     var path = document.getElementsByClassName('pathelement');
2933 14 Nov 14 olle 1212     if (path && path.length)
2933 14 Nov 14 olle 1213     {
2933 14 Nov 14 olle 1214       // Set program title
4159 17 Oct 16 olle 1215       var simpleElement = false;
2933 14 Nov 14 olle 1216       if (path[0].firstChild)
2933 14 Nov 14 olle 1217       {
2933 14 Nov 14 olle 1218         // Set program title for link (anchor tag)
2933 14 Nov 14 olle 1219         path[0].firstChild.innerHTML = Meludi.TITLE;
2933 14 Nov 14 olle 1220       }
2933 14 Nov 14 olle 1221       else
2933 14 Nov 14 olle 1222       {
2933 14 Nov 14 olle 1223         // Set program title for simple element (used for index.jsp page title)
2933 14 Nov 14 olle 1224         path[0].innerHTML += '<span id="meludi-title">'+Meludi.TITLE+'</span>';
4159 17 Oct 16 olle 1225         simpleElement = true;
2933 14 Nov 14 olle 1226       }
4159 17 Oct 16 olle 1227       // Set project name
4159 17 Oct 16 olle 1228       var projectName = internal.getActiveProjectName(simpleElement);
4159 17 Oct 16 olle 1229       path[path.length-1].innerHTML += '<span id="meludi-project">'+projectName+'</span>';
2933 14 Nov 14 olle 1230       // Set program title plus version
2933 14 Nov 14 olle 1231       path[path.length-1].innerHTML += '<span id="meludi-version">['+Meludi.TITLE+' '+Meludi.VERSION+']</span>';
2933 14 Nov 14 olle 1232     }
2933 14 Nov 14 olle 1233
2933 14 Nov 14 olle 1234     var programTitle = document.getElementById('programtitle');
2933 14 Nov 14 olle 1235     if (programTitle)
2933 14 Nov 14 olle 1236     {
2933 14 Nov 14 olle 1237       programTitle.innerHTML = Meludi.TITLE;
2933 14 Nov 14 olle 1238     }
2933 14 Nov 14 olle 1239   }
4159 17 Oct 16 olle 1240
4159 17 Oct 16 olle 1241   /**
4159 17 Oct 16 olle 1242     Get name of active project.
4159 17 Oct 16 olle 1243   */
4159 17 Oct 16 olle 1244   internal.getActiveProjectName = function(simpleElement)
4159 17 Oct 16 olle 1245   {
4159 17 Oct 16 olle 1246     // Url for link (anchor tag)
4159 17 Oct 16 olle 1247     var url = '../Session.servlet?ID='+App.getSessionId();
4159 17 Oct 16 olle 1248     if (simpleElement)
4159 17 Oct 16 olle 1249     {
4159 17 Oct 16 olle 1250       // Url for simple element (used for index.jsp page title)
4159 17 Oct 16 olle 1251       url = './Session.servlet?ID='+App.getSessionId();
4159 17 Oct 16 olle 1252     }
4159 17 Oct 16 olle 1253     url += '&cmd=GetActiveProjectName';
4159 17 Oct 16 olle 1254     var response = Wizard.syncJsonRequest(url);
4159 17 Oct 16 olle 1255     return response ? response.projectname : null;
4159 17 Oct 16 olle 1256   }
2933 14 Nov 14 olle 1257   
2933 14 Nov 14 olle 1258   internal.confirmLeaveWizard = function(event)
2933 14 Nov 14 olle 1259   {
2933 14 Nov 14 olle 1260     if (hasFatalError) return;
2933 14 Nov 14 olle 1261     if (!forceConfirm)
2933 14 Nov 14 olle 1262     {
2933 14 Nov 14 olle 1263       if (currentStep == 1 && noConfirmOnFirstStep) return;
2933 14 Nov 14 olle 1264       if (hasSentRegistration && numLiveAsyncRequests == 0) return;
2933 14 Nov 14 olle 1265     }
2933 14 Nov 14 olle 1266     forceConfirm = false;
2933 14 Nov 14 olle 1267     event.preventDefault();
2933 14 Nov 14 olle 1268   }
2933 14 Nov 14 olle 1269   
2933 14 Nov 14 olle 1270   // Initialize some event handlers
2933 14 Nov 14 olle 1271   internal.initElements = function(element, autoInit)
2933 14 Nov 14 olle 1272   {
2933 14 Nov 14 olle 1273     if (autoInit == 'focus-on-enter')
2933 14 Nov 14 olle 1274     {
2933 14 Nov 14 olle 1275       Events.addEventHandler(element, 'keypress', wizard.focusOnEnter);
2933 14 Nov 14 olle 1276     }
2933 14 Nov 14 olle 1277   }
2933 14 Nov 14 olle 1278   
2933 14 Nov 14 olle 1279   /**
2933 14 Nov 14 olle 1280     Display a global wizard-status message. This may for example be
2933 14 Nov 14 olle 1281     an error message, a work-in-progress indicator, etc.
2933 14 Nov 14 olle 1282   */
2933 14 Nov 14 olle 1283   wizard.setWizardStatus = function(className, msg)
2933 14 Nov 14 olle 1284   {
2933 14 Nov 14 olle 1285     var status = Doc.element('wizard-status');
2933 14 Nov 14 olle 1286     status.className = className;
2933 14 Nov 14 olle 1287     status.innerHTML = msg;
2933 14 Nov 14 olle 1288     Doc.show(status);
2933 14 Nov 14 olle 1289   }
2933 14 Nov 14 olle 1290
2933 14 Nov 14 olle 1291   // Disable all form elements inside the given container
2933 14 Nov 14 olle 1292   internal.disableAllFormElements = function(container, hideButtons)
2933 14 Nov 14 olle 1293   {
2933 14 Nov 14 olle 1294     container = Doc.element(container);
2933 14 Nov 14 olle 1295     var input = container.getElementsByTagName('input');
2933 14 Nov 14 olle 1296     for (var i = 0; i < input.length; i++)
2933 14 Nov 14 olle 1297     {
2933 14 Nov 14 olle 1298       input[i].disabled = true;
2933 14 Nov 14 olle 1299     }
2933 14 Nov 14 olle 1300     var select = container.getElementsByTagName('select');
2933 14 Nov 14 olle 1301     for (var i = 0; i < select.length; i++)
2933 14 Nov 14 olle 1302     {
2933 14 Nov 14 olle 1303       select[i].disabled = true;
2933 14 Nov 14 olle 1304     }
2933 14 Nov 14 olle 1305     var text = container.getElementsByTagName('textarea');
2933 14 Nov 14 olle 1306     for (var i = 0; i < text.length; i++)
2933 14 Nov 14 olle 1307     {
2933 14 Nov 14 olle 1308       text[i].disabled = true;
2933 14 Nov 14 olle 1309     }
2933 14 Nov 14 olle 1310     if (hideButtons)
2933 14 Nov 14 olle 1311     {
2933 14 Nov 14 olle 1312       internal.hideButtons(container);
2933 14 Nov 14 olle 1313     }
2933 14 Nov 14 olle 1314   }
2933 14 Nov 14 olle 1315
2933 14 Nov 14 olle 1316   // Hide all 'basicbuttons':s in the given container
2933 14 Nov 14 olle 1317   internal.hideButtons = function(container)
2933 14 Nov 14 olle 1318   {
2933 14 Nov 14 olle 1319     container = Doc.element(container);
2933 14 Nov 14 olle 1320     var buttons = container.getElementsByClassName('basicbutton');
2933 14 Nov 14 olle 1321     for (var i = 0; i < buttons.length; i++)
2933 14 Nov 14 olle 1322     {
2933 14 Nov 14 olle 1323       Doc.hide(buttons[i]);
2933 14 Nov 14 olle 1324     }
2933 14 Nov 14 olle 1325   }
2933 14 Nov 14 olle 1326
2933 14 Nov 14 olle 1327   Doc.addFinalizer(internal.initWizard);
2933 14 Nov 14 olle 1328   Doc.addElementInitializer(internal.initElements);
2933 14 Nov 14 olle 1329   return wizard;
2933 14 Nov 14 olle 1330 }();
2933 14 Nov 14 olle 1331