extensions/net.sf.basedb.relax/trunk/resources/relax.js

Code
Comments
Other
Rev Date Author Line
4354 13 Feb 17 nicklas 1
4354 13 Feb 17 nicklas 2 var Relax = function()
4354 13 Feb 17 nicklas 3 {
4354 13 Feb 17 nicklas 4   var relax = {};
4354 13 Feb 17 nicklas 5   
5979 24 Jun 20 nicklas 6   relax.VERSION = '1.7-dev';
4354 13 Feb 17 nicklas 7
4632 22 Nov 17 nicklas 8   
4632 22 Nov 17 nicklas 9   relax.checkIsAdmin = function(message, callback, servletDir)
4632 22 Nov 17 nicklas 10   {
4632 22 Nov 17 nicklas 11     var url = (servletDir || '../') + 'Session.servlet?ID='+App.getSessionId();
4632 22 Nov 17 nicklas 12     url += '&cmd=CheckIsAdmin';
4632 22 Nov 17 nicklas 13     if (message) url += '&message='+encodeURIComponent(message);
4632 22 Nov 17 nicklas 14     if (!callback) callback = function() {};
4632 22 Nov 17 nicklas 15     Wizard.asyncJsonRequest(url, callback);
4632 22 Nov 17 nicklas 16   }
4632 22 Nov 17 nicklas 17   
4354 13 Feb 17 nicklas 18   return relax;
4354 13 Feb 17 nicklas 19 }();
4354 13 Feb 17 nicklas 20
4354 13 Feb 17 nicklas 21
4354 13 Feb 17 nicklas 22 var Wizard = function()
4354 13 Feb 17 nicklas 23 {
4354 13 Feb 17 nicklas 24   var wizard = {};
4354 13 Feb 17 nicklas 25   var internal = {};
5284 06 Feb 19 nicklas 26   var debug = 0;
4354 13 Feb 17 nicklas 27   
4354 13 Feb 17 nicklas 28   var numLiveAsyncRequests = 0;
4354 13 Feb 17 nicklas 29   var hasFatalError = false;
4631 21 Nov 17 nicklas 30   var currentStep = 1;
4631 21 Nov 17 nicklas 31   var hasSentRegistration = false;
4631 21 Nov 17 nicklas 32   var forceConfirm = false;
4631 21 Nov 17 nicklas 33   var noConfirmOnFirstStep = true;
5078 08 Nov 18 nicklas 34   var progressTimer = 0;
4354 13 Feb 17 nicklas 35   
4354 13 Feb 17 nicklas 36   /**
4354 13 Feb 17 nicklas 37     Submit an ansynchronous request for JSON data. 'GET' method
4354 13 Feb 17 nicklas 38     is used if 'method' parameter is not set.
4354 13 Feb 17 nicklas 39     The 'callback' should be a method accepting a single
4354 13 Feb 17 nicklas 40     JSON parameter object. If the 'status' of the response
4354 13 Feb 17 nicklas 41     is not 'ok' this method will call setFatalError and
4354 13 Feb 17 nicklas 42     without calling the callback method.
4354 13 Feb 17 nicklas 43     
4354 13 Feb 17 nicklas 44     The 'errorCallback' is an optional function parameter that should
4354 13 Feb 17 nicklas 45     take two parameters. The first is an Error object and the second is
4354 13 Feb 17 nicklas 46     the JSON response. The seconds parameter only has a value if the error 
4354 13 Feb 17 nicklas 47     happens after parsing the response and is null otherwise.
4354 13 Feb 17 nicklas 48   */
4354 13 Feb 17 nicklas 49   wizard.asyncJsonRequest = function(url, callback, method, postdata, errorCallback)
4354 13 Feb 17 nicklas 50   {
4354 13 Feb 17 nicklas 51     if (debug)
4354 13 Feb 17 nicklas 52     {
4354 13 Feb 17 nicklas 53       App.debug((method || 'GET') + ': ' + url);
4354 13 Feb 17 nicklas 54       if (postdata) App.debug(postdata);
4354 13 Feb 17 nicklas 55     }
4354 13 Feb 17 nicklas 56     var request = Ajax.getXmlHttpRequest();
4354 13 Feb 17 nicklas 57     request.jsonCallback = callback;
4354 13 Feb 17 nicklas 58     request.errorCallback = errorCallback;
4354 13 Feb 17 nicklas 59     request.open(method || 'GET', url, true);
4354 13 Feb 17 nicklas 60     // Firefox only adds request header with needed "boundary" info, if request header is not set explicitly
4354 13 Feb 17 nicklas 61     if (postdata && !(postdata instanceof FormData)) 
4354 13 Feb 17 nicklas 62     {
4354 13 Feb 17 nicklas 63       request.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
4354 13 Feb 17 nicklas 64     }
4354 13 Feb 17 nicklas 65     Ajax.setReadyStateHandler(request, internal.asyncCallbackWrapper, internal.asyncCallbackWrapper);
4354 13 Feb 17 nicklas 66     numLiveAsyncRequests++;
4354 13 Feb 17 nicklas 67     request.send(postdata || null);
4354 13 Feb 17 nicklas 68   }
4354 13 Feb 17 nicklas 69   
4354 13 Feb 17 nicklas 70   /**
4354 13 Feb 17 nicklas 71     Callback wrapper for ansynchronous requests.
4354 13 Feb 17 nicklas 72   */
4354 13 Feb 17 nicklas 73   internal.asyncCallbackWrapper = function(request)
4354 13 Feb 17 nicklas 74   {
4354 13 Feb 17 nicklas 75     numLiveAsyncRequests--;
4354 13 Feb 17 nicklas 76     if (debug) App.debug(request.responseText);
4354 13 Feb 17 nicklas 77     if (!hasFatalError) Wizard.hideWizardStatus();
4354 13 Feb 17 nicklas 78
4354 13 Feb 17 nicklas 79     var response = null;
4354 13 Feb 17 nicklas 80     var messages = null;
4354 13 Feb 17 nicklas 81     try
4354 13 Feb 17 nicklas 82     {
4354 13 Feb 17 nicklas 83       if (request.status != 200)
4354 13 Feb 17 nicklas 84       {
4354 13 Feb 17 nicklas 85         throw new Error(request.responseText);
4354 13 Feb 17 nicklas 86       }
4354 13 Feb 17 nicklas 87       else
4354 13 Feb 17 nicklas 88       {
4354 13 Feb 17 nicklas 89         if (request.getResponseHeader('Content-Type').indexOf('json') != -1)
4354 13 Feb 17 nicklas 90         {
4354 13 Feb 17 nicklas 91           response = JSON.parse(request.responseText);
4354 13 Feb 17 nicklas 92           messages = response.messages;
4354 13 Feb 17 nicklas 93           if (response.status != 'ok')
4354 13 Feb 17 nicklas 94           {
4354 13 Feb 17 nicklas 95             throw new Error(response.message || response.stacktrace);
4354 13 Feb 17 nicklas 96           }
4354 13 Feb 17 nicklas 97         }
4354 13 Feb 17 nicklas 98         else
4354 13 Feb 17 nicklas 99         {
4354 13 Feb 17 nicklas 100           response = request.responseText;
4354 13 Feb 17 nicklas 101         }
4354 13 Feb 17 nicklas 102         if (request.jsonCallback && request.jsonCallback.call)
4354 13 Feb 17 nicklas 103         {
4354 13 Feb 17 nicklas 104           request.jsonCallback.call(null, response);
4354 13 Feb 17 nicklas 105         }
4354 13 Feb 17 nicklas 106       }
4354 13 Feb 17 nicklas 107     }
4354 13 Feb 17 nicklas 108     catch (err)
4354 13 Feb 17 nicklas 109     {
4354 13 Feb 17 nicklas 110       if (request.errorCallback && request.errorCallback.call)
4354 13 Feb 17 nicklas 111       {
4354 13 Feb 17 nicklas 112         request.errorCallback.call(null, err, response);
4354 13 Feb 17 nicklas 113       }
4354 13 Feb 17 nicklas 114       else
4354 13 Feb 17 nicklas 115       {
4354 13 Feb 17 nicklas 116         Wizard.setFatalError(err, messages);
4354 13 Feb 17 nicklas 117       }
4354 13 Feb 17 nicklas 118     }
4354 13 Feb 17 nicklas 119   }
4631 21 Nov 17 nicklas 120   
4631 21 Nov 17 nicklas 121   wizard.isValid = function(element)
4631 21 Nov 17 nicklas 122   {
4631 21 Nov 17 nicklas 123     return Data.int(element, 'valid', 1);
4631 21 Nov 17 nicklas 124   }
4354 13 Feb 17 nicklas 125
4631 21 Nov 17 nicklas 126   wizard.initFileSelectionField = function(element)
4631 21 Nov 17 nicklas 127   {
4631 21 Nov 17 nicklas 128     element = Doc.element(element);
4631 21 Nov 17 nicklas 129     Events.addEventHandler(element, 'change', wizard.fileChanged);
4631 21 Nov 17 nicklas 130     Events.sendChangeEvent(element);
4631 21 Nov 17 nicklas 131   }
4354 13 Feb 17 nicklas 132   
4631 21 Nov 17 nicklas 133   wizard.fileChanged = function(event)
4631 21 Nov 17 nicklas 134   {
4631 21 Nov 17 nicklas 135     var target = event.currentTarget;
4631 21 Nov 17 nicklas 136     
4631 21 Nov 17 nicklas 137     var isValid = false;
4631 21 Nov 17 nicklas 138     var isWarning = false;
4631 21 Nov 17 nicklas 139     
4631 21 Nov 17 nicklas 140     // Reset current status
4631 21 Nov 17 nicklas 141     wizard.setInputStatus(target);
4631 21 Nov 17 nicklas 142     
4631 21 Nov 17 nicklas 143     var path = target.value;
4631 21 Nov 17 nicklas 144     if (path == '')
4631 21 Nov 17 nicklas 145     {
4631 21 Nov 17 nicklas 146       // No file, is this an error or a warning?
4631 21 Nov 17 nicklas 147       var optional = target.className.indexOf('required') == -1;
4631 21 Nov 17 nicklas 148       wizard.setInputStatus(target, optional ? 'warning' : 'invalid', 'Missing');
4631 21 Nov 17 nicklas 149       isValid = optional;
4631 21 Nov 17 nicklas 150       isWarning = optional;
4631 21 Nov 17 nicklas 151     }
4631 21 Nov 17 nicklas 152     else
4631 21 Nov 17 nicklas 153     {
4631 21 Nov 17 nicklas 154       Wizard.setInputStatus(target, 'valid');
4631 21 Nov 17 nicklas 155       isValid = true;
4631 21 Nov 17 nicklas 156     }
4631 21 Nov 17 nicklas 157     
4631 21 Nov 17 nicklas 158     Data.set(target, 'valid', isValid ? 1 : 0);
4631 21 Nov 17 nicklas 159     Data.set(target, 'warning', isWarning ? 1 : 0);
4631 21 Nov 17 nicklas 160     
4631 21 Nov 17 nicklas 161     if (!isValid && target.focus) target.focus();
4631 21 Nov 17 nicklas 162   }
4631 21 Nov 17 nicklas 163   
4354 13 Feb 17 nicklas 164   /**
4631 21 Nov 17 nicklas 165     Change display status for an input field.
4631 21 Nov 17 nicklas 166     @param prefix ID prefix to locate tags
4631 21 Nov 17 nicklas 167     @param clazz The message clazz (valid, invalid, warning) or empty
4631 21 Nov 17 nicklas 168     @param message The message (may be empty)
4631 21 Nov 17 nicklas 169   */
4631 21 Nov 17 nicklas 170   wizard.setInputStatus = function(prefix, clazz, message)
4631 21 Nov 17 nicklas 171   {
4631 21 Nov 17 nicklas 172     if (prefix.id) prefix = prefix.id;
4631 21 Nov 17 nicklas 173     
4631 21 Nov 17 nicklas 174     var statusTag = Doc.element(prefix + '.status');
4631 21 Nov 17 nicklas 175     
4631 21 Nov 17 nicklas 176     if (statusTag)
4631 21 Nov 17 nicklas 177     {
4631 21 Nov 17 nicklas 178       statusTag.className = 'status ' + (clazz || '');
4631 21 Nov 17 nicklas 179       var trTag = statusTag.parentNode;
4631 21 Nov 17 nicklas 180       var trClass = Data.get(trTag, 'original-class');
4631 21 Nov 17 nicklas 181       if (!trClass)
4631 21 Nov 17 nicklas 182       {
4631 21 Nov 17 nicklas 183         trClass = trTag.className || 'foo';
4631 21 Nov 17 nicklas 184         Data.set(trTag, 'original-class', trClass);
4631 21 Nov 17 nicklas 185       }
4631 21 Nov 17 nicklas 186       trTag.className = trClass + ' ' + (clazz || '');
4631 21 Nov 17 nicklas 187     }
4631 21 Nov 17 nicklas 188     
4631 21 Nov 17 nicklas 189     var msgTag = Doc.element(prefix + '.message');
4631 21 Nov 17 nicklas 190     if (msgTag)
4631 21 Nov 17 nicklas 191     {
4631 21 Nov 17 nicklas 192       if (message)
4631 21 Nov 17 nicklas 193       {
4631 21 Nov 17 nicklas 194         msgTag.innerHTML = message;
4631 21 Nov 17 nicklas 195         Doc.show(msgTag, Data.get(msgTag, 'display', 'inline'));
4631 21 Nov 17 nicklas 196       }
4631 21 Nov 17 nicklas 197       else
4631 21 Nov 17 nicklas 198       {
4631 21 Nov 17 nicklas 199         msgTag.innerHTML = message;
4631 21 Nov 17 nicklas 200         Doc.hide(msgTag);
4631 21 Nov 17 nicklas 201       }
4631 21 Nov 17 nicklas 202     }
4631 21 Nov 17 nicklas 203     else if (statusTag)
4631 21 Nov 17 nicklas 204     {
4631 21 Nov 17 nicklas 205       statusTag.title = message || '';
4631 21 Nov 17 nicklas 206     }
4631 21 Nov 17 nicklas 207   }
4631 21 Nov 17 nicklas 208   
4631 21 Nov 17 nicklas 209   /**
4631 21 Nov 17 nicklas 210     Event handler for input fields, that go to the
4631 21 Nov 17 nicklas 211     next wizard step if TAB or ENTER key is pressed.
4631 21 Nov 17 nicklas 212     A short delay is used to allow other event handler
4631 21 Nov 17 nicklas 213     to run first (eg. for validation).
4631 21 Nov 17 nicklas 214   */
4631 21 Nov 17 nicklas 215   wizard.goNextOnTabOrEnter = function(event)
4631 21 Nov 17 nicklas 216   {
4631 21 Nov 17 nicklas 217     if (event.keyCode == 9 || event.keyCode == 13) 
4631 21 Nov 17 nicklas 218     {
4631 21 Nov 17 nicklas 219       setTimeout(function() { wizard.goNext(true) }, 200);
4631 21 Nov 17 nicklas 220     }
4631 21 Nov 17 nicklas 221   }
4631 21 Nov 17 nicklas 222   
4631 21 Nov 17 nicklas 223   /**
4631 21 Nov 17 nicklas 224     Event handler for input fields, that go to the
4631 21 Nov 17 nicklas 225     next wizard step if TAB key is pressed.
4631 21 Nov 17 nicklas 226     A short delay is used to allow other event handler
4631 21 Nov 17 nicklas 227     to run first (eg. for validation).
4631 21 Nov 17 nicklas 228   */
4631 21 Nov 17 nicklas 229   wizard.goNextOnTab = function(event)
4631 21 Nov 17 nicklas 230   {
4631 21 Nov 17 nicklas 231     if (event.keyCode == 9) 
4631 21 Nov 17 nicklas 232     {
4631 21 Nov 17 nicklas 233       setTimeout(function() { wizard.goNext(true) }, 200);
4631 21 Nov 17 nicklas 234     }
4631 21 Nov 17 nicklas 235   }
4631 21 Nov 17 nicklas 236
4631 21 Nov 17 nicklas 237   /**
4631 21 Nov 17 nicklas 238     Event handler for input fields, that changes
4631 21 Nov 17 nicklas 239     focus to the next element. The next element
4631 21 Nov 17 nicklas 240     should be defined by 'data-next-focus' attribute.
4631 21 Nov 17 nicklas 241     It is recommended that this is consisistent with TAB.
4631 21 Nov 17 nicklas 242   */
4631 21 Nov 17 nicklas 243   wizard.focusOnEnter = function(event)
4631 21 Nov 17 nicklas 244   {
4631 21 Nov 17 nicklas 245     if (event.keyCode == 13)
4631 21 Nov 17 nicklas 246     {
4631 21 Nov 17 nicklas 247       var nextFocus = Doc.element(Data.get(event.currentTarget, 'next-focus'));
4631 21 Nov 17 nicklas 248       if (nextFocus && nextFocus.focus) nextFocus.focus();
4631 21 Nov 17 nicklas 249     }
4631 21 Nov 17 nicklas 250   }
4631 21 Nov 17 nicklas 251   
4631 21 Nov 17 nicklas 252   // Event handler for the 'Next' navigation button
4631 21 Nov 17 nicklas 253   wizard.goNextOnClick = function(event)
4631 21 Nov 17 nicklas 254   {
4631 21 Nov 17 nicklas 255     wizard.goNext(false);
4631 21 Nov 17 nicklas 256   }
4631 21 Nov 17 nicklas 257   
4631 21 Nov 17 nicklas 258   /**
4631 21 Nov 17 nicklas 259     Go to the next step in the wizard. This method will first
4631 21 Nov 17 nicklas 260     submit 'wizard-validate' event to the current step. If at 
4631 21 Nov 17 nicklas 261     least one event handler calls 'Event.preventDefault()' the 
4631 21 Nov 17 nicklas 262     processing is aborted. 
4631 21 Nov 17 nicklas 263     
4631 21 Nov 17 nicklas 264     Otherwise, the current step is disabled and the 'wizard-initialize' 
4631 21 Nov 17 nicklas 265     event is sent to the next step. The event handler is responsible
4631 21 Nov 17 nicklas 266     for calling 'Wizard.setCurrentStep' to display the next step.
4631 21 Nov 17 nicklas 267   */
4631 21 Nov 17 nicklas 268   wizard.goNext = function(auto)
4631 21 Nov 17 nicklas 269   {
4631 21 Nov 17 nicklas 270     var verify = Doc.element('verifyGoNext');
4631 21 Nov 17 nicklas 271     if (verify && !verify.checked) return;
4631 21 Nov 17 nicklas 272     
4631 21 Nov 17 nicklas 273     var details = { 'auto': auto };
4631 21 Nov 17 nicklas 274     
4631 21 Nov 17 nicklas 275     // Send 'wizard-validate' event to current step
4631 21 Nov 17 nicklas 276     var step = Doc.element('step-'+currentStep);
4631 21 Nov 17 nicklas 277     var evt = document.createEvent('CustomEvent');
4631 21 Nov 17 nicklas 278     evt.initCustomEvent('wizard-validate', true, true, details);
4631 21 Nov 17 nicklas 279     if (!step.dispatchEvent(evt)) 
4631 21 Nov 17 nicklas 280     {
4631 21 Nov 17 nicklas 281       wizard.notifyError();
4631 21 Nov 17 nicklas 282       return;
4631 21 Nov 17 nicklas 283     }
4631 21 Nov 17 nicklas 284   
4631 21 Nov 17 nicklas 285     // Hide all navigation buttons and disable form controls in current step
4631 21 Nov 17 nicklas 286     internal.hideButtons('navigation');
4631 21 Nov 17 nicklas 287     internal.disableStep(step);
4631 21 Nov 17 nicklas 288     
4631 21 Nov 17 nicklas 289     // Send 'wizard-initialize' to the next step
4631 21 Nov 17 nicklas 290     var nextStep = Doc.element('step-'+(currentStep+1));
4631 21 Nov 17 nicklas 291     var evt = document.createEvent('CustomEvent');
4631 21 Nov 17 nicklas 292     evt.initCustomEvent('wizard-initialize', true, true, details);
4631 21 Nov 17 nicklas 293     nextStep.dispatchEvent(evt);
4631 21 Nov 17 nicklas 294   }
4631 21 Nov 17 nicklas 295   
4631 21 Nov 17 nicklas 296   wizard.notifyError = function()
4631 21 Nov 17 nicklas 297   {
4631 21 Nov 17 nicklas 298     Doc.addClass('wizard', 'flash-error');
4631 21 Nov 17 nicklas 299     setTimeout(internal.stopFlashing, 2000);
4631 21 Nov 17 nicklas 300   }
4631 21 Nov 17 nicklas 301   
4631 21 Nov 17 nicklas 302   internal.stopFlashing = function()
4631 21 Nov 17 nicklas 303   {
4631 21 Nov 17 nicklas 304     Doc.removeClass('wizard', 'flash-error');
4631 21 Nov 17 nicklas 305   }
4631 21 Nov 17 nicklas 306
4631 21 Nov 17 nicklas 307   /**
4631 21 Nov 17 nicklas 308     Finalize the registration of the wizard. This method will
4631 21 Nov 17 nicklas 309     first submit 'wizard-validate' to the current step. If at 
4631 21 Nov 17 nicklas 310     least one event handler calls 'Event.preventDefault()' the 
4631 21 Nov 17 nicklas 311     processing is aborted.
4631 21 Nov 17 nicklas 312     
4631 21 Nov 17 nicklas 313     Otherwise, the current step is disabled and the 'wizard-submit' 
4631 21 Nov 17 nicklas 314     event is sent to the 'wizard'. The event handler is responsible
4631 21 Nov 17 nicklas 315     for finalizing the registration and displaying a proper
4631 21 Nov 17 nicklas 316     message, for example, by calling Wizard.showFinalMessage()
4631 21 Nov 17 nicklas 317     
4631 21 Nov 17 nicklas 318     The 'data' is passed on to the 'wizard-validate' and 
4631 21 Nov 17 nicklas 319     'wizard-submit' events as the Event.details object.
4631 21 Nov 17 nicklas 320   */
4631 21 Nov 17 nicklas 321   wizard.goRegister = function(data)
4631 21 Nov 17 nicklas 322   {
4631 21 Nov 17 nicklas 323     // Check if verification is enabled
4631 21 Nov 17 nicklas 324     var verify = Doc.element('verifyGoNext');
4631 21 Nov 17 nicklas 325     if (verify && !verify.checked) return;
4631 21 Nov 17 nicklas 326     
4631 21 Nov 17 nicklas 327     // Send 'wizard-validate' event to current step
4631 21 Nov 17 nicklas 328     var step = Doc.element('step-'+currentStep);
4631 21 Nov 17 nicklas 329     var evt = document.createEvent('CustomEvent');
4631 21 Nov 17 nicklas 330     evt.initCustomEvent('wizard-validate', true, true, data);
4631 21 Nov 17 nicklas 331     if (!step.dispatchEvent(evt)) 
4631 21 Nov 17 nicklas 332     {
4631 21 Nov 17 nicklas 333       wizard.notifyError();
4631 21 Nov 17 nicklas 334       return;
4631 21 Nov 17 nicklas 335     }
4631 21 Nov 17 nicklas 336   
4631 21 Nov 17 nicklas 337     internal.hideButtons('navigation');
4631 21 Nov 17 nicklas 338     internal.disableStep(step);
4631 21 Nov 17 nicklas 339     
4631 21 Nov 17 nicklas 340     // Send 'wizard-submit' to the next step
4631 21 Nov 17 nicklas 341     var wiz = Doc.element('wizard');
4631 21 Nov 17 nicklas 342     hasSentRegistration = true;
4631 21 Nov 17 nicklas 343     var evt = document.createEvent('CustomEvent');
4631 21 Nov 17 nicklas 344     evt.initCustomEvent('wizard-submit', true, true, data);
4631 21 Nov 17 nicklas 345     wiz.dispatchEvent(evt);
4631 21 Nov 17 nicklas 346   }
4631 21 Nov 17 nicklas 347   
4631 21 Nov 17 nicklas 348   wizard.setNoConfirmOnFirstStep = function(cf)
4631 21 Nov 17 nicklas 349   {
4631 21 Nov 17 nicklas 350     noConfirmOnFirstStep = cf;
4631 21 Nov 17 nicklas 351   }
4631 21 Nov 17 nicklas 352   
4631 21 Nov 17 nicklas 353   // Ask the user for confirmation and then restart the wizard
4631 21 Nov 17 nicklas 354   wizard.cancelWizard = function()
4631 21 Nov 17 nicklas 355   {
4631 21 Nov 17 nicklas 356     forceConfirm = true;
4631 21 Nov 17 nicklas 357     wizard.restartWizard();
4631 21 Nov 17 nicklas 358   }
4631 21 Nov 17 nicklas 359   
4631 21 Nov 17 nicklas 360   // Restart the wizard without asking the user for confirmation
4631 21 Nov 17 nicklas 361   wizard.restartWizard = function()
4631 21 Nov 17 nicklas 362   {
4631 21 Nov 17 nicklas 363     var url = location.href;
4631 21 Nov 17 nicklas 364     if (url.indexOf('&restart=1') == -1) url += '&restart=1';
4631 21 Nov 17 nicklas 365     location.href = url;
4631 21 Nov 17 nicklas 366   }
4631 21 Nov 17 nicklas 367   
4631 21 Nov 17 nicklas 368   wizard.setCurrentStep = function(stepNo)
4631 21 Nov 17 nicklas 369   {
4631 21 Nov 17 nicklas 370     currentStep = stepNo;
4631 21 Nov 17 nicklas 371     internal.enableStep(Doc.element('step-'+currentStep));
4631 21 Nov 17 nicklas 372   }
4631 21 Nov 17 nicklas 373
4631 21 Nov 17 nicklas 374   internal.disableStep = function(step)
4631 21 Nov 17 nicklas 375   {
4631 21 Nov 17 nicklas 376     step = Doc.element(step);
4631 21 Nov 17 nicklas 377     internal.disableAllFormElements(step);
4631 21 Nov 17 nicklas 378     Doc.addClass(step, 'disabled');
4631 21 Nov 17 nicklas 379     Doc.hide('gonext-message');
4631 21 Nov 17 nicklas 380     var stepNo = step.getElementsByClassName('step-no')[0];
4631 21 Nov 17 nicklas 381     Events.addEventHandler(stepNo, 'click', internal.togglePastStep, {'step-id': step.id});
4631 21 Nov 17 nicklas 382     stepNo.title = 'Show/hide this section';
4631 21 Nov 17 nicklas 383   }
4631 21 Nov 17 nicklas 384   
4631 21 Nov 17 nicklas 385   internal.enableStep = function(step)
4631 21 Nov 17 nicklas 386   {
4631 21 Nov 17 nicklas 387     step = Doc.element(step);
4631 21 Nov 17 nicklas 388     Doc.removeClass(step, 'disabled');
4631 21 Nov 17 nicklas 389     Doc.show(step);
4631 21 Nov 17 nicklas 390   }
4631 21 Nov 17 nicklas 391   
4631 21 Nov 17 nicklas 392   // Toggle visibility of a past step
4631 21 Nov 17 nicklas 393   // The step is hidden if the 'auto-hide' class is present
4631 21 Nov 17 nicklas 394   internal.togglePastStep = function(event)
4631 21 Nov 17 nicklas 395   {
4631 21 Nov 17 nicklas 396     var step = Data.get(event.currentTarget, 'step-id');
4631 21 Nov 17 nicklas 397     Doc.addOrRemoveClass(step, 'auto-hide');
4631 21 Nov 17 nicklas 398   }
4631 21 Nov 17 nicklas 399
4631 21 Nov 17 nicklas 400   
4631 21 Nov 17 nicklas 401   /**
4354 13 Feb 17 nicklas 402     A fatal error has occurred and the wizard will not be able to continue.
4354 13 Feb 17 nicklas 403     This method will display the error message, disable all form input fields
4354 13 Feb 17 nicklas 404     and buttons (except the 'Restart' button).
4354 13 Feb 17 nicklas 405   */
4354 13 Feb 17 nicklas 406   wizard.setFatalError = function(err, messages)
4354 13 Feb 17 nicklas 407   {
4354 13 Feb 17 nicklas 408     hasFatalError = true;
4354 13 Feb 17 nicklas 409     var msg = err;
4354 13 Feb 17 nicklas 410     if (err.toString)
4354 13 Feb 17 nicklas 411     {
4354 13 Feb 17 nicklas 412       App.debug(err.toString());
4354 13 Feb 17 nicklas 413       msg = Strings.encodeTags(err.toString());
4354 13 Feb 17 nicklas 414       if (err.stack && !messages)
4354 13 Feb 17 nicklas 415       {
4354 13 Feb 17 nicklas 416         App.debug(err.stack);
4354 13 Feb 17 nicklas 417         msg += '<br><pre>'+Strings.encodeTags(err.stack)+'</pre>';
4354 13 Feb 17 nicklas 418       }
4354 13 Feb 17 nicklas 419     }
4354 13 Feb 17 nicklas 420     else
4354 13 Feb 17 nicklas 421     {
4354 13 Feb 17 nicklas 422       App.debug(msg);
4354 13 Feb 17 nicklas 423     }
4354 13 Feb 17 nicklas 424     
4354 13 Feb 17 nicklas 425     if (messages) 
4354 13 Feb 17 nicklas 426     {
4354 13 Feb 17 nicklas 427       msg = '<div class="messagecontainer error">'+msg+'</div>'+internal.generateMessageList(messages).html;
4354 13 Feb 17 nicklas 428       wizard.setWizardStatus('success', msg);
4354 13 Feb 17 nicklas 429     }
4354 13 Feb 17 nicklas 430     else
4354 13 Feb 17 nicklas 431     {
4354 13 Feb 17 nicklas 432       wizard.setWizardStatus('messagecontainer error', msg || 'Unexpected failure!');
4354 13 Feb 17 nicklas 433     }
4354 13 Feb 17 nicklas 434     
4354 13 Feb 17 nicklas 435     Doc.addClass('wizard', 'disabled');
4354 13 Feb 17 nicklas 436     internal.disableAllFormElements('wizard', true);
4354 13 Feb 17 nicklas 437     Doc.show('gorestart');
4354 13 Feb 17 nicklas 438   }
4354 13 Feb 17 nicklas 439
4354 13 Feb 17 nicklas 440   
4354 13 Feb 17 nicklas 441   /**
4354 13 Feb 17 nicklas 442     Display a 'loading' global wizard-status message.
4354 13 Feb 17 nicklas 443     The 'progress' parameter is optional. If given,
4354 13 Feb 17 nicklas 444     it should be the name of a progress reporter.
4354 13 Feb 17 nicklas 445     This activates the display of a progress bar which
4476 28 Apr 17 nicklas 446     Relax will update at regular intervals in the background.
4354 13 Feb 17 nicklas 447     See SessionServlet (cmd=GetProgress) for more information.
4354 13 Feb 17 nicklas 448   */
4354 13 Feb 17 nicklas 449   wizard.showLoadingAnimation = function(msg, progress)
4354 13 Feb 17 nicklas 450   {
4354 13 Feb 17 nicklas 451     wizard.setWizardStatus('loading', msg  || 'Working, please wait...');
4631 21 Nov 17 nicklas 452     if (progress)
4631 21 Nov 17 nicklas 453     {
4631 21 Nov 17 nicklas 454       var progressBar = Doc.element('wizard-progress');
4631 21 Nov 17 nicklas 455       progressBar.classList.add('progress-bar');
4631 21 Nov 17 nicklas 456
4631 21 Nov 17 nicklas 457       // Get/create child elements
4631 21 Nov 17 nicklas 458       var done = Doc.element('wizard-progress-done');
4631 21 Nov 17 nicklas 459       if (!done)
4631 21 Nov 17 nicklas 460       {
4631 21 Nov 17 nicklas 461         done = document.createElement('span');
4631 21 Nov 17 nicklas 462         done.id = 'wizard-progress-done';
4631 21 Nov 17 nicklas 463         done.className = 'progress-bar-done bg-filled-100 topborder bottomborder leftborder';
4631 21 Nov 17 nicklas 464         progressBar.appendChild(done);
4631 21 Nov 17 nicklas 465       }
4631 21 Nov 17 nicklas 466       var remain = Doc.element('wizard-progress-remain');
4631 21 Nov 17 nicklas 467       if (!remain)
4631 21 Nov 17 nicklas 468       {
4631 21 Nov 17 nicklas 469         remain = document.createElement('span');
4631 21 Nov 17 nicklas 470         remain.id = 'wizard-progress-remain';
4631 21 Nov 17 nicklas 471         remain.className = 'progress-bar-remain topborder bottomborder rightborder';
4631 21 Nov 17 nicklas 472         progressBar.appendChild(remain);
4631 21 Nov 17 nicklas 473       }
4631 21 Nov 17 nicklas 474         
4631 21 Nov 17 nicklas 475       progressBar.setAttribute('value', '0%');
4631 21 Nov 17 nicklas 476       done.style.width = '0%';
4631 21 Nov 17 nicklas 477       remain.style.width = '100%';
4631 21 Nov 17 nicklas 478       Doc.show(progressBar);
4631 21 Nov 17 nicklas 479       
4631 21 Nov 17 nicklas 480       // Initial request for updating the progress bar
4631 21 Nov 17 nicklas 481       progressTimer = setTimeout(internal.requestProgressUpdate, 1500, progress);
4631 21 Nov 17 nicklas 482     }
4354 13 Feb 17 nicklas 483   }
4354 13 Feb 17 nicklas 484   
4631 21 Nov 17 nicklas 485   /**
4631 21 Nov 17 nicklas 486     Make a request for the progress information. The 'progress'
4631 21 Nov 17 nicklas 487     parameter is the name of a progress bar.
4631 21 Nov 17 nicklas 488   */
4631 21 Nov 17 nicklas 489   internal.requestProgressUpdate = function(progress)
4631 21 Nov 17 nicklas 490   {
4631 21 Nov 17 nicklas 491     if (hasFatalError) return;
4631 21 Nov 17 nicklas 492     var url = '../Session.servlet?ID='+App.getSessionId();
4631 21 Nov 17 nicklas 493     url += '&cmd=GetProgress';
4631 21 Nov 17 nicklas 494     url += '&name='+encodeURIComponent(progress);
4631 21 Nov 17 nicklas 495     
4631 21 Nov 17 nicklas 496     var request = Ajax.getXmlHttpRequest();
4631 21 Nov 17 nicklas 497     request.open("GET", url, true);
4631 21 Nov 17 nicklas 498     Ajax.setReadyStateHandler(request, internal.onProgressReport, internal.onProgressReport);
4631 21 Nov 17 nicklas 499     request.send(null);
4631 21 Nov 17 nicklas 500   }
4631 21 Nov 17 nicklas 501   
4631 21 Nov 17 nicklas 502   /**
4631 21 Nov 17 nicklas 503     Callback when receiving a progress update.
4631 21 Nov 17 nicklas 504   */
4631 21 Nov 17 nicklas 505   internal.onProgressReport = function(request)
4631 21 Nov 17 nicklas 506   {
4631 21 Nov 17 nicklas 507     if (hasFatalError) return;
4631 21 Nov 17 nicklas 508     if (debug) App.debug(Strings.encodeTags(request.responseText));
4631 21 Nov 17 nicklas 509     var response;
4631 21 Nov 17 nicklas 510     var error = false;
4631 21 Nov 17 nicklas 511     try
4631 21 Nov 17 nicklas 512     {
4631 21 Nov 17 nicklas 513       response = JSON.parse(request.responseText);
4631 21 Nov 17 nicklas 514       if (response.status != 'ok')
4631 21 Nov 17 nicklas 515       {
4631 21 Nov 17 nicklas 516         error = response.message || response.stacktrace || 'Unexpected error';
4631 21 Nov 17 nicklas 517       }
4631 21 Nov 17 nicklas 518     }
4631 21 Nov 17 nicklas 519     catch (ex)
4631 21 Nov 17 nicklas 520     {
4631 21 Nov 17 nicklas 521       error = ex;
4631 21 Nov 17 nicklas 522     }
4631 21 Nov 17 nicklas 523     
4631 21 Nov 17 nicklas 524     if (error)
4631 21 Nov 17 nicklas 525     {
4631 21 Nov 17 nicklas 526       return;
4631 21 Nov 17 nicklas 527     }
4631 21 Nov 17 nicklas 528   
4631 21 Nov 17 nicklas 529     var progress = response.progress;
4631 21 Nov 17 nicklas 530     var progressBar = Doc.element('wizard-progress');
4631 21 Nov 17 nicklas 531   
4631 21 Nov 17 nicklas 532     if (!progress) 
4631 21 Nov 17 nicklas 533     {
4631 21 Nov 17 nicklas 534       // Give up if no progress information
4631 21 Nov 17 nicklas 535       Doc.hide(progressBar);
4631 21 Nov 17 nicklas 536       return;
4631 21 Nov 17 nicklas 537     }
4631 21 Nov 17 nicklas 538     
4631 21 Nov 17 nicklas 539     var done = Doc.element('wizard-progress-done');
4631 21 Nov 17 nicklas 540     var remain = Doc.element('wizard-progress-remain');
4631 21 Nov 17 nicklas 541   
4631 21 Nov 17 nicklas 542     progressBar.setAttribute('value', progress.percent+'%');
4631 21 Nov 17 nicklas 543     done.style.width = progress.percent+'%';
4631 21 Nov 17 nicklas 544     remain.style.width = (100-progress.percent)+'%';
4631 21 Nov 17 nicklas 545     
4631 21 Nov 17 nicklas 546     if (progress.message)
4631 21 Nov 17 nicklas 547     {
4631 21 Nov 17 nicklas 548       Doc.element('wizard-status').innerHTML = Strings.encodeTags(progress.message);
4631 21 Nov 17 nicklas 549     }
4631 21 Nov 17 nicklas 550     
4631 21 Nov 17 nicklas 551     if (progress.percent < 100)
4631 21 Nov 17 nicklas 552     {
4631 21 Nov 17 nicklas 553       // Continue to request updates until we 100% has been reached
4631 21 Nov 17 nicklas 554       progressTimer = setTimeout(internal.requestProgressUpdate, 1500, progress.name);
4631 21 Nov 17 nicklas 555     }
4631 21 Nov 17 nicklas 556     else
4631 21 Nov 17 nicklas 557     {
4631 21 Nov 17 nicklas 558       progressTimer = null;
4631 21 Nov 17 nicklas 559       Doc.hide(progressBar);
4631 21 Nov 17 nicklas 560     }
4631 21 Nov 17 nicklas 561   }
4631 21 Nov 17 nicklas 562
4631 21 Nov 17 nicklas 563   
4354 13 Feb 17 nicklas 564   wizard.showStatusMessage = function(msg)
4354 13 Feb 17 nicklas 565   {
4354 13 Feb 17 nicklas 566     wizard.setWizardStatus('messagecontainer note', msg);
4354 13 Feb 17 nicklas 567   }
4354 13 Feb 17 nicklas 568
4354 13 Feb 17 nicklas 569   /**
4354 13 Feb 17 nicklas 570     Hide the current global wizard-status message.
4354 13 Feb 17 nicklas 571   */
4354 13 Feb 17 nicklas 572   wizard.hideWizardStatus = function()
4354 13 Feb 17 nicklas 573   {
4354 13 Feb 17 nicklas 574     Doc.hide('wizard-status');
4354 13 Feb 17 nicklas 575     Doc.hide('wizard-progress');
4354 13 Feb 17 nicklas 576   }
4631 21 Nov 17 nicklas 577   
4631 21 Nov 17 nicklas 578   wizard.showGoNextConfirmation = function(verify, msg)
4631 21 Nov 17 nicklas 579   {
4631 21 Nov 17 nicklas 580     var check = '';
4631 21 Nov 17 nicklas 581     if (verify)
4631 21 Nov 17 nicklas 582     {
4631 21 Nov 17 nicklas 583       check = '<input type="checkbox" name="verifyGoNext" id="verifyGoNext">';
4631 21 Nov 17 nicklas 584       Doc.addClass('gonext', 'disabled');
4631 21 Nov 17 nicklas 585       Doc.addClass('goregister', 'disabled');
4631 21 Nov 17 nicklas 586     }
4354 13 Feb 17 nicklas 587     
4631 21 Nov 17 nicklas 588     var gonext = Doc.element('gonext-message');
4631 21 Nov 17 nicklas 589     gonext.innerHTML = check + msg;
4631 21 Nov 17 nicklas 590     Doc.show(gonext);
4631 21 Nov 17 nicklas 591     
4631 21 Nov 17 nicklas 592     if (verify)
4631 21 Nov 17 nicklas 593     {
4631 21 Nov 17 nicklas 594       Events.addEventHandler('verifyGoNext', 'click', internal.verifyInternalOnClick);
4631 21 Nov 17 nicklas 595     }
4631 21 Nov 17 nicklas 596   }
4631 21 Nov 17 nicklas 597   
4631 21 Nov 17 nicklas 598   wizard.hideGoNextConfirmation = function()
4631 21 Nov 17 nicklas 599   {
4631 21 Nov 17 nicklas 600     var gonext = Doc.element('gonext-message');
4631 21 Nov 17 nicklas 601     gonext.innerHTML = '';
4631 21 Nov 17 nicklas 602     Doc.hide(gonext);
4631 21 Nov 17 nicklas 603     Doc.removeClass('gonext', 'disabled');
4631 21 Nov 17 nicklas 604     Doc.removeClass('goregister', 'disabled');
4631 21 Nov 17 nicklas 605   }
4631 21 Nov 17 nicklas 606   
4631 21 Nov 17 nicklas 607   internal.verifyInternalOnClick = function(event)
4631 21 Nov 17 nicklas 608   {
4631 21 Nov 17 nicklas 609     var frm = document.forms['reggie'];
4631 21 Nov 17 nicklas 610     var checked = event.currentTarget.checked;
4631 21 Nov 17 nicklas 611     Doc.addOrRemoveClass('goregister', 'disabled', !checked);
4631 21 Nov 17 nicklas 612     Doc.addOrRemoveClass('gonext', 'disabled', !checked);
4631 21 Nov 17 nicklas 613   }
4631 21 Nov 17 nicklas 614
4354 13 Feb 17 nicklas 615   /**
4631 21 Nov 17 nicklas 616     Show final registration messages in a list.
4631 21 Nov 17 nicklas 617   */
4631 21 Nov 17 nicklas 618   wizard.showFinalMessage = function(messages)
4631 21 Nov 17 nicklas 619   {
4631 21 Nov 17 nicklas 620     var msg = internal.generateMessageList(messages);
5078 08 Nov 18 nicklas 621
5078 08 Nov 18 nicklas 622     var status = Doc.element('wizard-messages') || Doc.element('wizard-status');
5078 08 Nov 18 nicklas 623     status.className = 'success';
5078 08 Nov 18 nicklas 624     status.innerHTML = msg.html;
5078 08 Nov 18 nicklas 625     Doc.show(status);
5078 08 Nov 18 nicklas 626
4631 21 Nov 17 nicklas 627     if (progressTimer) clearTimeout(progressTimer);
4631 21 Nov 17 nicklas 628     return { 'errors': msg.errors, 'warnings': msg.warnings };
4631 21 Nov 17 nicklas 629   }
4631 21 Nov 17 nicklas 630
4631 21 Nov 17 nicklas 631   internal.generateMessageList = function(messages)
4631 21 Nov 17 nicklas 632   {
4631 21 Nov 17 nicklas 633     var msg = '<ul>';
4631 21 Nov 17 nicklas 634     var numWarnings = 0;
4631 21 Nov 17 nicklas 635     var numErrors = 0;
4631 21 Nov 17 nicklas 636     for (var i = 0; i < messages.length; i++)
4631 21 Nov 17 nicklas 637     {
4631 21 Nov 17 nicklas 638       var msgLine = messages[i];
4631 21 Nov 17 nicklas 639       if (msgLine.indexOf('[Warning]') >= 0)
4631 21 Nov 17 nicklas 640       {
4631 21 Nov 17 nicklas 641         msg += '<li class="warning">' + Strings.encodeTags(msgLine.replace('[Warning]', ''));
4631 21 Nov 17 nicklas 642         numWarnings++;
4631 21 Nov 17 nicklas 643       }
4631 21 Nov 17 nicklas 644       else if (msgLine.indexOf('[Error]') >= 0)
4631 21 Nov 17 nicklas 645       {
4631 21 Nov 17 nicklas 646         msg += '<li class="error">' + Strings.encodeTags(msgLine.replace('[Error]', ''));
4631 21 Nov 17 nicklas 647         numErrors++;
4631 21 Nov 17 nicklas 648       }
4631 21 Nov 17 nicklas 649       else
4631 21 Nov 17 nicklas 650       {
4631 21 Nov 17 nicklas 651         msg += '<li class="ok">' + Strings.encodeTags(msgLine);
4631 21 Nov 17 nicklas 652       }
4631 21 Nov 17 nicklas 653     }
4631 21 Nov 17 nicklas 654     msg += '</ul>';
4631 21 Nov 17 nicklas 655     return { 'html': msg, 'errors': numErrors, 'warnings': numWarnings };
4631 21 Nov 17 nicklas 656   }
4631 21 Nov 17 nicklas 657
4631 21 Nov 17 nicklas 658   /**
4354 13 Feb 17 nicklas 659     Initialize the wizard:
4354 13 Feb 17 nicklas 660     
4354 13 Feb 17 nicklas 661     * Check that a project is active
4354 13 Feb 17 nicklas 662   */
4354 13 Feb 17 nicklas 663   internal.initWizard = function()
4354 13 Feb 17 nicklas 664   {
4354 13 Feb 17 nicklas 665     var path = document.getElementsByClassName('path');
4354 13 Feb 17 nicklas 666     if (path && path.length)
4354 13 Feb 17 nicklas 667     {
4354 13 Feb 17 nicklas 668       var relaxVersion = document.createElement('span');
4354 13 Feb 17 nicklas 669       relaxVersion.id = 'relax-version';
4354 13 Feb 17 nicklas 670       relaxVersion.innerHTML = '[Relax '+Relax.VERSION+']';
4354 13 Feb 17 nicklas 671       path[0].appendChild(relaxVersion);
4354 13 Feb 17 nicklas 672     }
4354 13 Feb 17 nicklas 673   }
4354 13 Feb 17 nicklas 674     
4354 13 Feb 17 nicklas 675   /**
4354 13 Feb 17 nicklas 676     Display a global wizard-status message. This may for example be
4354 13 Feb 17 nicklas 677     an error message, a work-in-progress indicator, etc.
4354 13 Feb 17 nicklas 678   */
4354 13 Feb 17 nicklas 679   wizard.setWizardStatus = function(className, msg)
4354 13 Feb 17 nicklas 680   {
4354 13 Feb 17 nicklas 681     var status = Doc.element('wizard-status');
4354 13 Feb 17 nicklas 682     status.className = className;
4354 13 Feb 17 nicklas 683     status.innerHTML = msg;
4354 13 Feb 17 nicklas 684     Doc.show(status);
4354 13 Feb 17 nicklas 685   }
4354 13 Feb 17 nicklas 686
4354 13 Feb 17 nicklas 687   // Disable all form elements inside the given container
4354 13 Feb 17 nicklas 688   internal.disableAllFormElements = function(container, hideButtons)
4354 13 Feb 17 nicklas 689   {
4354 13 Feb 17 nicklas 690     container = Doc.element(container);
4632 22 Nov 17 nicklas 691     if (!container) return;
4354 13 Feb 17 nicklas 692     var input = container.getElementsByTagName('input');
4354 13 Feb 17 nicklas 693     for (var i = 0; i < input.length; i++)
4354 13 Feb 17 nicklas 694     {
4354 13 Feb 17 nicklas 695       input[i].disabled = true;
4354 13 Feb 17 nicklas 696     }
4354 13 Feb 17 nicklas 697     var select = container.getElementsByTagName('select');
4354 13 Feb 17 nicklas 698     for (var i = 0; i < select.length; i++)
4354 13 Feb 17 nicklas 699     {
4354 13 Feb 17 nicklas 700       select[i].disabled = true;
4354 13 Feb 17 nicklas 701     }
4354 13 Feb 17 nicklas 702     var text = container.getElementsByTagName('textarea');
4354 13 Feb 17 nicklas 703     for (var i = 0; i < text.length; i++)
4354 13 Feb 17 nicklas 704     {
4354 13 Feb 17 nicklas 705       text[i].disabled = true;
4354 13 Feb 17 nicklas 706     }
4354 13 Feb 17 nicklas 707     if (hideButtons)
4354 13 Feb 17 nicklas 708     {
4354 13 Feb 17 nicklas 709       internal.hideButtons(container);
4354 13 Feb 17 nicklas 710     }
4354 13 Feb 17 nicklas 711   }
4354 13 Feb 17 nicklas 712
4354 13 Feb 17 nicklas 713   // Hide all 'basicbuttons':s in the given container
4354 13 Feb 17 nicklas 714   internal.hideButtons = function(container)
4354 13 Feb 17 nicklas 715   {
4354 13 Feb 17 nicklas 716     container = Doc.element(container);
4354 13 Feb 17 nicklas 717     var buttons = container.getElementsByClassName('basicbutton');
4354 13 Feb 17 nicklas 718     for (var i = 0; i < buttons.length; i++)
4354 13 Feb 17 nicklas 719     {
4354 13 Feb 17 nicklas 720       Doc.hide(buttons[i]);
4354 13 Feb 17 nicklas 721     }
4354 13 Feb 17 nicklas 722   }
4354 13 Feb 17 nicklas 723
4354 13 Feb 17 nicklas 724   Doc.addFinalizer(internal.initWizard);
4354 13 Feb 17 nicklas 725   return wizard;
4354 13 Feb 17 nicklas 726 }();
4354 13 Feb 17 nicklas 727
4360 15 Feb 17 nicklas 728 /**
4360 15 Feb 17 nicklas 729   Holds one or more filter criterias. Use the 'add*' methods
4360 15 Feb 17 nicklas 730   to add criterias to the filter, and the 'check(item)' method
4360 15 Feb 17 nicklas 731   to evaluate all criterias against a single item.
4360 15 Feb 17 nicklas 732 */
4360 15 Feb 17 nicklas 733 var Filter = function()
4360 15 Feb 17 nicklas 734 {
4360 15 Feb 17 nicklas 735   this.criterias = [];
4360 15 Feb 17 nicklas 736 }
4360 15 Feb 17 nicklas 737
4360 15 Feb 17 nicklas 738 /**
4360 15 Feb 17 nicklas 739   Adds a text criteria comparing the given item property to
4360 15 Feb 17 nicklas 740   a static value (f2).
4360 15 Feb 17 nicklas 741 */
4360 15 Feb 17 nicklas 742 Filter.prototype.addTextCriteria = function(itemProp, f2)
4360 15 Feb 17 nicklas 743 {
4360 15 Feb 17 nicklas 744   if (f2 != '') 
4360 15 Feb 17 nicklas 745   {
4360 15 Feb 17 nicklas 746     var cmp;
4360 15 Feb 17 nicklas 747     if (f2 == '=')
4360 15 Feb 17 nicklas 748     {
4360 15 Feb 17 nicklas 749       cmp = Comparator.eq;
4360 15 Feb 17 nicklas 750       f2 = null;
4360 15 Feb 17 nicklas 751     }
4360 15 Feb 17 nicklas 752     else if (f2 == '<>')
4360 15 Feb 17 nicklas 753     {
4360 15 Feb 17 nicklas 754       cmp = Comparator.neq;
4360 15 Feb 17 nicklas 755       f2 = null;
4360 15 Feb 17 nicklas 756     }
4360 15 Feb 17 nicklas 757     else
4360 15 Feb 17 nicklas 758     {
4360 15 Feb 17 nicklas 759       cmp = Comparator.eq;
4360 15 Feb 17 nicklas 760     }
4360 15 Feb 17 nicklas 761     this.criterias[this.criterias.length] = function(item) { return cmp(itemProp(item), f2) };
4360 15 Feb 17 nicklas 762   }
4360 15 Feb 17 nicklas 763 }
4360 15 Feb 17 nicklas 764
4360 15 Feb 17 nicklas 765 /**
4360 15 Feb 17 nicklas 766   Adds a text criteria checking if the given item property to
4360 15 Feb 17 nicklas 767   contains a static value (f2).
4360 15 Feb 17 nicklas 768 */
4360 15 Feb 17 nicklas 769 Filter.prototype.addContainsCriteria = function(itemProp, f2)
4360 15 Feb 17 nicklas 770 {
4360 15 Feb 17 nicklas 771   if (f2 != '') 
4360 15 Feb 17 nicklas 772   {
4360 15 Feb 17 nicklas 773     var cmp;
4360 15 Feb 17 nicklas 774     if (f2 == '=')
4360 15 Feb 17 nicklas 775     {
4360 15 Feb 17 nicklas 776       cmp = Comparator.eq;
4360 15 Feb 17 nicklas 777       f2 = null;
4360 15 Feb 17 nicklas 778     }
4360 15 Feb 17 nicklas 779     else if (f2 == '<>')
4360 15 Feb 17 nicklas 780     {
4360 15 Feb 17 nicklas 781       cmp = Comparator.neq;
4360 15 Feb 17 nicklas 782       f2 = null;
4360 15 Feb 17 nicklas 783     }
4360 15 Feb 17 nicklas 784     else
4360 15 Feb 17 nicklas 785     {
4360 15 Feb 17 nicklas 786       cmp = Comparator.contains;
4360 15 Feb 17 nicklas 787     }
4360 15 Feb 17 nicklas 788     this.criterias[this.criterias.length] = function(item) { return cmp(itemProp(item), f2) };
4360 15 Feb 17 nicklas 789   }
4360 15 Feb 17 nicklas 790 }
4360 15 Feb 17 nicklas 791
4360 15 Feb 17 nicklas 792 /**
4360 15 Feb 17 nicklas 793   Evaluate all criterias. Return true if all pass, false otherwise.
4360 15 Feb 17 nicklas 794 */
4360 15 Feb 17 nicklas 795 Filter.prototype.check = function(item)
4360 15 Feb 17 nicklas 796 {
4360 15 Feb 17 nicklas 797   for (var i = 0; i < this.criterias.length; i++)
4360 15 Feb 17 nicklas 798   {
4360 15 Feb 17 nicklas 799     if (!this.criterias[i](item)) return false;
4360 15 Feb 17 nicklas 800   }
4360 15 Feb 17 nicklas 801   return true;
4360 15 Feb 17 nicklas 802 }
4360 15 Feb 17 nicklas 803
4360 15 Feb 17 nicklas 804
4360 15 Feb 17 nicklas 805 var Comparator = function()
4360 15 Feb 17 nicklas 806 {
4360 15 Feb 17 nicklas 807   var cmp = {};
4360 15 Feb 17 nicklas 808   
4360 15 Feb 17 nicklas 809   /**
4360 15 Feb 17 nicklas 810     Return a comparator based on the symbol
4360 15 Feb 17 nicklas 811     which can be either '>' or '<' to return
4360 15 Feb 17 nicklas 812     Comparator.gt or Comparator.lt. Otherwise
4360 15 Feb 17 nicklas 813     the given default or Comparator.eq is returned.
4360 15 Feb 17 nicklas 814   */
4360 15 Feb 17 nicklas 815   cmp.get = function(symbol, defaultCmp)
4360 15 Feb 17 nicklas 816   {
4360 15 Feb 17 nicklas 817     var c;
4360 15 Feb 17 nicklas 818     if (symbol == '<')
4360 15 Feb 17 nicklas 819     {
4360 15 Feb 17 nicklas 820       c = cmp.lt;
4360 15 Feb 17 nicklas 821     }
4360 15 Feb 17 nicklas 822     else if (symbol == '>')
4360 15 Feb 17 nicklas 823     {
4360 15 Feb 17 nicklas 824       c = cmp.gt;
4360 15 Feb 17 nicklas 825     }
4360 15 Feb 17 nicklas 826     else
4360 15 Feb 17 nicklas 827     {
4360 15 Feb 17 nicklas 828       c = defaultCmp || cmp.eq;
4360 15 Feb 17 nicklas 829     }
4360 15 Feb 17 nicklas 830     return c;
4360 15 Feb 17 nicklas 831   }
4360 15 Feb 17 nicklas 832   
4360 15 Feb 17 nicklas 833   // Compare if two values are equal
4360 15 Feb 17 nicklas 834   cmp.eq = function(v1, v2)
4360 15 Feb 17 nicklas 835   {
4360 15 Feb 17 nicklas 836     return v1 == v2;
4360 15 Feb 17 nicklas 837   }
4360 15 Feb 17 nicklas 838   
4360 15 Feb 17 nicklas 839   // Compare if two values are different
4360 15 Feb 17 nicklas 840   cmp.neq = function(v1, v2)
4360 15 Feb 17 nicklas 841   {
4360 15 Feb 17 nicklas 842     return v1 != v2;
4360 15 Feb 17 nicklas 843   }
4360 15 Feb 17 nicklas 844   
4360 15 Feb 17 nicklas 845   // Check if v2 is contained in v1
4360 15 Feb 17 nicklas 846   cmp.contains = function(v1, v2)
4360 15 Feb 17 nicklas 847   {
4360 15 Feb 17 nicklas 848     return v1 != null && v2 != null && v1.indexOf(v2) >= 0;
4360 15 Feb 17 nicklas 849   }
4360 15 Feb 17 nicklas 850   
4360 15 Feb 17 nicklas 851   // Compare if two values are appoximately equals (difference is not more than 0.05)
4360 15 Feb 17 nicklas 852   cmp.approx = function(v1, v2)
4360 15 Feb 17 nicklas 853   {
4360 15 Feb 17 nicklas 854     return Math.abs(v2 - v1) < 0.05;
4360 15 Feb 17 nicklas 855   }
4360 15 Feb 17 nicklas 856   
4360 15 Feb 17 nicklas 857   // Compare if v1 starts with the same string as v2
4360 15 Feb 17 nicklas 858   cmp.startsWith = function(v1, v2)
4360 15 Feb 17 nicklas 859   {
4360 15 Feb 17 nicklas 860     return v1 != null && v1.indexOf(v2) == 0;
4360 15 Feb 17 nicklas 861   }
4360 15 Feb 17 nicklas 862   
4360 15 Feb 17 nicklas 863   // Compare if v1 is greater than or equal to v2
4360 15 Feb 17 nicklas 864   cmp.gt = function(v1, v2)
4360 15 Feb 17 nicklas 865   {
4360 15 Feb 17 nicklas 866     return v1 != null && v2 != null && v1 >= v2;
4360 15 Feb 17 nicklas 867   }
4360 15 Feb 17 nicklas 868   
4360 15 Feb 17 nicklas 869   // Compare if v1 is less than or equal to v2
4360 15 Feb 17 nicklas 870   cmp.lt = function(v1, v2)
4360 15 Feb 17 nicklas 871   {
4360 15 Feb 17 nicklas 872     return v1 != null && v2 != null && v1 <= v2;
4360 15 Feb 17 nicklas 873   }
4360 15 Feb 17 nicklas 874   
4360 15 Feb 17 nicklas 875   return cmp;
4360 15 Feb 17 nicklas 876 }();
4360 15 Feb 17 nicklas 877
4360 15 Feb 17 nicklas 878
4360 15 Feb 17 nicklas 879