Changeset 4631
- Timestamp:
- Nov 21, 2017, 2:35:09 PM (6 years ago)
- Location:
- extensions/net.sf.basedb.relax/trunk
- Files:
-
- 9 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/net.sf.basedb.relax/trunk/META-INF/servlets.xml
r4350 r4631 5 5 <servlet-class>net.sf.basedb.relax.servlet.InstallServlet</servlet-class> 6 6 </servlet> 7 <servlet> 8 <servlet-name>Session</servlet-name> 9 <servlet-class>net.sf.basedb.relax.servlet.SessionServlet</servlet-class> 10 </servlet> 11 <servlet> 12 <servlet-name>Export</servlet-name> 13 <servlet-class>net.sf.basedb.relax.servlet.ExportServlet</servlet-class> 14 </servlet> 7 15 </servlets> -
extensions/net.sf.basedb.relax/trunk/resources/css/relax.css
r4362 r4631 27 27 display: none; 28 28 } 29 30 .wizard 31 { 32 margin: 0em; 33 box-sizing: border-box; 34 } 35 36 .wizard .step 37 { 38 position: relative; 39 margin-bottom: 1em; 40 display: none; 41 } 42 43 .wizard.disabled 44 { 45 pointer-events: none; 46 } 47 48 .wizard.disabled .step, .wizard .step.disabled, .wizard.disabled .step-form 49 { 50 filter: url(filters.svg#grayscale); /* Firfox, etc */ 51 filter: gray; /* IE */ 52 opacity: 0.75; 53 } 54 55 .wizard .step-no 56 { 57 position: absolute; 58 top: 0; 59 left: 0; 60 bottom: 0; 61 width: 2rem; 62 text-align: center; 63 font-size: 150%; 64 font-weight: bold; 65 padding-top: 2px; 66 color: #FFFFFF; 67 background-color: #224488; 68 } 69 70 .wizard .step-title 71 { 72 margin-left: 2rem; 73 padding: 2px 4px 2px 4px; 74 border-bottom-width: 1px; 75 border-top-width: 1px; 76 background-color: #E8E8E8; 77 color: #224488; 78 font-weight: bold; 79 } 80 81 .wizard .step-title .helpicon 82 { 83 margin-left: 1em; 84 } 85 86 .wizard .step-content 87 { 88 margin-left: 2rem; 89 border-bottom-width: 1px; 90 } 91 92 .wizard .step.disabled .step-no 93 { 94 cursor: pointer; 95 } 96 97 .wizard .step.disabled .step-content 98 { 99 pointer-events: none; 100 } 101 102 .wizard .step.disabled.auto-hide .step-no 103 { 104 font-size: 100%; 105 } 106 107 .wizard .step.disabled.auto-hide .step-content 108 { 109 display: none; 110 } 111 112 113 .wizard .step-form 114 { 115 width: 100%; 116 border-collapse: collapse; 117 } 118 119 120 .wizard .step-form > tbody > tr > td 121 { 122 padding: 1px 2px 1px 4px; 123 vertical-align: baseline; 124 } 125 126 .wizard .step-form > tbody > tr.align-top > td 127 { 128 vertical-align: top; 129 } 130 131 .wizard .step-form > tbody > tr.align-middle > td 132 { 133 vertical-align: middle; 134 } 135 136 .wizard .step-form .prompt 137 { 138 width: 18em; 139 min-width: 18em; 140 font-weight: bold; 141 white-space: nowrap; 142 } 143 144 .wizard .step-form .subprompt 145 { 146 width: 18em; 147 min-width: 18em; 148 text-align: right; 149 font-weight: normal; 150 white-space: nowrap; 151 } 152 153 .wizard .step-form .section-header td:not(.help) 154 { 155 background-color: #E8E8E8; 156 white-space: nowrap; 157 } 158 159 .wizard .step-form .section-header td 160 { 161 padding: 3px 2px 3px 4px; 162 } 163 164 .wizard .step-form .section-header td:first-child 165 { 166 font-weight: bold; 167 } 168 169 .wizard .step-form .section-header td:first-child:before 170 { 171 content: '› '; 172 color: #999999; 173 } 174 175 .wizard .step-form .info-section tr:not(.section-header) td:not(.help) 176 { 177 background-color: rgba(232, 232, 232, 0.5); 178 } 179 180 .wizard .step-form .info-section .prompt 181 { 182 font-weight: normal; 183 padding-left: 2em; 184 text-align: left; 185 } 186 187 .wizard .step-form .info-section .info 188 { 189 font-style: italic; 190 } 191 192 .wizard .step-form .info-section .item-description 193 { 194 white-space: pre-wrap; 195 height: 6em; 196 max-height: 6em; 197 overflow: auto; 198 } 199 200 .wizard .step-form .input 201 { 202 width: 36em; 203 } 204 205 .wizard .step-form .input select, .wizard .step-form .input input[type="text"], .wizard .step-form .input textarea 206 { 207 width: 95%; 208 } 209 210 .wizard .step-form .status 211 { 212 width: 20px; 213 background-repeat: no-repeat; 214 background-position: 50% 50%; 215 } 216 217 .wizard .step-form .align-top .status 218 { 219 background-position: 50% 2px; 220 transform-origin: 50% 10px; 221 } 222 223 .wizard .step-form .status.invalid 224 { 225 background-image: url('../images/error.png'); 226 } 227 228 .wizard.flash-error .step-form .status.invalid 229 { 230 animation: enlarge 1s infinite; 231 } 232 233 .wizard.flash-error .step-form tr.invalid, .wizard.flash-error .step-form td.invalid 234 { 235 animation: flash 1s infinite; 236 } 237 238 @keyframes flash 239 { 240 0% { background-color: inherit; } 241 50% { background-color: #FFCCCC; } 242 100% { background-color: inherit; } 243 } 244 245 @keyframes enlarge 246 { 247 0% { transform: scale(1,1); } 248 50% { transform: scale(2,2); } 249 100% { transform: scale(1,1); } 250 } 251 252 .wizard .step-form .status.warning 253 { 254 background-image: url('../images/warning.png'); 255 } 256 .wizard .step-form .status.valid 257 { 258 background-image: url('../images/ok.png'); 259 } 260 261 .wizard .step-form .status.checking 262 { 263 background-image: url('../images/loading-small.gif'); 264 } 265 266 .wizard .step-form .status.flag 267 { 268 background-image: url('../images/flag.png'); 269 } 270 271 .wizard .step-form .status.new 272 { 273 background-image: url('../images/new.png'); 274 } 275 276 .wizard .step-form .help 277 { 278 background-color: rgba(208, 208, 208, 0.5); 279 font-style: italic; 280 } 281 282 .wizard .step-form .help .message 283 { 284 color: #C80000; 285 font-weight: bold; 286 padding-right: 6px; 287 display: none; 288 } 289 290 .wizard .navigation 291 { 292 margin-left: 2.5em; 293 margin-top: 1em; 294 margin-bottom: 5em; 295 border-spacing: 4px 0; 296 } 297 298 .wizard .navigation #gorestart 299 { 300 pointer-events: all !important; 301 } 302 303 .navigation .basicbutton 304 { 305 display: none; 306 } 307 308 .navigation .message 309 { 310 color: #CC0000; 311 font-weight: bold; 312 padding-left: 0.5em; 313 } 314 315 .progress-bar 316 { 317 display: none; 318 margin-top: 0.0em; 319 margin-left: 5em; 320 width: 200px; 321 white-space: nowrap; 322 } 323 324 .progress-bar::after 325 { 326 content: attr(value); 327 vertical-align: top; 328 padding-left: 0.5em; 329 } 330 331 .progress-bar span 332 { 333 display: inline-block; 334 height: 1.4em; 335 } 336 337 .success li 338 { 339 background-position: 0 50%; 340 background-repeat: no-repeat; 341 padding-left: 20px; 342 list-style-type: none; 343 line-height: 1.75; 344 } 345 346 .success li.ok 347 { 348 background-image: url('../images/ok.png'); 349 } 350 351 .success li.warning 352 { 353 background-image: url('../images/warning.png'); 354 } 355 356 .success li.error 357 { 358 background-image: url('../images/error.png'); 359 background-color: transparent !important; 360 color: #990000 !important; 361 } -
extensions/net.sf.basedb.relax/trunk/resources/relax.js
r4610 r4631 18 18 var numLiveAsyncRequests = 0; 19 19 var hasFatalError = false; 20 var currentStep = 1; 21 var hasSentRegistration = false; 22 var forceConfirm = false; 23 var noConfirmOnFirstStep = true; 20 24 21 25 /** … … 103 107 } 104 108 } 109 110 wizard.isValid = function(element) 111 { 112 return Data.int(element, 'valid', 1); 113 } 114 115 wizard.initFileSelectionField = function(element) 116 { 117 element = Doc.element(element); 118 Events.addEventHandler(element, 'change', wizard.fileChanged); 119 Events.sendChangeEvent(element); 120 } 121 122 wizard.fileChanged = function(event) 123 { 124 var target = event.currentTarget; 125 126 var isValid = false; 127 var isWarning = false; 128 129 // Reset current status 130 wizard.setInputStatus(target); 131 132 var path = target.value; 133 if (path == '') 134 { 135 // No file, is this an error or a warning? 136 var optional = target.className.indexOf('required') == -1; 137 wizard.setInputStatus(target, optional ? 'warning' : 'invalid', 'Missing'); 138 isValid = optional; 139 isWarning = optional; 140 } 141 else 142 { 143 Wizard.setInputStatus(target, 'valid'); 144 isValid = true; 145 } 146 147 Data.set(target, 'valid', isValid ? 1 : 0); 148 Data.set(target, 'warning', isWarning ? 1 : 0); 149 150 if (!isValid && target.focus) target.focus(); 151 } 152 153 /** 154 Change display status for an input field. 155 @param prefix ID prefix to locate tags 156 @param clazz The message clazz (valid, invalid, warning) or empty 157 @param message The message (may be empty) 158 */ 159 wizard.setInputStatus = function(prefix, clazz, message) 160 { 161 if (prefix.id) prefix = prefix.id; 162 163 var statusTag = Doc.element(prefix + '.status'); 164 165 if (statusTag) 166 { 167 statusTag.className = 'status ' + (clazz || ''); 168 var trTag = statusTag.parentNode; 169 var trClass = Data.get(trTag, 'original-class'); 170 if (!trClass) 171 { 172 trClass = trTag.className || 'foo'; 173 Data.set(trTag, 'original-class', trClass); 174 } 175 trTag.className = trClass + ' ' + (clazz || ''); 176 } 177 178 var msgTag = Doc.element(prefix + '.message'); 179 if (msgTag) 180 { 181 if (message) 182 { 183 msgTag.innerHTML = message; 184 Doc.show(msgTag, Data.get(msgTag, 'display', 'inline')); 185 } 186 else 187 { 188 msgTag.innerHTML = message; 189 Doc.hide(msgTag); 190 } 191 } 192 else if (statusTag) 193 { 194 statusTag.title = message || ''; 195 } 196 } 197 198 /** 199 Event handler for input fields, that go to the 200 next wizard step if TAB or ENTER key is pressed. 201 A short delay is used to allow other event handler 202 to run first (eg. for validation). 203 */ 204 wizard.goNextOnTabOrEnter = function(event) 205 { 206 if (event.keyCode == 9 || event.keyCode == 13) 207 { 208 setTimeout(function() { wizard.goNext(true) }, 200); 209 } 210 } 211 212 /** 213 Event handler for input fields, that go to the 214 next wizard step if TAB key is pressed. 215 A short delay is used to allow other event handler 216 to run first (eg. for validation). 217 */ 218 wizard.goNextOnTab = function(event) 219 { 220 if (event.keyCode == 9) 221 { 222 setTimeout(function() { wizard.goNext(true) }, 200); 223 } 224 } 225 226 /** 227 Event handler for input fields, that changes 228 focus to the next element. The next element 229 should be defined by 'data-next-focus' attribute. 230 It is recommended that this is consisistent with TAB. 231 */ 232 wizard.focusOnEnter = function(event) 233 { 234 if (event.keyCode == 13) 235 { 236 var nextFocus = Doc.element(Data.get(event.currentTarget, 'next-focus')); 237 if (nextFocus && nextFocus.focus) nextFocus.focus(); 238 } 239 } 240 241 // Event handler for the 'Next' navigation button 242 wizard.goNextOnClick = function(event) 243 { 244 wizard.goNext(false); 245 } 246 247 /** 248 Go to the next step in the wizard. This method will first 249 submit 'wizard-validate' event to the current step. If at 250 least one event handler calls 'Event.preventDefault()' the 251 processing is aborted. 252 253 Otherwise, the current step is disabled and the 'wizard-initialize' 254 event is sent to the next step. The event handler is responsible 255 for calling 'Wizard.setCurrentStep' to display the next step. 256 */ 257 wizard.goNext = function(auto) 258 { 259 var verify = Doc.element('verifyGoNext'); 260 if (verify && !verify.checked) return; 261 262 var details = { 'auto': auto }; 263 264 // Send 'wizard-validate' event to current step 265 var step = Doc.element('step-'+currentStep); 266 var evt = document.createEvent('CustomEvent'); 267 evt.initCustomEvent('wizard-validate', true, true, details); 268 if (!step.dispatchEvent(evt)) 269 { 270 wizard.notifyError(); 271 return; 272 } 273 274 // Hide all navigation buttons and disable form controls in current step 275 internal.hideButtons('navigation'); 276 internal.disableStep(step); 277 278 // Send 'wizard-initialize' to the next step 279 var nextStep = Doc.element('step-'+(currentStep+1)); 280 var evt = document.createEvent('CustomEvent'); 281 evt.initCustomEvent('wizard-initialize', true, true, details); 282 nextStep.dispatchEvent(evt); 283 } 284 285 wizard.notifyError = function() 286 { 287 Doc.addClass('wizard', 'flash-error'); 288 setTimeout(internal.stopFlashing, 2000); 289 } 290 291 internal.stopFlashing = function() 292 { 293 Doc.removeClass('wizard', 'flash-error'); 294 } 295 296 /** 297 Finalize the registration of the wizard. This method will 298 first submit 'wizard-validate' to the current step. If at 299 least one event handler calls 'Event.preventDefault()' the 300 processing is aborted. 301 302 Otherwise, the current step is disabled and the 'wizard-submit' 303 event is sent to the 'wizard'. The event handler is responsible 304 for finalizing the registration and displaying a proper 305 message, for example, by calling Wizard.showFinalMessage() 306 307 The 'data' is passed on to the 'wizard-validate' and 308 'wizard-submit' events as the Event.details object. 309 */ 310 wizard.goRegister = function(data) 311 { 312 // Check if verification is enabled 313 var verify = Doc.element('verifyGoNext'); 314 if (verify && !verify.checked) return; 315 316 // Send 'wizard-validate' event to current step 317 var step = Doc.element('step-'+currentStep); 318 var evt = document.createEvent('CustomEvent'); 319 evt.initCustomEvent('wizard-validate', true, true, data); 320 if (!step.dispatchEvent(evt)) 321 { 322 wizard.notifyError(); 323 return; 324 } 325 326 internal.hideButtons('navigation'); 327 internal.disableStep(step); 328 329 // Send 'wizard-submit' to the next step 330 var wiz = Doc.element('wizard'); 331 hasSentRegistration = true; 332 var evt = document.createEvent('CustomEvent'); 333 evt.initCustomEvent('wizard-submit', true, true, data); 334 wiz.dispatchEvent(evt); 335 } 336 337 wizard.setNoConfirmOnFirstStep = function(cf) 338 { 339 noConfirmOnFirstStep = cf; 340 } 341 342 // Ask the user for confirmation and then restart the wizard 343 wizard.cancelWizard = function() 344 { 345 forceConfirm = true; 346 wizard.restartWizard(); 347 } 348 349 // Restart the wizard without asking the user for confirmation 350 wizard.restartWizard = function() 351 { 352 var url = location.href; 353 if (url.indexOf('&restart=1') == -1) url += '&restart=1'; 354 location.href = url; 355 } 356 357 wizard.setCurrentStep = function(stepNo) 358 { 359 currentStep = stepNo; 360 internal.enableStep(Doc.element('step-'+currentStep)); 361 } 362 363 internal.disableStep = function(step) 364 { 365 step = Doc.element(step); 366 internal.disableAllFormElements(step); 367 Doc.addClass(step, 'disabled'); 368 Doc.hide('gonext-message'); 369 var stepNo = step.getElementsByClassName('step-no')[0]; 370 Events.addEventHandler(stepNo, 'click', internal.togglePastStep, {'step-id': step.id}); 371 stepNo.title = 'Show/hide this section'; 372 } 373 374 internal.enableStep = function(step) 375 { 376 step = Doc.element(step); 377 Doc.removeClass(step, 'disabled'); 378 Doc.show(step); 379 } 380 381 // Toggle visibility of a past step 382 // The step is hidden if the 'auto-hide' class is present 383 internal.togglePastStep = function(event) 384 { 385 var step = Data.get(event.currentTarget, 'step-id'); 386 Doc.addOrRemoveClass(step, 'auto-hide'); 387 } 105 388 106 389 … … 156 439 { 157 440 wizard.setWizardStatus('loading', msg || 'Working, please wait...'); 158 } 441 if (progress) 442 { 443 var progressBar = Doc.element('wizard-progress'); 444 progressBar.classList.add('progress-bar'); 445 446 // Get/create child elements 447 var done = Doc.element('wizard-progress-done'); 448 if (!done) 449 { 450 done = document.createElement('span'); 451 done.id = 'wizard-progress-done'; 452 done.className = 'progress-bar-done bg-filled-100 topborder bottomborder leftborder'; 453 progressBar.appendChild(done); 454 } 455 var remain = Doc.element('wizard-progress-remain'); 456 if (!remain) 457 { 458 remain = document.createElement('span'); 459 remain.id = 'wizard-progress-remain'; 460 remain.className = 'progress-bar-remain topborder bottomborder rightborder'; 461 progressBar.appendChild(remain); 462 } 463 464 progressBar.setAttribute('value', '0%'); 465 done.style.width = '0%'; 466 remain.style.width = '100%'; 467 Doc.show(progressBar); 468 469 // Initial request for updating the progress bar 470 progressTimer = setTimeout(internal.requestProgressUpdate, 1500, progress); 471 } 472 } 473 474 /** 475 Make a request for the progress information. The 'progress' 476 parameter is the name of a progress bar. 477 */ 478 internal.requestProgressUpdate = function(progress) 479 { 480 if (hasFatalError) return; 481 var url = '../Session.servlet?ID='+App.getSessionId(); 482 url += '&cmd=GetProgress'; 483 url += '&name='+encodeURIComponent(progress); 484 485 var request = Ajax.getXmlHttpRequest(); 486 request.open("GET", url, true); 487 Ajax.setReadyStateHandler(request, internal.onProgressReport, internal.onProgressReport); 488 request.send(null); 489 } 490 491 /** 492 Callback when receiving a progress update. 493 */ 494 internal.onProgressReport = function(request) 495 { 496 if (hasFatalError) return; 497 if (debug) App.debug(Strings.encodeTags(request.responseText)); 498 var response; 499 var error = false; 500 try 501 { 502 response = JSON.parse(request.responseText); 503 if (response.status != 'ok') 504 { 505 error = response.message || response.stacktrace || 'Unexpected error'; 506 } 507 } 508 catch (ex) 509 { 510 error = ex; 511 } 512 513 if (error) 514 { 515 return; 516 } 517 518 var progress = response.progress; 519 var progressBar = Doc.element('wizard-progress'); 520 521 if (!progress) 522 { 523 // Give up if no progress information 524 Doc.hide(progressBar); 525 return; 526 } 527 528 var done = Doc.element('wizard-progress-done'); 529 var remain = Doc.element('wizard-progress-remain'); 530 531 progressBar.setAttribute('value', progress.percent+'%'); 532 done.style.width = progress.percent+'%'; 533 remain.style.width = (100-progress.percent)+'%'; 534 535 if (progress.message) 536 { 537 Doc.element('wizard-status').innerHTML = Strings.encodeTags(progress.message); 538 } 539 540 if (progress.percent < 100) 541 { 542 // Continue to request updates until we 100% has been reached 543 progressTimer = setTimeout(internal.requestProgressUpdate, 1500, progress.name); 544 } 545 else 546 { 547 progressTimer = null; 548 Doc.hide(progressBar); 549 } 550 } 551 159 552 160 553 wizard.showStatusMessage = function(msg) … … 172 565 Doc.hide('wizard-progress'); 173 566 } 174 567 568 wizard.showGoNextConfirmation = function(verify, msg) 569 { 570 var check = ''; 571 if (verify) 572 { 573 check = '<input type="checkbox" name="verifyGoNext" id="verifyGoNext">'; 574 Doc.addClass('gonext', 'disabled'); 575 Doc.addClass('goregister', 'disabled'); 576 } 577 578 var gonext = Doc.element('gonext-message'); 579 gonext.innerHTML = check + msg; 580 Doc.show(gonext); 581 582 if (verify) 583 { 584 Events.addEventHandler('verifyGoNext', 'click', internal.verifyInternalOnClick); 585 } 586 } 587 588 wizard.hideGoNextConfirmation = function() 589 { 590 var gonext = Doc.element('gonext-message'); 591 gonext.innerHTML = ''; 592 Doc.hide(gonext); 593 Doc.removeClass('gonext', 'disabled'); 594 Doc.removeClass('goregister', 'disabled'); 595 } 596 597 internal.verifyInternalOnClick = function(event) 598 { 599 var frm = document.forms['reggie']; 600 var checked = event.currentTarget.checked; 601 Doc.addOrRemoveClass('goregister', 'disabled', !checked); 602 Doc.addOrRemoveClass('gonext', 'disabled', !checked); 603 } 604 605 /** 606 Show final registration messages in a list. 607 */ 608 wizard.showFinalMessage = function(messages) 609 { 610 var msg = internal.generateMessageList(messages); 611 wizard.setWizardStatus('success', msg.html); 612 if (progressTimer) clearTimeout(progressTimer); 613 return { 'errors': msg.errors, 'warnings': msg.warnings }; 614 } 615 616 internal.generateMessageList = function(messages) 617 { 618 var msg = '<ul>'; 619 var numWarnings = 0; 620 var numErrors = 0; 621 for (var i = 0; i < messages.length; i++) 622 { 623 var msgLine = messages[i]; 624 if (msgLine.indexOf('[Warning]') >= 0) 625 { 626 msg += '<li class="warning">' + Strings.encodeTags(msgLine.replace('[Warning]', '')); 627 numWarnings++; 628 } 629 else if (msgLine.indexOf('[Error]') >= 0) 630 { 631 msg += '<li class="error">' + Strings.encodeTags(msgLine.replace('[Error]', '')); 632 numErrors++; 633 } 634 else 635 { 636 msg += '<li class="ok">' + Strings.encodeTags(msgLine); 637 } 638 } 639 msg += '</ul>'; 640 return { 'html': msg, 'errors': numErrors, 'warnings': numWarnings }; 641 } 642 175 643 /** 176 644 Initialize the wizard:
Note: See TracChangeset
for help on using the changeset viewer.