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

Code
Comments
Other
Rev Date Author Line
2599 25 Aug 14 nicklas 1
2599 25 Aug 14 nicklas 2 var Reggie = function()
2599 25 Aug 14 nicklas 3 {
2599 25 Aug 14 nicklas 4   var reggie = {};
2599 25 Aug 14 nicklas 5   var internal = {};
2801 13 Oct 14 nicklas 6   
7446 20 Nov 23 nicklas 7   reggie.VERSION = '4.51-dev';
2599 25 Aug 14 nicklas 8
2662 12 Sep 14 nicklas 9   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'];
2662 12 Sep 14 nicklas 10
2621 01 Sep 14 nicklas 11   var GENERIC_STRATAGENE_NAME = 'Stratagene.r';
2621 01 Sep 14 nicklas 12   
2840 20 Oct 14 nicklas 13   var CASENAME_WITH_SUFFIX = /^\d{7}(C|D)?$/;
2599 25 Aug 14 nicklas 14   var CASENAME = /^\d{7}$/;
2599 25 Aug 14 nicklas 15   
2602 27 Aug 14 nicklas 16   var RCCID_WITH_SUFFIX = /^\d{10}(B|C|D){1}$/;
6801 11 Aug 22 nicklas 17   var RCCID_NEW_PATTERN = /^\d{4}-\d{8}$/;
2599 25 Aug 14 nicklas 18   
2698 25 Sep 14 nicklas 19   var currentDirectory;
2698 25 Sep 14 nicklas 20   
2599 25 Aug 14 nicklas 21   /*
2840 20 Oct 14 nicklas 22     Verify that the 'case' name is a 7-digit value + optional C/D suffix
2599 25 Aug 14 nicklas 23   */
6277 03 Jun 21 nicklas 24   reggie.isValidCaseName = function(caseName, allowSuffix)
2599 25 Aug 14 nicklas 25   {
2599 25 Aug 14 nicklas 26     return caseName.match(allowSuffix ? CASENAME_WITH_SUFFIX : CASENAME);
2599 25 Aug 14 nicklas 27   }
2599 25 Aug 14 nicklas 28   
6277 03 Jun 21 nicklas 29   /**
6277 03 Jun 21 nicklas 30     Alternate check of 'case' name that supports checking prefixes
6277 03 Jun 21 nicklas 31     and suffixes. The prefixes and suffixes are inserted into
6277 03 Jun 21 nicklas 32     the regexp as they are so they should typically be a pipe-separated
6277 03 Jun 21 nicklas 33     list of values inside parenthesis: (C|D)?
6277 03 Jun 21 nicklas 34   */
6277 03 Jun 21 nicklas 35   reggie.checkValidCaseName = function(caseName, prefix, suffix)
6277 03 Jun 21 nicklas 36   {
6277 03 Jun 21 nicklas 37     var rexp = new RegExp('^'+(prefix||'')+'\\d{7}'+(suffix||'')+'$');
6277 03 Jun 21 nicklas 38     return rexp.test(caseName);
6277 03 Jun 21 nicklas 39   }  
6277 03 Jun 21 nicklas 40   
2602 27 Aug 14 nicklas 41   /*
6801 11 Aug 22 nicklas 42     Verify that the RCCID number matches either the
6801 11 Aug 22 nicklas 43     - new pattern: NNNN-NNNNNNNN where N is a digit
6801 11 Aug 22 nicklas 44     - old pattern: 10-digit value + 'B', 'C', or 'D' suffix
2602 27 Aug 14 nicklas 45    */
2602 27 Aug 14 nicklas 46   reggie.isValidRccidNumber = function(rccidNumber)
2602 27 Aug 14 nicklas 47   {
6801 11 Aug 22 nicklas 48     return rccidNumber.match(RCCID_NEW_PATTERN) || rccidNumber.match(RCCID_WITH_SUFFIX);
2602 27 Aug 14 nicklas 49   }
2602 27 Aug 14 nicklas 50
2599 25 Aug 14 nicklas 51   /**
2602 27 Aug 14 nicklas 52     Check the control digit of the given personal number.
2602 27 Aug 14 nicklas 53     @pnr The 10-digit personal number in the form YYMMDDXXXX
2602 27 Aug 14 nicklas 54   */
2602 27 Aug 14 nicklas 55   reggie.personalNumberControlDigitCheck = function(pnr)
2602 27 Aug 14 nicklas 56   {
2602 27 Aug 14 nicklas 57     var sum = 0;
2602 27 Aug 14 nicklas 58     var factor = 2;
2602 27 Aug 14 nicklas 59     for (var i = 0; i < 9; i++)
2602 27 Aug 14 nicklas 60     {
2602 27 Aug 14 nicklas 61       var digit = parseInt(pnr.substr(i, 1), 10);
2602 27 Aug 14 nicklas 62       var tmp = factor * digit;
2602 27 Aug 14 nicklas 63       sum += tmp >= 10 ? tmp - 9: tmp;
2602 27 Aug 14 nicklas 64       factor = factor == 2 ? 1 : 2;
2602 27 Aug 14 nicklas 65     }
2602 27 Aug 14 nicklas 66     
2602 27 Aug 14 nicklas 67     var control = 10 - (sum % 10);
2602 27 Aug 14 nicklas 68     if (control == 10) control = 0;
2602 27 Aug 14 nicklas 69     return (control == parseInt(pnr.substr(9, 1), 10))
2602 27 Aug 14 nicklas 70   }
2602 27 Aug 14 nicklas 71   
2602 27 Aug 14 nicklas 72   /**
2599 25 Aug 14 nicklas 73     Autofill a date-string.
2599 25 Aug 14 nicklas 74     The supplemented date-string will have the format yyyyMMdd when it's returned.
2599 25 Aug 14 nicklas 75     If the short-date in format MMdd is larger the current date, the year before will be used.
2599 25 Aug 14 nicklas 76     
2599 25 Aug 14 nicklas 77     @param shortDate Date in format 'MMdd' or in 'yyMMdd'
2599 25 Aug 14 nicklas 78     @param allowSixDigitDates Boolean Flag indicating if 6-digit dates should be auto-filled (default = false).
2599 25 Aug 14 nicklas 79   */
2599 25 Aug 14 nicklas 80   reggie.autoFillDate = function(shortDate, allowSixDigitDates)
2599 25 Aug 14 nicklas 81   {
2599 25 Aug 14 nicklas 82     shortDate = shortDate.replace("-","");
2599 25 Aug 14 nicklas 83     var fullDate = shortDate;
2599 25 Aug 14 nicklas 84   
2599 25 Aug 14 nicklas 85     var currentDate = new Date();
2599 25 Aug 14 nicklas 86     var currentYear = currentDate.getFullYear();
2599 25 Aug 14 nicklas 87     var currentMonth = currentDate.getMonth()+1;
2599 25 Aug 14 nicklas 88     
2599 25 Aug 14 nicklas 89     if (shortDate.length == 4 && Dates.isDate(shortDate, 'MMdd'))
2599 25 Aug 14 nicklas 90     {
2599 25 Aug 14 nicklas 91       var month = parseInt(shortDate.substring(0, 2), 10);
2599 25 Aug 14 nicklas 92       var day = parseInt(shortDate.substring(2), 10);
2599 25 Aug 14 nicklas 93       if ((month > currentMonth) || (month == currentMonth && day > currentDate.getDate())) 
2599 25 Aug 14 nicklas 94       {
2599 25 Aug 14 nicklas 95         currentYear--;
2599 25 Aug 14 nicklas 96       }
2599 25 Aug 14 nicklas 97       fullDate = currentYear+shortDate;
2599 25 Aug 14 nicklas 98     }
2599 25 Aug 14 nicklas 99     else if (allowSixDigitDates && shortDate.length == 6 && Dates.isDate(shortDate, 'yyMMdd'))
2599 25 Aug 14 nicklas 100     {
2599 25 Aug 14 nicklas 101       var year = parseInt(shortDate.substring(0,2), 10);    
2599 25 Aug 14 nicklas 102       fullDate = ((2000+year) > currentYear ? "19" : "20") + fullDate;
2599 25 Aug 14 nicklas 103     }  
2599 25 Aug 14 nicklas 104     return fullDate;  
2599 25 Aug 14 nicklas 105   }
2599 25 Aug 14 nicklas 106   
2602 27 Aug 14 nicklas 107   reggie.autoFillTime = function(shortTime)
2602 27 Aug 14 nicklas 108   {
2602 27 Aug 14 nicklas 109     var fullTimeString = shortTime;
2602 27 Aug 14 nicklas 110     if (shortTime.length==3)
2602 27 Aug 14 nicklas 111     {
2602 27 Aug 14 nicklas 112       fullTimeString = "0"+shortTime;
2602 27 Aug 14 nicklas 113     }
2602 27 Aug 14 nicklas 114     return fullTimeString;
2602 27 Aug 14 nicklas 115   }
2602 27 Aug 14 nicklas 116
2599 25 Aug 14 nicklas 117   /**
2602 27 Aug 14 nicklas 118     Convert a 2-digit year to a 4-digit year. Assuming
2602 27 Aug 14 nicklas 119     that the short year is between 1 and 100 years old. 
2602 27 Aug 14 nicklas 120   */
2602 27 Aug 14 nicklas 121   reggie.fullYear = function(shortYear)
2602 27 Aug 14 nicklas 122   {
2602 27 Aug 14 nicklas 123     var thisYear = new Date().getFullYear();
2602 27 Aug 14 nicklas 124     var fullYear = shortYear + 100*Math.floor((thisYear - shortYear - 1) / 100);
2602 27 Aug 14 nicklas 125     return fullYear;
2602 27 Aug 14 nicklas 126   }
2610 28 Aug 14 nicklas 127   
6716 29 Apr 22 nicklas 128   reggie.formatCount = function(count, nullValue)
3049 17 Dec 14 nicklas 129   {
5802 19 Dec 19 nicklas 130     var unit = '';
7392 03 Nov 23 nicklas 131     if (count > 1_000_000_000)
3049 17 Dec 14 nicklas 132     {
7392 03 Nov 23 nicklas 133       count = count / 1_000_000_000;
7392 03 Nov 23 nicklas 134       unit = '&thinsp;G';
3049 17 Dec 14 nicklas 135     }
7392 03 Nov 23 nicklas 136     else if (count > 1_000_000)
7392 03 Nov 23 nicklas 137     {
7392 03 Nov 23 nicklas 138       count = count / 1_000_000;
7392 03 Nov 23 nicklas 139       unit = '&thinsp;M';
7392 03 Nov 23 nicklas 140     }
3049 17 Dec 14 nicklas 141     else if (count > 1000)
3049 17 Dec 14 nicklas 142     {
5802 19 Dec 19 nicklas 143       count = count / 1000;
7392 03 Nov 23 nicklas 144       unit = '&thinsp;k';
3049 17 Dec 14 nicklas 145     }
5802 19 Dec 19 nicklas 146     else
5802 19 Dec 19 nicklas 147     {
6716 29 Apr 22 nicklas 148       return count == null ? nullValue || '' : count;
5802 19 Dec 19 nicklas 149     }
7392 03 Nov 23 nicklas 150     var numDecimals = count < 10 ? 2 : (count < 100 ? 1 : 0);
5802 19 Dec 19 nicklas 151     return count.toFixed(numDecimals)+unit;
3049 17 Dec 14 nicklas 152   }
3049 17 Dec 14 nicklas 153   
4817 21 May 18 nicklas 154   reggie.formatNumber = function(number, unit, baseDecimals, maxDecimals)
2610 28 Aug 14 nicklas 155   {
2610 28 Aug 14 nicklas 156     if (number == null) return '';
2610 28 Aug 14 nicklas 157     
2610 28 Aug 14 nicklas 158     var numDecimals;
7341 11 Sep 23 nicklas 159     if (baseDecimals == undefined || baseDecimals == null) baseDecimals = 2;
3827 05 Apr 16 nicklas 160     var tmp = Math.abs(number);
4164 20 Oct 16 nicklas 161     if (tmp < 1)
2610 28 Aug 14 nicklas 162     {
4164 20 Oct 16 nicklas 163       numDecimals = baseDecimals+1;
4164 20 Oct 16 nicklas 164     }
4164 20 Oct 16 nicklas 165     else if (tmp < 10)
4164 20 Oct 16 nicklas 166     {
2610 28 Aug 14 nicklas 167       numDecimals = baseDecimals;
2610 28 Aug 14 nicklas 168     }
3827 05 Apr 16 nicklas 169     else if (tmp < 100)
2610 28 Aug 14 nicklas 170     {
2610 28 Aug 14 nicklas 171       numDecimals = baseDecimals-1;
2610 28 Aug 14 nicklas 172     }
2610 28 Aug 14 nicklas 173     else
2610 28 Aug 14 nicklas 174     {
2610 28 Aug 14 nicklas 175       numDecimals = baseDecimals-2;
2610 28 Aug 14 nicklas 176     }
3149 26 Feb 15 nicklas 177     if (numDecimals < 0) numDecimals = 0;
4817 21 May 18 nicklas 178     if (maxDecimals && numDecimals > maxDecimals) numDecimals = maxDecimals;
2602 27 Aug 14 nicklas 179
2610 28 Aug 14 nicklas 180     var result = number.toFixed(numDecimals);
6879 22 Nov 22 nicklas 181     if (unit) 
6879 22 Nov 22 nicklas 182     {
6879 22 Nov 22 nicklas 183       // Special case for 100% without decimals
6879 22 Nov 22 nicklas 184       if (unit=='%' && result.indexOf('100')==0) result = '100';
6879 22 Nov 22 nicklas 185       result += unit;  
6879 22 Nov 22 nicklas 186     }
2610 28 Aug 14 nicklas 187     return result;
2610 28 Aug 14 nicklas 188   }
2610 28 Aug 14 nicklas 189
2636 04 Sep 14 nicklas 190   /**
2636 04 Sep 14 nicklas 191     Reformat a date string in YYYYMMDD or YYYYMMDD HHMM format
2636 04 Sep 14 nicklas 192     to YYYY-MM-DD HH:MM
2636 04 Sep 14 nicklas 193   */
2647 10 Sep 14 nicklas 194   reggie.reformatDate = function(value, defaultValue)
2636 04 Sep 14 nicklas 195   {
2647 10 Sep 14 nicklas 196     if (!value) return defaultValue || '';
2636 04 Sep 14 nicklas 197     if (value.length == 8)
2636 04 Sep 14 nicklas 198     {
2636 04 Sep 14 nicklas 199       // YYYYMMDD
2636 04 Sep 14 nicklas 200       value = value.substr(0, 4) + '-' + value.substr(4, 2) + '-' + value.substr(6, 2);
2636 04 Sep 14 nicklas 201     }
2636 04 Sep 14 nicklas 202     else if (value.length == 13)
2636 04 Sep 14 nicklas 203     {
2636 04 Sep 14 nicklas 204       // YYYYMMDD HHMM
2636 04 Sep 14 nicklas 205       value = value.substr(0, 4) + '-' + value.substr(4, 2) + '-' + value.substr(6, 2) + ' ' + value.substr(9, 2) + ':' + value.substr(11, 2);
2636 04 Sep 14 nicklas 206     }
2636 04 Sep 14 nicklas 207     return value;
2636 04 Sep 14 nicklas 208   }
2610 28 Aug 14 nicklas 209
5481 11 Jun 19 nicklas 210   /**
5481 11 Jun 19 nicklas 211     Insert soft line breaks in the name at appropriate points
5481 11 Jun 19 nicklas 212     after '_' and '.'
5481 11 Jun 19 nicklas 213   */
5481 11 Jun 19 nicklas 214   reggie.softLineBreaks = function(value)
5481 11 Jun 19 nicklas 215   {
5481 11 Jun 19 nicklas 216     if (value)
5481 11 Jun 19 nicklas 217     {
5481 11 Jun 19 nicklas 218       value = value.replace(/([_.])+/g, '$1&#8203;');
5481 11 Jun 19 nicklas 219     }
5481 11 Jun 19 nicklas 220     return value;
5481 11 Jun 19 nicklas 221   }
2602 27 Aug 14 nicklas 222   
2602 27 Aug 14 nicklas 223   /**
2599 25 Aug 14 nicklas 224     Get subtype information.
2599 25 Aug 14 nicklas 225   */
2599 25 Aug 14 nicklas 226   reggie.getSubtypeInfo = function(subtype)
2599 25 Aug 14 nicklas 227   {
2599 25 Aug 14 nicklas 228     var url = '../Subtype.servlet?ID='+App.getSessionId();
2599 25 Aug 14 nicklas 229     url += '&cmd=GetSubtypeInfo&name='+subtype;
2599 25 Aug 14 nicklas 230     var response = Wizard.syncJsonRequest(url);
2599 25 Aug 14 nicklas 231     return response ? response.subtype : null;
2599 25 Aug 14 nicklas 232   }
2599 25 Aug 14 nicklas 233   
4668 01 Feb 18 nicklas 234   /**
5435 17 May 19 nicklas 235     Get annotation type information.
5435 17 May 19 nicklas 236   */
5435 17 May 19 nicklas 237   reggie.getAnnotationTypeInfo = function(annotationType)
5435 17 May 19 nicklas 238   {
5435 17 May 19 nicklas 239     var url = '../Subtype.servlet?ID='+App.getSessionId();
5435 17 May 19 nicklas 240     url += '&cmd=GetAnnotationTypeInfo&name='+annotationType;
5435 17 May 19 nicklas 241     var response = Wizard.syncJsonRequest(url);
5435 17 May 19 nicklas 242     return response ? response.annotationType : null;
5435 17 May 19 nicklas 243   }
5435 17 May 19 nicklas 244   
5435 17 May 19 nicklas 245   /**
4668 01 Feb 18 nicklas 246     Get data file type information.
4668 01 Feb 18 nicklas 247   */
4668 01 Feb 18 nicklas 248   reggie.getDataFileTypeInfo = function(filetype)
4668 01 Feb 18 nicklas 249   {
4668 01 Feb 18 nicklas 250     var url = '../Subtype.servlet?ID='+App.getSessionId();
4668 01 Feb 18 nicklas 251     url += '&cmd=GetDataFileTypeInfo&name='+filetype;
4668 01 Feb 18 nicklas 252     var response = Wizard.syncJsonRequest(url);
4668 01 Feb 18 nicklas 253     return response ? response.fileType : null;
4668 01 Feb 18 nicklas 254   }
4668 01 Feb 18 nicklas 255   
5392 02 May 19 nicklas 256   /**
5392 02 May 19 nicklas 257     Get bioplate type information.
5392 02 May 19 nicklas 258   */
5392 02 May 19 nicklas 259   reggie.getPlateTypeInfo = function(platetype)
5392 02 May 19 nicklas 260   {
5392 02 May 19 nicklas 261     var url = '../Subtype.servlet?ID='+App.getSessionId();
5392 02 May 19 nicklas 262     url += '&cmd=GetPlateTypeInfo&name='+platetype;
5392 02 May 19 nicklas 263     var response = Wizard.syncJsonRequest(url);
5392 02 May 19 nicklas 264     return response ? response.plateType : null;
5392 02 May 19 nicklas 265   }
5392 02 May 19 nicklas 266
2666 15 Sep 14 nicklas 267   reggie.setCurrentDirectory = function(path)
2666 15 Sep 14 nicklas 268   {
2698 25 Sep 14 nicklas 269     if (path == currentDirectory) return;
2666 15 Sep 14 nicklas 270     var url = '../Session.servlet?ID='+App.getSessionId();
2666 15 Sep 14 nicklas 271     url += '&cmd=SetCurrentDirectory&path='+encodeURIComponent(path);
2666 15 Sep 14 nicklas 272     Wizard.syncJsonRequest(url);
2698 25 Sep 14 nicklas 273     currentDirectory = path;
2666 15 Sep 14 nicklas 274   }
2666 15 Sep 14 nicklas 275   
2599 25 Aug 14 nicklas 276   /**
2599 25 Aug 14 nicklas 277     Load protocols of the given subtype and add them
2599 25 Aug 14 nicklas 278     to a selection list. This method submits an
2599 25 Aug 14 nicklas 279     async request to the server and then returns
2599 25 Aug 14 nicklas 280     immediately.
2599 25 Aug 14 nicklas 281   */
3833 08 Apr 16 nicklas 282   reggie.loadProtocols = function(subtype, list, annotations, filter)
2599 25 Aug 14 nicklas 283   {
2599 25 Aug 14 nicklas 284     list = Doc.element(list);
2599 25 Aug 14 nicklas 285     list.length=0;
2599 25 Aug 14 nicklas 286     list[0] = new Option('loading...', '');
2599 25 Aug 14 nicklas 287     Doc.addClass(list, 'list-loading');
2599 25 Aug 14 nicklas 288     var url = '../Protocol.servlet?ID='+App.getSessionId();
2599 25 Aug 14 nicklas 289     url += '&cmd=GetProtocols&subtype='+subtype;
3115 06 Feb 15 nicklas 290     if (annotations)
3115 06 Feb 15 nicklas 291     {
3115 06 Feb 15 nicklas 292       url += '&annotations='+annotations;
3115 06 Feb 15 nicklas 293     }
3833 08 Apr 16 nicklas 294     if (filter)
3833 08 Apr 16 nicklas 295     {
3833 08 Apr 16 nicklas 296       url += '&filter='+encodeURIComponent(filter);
3833 08 Apr 16 nicklas 297     }
2599 25 Aug 14 nicklas 298     Wizard.asyncJsonRequest(url, 
2599 25 Aug 14 nicklas 299       function(response)
2599 25 Aug 14 nicklas 300       {
3269 23 Apr 15 nicklas 301         internal.fillList(response.protocols, list, !list.classList.contains('required'));
2599 25 Aug 14 nicklas 302       }
2599 25 Aug 14 nicklas 303     );
2599 25 Aug 14 nicklas 304   }
2599 25 Aug 14 nicklas 305   
2599 25 Aug 14 nicklas 306   /**
2599 25 Aug 14 nicklas 307     Load software of the given subtype and add them
2599 25 Aug 14 nicklas 308     to a selection list. This method submits an
2599 25 Aug 14 nicklas 309     async request to the server and then returns
2599 25 Aug 14 nicklas 310     immediately.
3616 23 Nov 15 nicklas 311     @annotations Comma separated list of static constant names in class Annotationtype
3616 23 Nov 15 nicklas 312     @filter Comma separated list of filter values. Each value is matched against
3616 23 Nov 15 nicklas 313       the annotation type on the same position in the list
2599 25 Aug 14 nicklas 314   */
3616 23 Nov 15 nicklas 315   reggie.loadSoftware = function(subtype, list, annotations, filter)
2599 25 Aug 14 nicklas 316   {
2599 25 Aug 14 nicklas 317     list = Doc.element(list);
2599 25 Aug 14 nicklas 318     list.length=0;
2599 25 Aug 14 nicklas 319     list[0] = new Option('loading...', '');
2599 25 Aug 14 nicklas 320     Doc.addClass(list, 'list-loading');
2599 25 Aug 14 nicklas 321     var url = '../Software.servlet?ID='+App.getSessionId();
2599 25 Aug 14 nicklas 322     url += '&cmd=GetSoftware&subtype='+subtype;
3115 06 Feb 15 nicklas 323     if (annotations)
3115 06 Feb 15 nicklas 324     {
3616 23 Nov 15 nicklas 325       url += '&annotations='+encodeURIComponent(annotations);
3115 06 Feb 15 nicklas 326     }
3616 23 Nov 15 nicklas 327     if (filter)
3616 23 Nov 15 nicklas 328     {
3616 23 Nov 15 nicklas 329       url += '&filter='+encodeURIComponent(filter);
3616 23 Nov 15 nicklas 330     }
2599 25 Aug 14 nicklas 331     Wizard.asyncJsonRequest(url, 
2599 25 Aug 14 nicklas 332       function(response)
2599 25 Aug 14 nicklas 333       {
3269 23 Apr 15 nicklas 334         internal.fillList(response.software, list, !list.classList.contains('required'));
2599 25 Aug 14 nicklas 335       }
2599 25 Aug 14 nicklas 336     );
2599 25 Aug 14 nicklas 337   }
2647 10 Sep 14 nicklas 338   
2647 10 Sep 14 nicklas 339   /**
2647 10 Sep 14 nicklas 340     Load hardware of the given subtype and add them
2647 10 Sep 14 nicklas 341     to a selection list. This method submits an
2647 10 Sep 14 nicklas 342     async request to the server and then returns
2647 10 Sep 14 nicklas 343     immediately.
2647 10 Sep 14 nicklas 344   */
5469 04 Jun 19 nicklas 345   reggie.loadHardware = function(subtype, list, annotations, filter)
2647 10 Sep 14 nicklas 346   {
2647 10 Sep 14 nicklas 347     list = Doc.element(list);
2647 10 Sep 14 nicklas 348     list.length=0;
2647 10 Sep 14 nicklas 349     list[0] = new Option('loading...', '');
2647 10 Sep 14 nicklas 350     Doc.addClass(list, 'list-loading');
2647 10 Sep 14 nicklas 351     var url = '../Hardware.servlet?ID='+App.getSessionId();
2647 10 Sep 14 nicklas 352     url += '&cmd=GetHardware&subtype='+subtype;
2647 10 Sep 14 nicklas 353     if (annotations)
2647 10 Sep 14 nicklas 354     {
2647 10 Sep 14 nicklas 355       url += '&annotations='+annotations;
2647 10 Sep 14 nicklas 356     }
5469 04 Jun 19 nicklas 357     if (filter)
5469 04 Jun 19 nicklas 358     {
5469 04 Jun 19 nicklas 359       url += '&filter='+encodeURIComponent(filter);
5469 04 Jun 19 nicklas 360     }
2647 10 Sep 14 nicklas 361     Wizard.asyncJsonRequest(url, 
2647 10 Sep 14 nicklas 362       function(response)
2647 10 Sep 14 nicklas 363       {
3269 23 Apr 15 nicklas 364         internal.fillList(response.hardware, list, !list.classList.contains('required'));
2647 10 Sep 14 nicklas 365       }
2647 10 Sep 14 nicklas 366     );
2647 10 Sep 14 nicklas 367   }
2599 25 Aug 14 nicklas 368
2599 25 Aug 14 nicklas 369   // Fills a selection list with items
2599 25 Aug 14 nicklas 370   internal.fillList = function(items, list, addNoneOption)
2599 25 Aug 14 nicklas 371   {
2599 25 Aug 14 nicklas 372     Doc.removeClass(list, 'list-loading');
2599 25 Aug 14 nicklas 373     list.length = 0;
2599 25 Aug 14 nicklas 374     for (var i = 0; i < items.length; i++)
2599 25 Aug 14 nicklas 375     {
2599 25 Aug 14 nicklas 376       var item = items[i];
4583 21 Sep 17 nicklas 377       var option = new Option(item.name, item.id, item.isDefault, item.isDefault);
2647 10 Sep 14 nicklas 378       option.item = item;
2647 10 Sep 14 nicklas 379       list[list.length] = option;
2599 25 Aug 14 nicklas 380     }
2599 25 Aug 14 nicklas 381     if (list.length > 0) Wizard.setInputStatus(list.id, 'valid');
2599 25 Aug 14 nicklas 382     if (addNoneOption)
2599 25 Aug 14 nicklas 383     {
2599 25 Aug 14 nicklas 384       list[list.length] = new Option('- none -', '');
2599 25 Aug 14 nicklas 385     }
3115 06 Feb 15 nicklas 386     Events.sendChangeEvent(list);
2599 25 Aug 14 nicklas 387   }
2599 25 Aug 14 nicklas 388   
4990 01 Oct 18 nicklas 389   /**
4990 01 Oct 18 nicklas 390     Get the list option with the specified value.
4990 01 Oct 18 nicklas 391   */
4990 01 Oct 18 nicklas 392   reggie.getListOption = function(list, value)
4990 01 Oct 18 nicklas 393   {
4990 01 Oct 18 nicklas 394     list = Doc.element(list);
4990 01 Oct 18 nicklas 395     for (var i = 0; i < list.length; i++)
4990 01 Oct 18 nicklas 396     {
4990 01 Oct 18 nicklas 397       if (list[i].value == value) return list[i];
4990 01 Oct 18 nicklas 398     }
4990 01 Oct 18 nicklas 399     return null;
4990 01 Oct 18 nicklas 400   }
4990 01 Oct 18 nicklas 401   
2621 01 Sep 14 nicklas 402   reggie.isStratagene = function(sampleName)
2621 01 Sep 14 nicklas 403   {
2621 01 Sep 14 nicklas 404     return sampleName.indexOf(GENERIC_STRATAGENE_NAME) == 0;
2621 01 Sep 14 nicklas 405   }
2599 25 Aug 14 nicklas 406
5552 12 Aug 19 nicklas 407   // If the name doesn't start with 7 digits it is an external sample
2621 01 Sep 14 nicklas 408   reggie.isExternal = function(sampleName)
2621 01 Sep 14 nicklas 409   {
5552 12 Aug 19 nicklas 410     return sampleName.search(/^\d{7}/) == -1;
2621 01 Sep 14 nicklas 411   }
2621 01 Sep 14 nicklas 412
2662 12 Sep 14 nicklas 413   reggie.wellToAlpha = function(wellNo)
2662 12 Sep 14 nicklas 414   {
2662 12 Sep 14 nicklas 415     return wellNo >=0 && wellNo < WELL_ALPHA.length ? WELL_ALPHA[wellNo] : '?';
2662 12 Sep 14 nicklas 416   }
2621 01 Sep 14 nicklas 417   
2774 09 Oct 14 nicklas 418   reggie.alphaToWell = function(wellAlpha)
2774 09 Oct 14 nicklas 419   {
2774 09 Oct 14 nicklas 420     return WELL_ALPHA.indexOf(wellAlpha.toUpperCase());
2774 09 Oct 14 nicklas 421   }
2774 09 Oct 14 nicklas 422   
2608 28 Aug 14 nicklas 423   /**
7372 06 Oct 23 nicklas 424     Utility function for getting the 'submit' options from the given
7372 06 Oct 23 nicklas 425     'config' object. Normally, the config['submit'] value is used, but
7372 06 Oct 23 nicklas 426     if a parameterSet is enabled we also check the config['submit.paramterSet']
7372 06 Oct 23 nicklas 427     value. If the debug option is TRUE we also add the config['submit-debug']
7372 06 Oct 23 nicklas 428     or config['submit-debug.parameterSet'].
7372 06 Oct 23 nicklas 429     See OpenGridServlet.getExtraConfig() for more information about how the 'config'
7372 06 Oct 23 nicklas 430     object is created.
7372 06 Oct 23 nicklas 431   */
7372 06 Oct 23 nicklas 432   reggie.getSubmitOptions = function(config, debug, parameterSet, configKey)
7372 06 Oct 23 nicklas 433   {
7372 06 Oct 23 nicklas 434     if (!configKey) configKey = 'submit';
7372 06 Oct 23 nicklas 435     var opt = [];
7372 06 Oct 23 nicklas 436     if (parameterSet && config[configKey+'.'+parameterSet])
7372 06 Oct 23 nicklas 437     {
7372 06 Oct 23 nicklas 438       opt[opt.length] = '# parameter set: '+parameterSet;
7372 06 Oct 23 nicklas 439       opt[opt.length] = config[configKey+'.'+parameterSet];
7372 06 Oct 23 nicklas 440     }
7372 06 Oct 23 nicklas 441     else
7372 06 Oct 23 nicklas 442     {
7372 06 Oct 23 nicklas 443       opt[opt.length] = config[configKey];
7372 06 Oct 23 nicklas 444     }
7372 06 Oct 23 nicklas 445     if (debug)
7372 06 Oct 23 nicklas 446     {
7372 06 Oct 23 nicklas 447       opt[opt.length] = (parameterSet?config[configKey+'-debug.'+parameterSet]:null) || config[configKey+'-debug'];
7372 06 Oct 23 nicklas 448     }
7372 06 Oct 23 nicklas 449     return opt.join('\n');
7372 06 Oct 23 nicklas 450   }
7372 06 Oct 23 nicklas 451   
7372 06 Oct 23 nicklas 452   /**
2608 28 Aug 14 nicklas 453     Open a popup window and copy a part of the current window to the popup
2608 28 Aug 14 nicklas 454     and make it suitable for printin.
2608 28 Aug 14 nicklas 455   
2608 28 Aug 14 nicklas 456     @param printElementId The id of a html tag in the current page that should
2608 28 Aug 14 nicklas 457       be copied to the print window
2608 28 Aug 14 nicklas 458     @param pageTitle The title of the print window
2608 28 Aug 14 nicklas 459     @param pageOrientation 'landscape' or 'portrait' (default)
2608 28 Aug 14 nicklas 460     @param printNote Optional note intended to include instructions how to configure
2608 28 Aug 14 nicklas 461       the browser for optimal printing (eg. set to landscape and scale to 75%)
2608 28 Aug 14 nicklas 462   */
2608 28 Aug 14 nicklas 463   reggie.openPrintWindow = function(printElementId, pageTitle, pageOrientation, printNote, reggieRoot, extraStyles)
2608 28 Aug 14 nicklas 464   {
2608 28 Aug 14 nicklas 465     // Default width/height is for 'portrait' orientation
2608 28 Aug 14 nicklas 466     var width = 900;
2608 28 Aug 14 nicklas 467     var height = 900;
2608 28 Aug 14 nicklas 468     if (pageOrientation == 'landscape')
2608 28 Aug 14 nicklas 469     {
2608 28 Aug 14 nicklas 470       width = 1300;
2608 28 Aug 14 nicklas 471       height = 700;
2608 28 Aug 14 nicklas 472     }
2608 28 Aug 14 nicklas 473     
2608 28 Aug 14 nicklas 474     var url = 'print_template.jsp?ID='+App.getSessionId();
2608 28 Aug 14 nicklas 475     if (extraStyles) url += '&extraStyles='+extraStyles;
2608 28 Aug 14 nicklas 476     if (reggieRoot) url = reggieRoot+url;
2608 28 Aug 14 nicklas 477     // Open the print-window 
2612 29 Aug 14 nicklas 478     internal.printOptions = {
2612 29 Aug 14 nicklas 479       'printElementId': printElementId,
2612 29 Aug 14 nicklas 480       'pageTitle': pageTitle, 
2612 29 Aug 14 nicklas 481       'pageOrientation': pageOrientation, 
2612 29 Aug 14 nicklas 482       'printNote': printNote
2612 29 Aug 14 nicklas 483     };
5780 10 Dec 19 nicklas 484     var printWin = window.open(url, 'PrintWindow', 'width='+width+',height='+height+',toolbar=yes,location=yes,directories=no,status=no,menubar=yes,scrollbars=yes,resizable=yes');
2608 28 Aug 14 nicklas 485   }
2608 28 Aug 14 nicklas 486
2612 29 Aug 14 nicklas 487   reggie.finalizePrint = function(printWin)
2612 29 Aug 14 nicklas 488   {
2612 29 Aug 14 nicklas 489     // Set page title...
2612 29 Aug 14 nicklas 490     if (internal.printOptions.pageTitle) 
2612 29 Aug 14 nicklas 491     {
2612 29 Aug 14 nicklas 492       printWin.document.title = internal.printOptions.pageTitle;
2612 29 Aug 14 nicklas 493     }
2612 29 Aug 14 nicklas 494   
2612 29 Aug 14 nicklas 495     // ...orientation...
2612 29 Aug 14 nicklas 496     if (internal.printOptions.pageOrientation)
2612 29 Aug 14 nicklas 497     {
2612 29 Aug 14 nicklas 498       var paper = printWin.document.getElementById('paper');
2612 29 Aug 14 nicklas 499       paper.className += ' ' + internal.printOptions.pageOrientation;
2612 29 Aug 14 nicklas 500     }
2612 29 Aug 14 nicklas 501     
2612 29 Aug 14 nicklas 502     // ... and print note
2612 29 Aug 14 nicklas 503     if (internal.printOptions.printNote)
2612 29 Aug 14 nicklas 504     {
2612 29 Aug 14 nicklas 505       var note = printWin.document.getElementById('printNote');
2612 29 Aug 14 nicklas 506       note.innerHTML = internal.printOptions.printNote;
2612 29 Aug 14 nicklas 507     }
2612 29 Aug 14 nicklas 508     
2612 29 Aug 14 nicklas 509     // Get the HTML from the <div> tag to be printed
2612 29 Aug 14 nicklas 510     var printElement = Doc.element(internal.printOptions.printElementId);
2612 29 Aug 14 nicklas 511     var printHtml = printElement.innerHTML;
2612 29 Aug 14 nicklas 512     // Replace all <canvas> elements with <img>
2612 29 Aug 14 nicklas 513     // since that seems the only way to make things work in IE
2612 29 Aug 14 nicklas 514     printHtml = printHtml.replace(/\<canvas.*?\<\/canvas\>/g, '<img class="canvas-copy">');
3544 15 Oct 15 nicklas 515     // Replace <input> elements with <span>
3544 15 Oct 15 nicklas 516     printHtml = printHtml.replace(/\<input.*?\>/g, '<span class="input-copy"></span>');
3544 15 Oct 15 nicklas 517
2612 29 Aug 14 nicklas 518     // Copy the HTML to the print-area in the print-window
2612 29 Aug 14 nicklas 519     var printArea = printWin.document.getElementById('printarea');
2612 29 Aug 14 nicklas 520     printArea.innerHTML = printHtml;
2612 29 Aug 14 nicklas 521   
2612 29 Aug 14 nicklas 522     // Copy the <canvas> elements as images to the <img> elements
2612 29 Aug 14 nicklas 523     // using toDataURL()
2612 29 Aug 14 nicklas 524     var srcCanvas = printElement.getElementsByTagName('canvas');
2612 29 Aug 14 nicklas 525     var printImg = printArea.getElementsByClassName('canvas-copy');
2612 29 Aug 14 nicklas 526     for (var i = 0; i < srcCanvas.length; i++)
2612 29 Aug 14 nicklas 527     {
2612 29 Aug 14 nicklas 528       printImg[i].src = srcCanvas[i].toDataURL();
2612 29 Aug 14 nicklas 529     }
3544 15 Oct 15 nicklas 530
3544 15 Oct 15 nicklas 531     // Copy values from <input> elements to the <span> elements
3544 15 Oct 15 nicklas 532     // Radio and checkboxes are set to 'x' if checked
3544 15 Oct 15 nicklas 533     // Other elements use the 'value' property
3544 15 Oct 15 nicklas 534     var srcInput = printElement.getElementsByTagName('input');
3544 15 Oct 15 nicklas 535     var printInput = printArea.getElementsByClassName('input-copy');
3544 15 Oct 15 nicklas 536     for (var i = 0; i < srcInput.length; i++)
3544 15 Oct 15 nicklas 537     {
3544 15 Oct 15 nicklas 538       var input = srcInput[i];
3544 15 Oct 15 nicklas 539       var value = Strings.encodeTags(input.value);
3544 15 Oct 15 nicklas 540       if (input.type == 'radio' || input.type == 'checkbox')
3544 15 Oct 15 nicklas 541       {
3544 15 Oct 15 nicklas 542         value = input.checked ? '<b>×</b>' : '';
3544 15 Oct 15 nicklas 543       }
3544 15 Oct 15 nicklas 544       printInput[i].innerHTML = value;
3544 15 Oct 15 nicklas 545     }
2612 29 Aug 14 nicklas 546     
2612 29 Aug 14 nicklas 547   }
2612 29 Aug 14 nicklas 548   
5019 10 Oct 18 nicklas 549   
5019 10 Oct 18 nicklas 550   /**
5019 10 Oct 18 nicklas 551     Opens the case summary as a popup as a reaction to the given event.
5019 10 Oct 18 nicklas 552     The event target should contain a 'data-name' attribute with the 
5019 10 Oct 18 nicklas 553     item name to show in the case summary.
5019 10 Oct 18 nicklas 554   */
5019 10 Oct 18 nicklas 555   reggie.openCaseSummaryPopupOnEvent = function(event)
5019 10 Oct 18 nicklas 556   {
5019 10 Oct 18 nicklas 557     var name = Data.get(event.currentTarget, 'name');
5019 10 Oct 18 nicklas 558     reggie.openCaseSummaryPopup(name);
5019 10 Oct 18 nicklas 559   }
5019 10 Oct 18 nicklas 560   
5019 10 Oct 18 nicklas 561   /**
5019 10 Oct 18 nicklas 562     Opens the case summary as a popup for the given item name.
5019 10 Oct 18 nicklas 563   */
5019 10 Oct 18 nicklas 564   reggie.openCaseSummaryPopup = function(name)
5019 10 Oct 18 nicklas 565   {
5019 10 Oct 18 nicklas 566     if (!name) return;
5019 10 Oct 18 nicklas 567     var url = '../reports/case_summary.jsp?ID='+App.getSessionId();
7150 09 May 23 nicklas 568     url += '&caseName='+encodeURIComponent(name);
5019 10 Oct 18 nicklas 569     url += '&highlight='+encodeURIComponent(name);
5019 10 Oct 18 nicklas 570     url += '&pageType=popup';
7150 09 May 23 nicklas 571     Dialogs.openPopup(url, 'CaseSummary'+name.replace(/[^\w]/g, ''), 1200, 800);
5019 10 Oct 18 nicklas 572   }
5019 10 Oct 18 nicklas 573   
2599 25 Aug 14 nicklas 574   return reggie;
2599 25 Aug 14 nicklas 575 }();
2599 25 Aug 14 nicklas 576
2599 25 Aug 14 nicklas 577
2599 25 Aug 14 nicklas 578
2599 25 Aug 14 nicklas 579
2599 25 Aug 14 nicklas 580 var Wizard = function()
2599 25 Aug 14 nicklas 581 {
2599 25 Aug 14 nicklas 582   var wizard = {};
2599 25 Aug 14 nicklas 583   var internal = {};
7444 20 Nov 23 nicklas 584   var debug = 0;
2599 25 Aug 14 nicklas 585   
2599 25 Aug 14 nicklas 586   var currentStep = 1;
2658 12 Sep 14 nicklas 587   var numLiveAsyncRequests = 0;
2658 12 Sep 14 nicklas 588   var hasSentRegistration = false;
2658 12 Sep 14 nicklas 589   var forceConfirm = false;
2803 14 Oct 14 nicklas 590   var noConfirmOnFirstStep = true;
5058 29 Oct 18 nicklas 591   var noConfirm = false;
2676 17 Sep 14 nicklas 592   var hasFatalError = false;
4477 03 May 17 nicklas 593   var progressTimer = null;
2599 25 Aug 14 nicklas 594   
2599 25 Aug 14 nicklas 595   /**
2599 25 Aug 14 nicklas 596     Validate the 'date'-input field that is the target of this event
2599 25 Aug 14 nicklas 597     The date is optional unless 'required' is part if it's className.
2599 25 Aug 14 nicklas 598     Dates should be either 4 or 8 digits with month+day or year+month+day.
2599 25 Aug 14 nicklas 599     If 'data-allow-six-digits' is set on the target element, the year
2599 25 Aug 14 nicklas 600     is allowed to be only 2 digits.
2599 25 Aug 14 nicklas 601     
2599 25 Aug 14 nicklas 602     4-digit (and 6-digit) dates auto-padded to 8 digits.
2599 25 Aug 14 nicklas 603     
2599 25 Aug 14 nicklas 604     The 'data-valid' attribute is set to 1 or 0 depending on the outcome,
2599 25 Aug 14 nicklas 605     and 'data-warning' is set if the date is missing on non-required fields.
2599 25 Aug 14 nicklas 606   */
2599 25 Aug 14 nicklas 607   wizard.validateDate = function(event)
2599 25 Aug 14 nicklas 608   {
2599 25 Aug 14 nicklas 609     var target = event.currentTarget;
2599 25 Aug 14 nicklas 610     var isValid = false;
2599 25 Aug 14 nicklas 611     var isWarning = false;
2599 25 Aug 14 nicklas 612     
2599 25 Aug 14 nicklas 613     // Reset current status
2599 25 Aug 14 nicklas 614     wizard.setInputStatus(target);
2599 25 Aug 14 nicklas 615     
2599 25 Aug 14 nicklas 616     var date = target.value;
2599 25 Aug 14 nicklas 617     if (date == '')
2599 25 Aug 14 nicklas 618     {
2599 25 Aug 14 nicklas 619       // No date, is this an error or a warning?
2599 25 Aug 14 nicklas 620       var optional = target.className.indexOf('required') == -1;
2599 25 Aug 14 nicklas 621       wizard.setInputStatus(target, optional ? 'warning' : 'invalid', 'Missing');
2599 25 Aug 14 nicklas 622       isValid = optional;
2599 25 Aug 14 nicklas 623       isWarning = optional;
2599 25 Aug 14 nicklas 624     }
2599 25 Aug 14 nicklas 625     else
2599 25 Aug 14 nicklas 626     {
2599 25 Aug 14 nicklas 627       var allowSixDigits = Data.int(target, 'allow-six-digits');
2599 25 Aug 14 nicklas 628       date = Reggie.autoFillDate(date, allowSixDigits);
2599 25 Aug 14 nicklas 629       target.value = date;
2599 25 Aug 14 nicklas 630       
2677 17 Sep 14 nicklas 631       var d = Dates.parseString(date, 'yyyyMMdd');
2677 17 Sep 14 nicklas 632       if (d == null)
2599 25 Aug 14 nicklas 633       {
2599 25 Aug 14 nicklas 634         Wizard.setInputStatus(target, 'invalid', 'Not a valid date');
2599 25 Aug 14 nicklas 635       }
2599 25 Aug 14 nicklas 636       else
2599 25 Aug 14 nicklas 637       {
2677 17 Sep 14 nicklas 638         var disallowFutureDate = Data.int(target, 'disallow-future-date');
2677 17 Sep 14 nicklas 639         var today = new Date();
2677 17 Sep 14 nicklas 640         if (disallowFutureDate && (d.getTime() > today.getTime()))
2677 17 Sep 14 nicklas 641         {
2677 17 Sep 14 nicklas 642           Wizard.setInputStatus(target, 'invalid', 'Future dates are not valid');
2677 17 Sep 14 nicklas 643         }
2677 17 Sep 14 nicklas 644         else
2677 17 Sep 14 nicklas 645         {
2677 17 Sep 14 nicklas 646           Wizard.setInputStatus(target, 'valid');
2677 17 Sep 14 nicklas 647           isValid = true;
2677 17 Sep 14 nicklas 648         }
2599 25 Aug 14 nicklas 649       }
2599 25 Aug 14 nicklas 650     }
2599 25 Aug 14 nicklas 651
2599 25 Aug 14 nicklas 652     Data.set(target, 'valid', isValid ? 1 : 0);
2599 25 Aug 14 nicklas 653     Data.set(target, 'warning', isWarning ? 1 : 0);
2599 25 Aug 14 nicklas 654     
2599 25 Aug 14 nicklas 655     if (!isValid && target.focus) target.focus();
2677 17 Sep 14 nicklas 656     return isValid;
2599 25 Aug 14 nicklas 657   }
2599 25 Aug 14 nicklas 658
3319 11 May 15 nicklas 659   /**
3319 11 May 15 nicklas 660     Validate the 'numeric' input field that is the target of this event
3319 11 May 15 nicklas 661     The value is optional unless 'required' is part if it's className.
3319 11 May 15 nicklas 662     
3319 11 May 15 nicklas 663     The 'data-default-value' can be set to a default value. If the 
3319 11 May 15 nicklas 664     given value is changed a warning is displayed.
3319 11 May 15 nicklas 665     
3319 11 May 15 nicklas 666     The 'data-valid' attribute is set to 1 or 0 depending on the outcome,
3319 11 May 15 nicklas 667     and 'data-warning' is set if the date is missing on non-required fields.
3319 11 May 15 nicklas 668   */
3319 11 May 15 nicklas 669   wizard.validateNumber = function(event)
3319 11 May 15 nicklas 670   {
3319 11 May 15 nicklas 671     var target = event.currentTarget;
3319 11 May 15 nicklas 672     var isValid = false;
3319 11 May 15 nicklas 673     var isWarning = false;
3319 11 May 15 nicklas 674     
3319 11 May 15 nicklas 675     // Reset current status
3319 11 May 15 nicklas 676     wizard.setInputStatus(target);
3319 11 May 15 nicklas 677     
3319 11 May 15 nicklas 678     var nbr = target.value;
3319 11 May 15 nicklas 679     if (nbr == '')
3319 11 May 15 nicklas 680     {
3319 11 May 15 nicklas 681       // No value, is this an error or a warning?
3319 11 May 15 nicklas 682       var optional = target.className.indexOf('required') == -1;
3319 11 May 15 nicklas 683       wizard.setInputStatus(target, optional ? 'warning' : 'invalid', 'Missing');
3319 11 May 15 nicklas 684       isValid = optional;
3319 11 May 15 nicklas 685       isWarning = optional;
3319 11 May 15 nicklas 686     }
3319 11 May 15 nicklas 687     else if (isNaN(parseFloat(nbr)))
3319 11 May 15 nicklas 688     {
3319 11 May 15 nicklas 689       wizard.setInputStatus(target, 'invalid', 'Not a number');
3319 11 May 15 nicklas 690     }
3319 11 May 15 nicklas 691     else
3319 11 May 15 nicklas 692     {
3319 11 May 15 nicklas 693       var value = parseFloat(nbr);
3319 11 May 15 nicklas 694       var min = Data.float(target, 'min-value');
3319 11 May 15 nicklas 695       var max = Data.float(target, 'max-value');
3319 11 May 15 nicklas 696       var def = Data.float(target, 'default-value');
3319 11 May 15 nicklas 697       
3319 11 May 15 nicklas 698       if (min != null && value < min)
3319 11 May 15 nicklas 699       {
3319 11 May 15 nicklas 700         Wizard.setInputStatus(target, 'invalid', 'Must be &gt;= ' + min);
3319 11 May 15 nicklas 701       }
3319 11 May 15 nicklas 702       else if (max != null && value > max)
3319 11 May 15 nicklas 703       {
3319 11 May 15 nicklas 704         Wizard.setInputStatus(target, 'invalid', 'Must be &lt;= ' + max);
3319 11 May 15 nicklas 705       }
3319 11 May 15 nicklas 706       else
3319 11 May 15 nicklas 707       {
3319 11 May 15 nicklas 708         isValid = true;
3319 11 May 15 nicklas 709         if (def != null && def != value)
3319 11 May 15 nicklas 710         {
3319 11 May 15 nicklas 711           Wizard.setInputStatus(target, 'warning', 'Default: ' + def);
3319 11 May 15 nicklas 712           isWarning = true;
3319 11 May 15 nicklas 713         }
3319 11 May 15 nicklas 714         else
3319 11 May 15 nicklas 715         {
3319 11 May 15 nicklas 716           Wizard.setInputStatus(target, 'valid');
3319 11 May 15 nicklas 717         }
3319 11 May 15 nicklas 718       }
3319 11 May 15 nicklas 719     }
3319 11 May 15 nicklas 720     
3319 11 May 15 nicklas 721     Data.set(target, 'valid', isValid ? 1 : 0);
3319 11 May 15 nicklas 722     Data.set(target, 'warning', isWarning ? 1 : 0);
3319 11 May 15 nicklas 723     
3319 11 May 15 nicklas 724     if (!isValid && target.focus) target.focus();
3319 11 May 15 nicklas 725     return isValid;
3319 11 May 15 nicklas 726     
3319 11 May 15 nicklas 727   }
2599 25 Aug 14 nicklas 728   
2599 25 Aug 14 nicklas 729   wizard.isValid = function(element)
2599 25 Aug 14 nicklas 730   {
2666 15 Sep 14 nicklas 731     return Data.int(element, 'valid', 1);
2599 25 Aug 14 nicklas 732   }
2599 25 Aug 14 nicklas 733
2666 15 Sep 14 nicklas 734
2666 15 Sep 14 nicklas 735   wizard.initFileSelectionField = function(element)
2666 15 Sep 14 nicklas 736   {
2666 15 Sep 14 nicklas 737     element = Doc.element(element);
2666 15 Sep 14 nicklas 738     
2666 15 Sep 14 nicklas 739     var subtype = Data.get(element, 'subtype');
2666 15 Sep 14 nicklas 740     if (subtype)
2666 15 Sep 14 nicklas 741     {
2675 17 Sep 14 nicklas 742       element.subtype = Reggie.getSubtypeInfo(subtype);
2666 15 Sep 14 nicklas 743     }
2666 15 Sep 14 nicklas 744     
4627 21 Nov 17 nicklas 745     if (element.type != 'file')
4627 21 Nov 17 nicklas 746     {
4627 21 Nov 17 nicklas 747       Buttons.addClickHandler(element.id + '.btn', wizard.browseOnClick, { 'file-field': element.id });
4627 21 Nov 17 nicklas 748       Events.doOnEnter(element, wizard.browseOnClick);
4627 21 Nov 17 nicklas 749     }
2666 15 Sep 14 nicklas 750     
2666 15 Sep 14 nicklas 751     Events.addEventHandler(element, 'base-selected', wizard.fileSelected);
2666 15 Sep 14 nicklas 752     Events.addEventHandler(element, 'change', wizard.fileChanged);
2675 17 Sep 14 nicklas 753     Events.sendChangeEvent(element);
2666 15 Sep 14 nicklas 754   }
2666 15 Sep 14 nicklas 755   
2666 15 Sep 14 nicklas 756   wizard.browseOnClick = function(event)
2666 15 Sep 14 nicklas 757   {
2666 15 Sep 14 nicklas 758     var fileField = Doc.element(Data.get(event.currentTarget, 'file-field', event.currentTarget.id));
2666 15 Sep 14 nicklas 759
2666 15 Sep 14 nicklas 760     var url = '&resetTemporary=1';
2666 15 Sep 14 nicklas 761     var nameFilter = Data.get(fileField, 'name-filter');
2666 15 Sep 14 nicklas 762     if (nameFilter)
2666 15 Sep 14 nicklas 763     {
2666 15 Sep 14 nicklas 764       url += '&tmpfilter:STRING:name='+encodeURIComponent(nameFilter);
2666 15 Sep 14 nicklas 765     }
2666 15 Sep 14 nicklas 766
2666 15 Sep 14 nicklas 767     var subtype = fileField.subtype;
2666 15 Sep 14 nicklas 768     if (subtype)
2666 15 Sep 14 nicklas 769     {
2666 15 Sep 14 nicklas 770       url += '&tmpfilter:INT:itemSubtype='+subtype.id;
2666 15 Sep 14 nicklas 771     }
2666 15 Sep 14 nicklas 772     
2666 15 Sep 14 nicklas 773     var directory = Data.get(fileField, 'directory');
2675 17 Sep 14 nicklas 774     if (directory && !Data.get(fileField, 'has-browsed'))
2666 15 Sep 14 nicklas 775     {
2666 15 Sep 14 nicklas 776       Reggie.setCurrentDirectory(directory);
2675 17 Sep 14 nicklas 777       Data.set(fileField, 'has-browsed', 1);
2666 15 Sep 14 nicklas 778     }
2666 15 Sep 14 nicklas 779     
2666 15 Sep 14 nicklas 780     Dialogs.selectItem('FILE', fileField, 0, url);
2666 15 Sep 14 nicklas 781   }
2666 15 Sep 14 nicklas 782   
2666 15 Sep 14 nicklas 783   wizard.fileSelected = function(event)
2666 15 Sep 14 nicklas 784   {
2666 15 Sep 14 nicklas 785     event.currentTarget.value = event.detail.name;
7160 11 May 23 nicklas 786     Data.set(event.currentTarget, 'file-id', event.detail.id);
2666 15 Sep 14 nicklas 787     Events.sendChangeEvent(event.currentTarget);
2666 15 Sep 14 nicklas 788   }
2666 15 Sep 14 nicklas 789   
2666 15 Sep 14 nicklas 790   wizard.fileChanged = function(event)
2666 15 Sep 14 nicklas 791   {
2666 15 Sep 14 nicklas 792     var target = event.currentTarget;
2666 15 Sep 14 nicklas 793     
2666 15 Sep 14 nicklas 794     var isValid = false;
2666 15 Sep 14 nicklas 795     var isWarning = false;
2666 15 Sep 14 nicklas 796     
2666 15 Sep 14 nicklas 797     // Reset current status
2666 15 Sep 14 nicklas 798     wizard.setInputStatus(target);
2666 15 Sep 14 nicklas 799     
2666 15 Sep 14 nicklas 800     var path = target.value;
2666 15 Sep 14 nicklas 801     if (path == '')
2666 15 Sep 14 nicklas 802     {
2666 15 Sep 14 nicklas 803       // No file, is this an error or a warning?
2666 15 Sep 14 nicklas 804       var optional = target.className.indexOf('required') == -1;
2666 15 Sep 14 nicklas 805       wizard.setInputStatus(target, optional ? 'warning' : 'invalid', 'Missing');
2666 15 Sep 14 nicklas 806       isValid = optional;
2666 15 Sep 14 nicklas 807       isWarning = optional;
2666 15 Sep 14 nicklas 808     }
2666 15 Sep 14 nicklas 809     else
2666 15 Sep 14 nicklas 810     {
2666 15 Sep 14 nicklas 811       Wizard.setInputStatus(target, 'valid');
2666 15 Sep 14 nicklas 812       isValid = true;
2666 15 Sep 14 nicklas 813     }
2666 15 Sep 14 nicklas 814     
2666 15 Sep 14 nicklas 815     Data.set(target, 'valid', isValid ? 1 : 0);
2666 15 Sep 14 nicklas 816     Data.set(target, 'warning', isWarning ? 1 : 0);
2666 15 Sep 14 nicklas 817     
2666 15 Sep 14 nicklas 818     if (!isValid && target.focus) target.focus();
2666 15 Sep 14 nicklas 819   }
2666 15 Sep 14 nicklas 820   
2666 15 Sep 14 nicklas 821   
2599 25 Aug 14 nicklas 822   /**
2599 25 Aug 14 nicklas 823     Change display status for an input field.
2599 25 Aug 14 nicklas 824     @param prefix ID prefix to locate tags
2599 25 Aug 14 nicklas 825     @param clazz The message clazz (valid, invalid, warning) or empty
2599 25 Aug 14 nicklas 826     @param message The message (may be empty)
2599 25 Aug 14 nicklas 827   */
2599 25 Aug 14 nicklas 828   wizard.setInputStatus = function(prefix, clazz, message)
2599 25 Aug 14 nicklas 829   {
2599 25 Aug 14 nicklas 830     if (prefix.id) prefix = prefix.id;
2599 25 Aug 14 nicklas 831     
2599 25 Aug 14 nicklas 832     var statusTag = Doc.element(prefix + '.status');
2599 25 Aug 14 nicklas 833     
3270 23 Apr 15 nicklas 834     if (statusTag)
2629 02 Sep 14 nicklas 835     {
3270 23 Apr 15 nicklas 836       statusTag.className = 'status ' + (clazz || '');
3270 23 Apr 15 nicklas 837       var trTag = statusTag.parentNode;
3270 23 Apr 15 nicklas 838       var trClass = Data.get(trTag, 'original-class');
3270 23 Apr 15 nicklas 839       if (!trClass)
3270 23 Apr 15 nicklas 840       {
3270 23 Apr 15 nicklas 841         trClass = trTag.className || 'foo';
3270 23 Apr 15 nicklas 842         Data.set(trTag, 'original-class', trClass);
3270 23 Apr 15 nicklas 843       }
3270 23 Apr 15 nicklas 844       trTag.className = trClass + ' ' + (clazz || '');
2629 02 Sep 14 nicklas 845     }
2629 02 Sep 14 nicklas 846     
2599 25 Aug 14 nicklas 847     var msgTag = Doc.element(prefix + '.message');
2599 25 Aug 14 nicklas 848     if (msgTag)
2599 25 Aug 14 nicklas 849     {
2599 25 Aug 14 nicklas 850       if (message)
2599 25 Aug 14 nicklas 851       {
2599 25 Aug 14 nicklas 852         msgTag.innerHTML = message;
2641 09 Sep 14 nicklas 853         Doc.show(msgTag, Data.get(msgTag, 'display', 'inline'));
2599 25 Aug 14 nicklas 854       }
2599 25 Aug 14 nicklas 855       else
2599 25 Aug 14 nicklas 856       {
2599 25 Aug 14 nicklas 857         msgTag.innerHTML = message;
2599 25 Aug 14 nicklas 858         Doc.hide(msgTag);
2599 25 Aug 14 nicklas 859       }
2599 25 Aug 14 nicklas 860     }
3270 23 Apr 15 nicklas 861     else if (statusTag)
2599 25 Aug 14 nicklas 862     {
2599 25 Aug 14 nicklas 863       statusTag.title = message || '';
2599 25 Aug 14 nicklas 864     }
2599 25 Aug 14 nicklas 865   }
2599 25 Aug 14 nicklas 866
2599 25 Aug 14 nicklas 867   
2599 25 Aug 14 nicklas 868   /**
2599 25 Aug 14 nicklas 869     Event handler for input fields, that go to the
2599 25 Aug 14 nicklas 870     next wizard step if TAB or ENTER key is pressed.
2599 25 Aug 14 nicklas 871     A short delay is used to allow other event handler
2599 25 Aug 14 nicklas 872     to run first (eg. for validation).
2599 25 Aug 14 nicklas 873   */
2599 25 Aug 14 nicklas 874   wizard.goNextOnTabOrEnter = function(event)
2599 25 Aug 14 nicklas 875   {
2599 25 Aug 14 nicklas 876     if (event.keyCode == 9 || event.keyCode == 13) 
2599 25 Aug 14 nicklas 877     {
6997 20 Jan 23 nicklas 878       if (event.keyCode == 13 && event.target.blur) event.target.blur();
2599 25 Aug 14 nicklas 879       setTimeout(function() { wizard.goNext(true) }, 200);
2599 25 Aug 14 nicklas 880     }
2599 25 Aug 14 nicklas 881   }
2599 25 Aug 14 nicklas 882   
2599 25 Aug 14 nicklas 883   /**
2677 17 Sep 14 nicklas 884     Event handler for input fields, that go to the
2677 17 Sep 14 nicklas 885     next wizard step if TAB key is pressed.
2677 17 Sep 14 nicklas 886     A short delay is used to allow other event handler
2677 17 Sep 14 nicklas 887     to run first (eg. for validation).
2677 17 Sep 14 nicklas 888   */
2677 17 Sep 14 nicklas 889   wizard.goNextOnTab = function(event)
2677 17 Sep 14 nicklas 890   {
2677 17 Sep 14 nicklas 891     if (event.keyCode == 9) 
2677 17 Sep 14 nicklas 892     {
2677 17 Sep 14 nicklas 893       setTimeout(function() { wizard.goNext(true) }, 200);
2677 17 Sep 14 nicklas 894     }
2677 17 Sep 14 nicklas 895   }
2677 17 Sep 14 nicklas 896   
2677 17 Sep 14 nicklas 897   /**
2599 25 Aug 14 nicklas 898     Event handler for input fields, that changes
2599 25 Aug 14 nicklas 899     focus to the next element. The next element
2599 25 Aug 14 nicklas 900     should be defined by 'data-next-focus' attribute.
2599 25 Aug 14 nicklas 901     It is recommended that this is consisistent with TAB.
2599 25 Aug 14 nicklas 902   */
2599 25 Aug 14 nicklas 903   wizard.focusOnEnter = function(event)
2599 25 Aug 14 nicklas 904   {
2599 25 Aug 14 nicklas 905     if (event.keyCode == 13)
2599 25 Aug 14 nicklas 906     {
2599 25 Aug 14 nicklas 907       var nextFocus = Doc.element(Data.get(event.currentTarget, 'next-focus'));
2599 25 Aug 14 nicklas 908       if (nextFocus && nextFocus.focus) nextFocus.focus();
2599 25 Aug 14 nicklas 909     }
2599 25 Aug 14 nicklas 910   }
2599 25 Aug 14 nicklas 911   
2599 25 Aug 14 nicklas 912   // Event handler for the 'Next' navigation button
6824 30 Aug 22 nicklas 913   wizard.goNextOnClick = function()
2599 25 Aug 14 nicklas 914   {
2599 25 Aug 14 nicklas 915     wizard.goNext(false);
2599 25 Aug 14 nicklas 916   }
2599 25 Aug 14 nicklas 917   
2599 25 Aug 14 nicklas 918   /**
2599 25 Aug 14 nicklas 919     Go to the next step in the wizard. This method will first
2599 25 Aug 14 nicklas 920     submit 'wizard-validate' event to the current step. If at 
2599 25 Aug 14 nicklas 921     least one event handler calls 'Event.preventDefault()' the 
2599 25 Aug 14 nicklas 922     processing is aborted. 
2599 25 Aug 14 nicklas 923     
2599 25 Aug 14 nicklas 924     Otherwise, the current step is disabled and the 'wizard-initialize' 
2599 25 Aug 14 nicklas 925     event is sent to the next step. The event handler is responsible
2599 25 Aug 14 nicklas 926     for calling 'Wizard.setCurrentStep' to display the next step.
2599 25 Aug 14 nicklas 927   */
2599 25 Aug 14 nicklas 928   wizard.goNext = function(auto)
2599 25 Aug 14 nicklas 929   {
2602 27 Aug 14 nicklas 930     var verify = Doc.element('verifyGoNext');
2602 27 Aug 14 nicklas 931     if (verify && !verify.checked) return;
2602 27 Aug 14 nicklas 932     
6277 03 Jun 21 nicklas 933     // Send 'wizard-validate' event to current step
2602 27 Aug 14 nicklas 934     var details = { 'auto': auto };
6277 03 Jun 21 nicklas 935     if (!wizard.validateCurrentStep(details)) return;
2599 25 Aug 14 nicklas 936
2599 25 Aug 14 nicklas 937     // Hide all navigation buttons and disable form controls in current step
2599 25 Aug 14 nicklas 938     internal.hideButtons('navigation');
6277 03 Jun 21 nicklas 939     internal.disableStep('step-'+currentStep);
2599 25 Aug 14 nicklas 940     
2599 25 Aug 14 nicklas 941     // Send 'wizard-initialize' to the next step
2599 25 Aug 14 nicklas 942     var nextStep = Doc.element('step-'+(currentStep+1));
6824 30 Aug 22 nicklas 943     var evt = new CustomEvent('wizard-initialize', {'bubbles': true, 'cancelable': true, 'detail': details});
2599 25 Aug 14 nicklas 944     nextStep.dispatchEvent(evt);
2599 25 Aug 14 nicklas 945   }
2599 25 Aug 14 nicklas 946   
6277 03 Jun 21 nicklas 947   wizard.validateCurrentStep = function(details)
6277 03 Jun 21 nicklas 948   {
6277 03 Jun 21 nicklas 949     // Send 'wizard-validate' event to current step
6277 03 Jun 21 nicklas 950     var step = Doc.element('step-'+currentStep);
6824 30 Aug 22 nicklas 951     var evt = new CustomEvent('wizard-validate', {'bubbles': true, 'cancelable': true, 'detail': details});
6277 03 Jun 21 nicklas 952     if (!step.dispatchEvent(evt)) 
6277 03 Jun 21 nicklas 953     {
6277 03 Jun 21 nicklas 954       wizard.notifyError();
6277 03 Jun 21 nicklas 955       return false;
6277 03 Jun 21 nicklas 956     }
6277 03 Jun 21 nicklas 957     return true;
6277 03 Jun 21 nicklas 958   }
6277 03 Jun 21 nicklas 959   
2653 11 Sep 14 nicklas 960   wizard.notifyError = function()
2653 11 Sep 14 nicklas 961   {
2653 11 Sep 14 nicklas 962     Doc.addClass('wizard', 'flash-error');
2653 11 Sep 14 nicklas 963     setTimeout(internal.stopFlashing, 2000);
2653 11 Sep 14 nicklas 964   }
2653 11 Sep 14 nicklas 965   
2629 02 Sep 14 nicklas 966   internal.stopFlashing = function()
2629 02 Sep 14 nicklas 967   {
2629 02 Sep 14 nicklas 968     Doc.removeClass('wizard', 'flash-error');
2629 02 Sep 14 nicklas 969   }
2629 02 Sep 14 nicklas 970   
2599 25 Aug 14 nicklas 971   /**
2599 25 Aug 14 nicklas 972     Finalize the registration of the wizard. This method will
2599 25 Aug 14 nicklas 973     first submit 'wizard-validate' to the current step. If at 
2599 25 Aug 14 nicklas 974     least one event handler calls 'Event.preventDefault()' the 
2599 25 Aug 14 nicklas 975     processing is aborted.
2599 25 Aug 14 nicklas 976     
2599 25 Aug 14 nicklas 977     Otherwise, the current step is disabled and the 'wizard-submit' 
2599 25 Aug 14 nicklas 978     event is sent to the 'wizard'. The event handler is responsible
2599 25 Aug 14 nicklas 979     for finalizing the registration and displaying a proper
2599 25 Aug 14 nicklas 980     message, for example, by calling Wizard.showFinalMessage()
3787 17 Mar 16 nicklas 981     
3787 17 Mar 16 nicklas 982     The 'data' is passed on to the 'wizard-validate' and 
3787 17 Mar 16 nicklas 983     'wizard-submit' events as the Event.details object.
2599 25 Aug 14 nicklas 984   */
3787 17 Mar 16 nicklas 985   wizard.goRegister = function(data)
2599 25 Aug 14 nicklas 986   {
2602 27 Aug 14 nicklas 987     // Check if verification is enabled
2602 27 Aug 14 nicklas 988     var verify = Doc.element('verifyGoNext');
2602 27 Aug 14 nicklas 989     if (verify && !verify.checked) return;
2602 27 Aug 14 nicklas 990     
2599 25 Aug 14 nicklas 991     // Send 'wizard-validate' event to current step
2599 25 Aug 14 nicklas 992     var step = Doc.element('step-'+currentStep);
6824 30 Aug 22 nicklas 993     var evt = new CustomEvent('wizard-validate', {'bubbles': true, 'cancelable': true, 'detail': data});
2629 02 Sep 14 nicklas 994     if (!step.dispatchEvent(evt)) 
2629 02 Sep 14 nicklas 995     {
2686 22 Sep 14 nicklas 996       wizard.notifyError();
2629 02 Sep 14 nicklas 997       return;
2629 02 Sep 14 nicklas 998     }
2599 25 Aug 14 nicklas 999
2599 25 Aug 14 nicklas 1000     internal.hideButtons('navigation');
2599 25 Aug 14 nicklas 1001     internal.disableStep(step);
2599 25 Aug 14 nicklas 1002     
2599 25 Aug 14 nicklas 1003     // Send 'wizard-submit' to the next step
2599 25 Aug 14 nicklas 1004     var wiz = Doc.element('wizard');
2658 12 Sep 14 nicklas 1005     hasSentRegistration = true;
6824 30 Aug 22 nicklas 1006     var evt = new CustomEvent('wizard-submit', {'bubbles': true, 'cancelable': true, 'detail': data});
2599 25 Aug 14 nicklas 1007     wiz.dispatchEvent(evt);
2924 13 Nov 14 nicklas 1008     wizard.hideDebugTools();
2599 25 Aug 14 nicklas 1009   }
2599 25 Aug 14 nicklas 1010   
2803 14 Oct 14 nicklas 1011   wizard.setNoConfirmOnFirstStep = function(cf)
2803 14 Oct 14 nicklas 1012   {
2803 14 Oct 14 nicklas 1013     noConfirmOnFirstStep = cf;
2803 14 Oct 14 nicklas 1014   }
2803 14 Oct 14 nicklas 1015   
5058 29 Oct 18 nicklas 1016   wizard.setNoConfirm = function(nc)
5058 29 Oct 18 nicklas 1017   {
5058 29 Oct 18 nicklas 1018     noConfirm = nc;
5058 29 Oct 18 nicklas 1019   }
5058 29 Oct 18 nicklas 1020   
2599 25 Aug 14 nicklas 1021   // Ask the user for confirmation and then restart the wizard
2599 25 Aug 14 nicklas 1022   wizard.cancelWizard = function()
2599 25 Aug 14 nicklas 1023   {
2658 12 Sep 14 nicklas 1024     forceConfirm = true;
2658 12 Sep 14 nicklas 1025     wizard.restartWizard();
2599 25 Aug 14 nicklas 1026   }
2599 25 Aug 14 nicklas 1027   
2599 25 Aug 14 nicklas 1028   // Restart the wizard without asking the user for confirmation
2599 25 Aug 14 nicklas 1029   wizard.restartWizard = function()
2599 25 Aug 14 nicklas 1030   {
2599 25 Aug 14 nicklas 1031     var url = location.href;
2599 25 Aug 14 nicklas 1032     if (url.indexOf('&restart=1') == -1) url += '&restart=1';
2599 25 Aug 14 nicklas 1033     location.href = url;
2599 25 Aug 14 nicklas 1034   }
2599 25 Aug 14 nicklas 1035   
2653 11 Sep 14 nicklas 1036   wizard.goPrint = function()
2653 11 Sep 14 nicklas 1037   {
2653 11 Sep 14 nicklas 1038     window.print();
2653 11 Sep 14 nicklas 1039   }
2653 11 Sep 14 nicklas 1040   
2599 25 Aug 14 nicklas 1041   wizard.setCurrentStep = function(stepNo)
2599 25 Aug 14 nicklas 1042   {
2599 25 Aug 14 nicklas 1043     currentStep = stepNo;
2599 25 Aug 14 nicklas 1044     internal.enableStep(Doc.element('step-'+currentStep));
2599 25 Aug 14 nicklas 1045   }
2599 25 Aug 14 nicklas 1046
2599 25 Aug 14 nicklas 1047   internal.disableStep = function(step)
2599 25 Aug 14 nicklas 1048   {
2599 25 Aug 14 nicklas 1049     step = Doc.element(step);
2599 25 Aug 14 nicklas 1050     internal.disableAllFormElements(step);
2599 25 Aug 14 nicklas 1051     Doc.addClass(step, 'disabled');
2602 27 Aug 14 nicklas 1052     Doc.hide('gonext-message');
2599 25 Aug 14 nicklas 1053     var stepNo = step.getElementsByClassName('step-no')[0];
2599 25 Aug 14 nicklas 1054     Events.addEventHandler(stepNo, 'click', internal.togglePastStep, {'step-id': step.id});
2599 25 Aug 14 nicklas 1055     stepNo.title = 'Show/hide this section';
2599 25 Aug 14 nicklas 1056   }
2599 25 Aug 14 nicklas 1057   
2599 25 Aug 14 nicklas 1058   internal.enableStep = function(step)
2599 25 Aug 14 nicklas 1059   {
2599 25 Aug 14 nicklas 1060     step = Doc.element(step);
2599 25 Aug 14 nicklas 1061     Doc.removeClass(step, 'disabled');
2599 25 Aug 14 nicklas 1062     Doc.show(step);
2599 25 Aug 14 nicklas 1063   }
2599 25 Aug 14 nicklas 1064
2599 25 Aug 14 nicklas 1065   // Toggle visibility of a past step
2599 25 Aug 14 nicklas 1066   // The step is hidden if the 'auto-hide' class is present
2599 25 Aug 14 nicklas 1067   internal.togglePastStep = function(event)
2599 25 Aug 14 nicklas 1068   {
2599 25 Aug 14 nicklas 1069     var step = Data.get(event.currentTarget, 'step-id');
2599 25 Aug 14 nicklas 1070     Doc.addOrRemoveClass(step, 'auto-hide');
2599 25 Aug 14 nicklas 1071   }
2599 25 Aug 14 nicklas 1072   
2599 25 Aug 14 nicklas 1073   wizard.syncJsonRequest = function(url, method, postdata)
2599 25 Aug 14 nicklas 1074   {
2599 25 Aug 14 nicklas 1075     if (debug)
2599 25 Aug 14 nicklas 1076     {
2599 25 Aug 14 nicklas 1077       App.debug((method || 'GET') + ': ' + url);
2599 25 Aug 14 nicklas 1078       if (postdata) App.debug(postdata);
2599 25 Aug 14 nicklas 1079     }
2599 25 Aug 14 nicklas 1080     var request = Ajax.getXmlHttpRequest();
2599 25 Aug 14 nicklas 1081     request.open(method || 'GET', url, false);
2599 25 Aug 14 nicklas 1082     if (postdata) 
2599 25 Aug 14 nicklas 1083     {
3752 17 Feb 16 nicklas 1084       request.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
2599 25 Aug 14 nicklas 1085     }
2599 25 Aug 14 nicklas 1086     request.send(postdata || null);
2599 25 Aug 14 nicklas 1087     
2599 25 Aug 14 nicklas 1088     if (debug) App.debug(request.responseText);
2676 17 Sep 14 nicklas 1089     if (!hasFatalError) Wizard.hideWizardStatus();
2599 25 Aug 14 nicklas 1090
2599 25 Aug 14 nicklas 1091     var response = null;
2599 25 Aug 14 nicklas 1092     var errorMsg = null;
2599 25 Aug 14 nicklas 1093     try
2599 25 Aug 14 nicklas 1094     {
2599 25 Aug 14 nicklas 1095       response = JSON.parse(request.responseText);
2599 25 Aug 14 nicklas 1096       if (response.status != 'ok')
2599 25 Aug 14 nicklas 1097       {
2599 25 Aug 14 nicklas 1098         errorMsg = response.message;
2599 25 Aug 14 nicklas 1099       }
2599 25 Aug 14 nicklas 1100     }
2599 25 Aug 14 nicklas 1101     catch (err)
2599 25 Aug 14 nicklas 1102     {
2599 25 Aug 14 nicklas 1103       errorMsg = err.toString ? err.toString() : err;
2599 25 Aug 14 nicklas 1104     }
2599 25 Aug 14 nicklas 1105     
2599 25 Aug 14 nicklas 1106     if (errorMsg)
2599 25 Aug 14 nicklas 1107     {
2599 25 Aug 14 nicklas 1108       Wizard.setFatalError(errorMsg);
2599 25 Aug 14 nicklas 1109       return null;
2599 25 Aug 14 nicklas 1110     }
2599 25 Aug 14 nicklas 1111     else
2599 25 Aug 14 nicklas 1112     {
2599 25 Aug 14 nicklas 1113       return response;
2599 25 Aug 14 nicklas 1114     }
2599 25 Aug 14 nicklas 1115   }
2599 25 Aug 14 nicklas 1116   
2599 25 Aug 14 nicklas 1117   /**
2599 25 Aug 14 nicklas 1118     Submit an ansynchronous request for JSON data. 'GET' method
2599 25 Aug 14 nicklas 1119     is used if 'method' parameter is not set.
2599 25 Aug 14 nicklas 1120     The 'callback' should be a method accepting a single
2599 25 Aug 14 nicklas 1121     JSON parameter object. If the 'status' of the response
2599 25 Aug 14 nicklas 1122     is not 'ok' this method will call setFatalError and
2599 25 Aug 14 nicklas 1123     without calling the callback method.
3998 15 Jun 16 nicklas 1124     
3998 15 Jun 16 nicklas 1125     The 'errorCallback' is an optional function parameter that should
3998 15 Jun 16 nicklas 1126     take two parameters. The first is an Error object and the second is
3998 15 Jun 16 nicklas 1127     the JSON response. The seconds parameter only has a value if the error 
3998 15 Jun 16 nicklas 1128     happens after parsing the response and is null otherwise.
2599 25 Aug 14 nicklas 1129   */
3998 15 Jun 16 nicklas 1130   wizard.asyncJsonRequest = function(url, callback, method, postdata, errorCallback)
2599 25 Aug 14 nicklas 1131   {
2599 25 Aug 14 nicklas 1132     if (debug)
2599 25 Aug 14 nicklas 1133     {
2599 25 Aug 14 nicklas 1134       App.debug((method || 'GET') + ': ' + url);
2599 25 Aug 14 nicklas 1135       if (postdata) App.debug(postdata);
2599 25 Aug 14 nicklas 1136     }
2599 25 Aug 14 nicklas 1137     var request = Ajax.getXmlHttpRequest();
2599 25 Aug 14 nicklas 1138     request.jsonCallback = callback;
3998 15 Jun 16 nicklas 1139     request.errorCallback = errorCallback;
2599 25 Aug 14 nicklas 1140     request.open(method || 'GET', url, true);
3786 17 Mar 16 olle 1141     // Firefox only adds request header with needed "boundary" info, if request header is not set explicitly
5910 17 Apr 20 nicklas 1142     if (postdata && !(postdata instanceof FormData) && !(postdata instanceof File)) 
2599 25 Aug 14 nicklas 1143     {
3752 17 Feb 16 nicklas 1144       request.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
2599 25 Aug 14 nicklas 1145     }
2599 25 Aug 14 nicklas 1146     Ajax.setReadyStateHandler(request, internal.asyncCallbackWrapper, internal.asyncCallbackWrapper);
2658 12 Sep 14 nicklas 1147     numLiveAsyncRequests++;
2599 25 Aug 14 nicklas 1148     request.send(postdata || null);
2599 25 Aug 14 nicklas 1149   }
2599 25 Aug 14 nicklas 1150   
2599 25 Aug 14 nicklas 1151   /**
2599 25 Aug 14 nicklas 1152     Callback wrapper for ansynchronous requests.
2599 25 Aug 14 nicklas 1153   */
2599 25 Aug 14 nicklas 1154   internal.asyncCallbackWrapper = function(request)
2599 25 Aug 14 nicklas 1155   {
2658 12 Sep 14 nicklas 1156     numLiveAsyncRequests--;
2599 25 Aug 14 nicklas 1157     if (debug) App.debug(request.responseText);
2676 17 Sep 14 nicklas 1158     if (!hasFatalError) Wizard.hideWizardStatus();
2599 25 Aug 14 nicklas 1159
2599 25 Aug 14 nicklas 1160     var response = null;
2675 17 Sep 14 nicklas 1161     var messages = null;
2599 25 Aug 14 nicklas 1162     try
2599 25 Aug 14 nicklas 1163     {
2603 27 Aug 14 nicklas 1164       if (request.status != 200)
2599 25 Aug 14 nicklas 1165       {
2622 02 Sep 14 nicklas 1166         throw new Error(request.responseText);
2599 25 Aug 14 nicklas 1167       }
2599 25 Aug 14 nicklas 1168       else
2599 25 Aug 14 nicklas 1169       {
2603 27 Aug 14 nicklas 1170         if (request.getResponseHeader('Content-Type').indexOf('json') != -1)
2603 27 Aug 14 nicklas 1171         {
2603 27 Aug 14 nicklas 1172           response = JSON.parse(request.responseText);
2675 17 Sep 14 nicklas 1173           messages = response.messages;
2603 27 Aug 14 nicklas 1174           if (response.status != 'ok')
2603 27 Aug 14 nicklas 1175           {
2622 02 Sep 14 nicklas 1176             throw new Error(response.message || response.stacktrace);
2603 27 Aug 14 nicklas 1177           }
2603 27 Aug 14 nicklas 1178         }
2603 27 Aug 14 nicklas 1179         else
2603 27 Aug 14 nicklas 1180         {
2603 27 Aug 14 nicklas 1181           response = request.responseText;
2603 27 Aug 14 nicklas 1182         }
2671 16 Sep 14 nicklas 1183         if (request.jsonCallback && request.jsonCallback.call)
2671 16 Sep 14 nicklas 1184         {
2671 16 Sep 14 nicklas 1185           request.jsonCallback.call(null, response);
2671 16 Sep 14 nicklas 1186         }
2599 25 Aug 14 nicklas 1187       }
2599 25 Aug 14 nicklas 1188     }
2599 25 Aug 14 nicklas 1189     catch (err)
2599 25 Aug 14 nicklas 1190     {
3998 15 Jun 16 nicklas 1191       if (request.errorCallback && request.errorCallback.call)
3998 15 Jun 16 nicklas 1192       {
3998 15 Jun 16 nicklas 1193         request.errorCallback.call(null, err, response);
3998 15 Jun 16 nicklas 1194       }
3998 15 Jun 16 nicklas 1195       else
3998 15 Jun 16 nicklas 1196       {
3998 15 Jun 16 nicklas 1197         Wizard.setFatalError(err, messages);
3998 15 Jun 16 nicklas 1198       }
2599 25 Aug 14 nicklas 1199     }
2599 25 Aug 14 nicklas 1200   }
2599 25 Aug 14 nicklas 1201
2599 25 Aug 14 nicklas 1202   
2599 25 Aug 14 nicklas 1203   /**
2599 25 Aug 14 nicklas 1204     A fatal error has occurred and the wizard will not be able to continue.
2599 25 Aug 14 nicklas 1205     This method will display the error message, disable all form input fields
2599 25 Aug 14 nicklas 1206     and buttons (except the 'Restart' button).
2599 25 Aug 14 nicklas 1207   */
2675 17 Sep 14 nicklas 1208   wizard.setFatalError = function(err, messages)
2599 25 Aug 14 nicklas 1209   {
2676 17 Sep 14 nicklas 1210     hasFatalError = true;
2662 12 Sep 14 nicklas 1211     var msg = err;
2662 12 Sep 14 nicklas 1212     if (err.toString)
2662 12 Sep 14 nicklas 1213     {
2662 12 Sep 14 nicklas 1214       App.debug(err.toString());
2662 12 Sep 14 nicklas 1215       msg = Strings.encodeTags(err.toString());
2675 17 Sep 14 nicklas 1216       if (err.stack && !messages)
2670 15 Sep 14 nicklas 1217       {
2670 15 Sep 14 nicklas 1218         App.debug(err.stack);
2670 15 Sep 14 nicklas 1219         msg += '<br><pre>'+Strings.encodeTags(err.stack)+'</pre>';
2670 15 Sep 14 nicklas 1220       }
2662 12 Sep 14 nicklas 1221     }
2662 12 Sep 14 nicklas 1222     else
2662 12 Sep 14 nicklas 1223     {
2662 12 Sep 14 nicklas 1224       App.debug(msg);
2662 12 Sep 14 nicklas 1225     }
2662 12 Sep 14 nicklas 1226     
2675 17 Sep 14 nicklas 1227     if (messages) 
2675 17 Sep 14 nicklas 1228     {
2675 17 Sep 14 nicklas 1229       msg = '<div class="messagecontainer error">'+msg+'</div>'+internal.generateMessageList(messages).html;
2803 14 Oct 14 nicklas 1230       wizard.setWizardStatus('success', msg);
2675 17 Sep 14 nicklas 1231     }
2675 17 Sep 14 nicklas 1232     else
2675 17 Sep 14 nicklas 1233     {
2803 14 Oct 14 nicklas 1234       wizard.setWizardStatus('messagecontainer error', msg || 'Unexpected failure!');
2675 17 Sep 14 nicklas 1235     }
2675 17 Sep 14 nicklas 1236     
2599 25 Aug 14 nicklas 1237     Doc.addClass('wizard', 'disabled');
2599 25 Aug 14 nicklas 1238     internal.disableAllFormElements('wizard', true);
2599 25 Aug 14 nicklas 1239     Doc.show('gorestart');
2599 25 Aug 14 nicklas 1240   }
2599 25 Aug 14 nicklas 1241
2599 25 Aug 14 nicklas 1242   
2599 25 Aug 14 nicklas 1243   /**
2599 25 Aug 14 nicklas 1244     Display a 'loading' global wizard-status message.
3904 29 Apr 16 nicklas 1245     The 'progress' parameter is optional. If given,
3904 29 Apr 16 nicklas 1246     it should be the name of a progress reporter.
3904 29 Apr 16 nicklas 1247     This activates the display of a progress bar which
3904 29 Apr 16 nicklas 1248     Reggie will update at regular intervals in the background.
3904 29 Apr 16 nicklas 1249     See SessionServlet (cmd=GetProgress) for more information.
2599 25 Aug 14 nicklas 1250   */
3904 29 Apr 16 nicklas 1251   wizard.showLoadingAnimation = function(msg, progress)
2599 25 Aug 14 nicklas 1252   {
3904 29 Apr 16 nicklas 1253     if (progress)
3904 29 Apr 16 nicklas 1254     {
5962 03 Jun 20 nicklas 1255       var progressMain = Doc.element('wizard-progress');
5962 03 Jun 20 nicklas 1256       
3904 29 Apr 16 nicklas 1257       // Get/create child elements
5962 03 Jun 20 nicklas 1258       var progressMsg = Doc.element('wizard-progress-msg');
5962 03 Jun 20 nicklas 1259       if (!progressMsg)
5962 03 Jun 20 nicklas 1260       {
5962 03 Jun 20 nicklas 1261         progressMsg = document.createElement('div');
5962 03 Jun 20 nicklas 1262         progressMsg.id = 'wizard-progress-msg';
5962 03 Jun 20 nicklas 1263         progressMsg.className = 'progress-bar-message loading';
5962 03 Jun 20 nicklas 1264         progressMain.appendChild(progressMsg);
5962 03 Jun 20 nicklas 1265       }
5962 03 Jun 20 nicklas 1266       progressMsg.innerHTML = msg ||  'Working, please wait...';
5962 03 Jun 20 nicklas 1267       
5962 03 Jun 20 nicklas 1268       var progressBar = Doc.element('wizard-progress-bar');
5962 03 Jun 20 nicklas 1269       if (!progressBar)
5962 03 Jun 20 nicklas 1270       {
5962 03 Jun 20 nicklas 1271         progressBar = document.createElement('div');
5962 03 Jun 20 nicklas 1272         progressBar.id = 'wizard-progress-bar';
5962 03 Jun 20 nicklas 1273         progressBar.className = 'progress-bar';
5962 03 Jun 20 nicklas 1274         progressMain.appendChild(progressBar);
5962 03 Jun 20 nicklas 1275       }
5962 03 Jun 20 nicklas 1276       
3904 29 Apr 16 nicklas 1277       var done = Doc.element('wizard-progress-done');
3904 29 Apr 16 nicklas 1278       if (!done)
3904 29 Apr 16 nicklas 1279       {
3904 29 Apr 16 nicklas 1280         done = document.createElement('span');
3904 29 Apr 16 nicklas 1281         done.id = 'wizard-progress-done';
3906 29 Apr 16 nicklas 1282         done.className = 'progress-bar-done bg-filled-100 topborder bottomborder leftborder';
3904 29 Apr 16 nicklas 1283         progressBar.appendChild(done);
3904 29 Apr 16 nicklas 1284       }
3904 29 Apr 16 nicklas 1285       var remain = Doc.element('wizard-progress-remain');
3904 29 Apr 16 nicklas 1286       if (!remain)
3904 29 Apr 16 nicklas 1287       {
3904 29 Apr 16 nicklas 1288         remain = document.createElement('span');
3904 29 Apr 16 nicklas 1289         remain.id = 'wizard-progress-remain';
3906 29 Apr 16 nicklas 1290         remain.className = 'progress-bar-remain topborder bottomborder rightborder';
3904 29 Apr 16 nicklas 1291         progressBar.appendChild(remain);
3904 29 Apr 16 nicklas 1292       }
3904 29 Apr 16 nicklas 1293         
3904 29 Apr 16 nicklas 1294       progressBar.setAttribute('value', '0%');
3904 29 Apr 16 nicklas 1295       done.style.width = '0%';
3904 29 Apr 16 nicklas 1296       remain.style.width = '100%';
5962 03 Jun 20 nicklas 1297       Doc.show(progressMain);
5962 03 Jun 20 nicklas 1298       Doc.hide('wizard-status');
3904 29 Apr 16 nicklas 1299       
3904 29 Apr 16 nicklas 1300       // Initial request for updating the progress bar
4477 03 May 17 nicklas 1301       progressTimer = setTimeout(internal.requestProgressUpdate, 1500, progress);
3904 29 Apr 16 nicklas 1302     }
5962 03 Jun 20 nicklas 1303     else
5962 03 Jun 20 nicklas 1304     {
5962 03 Jun 20 nicklas 1305       wizard.setWizardStatus('loading', msg  || 'Working, please wait...');
5962 03 Jun 20 nicklas 1306     }
2599 25 Aug 14 nicklas 1307   }
3904 29 Apr 16 nicklas 1308   
3904 29 Apr 16 nicklas 1309   /**
3904 29 Apr 16 nicklas 1310     Make a request for the progress information. The 'progress'
3904 29 Apr 16 nicklas 1311     parameter is the name of a progress bar.
3904 29 Apr 16 nicklas 1312   */
3904 29 Apr 16 nicklas 1313   internal.requestProgressUpdate = function(progress)
3904 29 Apr 16 nicklas 1314   {
3904 29 Apr 16 nicklas 1315     if (hasFatalError) return;
3904 29 Apr 16 nicklas 1316     var url = '../Session.servlet?ID='+App.getSessionId();
3904 29 Apr 16 nicklas 1317     url += '&cmd=GetProgress';
3904 29 Apr 16 nicklas 1318     url += '&name='+encodeURIComponent(progress);
3904 29 Apr 16 nicklas 1319     
3904 29 Apr 16 nicklas 1320     var request = Ajax.getXmlHttpRequest();
3904 29 Apr 16 nicklas 1321     request.open("GET", url, true);
3904 29 Apr 16 nicklas 1322     Ajax.setReadyStateHandler(request, internal.onProgressReport, internal.onProgressReport);
3904 29 Apr 16 nicklas 1323     request.send(null);
3904 29 Apr 16 nicklas 1324   }
3904 29 Apr 16 nicklas 1325   
3904 29 Apr 16 nicklas 1326   /**
3904 29 Apr 16 nicklas 1327     Callback when receiving a progress update.
3904 29 Apr 16 nicklas 1328   */
3904 29 Apr 16 nicklas 1329   internal.onProgressReport = function(request)
3904 29 Apr 16 nicklas 1330   {
3904 29 Apr 16 nicklas 1331     if (hasFatalError) return;
3904 29 Apr 16 nicklas 1332     if (debug) App.debug(Strings.encodeTags(request.responseText));
3904 29 Apr 16 nicklas 1333     var response;
3904 29 Apr 16 nicklas 1334     var error = false;
3904 29 Apr 16 nicklas 1335     try
3904 29 Apr 16 nicklas 1336     {
3904 29 Apr 16 nicklas 1337       response = JSON.parse(request.responseText);
3904 29 Apr 16 nicklas 1338       if (response.status != 'ok')
3904 29 Apr 16 nicklas 1339       {
3904 29 Apr 16 nicklas 1340         error = response.message || response.stacktrace || 'Unexpected error';
3904 29 Apr 16 nicklas 1341       }
3904 29 Apr 16 nicklas 1342     }
3904 29 Apr 16 nicklas 1343     catch (ex)
3904 29 Apr 16 nicklas 1344     {
3904 29 Apr 16 nicklas 1345       error = ex;
3904 29 Apr 16 nicklas 1346     }
3904 29 Apr 16 nicklas 1347     
3904 29 Apr 16 nicklas 1348     if (error)
3904 29 Apr 16 nicklas 1349     {
3904 29 Apr 16 nicklas 1350       return;
3904 29 Apr 16 nicklas 1351     }
2599 25 Aug 14 nicklas 1352
3904 29 Apr 16 nicklas 1353     var progress = response.progress;
5962 03 Jun 20 nicklas 1354     var progressMain = Doc.element('wizard-progress');
3904 29 Apr 16 nicklas 1355
5962 03 Jun 20 nicklas 1356     if (!progress || progress.percent >= 100) 
3904 29 Apr 16 nicklas 1357     {
5962 03 Jun 20 nicklas 1358       // Give up if no progress information or finished
5962 03 Jun 20 nicklas 1359       progressTimer = null;
5962 03 Jun 20 nicklas 1360       Doc.hide(progressMain);
3904 29 Apr 16 nicklas 1361       return;
3904 29 Apr 16 nicklas 1362     }
3904 29 Apr 16 nicklas 1363     
5962 03 Jun 20 nicklas 1364     var progressBar = Doc.element('wizard-progress-bar');
5962 03 Jun 20 nicklas 1365     var progressMsg = Doc.element('wizard-progress-msg');
3904 29 Apr 16 nicklas 1366     var done = Doc.element('wizard-progress-done');
3904 29 Apr 16 nicklas 1367     var remain = Doc.element('wizard-progress-remain');
3904 29 Apr 16 nicklas 1368
3904 29 Apr 16 nicklas 1369     progressBar.setAttribute('value', progress.percent+'%');
3904 29 Apr 16 nicklas 1370     done.style.width = progress.percent+'%';
3904 29 Apr 16 nicklas 1371     remain.style.width = (100-progress.percent)+'%';
3904 29 Apr 16 nicklas 1372     
3904 29 Apr 16 nicklas 1373     if (progress.message)
3904 29 Apr 16 nicklas 1374     {
5962 03 Jun 20 nicklas 1375       progressMsg.innerHTML = Strings.encodeTags(progress.message);
3904 29 Apr 16 nicklas 1376     }
3904 29 Apr 16 nicklas 1377     
3904 29 Apr 16 nicklas 1378     if (progress.percent < 100)
3904 29 Apr 16 nicklas 1379     {
3904 29 Apr 16 nicklas 1380       // Continue to request updates until we 100% has been reached
4477 03 May 17 nicklas 1381       progressTimer = setTimeout(internal.requestProgressUpdate, 1500, progress.name);
3904 29 Apr 16 nicklas 1382     }
3904 29 Apr 16 nicklas 1383   }
3904 29 Apr 16 nicklas 1384
2618 01 Sep 14 nicklas 1385   wizard.showStatusMessage = function(msg)
2618 01 Sep 14 nicklas 1386   {
2803 14 Oct 14 nicklas 1387     wizard.setWizardStatus('messagecontainer note', msg);
2618 01 Sep 14 nicklas 1388   }
2618 01 Sep 14 nicklas 1389   
5017 09 Oct 18 nicklas 1390   wizard.showGoNextConfirmation = function(verify, msg, defaultChecked)
2602 27 Aug 14 nicklas 1391   {
2602 27 Aug 14 nicklas 1392     var check = '';
2602 27 Aug 14 nicklas 1393     if (verify)
2602 27 Aug 14 nicklas 1394     {
5017 09 Oct 18 nicklas 1395       check = '<input type="checkbox" name="verifyGoNext" id="verifyGoNext"'+(defaultChecked?' checked':'')+'>';
5017 09 Oct 18 nicklas 1396       if (!defaultChecked)
5017 09 Oct 18 nicklas 1397       {
5017 09 Oct 18 nicklas 1398         Doc.addClass('gonext', 'disabled');
5017 09 Oct 18 nicklas 1399         Doc.addClass('goregister', 'disabled');
5017 09 Oct 18 nicklas 1400       }
2602 27 Aug 14 nicklas 1401     }
2602 27 Aug 14 nicklas 1402     
2602 27 Aug 14 nicklas 1403     var gonext = Doc.element('gonext-message');
2602 27 Aug 14 nicklas 1404     gonext.innerHTML = check + msg;
2602 27 Aug 14 nicklas 1405     Doc.show(gonext);
2602 27 Aug 14 nicklas 1406     
2602 27 Aug 14 nicklas 1407     if (verify)
2602 27 Aug 14 nicklas 1408     {
2602 27 Aug 14 nicklas 1409       Events.addEventHandler('verifyGoNext', 'click', internal.verifyInternalOnClick);
2602 27 Aug 14 nicklas 1410     }
2602 27 Aug 14 nicklas 1411   }
2602 27 Aug 14 nicklas 1412   
2602 27 Aug 14 nicklas 1413   wizard.hideGoNextConfirmation = function()
2602 27 Aug 14 nicklas 1414   {
2602 27 Aug 14 nicklas 1415     var gonext = Doc.element('gonext-message');
2602 27 Aug 14 nicklas 1416     gonext.innerHTML = '';
2602 27 Aug 14 nicklas 1417     Doc.hide(gonext);
2602 27 Aug 14 nicklas 1418     Doc.removeClass('gonext', 'disabled');
2602 27 Aug 14 nicklas 1419     Doc.removeClass('goregister', 'disabled');
2602 27 Aug 14 nicklas 1420   }
2602 27 Aug 14 nicklas 1421   
2602 27 Aug 14 nicklas 1422   internal.verifyInternalOnClick = function(event)
2602 27 Aug 14 nicklas 1423   {
2602 27 Aug 14 nicklas 1424     var checked = event.currentTarget.checked;
2602 27 Aug 14 nicklas 1425     Doc.addOrRemoveClass('goregister', 'disabled', !checked);
2602 27 Aug 14 nicklas 1426     Doc.addOrRemoveClass('gonext', 'disabled', !checked);
2602 27 Aug 14 nicklas 1427   }
2602 27 Aug 14 nicklas 1428   
2599 25 Aug 14 nicklas 1429   /**
2599 25 Aug 14 nicklas 1430     Show final registration messages in a list.
2599 25 Aug 14 nicklas 1431   */
2599 25 Aug 14 nicklas 1432   wizard.showFinalMessage = function(messages)
2599 25 Aug 14 nicklas 1433   {
2675 17 Sep 14 nicklas 1434     var msg = internal.generateMessageList(messages);
2803 14 Oct 14 nicklas 1435     wizard.setWizardStatus('success', msg.html);
4477 03 May 17 nicklas 1436     if (progressTimer) clearTimeout(progressTimer);
2675 17 Sep 14 nicklas 1437     return { 'errors': msg.errors, 'warnings': msg.warnings };
2675 17 Sep 14 nicklas 1438   }
2675 17 Sep 14 nicklas 1439   
2924 13 Nov 14 nicklas 1440   /**
2924 13 Nov 14 nicklas 1441     Show the debug toolbar.
2924 13 Nov 14 nicklas 1442   */
2924 13 Nov 14 nicklas 1443   wizard.showDebugTools = function()
2924 13 Nov 14 nicklas 1444   {
2924 13 Nov 14 nicklas 1445     var debugTools = Doc.element('debug-tools');
2924 13 Nov 14 nicklas 1446     if (!debugTools)
2924 13 Nov 14 nicklas 1447     {
2924 13 Nov 14 nicklas 1448       debugTools = document.createElement('div');
2924 13 Nov 14 nicklas 1449       debugTools.id = 'debug-tools';
2924 13 Nov 14 nicklas 1450       var wiz = Doc.element('wizard');
2924 13 Nov 14 nicklas 1451       wiz.parentNode.appendChild(debugTools);
2924 13 Nov 14 nicklas 1452     }
2924 13 Nov 14 nicklas 1453     var debugTitle = Doc.element('debug-tools-title');
2924 13 Nov 14 nicklas 1454     if (!debugTitle)
2924 13 Nov 14 nicklas 1455     {
2924 13 Nov 14 nicklas 1456       debugTitle = document.createElement('div');
2924 13 Nov 14 nicklas 1457       debugTitle.id = 'debug-tools-title';
2924 13 Nov 14 nicklas 1458       debugTitle.innerHTML = 'DEBUG TOOLS â€” USE FOR DEBUGGING ONLY â€” DO NOT USE ON PRODUCTION SERVER';
2924 13 Nov 14 nicklas 1459       debugTools.parentNode.insertBefore(debugTitle, debugTools);
2924 13 Nov 14 nicklas 1460     }
2924 13 Nov 14 nicklas 1461     Doc.show(debugTools, 'table-cell');
2924 13 Nov 14 nicklas 1462     Doc.show('debug-tools-title');
5161 30 Nov 18 nicklas 1463     Doc.addClass('wizard', 'debug-mode');
2924 13 Nov 14 nicklas 1464   }
2924 13 Nov 14 nicklas 1465
2924 13 Nov 14 nicklas 1466   /**
2924 13 Nov 14 nicklas 1467     Hide the debug toolbar.
2924 13 Nov 14 nicklas 1468   */
2924 13 Nov 14 nicklas 1469   wizard.hideDebugTools = function()
2924 13 Nov 14 nicklas 1470   {
2924 13 Nov 14 nicklas 1471     Doc.hide('debug-tools');
2924 13 Nov 14 nicklas 1472     Doc.hide('debug-tools-title');
5161 30 Nov 18 nicklas 1473     Doc.removeClass('wizard', 'debug-mode');
2924 13 Nov 14 nicklas 1474   }
2924 13 Nov 14 nicklas 1475
2691 24 Sep 14 nicklas 1476   
2691 24 Sep 14 nicklas 1477   /*
2691 24 Sep 14 nicklas 1478     Call this method once to start a repeating timer that will submit
2691 24 Sep 14 nicklas 1479     an Ajax request at regular intervals in order to keep the current login
2691 24 Sep 14 nicklas 1480     session alive. Once started there is no way to stop the timer except
2691 24 Sep 14 nicklas 1481     navigating away from the page.
2691 24 Sep 14 nicklas 1482     @param reggieRoot Optional relative path to the root of the Reggie installation (for pages in a subdirectory)
2691 24 Sep 14 nicklas 1483   */
2691 24 Sep 14 nicklas 1484   wizard.keepSessionAlive = function()
2691 24 Sep 14 nicklas 1485   {
2691 24 Sep 14 nicklas 1486     if (debug)
2691 24 Sep 14 nicklas 1487     {
2691 24 Sep 14 nicklas 1488       // Create a 'simulate timeout' checkbox
2691 24 Sep 14 nicklas 1489       var div = document.createElement('div');
2774 09 Oct 14 nicklas 1490       div.id = 'simulateTimeoutDiv';
2691 24 Sep 14 nicklas 1491       div.style.textAlign = 'center';
2691 24 Sep 14 nicklas 1492       div.innerHTML = '<label><input type="checkbox" id="simulateTimeout">Simulate session timeout</label>';
2924 13 Nov 14 nicklas 1493
2924 13 Nov 14 nicklas 1494       wizard.showDebugTools();
2924 13 Nov 14 nicklas 1495       var p = Doc.element('debug-tools');
2924 13 Nov 14 nicklas 1496       p.appendChild(div);
2691 24 Sep 14 nicklas 1497     }
2691 24 Sep 14 nicklas 1498     
2691 24 Sep 14 nicklas 1499     internal.scheduleKeepAlive();
2691 24 Sep 14 nicklas 1500   }
2691 24 Sep 14 nicklas 1501   
2691 24 Sep 14 nicklas 1502   // Schedule a keep-alive request
2691 24 Sep 14 nicklas 1503   internal.scheduleKeepAlive = function()
2691 24 Sep 14 nicklas 1504   {
2691 24 Sep 14 nicklas 1505     setTimeout(internal.sendKeepAlive, debug ? 5000 : 30000);
2691 24 Sep 14 nicklas 1506   }
2691 24 Sep 14 nicklas 1507
2691 24 Sep 14 nicklas 1508   // Send a keep-alive request
2691 24 Sep 14 nicklas 1509   internal.sendKeepAlive = function()
2691 24 Sep 14 nicklas 1510   {
2774 09 Oct 14 nicklas 1511     if (hasSentRegistration || hasFatalError) 
2774 09 Oct 14 nicklas 1512     {
2774 09 Oct 14 nicklas 1513       if (debug) Doc.hide('simulateTimeoutDiv');
2774 09 Oct 14 nicklas 1514       return;
2774 09 Oct 14 nicklas 1515     }
2691 24 Sep 14 nicklas 1516     var simulateTimeout = false;
2691 24 Sep 14 nicklas 1517     if (debug) 
2691 24 Sep 14 nicklas 1518     {
2691 24 Sep 14 nicklas 1519       var msg = 'Checking if session '+App.getSessionId() + ' is alive';
2691 24 Sep 14 nicklas 1520       var timeoutDiv = Doc.element('simulateTimeout');
2691 24 Sep 14 nicklas 1521       if (timeoutDiv && timeoutDiv.checked)
2691 24 Sep 14 nicklas 1522       {
2691 24 Sep 14 nicklas 1523         simulateTimeout = true;
2691 24 Sep 14 nicklas 1524         timeoutDiv.checked = false;
2691 24 Sep 14 nicklas 1525         msg += ' (simulating a session timeout)'
2691 24 Sep 14 nicklas 1526       }
2691 24 Sep 14 nicklas 1527       App.debug(msg);
2691 24 Sep 14 nicklas 1528     }
2691 24 Sep 14 nicklas 1529     
2691 24 Sep 14 nicklas 1530     var url = '../Session.servlet?ID='+App.getSessionId();
2691 24 Sep 14 nicklas 1531     url += '&cmd=CheckSession';
2691 24 Sep 14 nicklas 1532     if (simulateTimeout) url += '&simulateTimeout=1';
2691 24 Sep 14 nicklas 1533     
5605 13 Sep 19 nicklas 1534     var request = Ajax.getXmlHttpRequest();
5605 13 Sep 19 nicklas 1535     request.open("GET", url, true);
5605 13 Sep 19 nicklas 1536     Ajax.setReadyStateHandler(request, internal.onKeepAliveResponse, internal.onKeepAliveResponse);
5605 13 Sep 19 nicklas 1537     request.send(null);
2691 24 Sep 14 nicklas 1538   }
2691 24 Sep 14 nicklas 1539
2691 24 Sep 14 nicklas 1540   
5605 13 Sep 19 nicklas 1541   internal.onKeepAliveResponse = function(request)
2691 24 Sep 14 nicklas 1542   {
5605 13 Sep 19 nicklas 1543     if (debug) App.debug(request.responseText);
5605 13 Sep 19 nicklas 1544     var response = null;
5605 13 Sep 19 nicklas 1545     try
5605 13 Sep 19 nicklas 1546     {
5605 13 Sep 19 nicklas 1547       if (request.status != 200)
5605 13 Sep 19 nicklas 1548       {
5605 13 Sep 19 nicklas 1549         throw new Error(request.responseText);
5605 13 Sep 19 nicklas 1550       }
5605 13 Sep 19 nicklas 1551       else
5605 13 Sep 19 nicklas 1552       {
5605 13 Sep 19 nicklas 1553         if (request.getResponseHeader('Content-Type').indexOf('json') != -1)
5605 13 Sep 19 nicklas 1554         {
5605 13 Sep 19 nicklas 1555           response = JSON.parse(request.responseText);
5605 13 Sep 19 nicklas 1556           if (response.status != 'ok')
5605 13 Sep 19 nicklas 1557           {
5605 13 Sep 19 nicklas 1558             throw new Error(response.message || response.stacktrace);
5605 13 Sep 19 nicklas 1559           }
5605 13 Sep 19 nicklas 1560         }
5605 13 Sep 19 nicklas 1561       }
5605 13 Sep 19 nicklas 1562     }
5605 13 Sep 19 nicklas 1563     catch (err)
5605 13 Sep 19 nicklas 1564     {
5605 13 Sep 19 nicklas 1565       Wizard.setFatalError(err);
5605 13 Sep 19 nicklas 1566       return;
5605 13 Sep 19 nicklas 1567     }
5605 13 Sep 19 nicklas 1568     
2691 24 Sep 14 nicklas 1569     if (!response.session)
2691 24 Sep 14 nicklas 1570     {
2691 24 Sep 14 nicklas 1571       // Hide navigation buttons
2691 24 Sep 14 nicklas 1572       Doc.hide('navigation');
2691 24 Sep 14 nicklas 1573       Doc.addClass('wizard', 'disabled');
2691 24 Sep 14 nicklas 1574       
2691 24 Sep 14 nicklas 1575       // Show message
2691 24 Sep 14 nicklas 1576       var div = Doc.element('timeoutMessage');
2691 24 Sep 14 nicklas 1577       if (!div)
2691 24 Sep 14 nicklas 1578       {
2691 24 Sep 14 nicklas 1579         div = document.createElement('div');
2691 24 Sep 14 nicklas 1580         div.id = 'timeoutMessage';
2691 24 Sep 14 nicklas 1581         div.className = 'messagecontainer error link';
2691 24 Sep 14 nicklas 1582         div.innerHTML = 'You have been logged out due to inactivity or unstable internet connection. Click HERE to login again!';
2691 24 Sep 14 nicklas 1583         div.addEventListener('click', internal.openLoginWindow, false);
2691 24 Sep 14 nicklas 1584         div.addEventListener('logged-in', internal.loggedInAgain, false);
2691 24 Sep 14 nicklas 1585         var frm = document.forms['reggie'];
2691 24 Sep 14 nicklas 1586         frm.appendChild(div);
2691 24 Sep 14 nicklas 1587       }
2691 24 Sep 14 nicklas 1588       Doc.show(div);
2691 24 Sep 14 nicklas 1589     }
2691 24 Sep 14 nicklas 1590     else
2691 24 Sep 14 nicklas 1591     {
2691 24 Sep 14 nicklas 1592       internal.scheduleKeepAlive();
2691 24 Sep 14 nicklas 1593     }
2691 24 Sep 14 nicklas 1594   }
2691 24 Sep 14 nicklas 1595
2691 24 Sep 14 nicklas 1596   // Open popup window for logging in again
2691 24 Sep 14 nicklas 1597   internal.openLoginWindow = function()
2691 24 Sep 14 nicklas 1598   {
2691 24 Sep 14 nicklas 1599     if (debug) App.debug('Need to login again!');
2691 24 Sep 14 nicklas 1600     var url = '../keep_session_alive.jsp?ID='+App.getSessionId();
2691 24 Sep 14 nicklas 1601     Dialogs.openPopup(url, 'KeepSessionAlive', 800, 600);
2691 24 Sep 14 nicklas 1602   }
2691 24 Sep 14 nicklas 1603
2691 24 Sep 14 nicklas 1604   // Callback when the user has been successfully logged in
2691 24 Sep 14 nicklas 1605   internal.loggedInAgain = function()
2691 24 Sep 14 nicklas 1606   {
2691 24 Sep 14 nicklas 1607     if (debug) App.debug('Logged in again!');
2691 24 Sep 14 nicklas 1608     Doc.removeClass('wizard', 'disabled');
2691 24 Sep 14 nicklas 1609     Doc.hide('timeoutMessage');
2691 24 Sep 14 nicklas 1610     Doc.show('navigation');
2691 24 Sep 14 nicklas 1611     internal.scheduleKeepAlive();
2691 24 Sep 14 nicklas 1612   }
2691 24 Sep 14 nicklas 1613
2675 17 Sep 14 nicklas 1614   internal.generateMessageList = function(messages)
2675 17 Sep 14 nicklas 1615   {
2599 25 Aug 14 nicklas 1616     var msg = '<ul>';
6352 18 Aug 21 nicklas 1617     var debugMsg = '';
2675 17 Sep 14 nicklas 1618     var numWarnings = 0;
2675 17 Sep 14 nicklas 1619     var numErrors = 0;
2599 25 Aug 14 nicklas 1620     for (var i = 0; i < messages.length; i++)
2599 25 Aug 14 nicklas 1621     {
2599 25 Aug 14 nicklas 1622       var msgLine = messages[i];
6914 01 Dec 22 nicklas 1623       if (msgLine.indexOf('[HTML]') >= 0)
6914 01 Dec 22 nicklas 1624       {
6914 01 Dec 22 nicklas 1625         msgLine = msgLine.replace('[HTML]', '');
6914 01 Dec 22 nicklas 1626       }
6914 01 Dec 22 nicklas 1627       else
6914 01 Dec 22 nicklas 1628       {
6914 01 Dec 22 nicklas 1629         msgLine = Strings.encodeTags(msgLine);
6914 01 Dec 22 nicklas 1630       }
2599 25 Aug 14 nicklas 1631       if (msgLine.indexOf('[Warning]') >= 0)
2599 25 Aug 14 nicklas 1632       {
6914 01 Dec 22 nicklas 1633         msg += '<li class="warning">'+msgLine.replace('[Warning]', '');
2675 17 Sep 14 nicklas 1634         numWarnings++;
2599 25 Aug 14 nicklas 1635       }
2675 17 Sep 14 nicklas 1636       else if (msgLine.indexOf('[Error]') >= 0)
2675 17 Sep 14 nicklas 1637       {
6914 01 Dec 22 nicklas 1638         msg += '<li class="error">'+msgLine.replace('[Error]', '');
2675 17 Sep 14 nicklas 1639         numErrors++;
2675 17 Sep 14 nicklas 1640       }
4973 20 Sep 18 nicklas 1641       else if (msgLine.indexOf('[Debug]') >= 0)
4973 20 Sep 18 nicklas 1642       {
6914 01 Dec 22 nicklas 1643         debugMsg += '<li class="debug">'+msgLine.replace('[Debug]', '');
4973 20 Sep 18 nicklas 1644       }
2599 25 Aug 14 nicklas 1645       else
2599 25 Aug 14 nicklas 1646       {
6914 01 Dec 22 nicklas 1647         msg += '<li class="ok">'+msgLine;
2599 25 Aug 14 nicklas 1648       }
2599 25 Aug 14 nicklas 1649     }
6352 18 Aug 21 nicklas 1650     if (debug) msg += debugMsg;
6352 18 Aug 21 nicklas 1651     msg += '</ul>';
2675 17 Sep 14 nicklas 1652     return { 'html': msg, 'errors': numErrors, 'warnings': numWarnings };
2599 25 Aug 14 nicklas 1653   }
2599 25 Aug 14 nicklas 1654   
2599 25 Aug 14 nicklas 1655   /**
2599 25 Aug 14 nicklas 1656     Hide the current global wizard-status message.
2599 25 Aug 14 nicklas 1657   */
2599 25 Aug 14 nicklas 1658   wizard.hideWizardStatus = function()
2599 25 Aug 14 nicklas 1659   {
2599 25 Aug 14 nicklas 1660     Doc.hide('wizard-status');
3904 29 Apr 16 nicklas 1661     Doc.hide('wizard-progress');
2599 25 Aug 14 nicklas 1662   }
2599 25 Aug 14 nicklas 1663     
2599 25 Aug 14 nicklas 1664   /**
2599 25 Aug 14 nicklas 1665     Initialize the wizard:
2599 25 Aug 14 nicklas 1666     
2599 25 Aug 14 nicklas 1667     * Check that a project is active
2599 25 Aug 14 nicklas 1668   */
2599 25 Aug 14 nicklas 1669   internal.initWizard = function()
2599 25 Aug 14 nicklas 1670   {
2599 25 Aug 14 nicklas 1671     // Check if project is enabled
2599 25 Aug 14 nicklas 1672     var wiz = Doc.element('wizard');
2599 25 Aug 14 nicklas 1673     if (wiz)
2599 25 Aug 14 nicklas 1674     {
2599 25 Aug 14 nicklas 1675       if (!App.getActiveProjectId())
2599 25 Aug 14 nicklas 1676       {
2599 25 Aug 14 nicklas 1677         wizard.setFatalError('No project has been selected.');
2599 25 Aug 14 nicklas 1678       }
2658 12 Sep 14 nicklas 1679       window.addEventListener('beforeunload', internal.confirmLeaveWizard);
2599 25 Aug 14 nicklas 1680     }
2801 13 Oct 14 nicklas 1681     
3513 24 Sep 15 nicklas 1682     var path = document.getElementsByClassName('path');
2801 13 Oct 14 nicklas 1683     if (path && path.length)
2801 13 Oct 14 nicklas 1684     {
3513 24 Sep 15 nicklas 1685       var reggieVersion = document.createElement('span');
3513 24 Sep 15 nicklas 1686       reggieVersion.id = 'reggie-version';
3513 24 Sep 15 nicklas 1687       reggieVersion.innerHTML = '[Reggie '+Reggie.VERSION+']';
3513 24 Sep 15 nicklas 1688       path[0].appendChild(reggieVersion);
2801 13 Oct 14 nicklas 1689     }
2924 13 Nov 14 nicklas 1690     
2599 25 Aug 14 nicklas 1691   }
2599 25 Aug 14 nicklas 1692   
2658 12 Sep 14 nicklas 1693   internal.confirmLeaveWizard = function(event)
2658 12 Sep 14 nicklas 1694   {
2676 17 Sep 14 nicklas 1695     if (hasFatalError) return;
2658 12 Sep 14 nicklas 1696     if (!forceConfirm)
2658 12 Sep 14 nicklas 1697     {
5058 29 Oct 18 nicklas 1698       if (currentStep == 1 && noConfirmOnFirstStep || noConfirm) return;
2658 12 Sep 14 nicklas 1699       if (hasSentRegistration && numLiveAsyncRequests == 0) return;
2658 12 Sep 14 nicklas 1700     }
2658 12 Sep 14 nicklas 1701     forceConfirm = false;
2658 12 Sep 14 nicklas 1702     event.preventDefault();
2658 12 Sep 14 nicklas 1703   }
2658 12 Sep 14 nicklas 1704   
2599 25 Aug 14 nicklas 1705   // Initialize some event handlers
2599 25 Aug 14 nicklas 1706   internal.initElements = function(element, autoInit)
2599 25 Aug 14 nicklas 1707   {
2599 25 Aug 14 nicklas 1708     if (autoInit == 'focus-on-enter')
2599 25 Aug 14 nicklas 1709     {
2599 25 Aug 14 nicklas 1710       Events.addEventHandler(element, 'keypress', wizard.focusOnEnter);
2599 25 Aug 14 nicklas 1711     }
2599 25 Aug 14 nicklas 1712   }
2599 25 Aug 14 nicklas 1713   
2599 25 Aug 14 nicklas 1714   /**
2599 25 Aug 14 nicklas 1715     Display a global wizard-status message. This may for example be
2599 25 Aug 14 nicklas 1716     an error message, a work-in-progress indicator, etc.
2599 25 Aug 14 nicklas 1717   */
2803 14 Oct 14 nicklas 1718   wizard.setWizardStatus = function(className, msg)
2599 25 Aug 14 nicklas 1719   {
2599 25 Aug 14 nicklas 1720     var status = Doc.element('wizard-status');
2599 25 Aug 14 nicklas 1721     status.className = className;
2599 25 Aug 14 nicklas 1722     status.innerHTML = msg;
2599 25 Aug 14 nicklas 1723     Doc.show(status);
2599 25 Aug 14 nicklas 1724   }
2599 25 Aug 14 nicklas 1725
2599 25 Aug 14 nicklas 1726   // Disable all form elements inside the given container
2599 25 Aug 14 nicklas 1727   internal.disableAllFormElements = function(container, hideButtons)
2599 25 Aug 14 nicklas 1728   {
2599 25 Aug 14 nicklas 1729     container = Doc.element(container);
2599 25 Aug 14 nicklas 1730     var input = container.getElementsByTagName('input');
2599 25 Aug 14 nicklas 1731     for (var i = 0; i < input.length; i++)
2599 25 Aug 14 nicklas 1732     {
2599 25 Aug 14 nicklas 1733       input[i].disabled = true;
2599 25 Aug 14 nicklas 1734     }
2599 25 Aug 14 nicklas 1735     var select = container.getElementsByTagName('select');
2599 25 Aug 14 nicklas 1736     for (var i = 0; i < select.length; i++)
2599 25 Aug 14 nicklas 1737     {
2599 25 Aug 14 nicklas 1738       select[i].disabled = true;
2599 25 Aug 14 nicklas 1739     }
2599 25 Aug 14 nicklas 1740     var text = container.getElementsByTagName('textarea');
2599 25 Aug 14 nicklas 1741     for (var i = 0; i < text.length; i++)
2599 25 Aug 14 nicklas 1742     {
2599 25 Aug 14 nicklas 1743       text[i].disabled = true;
2599 25 Aug 14 nicklas 1744     }
2599 25 Aug 14 nicklas 1745     if (hideButtons)
2599 25 Aug 14 nicklas 1746     {
2599 25 Aug 14 nicklas 1747       internal.hideButtons(container);
2599 25 Aug 14 nicklas 1748     }
2599 25 Aug 14 nicklas 1749   }
2599 25 Aug 14 nicklas 1750
2599 25 Aug 14 nicklas 1751   // Hide all 'basicbuttons':s in the given container
2599 25 Aug 14 nicklas 1752   internal.hideButtons = function(container)
2599 25 Aug 14 nicklas 1753   {
2599 25 Aug 14 nicklas 1754     container = Doc.element(container);
2599 25 Aug 14 nicklas 1755     var buttons = container.getElementsByClassName('basicbutton');
2599 25 Aug 14 nicklas 1756     for (var i = 0; i < buttons.length; i++)
2599 25 Aug 14 nicklas 1757     {
2599 25 Aug 14 nicklas 1758       Doc.hide(buttons[i]);
2599 25 Aug 14 nicklas 1759     }
2599 25 Aug 14 nicklas 1760   }
2599 25 Aug 14 nicklas 1761
2599 25 Aug 14 nicklas 1762   Doc.addFinalizer(internal.initWizard);
2599 25 Aug 14 nicklas 1763   Doc.addElementInitializer(internal.initElements);
2599 25 Aug 14 nicklas 1764   return wizard;
2599 25 Aug 14 nicklas 1765 }();
2599 25 Aug 14 nicklas 1766