1/* 2The following errors were found when attempting to minify this file: 3- Line 37: Parse error. missing : after property id 4- Line 37: Parse error. illegal character 5- Line 37: Parse error. missing ; before statement 6- Line 37: Parse error. illegal character 7- Line 37: Parse error. syntax error 8- Line 38: Parse error. syntax error 9- Line 39: Parse error. syntax error 10- Line 40: Parse error. syntax error 11- Line 42: Parse error. syntax error 12- Line 43: Parse error. illegal character 13- Line 43: Parse error. missing ) after argument list 14- Line 43: Parse error. illegal character 15- Line 43: Parse error. syntax error 16- Line 44: Parse error. syntax error 17- Line 45: Parse error. syntax error 18- Line 46: Parse error. syntax error 19- Line 47: Parse error. syntax error 20- Line 49: Parse error. syntax error 21- Line 51: Parse error. missing ; before statement 22- Line 59: Parse error. syntax error 23- Line 61: Parse error. syntax error 24- Line 66: Parse error. invalid return 25- Line 67: Parse error. syntax error 26- Line 69: Parse error. missing ; before statement 27- Line 73: Parse error. syntax error 28- Line 74: Parse error. syntax error 29- Line 75: Parse error. syntax error 30- Line 77: Parse error. syntax error 31- Line 79: Parse error. missing ; before statement 32- Line 85: Parse error. illegal character 33- Line 85: Parse error. missing ; before statement 34- Line 85: Parse error. illegal character 35- Line 86: Parse error. syntax error 36- Line 87: Parse error. syntax error 37- Line 90: Parse error. syntax error 38- Line 93: Parse error. illegal character 39- Line 93: Parse error. missing ; before statement 40- Line 93: Parse error. illegal character 41- Line 97: Parse error. invalid return 42- Line 98: Parse error. syntax error 43- Line 100: Parse error. missing ; before statement 44- Line 101: Parse error. syntax error 45- Line 102: Parse error. syntax error 46- Line 103: Parse error. syntax error 47- Line 108: Parse error. invalid return 48- Line 113: Parse error. missing ; after for-loop initializer 49- Line 113: Parse error. missing ; before statement 50- Line 120: Parse error. syntax error 51- Line 124: Parse error. syntax error 52- Line 127: Parse error. syntax error 53- Line 129: Parse error. syntax error 54- Line 131: Parse error. syntax error 55- Line 132: Parse error. syntax error 56- Line 133: Parse error. syntax error 57- Line 398: Parse error. missing ; before statement 58*/ 59// Gets Json object using a given url. 60function GetJson(url) { 61 var result; 62 $.ajaxSetup({ async: false }); 63 $.post(url, function (data) { 64 result = data; 65 }); 66 $.ajaxSetup({ async: true }); 67 return result; 68} 69 70function maxLength(field, maxChars) { 71 if (field.value.length >= maxChars) { 72 event.returnValue = false; 73 return false; 74 } 75} 76 77function maxLengthPaste(field, maxChars) { 78 var copyText = field.value + window.clipboardData.getData("Text"); 79 field.value = copyText.substr(0, maxChars); 80 if ((copyText.length) > maxChars) { 81 return false; 82 } 83 event.returnValue = true; 84} 85 86function appendFilesToInput(appendInput, mainFileInput) { 87 const valid = validateMultiFileUpload(appendInput, true); 88 if (!valid) { 89 alert("The file you are trying to upload is not an allowed file type or has an invalid file name. These are the accepted characters: A-z 0-9 ~ ! ( ) - + = [ ] { } , . _"); 90 appendInput.value = null; 91 return; 92 } 93 const dt = new DataTransfer(); 94 const originalFiles = Array.from(mainFileInput.files); 95 const existingSet = new Set(originalFiles.map(({ name, size, lastModified }) => `${name}-${size}-${lastModified}`)); 96 originalFiles.forEach(file => { 97 dt.items.add(file); 98 }) 99 const addedFiles = Array.from(appendInput.files); 100 addedFiles.forEach(file => { 101 if (!existingSet.has(`${file.name}-${file.size}-${file.lastModified}`)) { 102 dt.items.add(file); 103 } 104 }) 105 mainFileInput.files = dt.files; 106 mainFileInput.dispatchEvent(new Event("change")); 107} 108 109function fileAppender(mainFileInput) { 110 const li = document.createElement("li"); 111 const label = document.createElement("label"); 112 label.innerHTML = '<span class="visuallyhidden">Add Files</span><svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" aria-hidden="true"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z"/></svg>' 113 const appendInput = document.createElement("input"); 114 appendInput.type = "file"; 115 appendInput.multiple = true; 116 appendInput.className = "visuallyhidden"; 117 appendInput.addEventListener("change", e => { 118 appendFilesToInput(appendInput, mainFileInput); 119 }); 120 label.appendChild(appendInput); 121 const placeholder = document.createElement("span"); 122 li.appendChild(placeholder); 123 li.appendChild(label); 124 return li; 125} 126 127function removeFileFromInput(input, idx) { 128 const dt = new DataTransfer(); 129 const files = Array.from(input.files); 130 files.splice(idx, 1);
131 files.forEach(file => { 132 dt.items.add(file); 133 }); 134 input.files = dt.files; 135} 136 137function listItemFile(input, file, idx) { 138 const li = document.createElement("li"); 139 const fileNameSpan = document.createElement("span"); 140 fileNameSpan.textContent = file.name; 141 li.appendChild(fileNameSpan); 142 const removeButton = document.createElement("button"); 143 removeButton.title = `Remove ${file.name}`; 144 removeButton.addEventListener("click", e => { 145 e.preventDefault(); 146 removeFileFromInput(input, idx); 147 input.dispatchEvent(new Event("change")); 148 }); 149 removeButton.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" fill="darkred" aria-hidden="true"><path d="m336-280 144-144 144 144 56-56-144-144 144-144-56-56-144 144-144-144-56 56 144 144-144 144 56 56ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"></path></svg>'; 150 const removeButtonSpan = document.createElement("span"); 151 removeButtonSpan.textContent = `Remove ${file.name}`; 152 removeButtonSpan.className = "visuallyhidden"; 153 removeButton.appendChild(removeButtonSpan); 154 li.appendChild(removeButton); 155 return li; 156} 157 158function listFileInputFiles(fileInput) { 159 if (fileInput.nextElementSibling?.className === "file-list") { 160 fileInput.nextElementSibling.remove(); 161 } 162 const files = fileInput.files || []; 163 const valid = files.length && validateMultiFileUpload(fileInput, true) 164 if (!valid) { 165 fileInput.value = null; 166 return; 167 } 168 if (files.length > 1) { 169 const ul = document.createElement("ul"); 170 ul.className = "file-list"; 171 for (let i = 0; i < files.length; i++) { 172 const li = listItemFile(fileInput, files[i], i); 173 ul.appendChild(li); 174 } 175 const fileAppenderLi = fileAppender(fileInput); 176 ul.appendChild(fileAppenderLi); 177 fileInput.after(ul); 178 } 179} 180 181function initFileInputs() { 182 if (!((window?.FeatureToggles?.isActive?.("CMS.FormCenter.MultipleFileUploadEnhancement")) || (window?.FeatureToggles?.features?.["CMS.FormCenter.MultipleFileUploadEnhancement"]))) { 183 return; 184 } 185 document.querySelectorAll(".FileUpload input[type='file']").forEach(fileInput => { 186 listFileInputFiles(fileInput); 187 fileInput.addEventListener("change", e => { 188 listFileInputFiles(fileInput) 189 }) 190 }); 191} 192; 193/// <reference path="../../../../Scripts/json2.js"> 194/// <reference path="../../../../Scripts/HtmlExtensionSupport.js"> 195/// <reference path="../../../../Scripts/UrlLibrary.js"> 196/// <reference path="../../../../Common/GlobalJSFunctionsDetail.js" /> 197/// <reference path="Conditions.js" /> 198/// <reference path="Validation.js" /> 199/// <reference path="/Assets/Scripts/DynamicForm/PrintSubmission.js" /> 200/// <reference path="../../../../Assets/Scripts/DateTimePicker/cp.datetimepicker.js" /> 201 202//////// ENUMERATIONS /////////// 203var FormCenterHomeJS = (function ($) { 204 var self = this; 205 206 // This value is set on the ItemDetailFE.ascx page, using a value from the 207 // View Model. 208 self.submissionURL = ''; 209 210 return self; 211}(jQuery)); 212 213var FormCenterHomeScriptResources = GetJson("/FormCenter/Localization"); 214 215// Field formats. 216var FieldValidation = { 217 Any: 0, 218 Letters: 1, 219 Numeric: 2, 220 PhoneNumber: 3, 221 PostalCode: 4, 222 EmailAddress: 5, 223 RegEx: 6, 224 Currency: 7, 225 Date: 8, 226 Time: 9, 227 DateTime: 10, 228 DateSpan: 11, 229 TimeSpan: 12, 230 DateTimeSpan: 13 231}; 232 233// Supported field types. 234var FieldTypes = { 235 ShortAnswer: 1, 236 LongAnswer: 2, 237 Checkboxes: 3, 238 RadioButtons: 4, 239 Dropdown: 5, 240 FileUpload: 6, 241 ReplyEmail: 10, 242 Password: 11, 243 DateTime: 18, 244 EPayment: 23 245}; 246 247//////// GLOBALS //////////////// 248 249// Stores instantiated form validator/condition instances for the current form. 250var formValidators = null; 251var formConditions = null; 252 253// Use with form submissions. 254var redirectNewWindow = null; 255 256//////// SUPPORT METHODS ////////f 257 258// Shows extra information for a form detail. 259function moreInfo(id) { 260 changeInfo(id, 'addClass', 'removeClass'); 261} 262 263// Hides extra information for a form detail. 264function lessInfo(id) { 265 changeInfo(id, 'removeClass', 'addClass'); 266} 267 268// Internal. Hides or shows extra information. 269function changeInfo(id, lessFn, moreFn) { 270 $([document.getElementById('spnLess' + id), document.getElementById('lnkMore' + id)])[lessFn]('hidden'); 271 $(document.getElementById('spnMore' + id))[moreFn]('hidden'); 272} 273 274// Assigns bulk action checkbox group to jQuery expression. 275function assignBulkCheckGroup($children, $parent) { 276 // Isolate children from parent in event of overlap ($children containing the $parent). 277 // Vastly simplifies the logic in the event handlers by doing this. 278 var $isolatedChildren = $children.filter( 279 function (index) { 280 return $parent.filter(this).length == 0; 281 } 282 ); 283 284 // Cache current number of checked children. 285 $isolatedChildren.lengthChecked = $isolatedChildren.filter(':checked').length; 286 287 // Hook childen change. 288 $isolatedChildren.change(function (event) { 289 $isolatedChildren.lengthChecked += (this.checked ? 1 : -1); 290 291 var allChildrenChecked = ($isolatedChildren.lengthChecked == $isolatedChildren.length); 292 293 $parent.each(function () { 294 this.checked = allChildrenChecked; 295 }); 296 }); 297 298 // Hook parent change. 299 $parent.change(function (event) { 300 var parentChecked = this.checked; 301 302 $isolatedChildren.lengthChecked = this.checked ? $isolatedChildren.length : 0; 303 304 $isolatedChildren.each(function () { 305 this.checked = parentChecked; 306 }); 307 }); 308} 309 310function initCommon() { 311 // Hack: Internet Explorer 7 mode bizarre display bugs. 312 $('.sidebar .search.noStyles').css('zoom', '1'); 313 314 // Hook search category bulk checks. 315 var $bulkCheck = $('#categoryFilter_0'); 316 var $bulkGroup = $('.categoryList input[type="checkbox"]'); 317 318 assignBulkCheckGroup($bulkGroup, $bulkCheck); 319 320 // Get input jQuery refs.
321 var $inputFCTerm = $('#inputFCTerm'); 322 var $inputFCSearch = $('#inputFCSearch'); 323 324 // Hook search button and textbox to capture enter key. 325 $inputFCTerm.keydown(function (event) { 326 // If user presses enter, submit for search. 327 switch (event.which) { 328 case 10: // LF 329 case 13: // CR 330 event.preventDefault(); 331 $inputFCSearch.click(); 332 break; 333 } 334 }); 335 336 $inputFCSearch.click(function (event) { 337 event.preventDefault(); 338 339 // Build search querystring. 340 var qs = {}; 341 var formID = extractFormIDFromURL(location.href); 342 var categoryID = extractCategoryIDFromURL(location.href); 343 344 var searchTerm = $.trim(isNull($inputFCTerm.val(), '')); 345 346 if (formID) 347 qs.formID = formID; 348 349 if (categoryID) 350 qs.categoryID = categoryID; 351 352 if (searchTerm != '') 353 qs.term = searchTerm; 354 355 if (!$bulkCheck[0].checked) { 356 var values = []; 357 358 $bulkGroup.filter(':checked').each(function () { 359 values.push(this.value); 360 }); 361 362 if (values.length > 0) 363 qs.categoryFilter = values.join(','); 364 } 365 366 // Set search URL and go. 367 window.location = '/FormCenter/Search' + (new QueryStringBuilder(qs)).toString(); 368 }); 369 370 // Hook search category dropdown. 371 var $catList = $('#categoryList'); 372 var $catListToggle = $('a.mega'); 373 374 $catListToggle.click(function (e) { 375 e.preventDefault(); 376 377 if ($catList.hasClass('open')) 378 $catList.slideUp(300); 379 else 380 $catList.slideDown(300); 381 382 $catListToggle.toggleClass('active'); 383 $catList.toggleClass('open'); 384 }); 385 386 // Show print dialog if URL contains standard print query string. 387 if (containsPrint(location.href)) 388 window.print(); 389} 390 391// Initialization for search (Search.aspx view). 392function initSearch() { 393 if (this.wasInit) 394 return; 395 396 this.wasInit = true; 397 398 attachCategoryVisibilityTogglers(); 399 400 initCommon(); 401} 402 403// Initialization for category/form list (Index.aspx view). 404function initCategoryList() { 405 if (this.wasInit) 406 return; 407 408 this.wasInit = true; 409 410 attachCategoryVisibilityTogglers(); 411 412 initCommon(); 413} 414 415// Initialization for confirmation (Confirmation.aspx view). 416function initConfirmation() { 417 if (this.wasInit) 418 return; 419 420 this.wasInit = true; 421 422 initCommon(); 423} 424 425function initPostSubmissionSpam() { 426 initCommon(); 427} 428 429 430// Causes current form to be submitted for printing. 431function printForm(saveData) { 432 if (formValidate()) { //check for valid responses before creating print window 433 var frm = document.aspnetForm; 434 var $form = $(document.aspnetForm); 435 var printPrevType = (getPrintPreviewType() == 1 ? 'Print' : 'Preview'); 436 var formID = extractFormIDFromURL(location.href); 437 438 $form.attr('target', 'PrintWindow'); 439 // Change target/action to print data. 440 frm.action = '/FormCenter/Print?formID=' + formID + '&' + printPrevType + '=YES&Save=' + (saveData ? 'True' : 'False'); 441 442 var savedProgressID = parseInt($('#hdnSavedProgressID').val(), 10); 443 444 if (!isNaN(savedProgressID)) { 445 frm.action = frm.action + '&savedProgressID=' + savedProgressID; 446 } 447 448 submitForm($form, true, saveData, formID); 449 } else { 450 enableDisableSubmit(true); 451 } 452} 453 454function submitFormHandler(e) { 455 try { 456 let json = JSON.parse(this.response); 457 458 if (this.status !== 200 || json.Success !== true) { 459 $('.submissionConfirmationMessage').html("Something went wrong with the submission. Please try again."); 460 $('.submissionConfirmation').show(); 461 enableDisableSubmit(true); 462 return; 463 } 464 465 const responseUrl = this.responseURL && new URL(this.responseURL); 466 const saveSubmission = responseUrl && responseUrl.searchParams.get('save') && responseUrl.searchParams.get('save').toLowerCase() === 'true'; 467 const doPrint = responseUrl && responseUrl.searchParams.get('print') && responseUrl.searchParams.get('print').toLowerCase() === 'true'; 468 const redirectAfterSubmissionSaved = json.Redirect && json.Redirect === true && saveSubmission === true; 469 470 if (redirectNewWindow) { 471 // There are two possible redirects in use: 472 // (1) The regular "submit" redirect for the form vs. category confirmation page. 473 // (2) The "conditional" redirect that is applied when a form condition is met. 474 // redirectNewWindow is the latter; redirectAfterSubmissionSaved below deals with the former. 475 window.open(redirectNewWindow); 476 redirectNewWindow = ''; 477 } 478 479 if (redirectAfterSubmissionSaved) 480 { 481 if (json.IsHttps === false) { 482 json.Message = json.Message.replace("https://", "http://"); 483 } 484 485 location.href = json.Message; 486 } 487 else { 488 if (saveSubmission === true) { 489 $('.submissionConfirmationMessage').html(json.Message); 490 typeof displayStep === "function" && displayStep(1); 491 $('.submitForm').hide(); 492 $('.submissionConfirmation').show(); 493 } 494 495 enableDisableSubmit(true); 496 } 497 498 if (doPrint === true) { 499 window.open("/FormCenter/Print?formId=" + json.FormId.toString() + '&save=' + (saveSubmission ? 'True' : 'False')); 500 } 501 502 if (json.Success === true) { 503 document.aspnetForm.reset(); 504 505 if (typeof (grecaptcha) !== "undefined") 506 { 507 grecaptcha.reset(); 508 } 509 } 510 511 !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights();
512 } catch (ex) { 513 console.log(ex); 514 } 515} 516 517function submitForm($form, print, saveSubmission, formID) { 518 var submittedViaWidget = $form.parents(".widgetBody").length > 0; 519 520 serializeSpecialFields(); 521 522 if (submittedViaWidget !== true) { 523 var printWindow; 524 525 if (print === true) 526 { 527 printWindow = window.open("", "PrintWindow"); 528 529 // Deferred object at the window level, this becomes available on the opened window via window.opener 530 // Whichever view gets rendered will resolve it and pass the appropriate status code. 531 window.deferredStatus = $.Deferred(); 532 } 533 534 if (printWindow) { 535 window.deferredStatus.done(function (status) { 536 if (status === CP_DynamicForm_PrintSubmission.StatusCodes.Success) { 537 if (saveSubmission && saveSubmission === true) { 538 window.location = '/FormCenter/Confirmation?formID=' + formID; 539 } 540 } else { 541 printWindow.close(); 542 543 if (saveSubmission) { 544 window.location = '/FormCenter/ErrorSubmittingForm?formID=' + formID; 545 } 546 } 547 }); 548 } 549 550 $form.submit(); 551 } 552 else { 553 var submissionUrl = FormCenterHomeJS.submissionURL + (saveSubmission ? '&save=True' : ""); 554 submissionUrl = submissionUrl + (print ? '&print=True' : ''); 555 556 var formData = new FormData($form[0]); 557 var xhr = new XMLHttpRequest(); 558 xhr.onload = submitFormHandler; 559 xhr.onloadend = ajaxPostBackEnd; 560 xhr.onerror = function() { console.log("A network error occurred with the transaction."); }; 561 xhr.open("POST", submissionUrl); 562 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 563 ajaxPostBackStart('Loading'); 564 xhr.send(formData); 565 } 566} 567 568function serializeSpecialFields() 569{ 570 submitCheckboxHandler(); 571 572 submitRadioHandler(); 573 574 submitDateTimeHandler(); 575} 576 577// Initialization for form item printing (Print.aspx view). 578function initFormPrint() { 579 if (this.wasInit) 580 return; 581 582 this.wasInit = true; 583 584 initCommon(); 585 586 initValidationAndConditions(); 587 588 registerFormPrintEvents(); 589} 590 591function initValidationAndConditions() { 592 // Register validation. 593 if (typeof getFormValidatorData !== 'undefined') { 594 formValidators = FieldValidator.createMulti(getFormValidatorData()); 595 } else { 596 formValidators = []; 597 } 598 599 // Register conditions. 600 if (getFormConditionData) { 601 formConditions = FieldConditions.createMulti(getFormConditionData(), formValidators); 602 } else { 603 formConditions = FieldConditions.createMulti([], formValidators); 604 } 605 606 // Register condition runner and make initial condition check. 607 formConditionsRunner = new FieldConditionsRunner(formConditions, $.noop, true, false); // TODO: Finish up, put debugCondRunnerLogResults for $.noop. 608 formConditionsRunner.run(); 609} 610 611// Initialization for form item (Item.aspx view). 612function initForm() { 613 614 if (this.wasInit) 615 return; 616 617 this.wasInit = true; 618 619 initCommon(); 620 initValidationAndConditions(); 621 initDatePickers(); 622 initTimePickers(); 623 initFileInputs(); 624 registerFormEvents(); // Hook up buttons (submit/cancel/etc). 625} 626 627function initDatePickers() { 628 if ($('.telerikDatePicker').length > 0) { 629 $('.telerikDatePicker').each(function () { 630 if (typeof (cp) !== 'undefined') { 631 var datePickerSelector = this.id ? '#' + this.id : this; 632 cp.datetimepicker && cp.datetimepicker.createDatePicker(datePickerSelector); 633 } 634 }); 635 } 636} 637 638function initTimePickers() { 639 if ($('.formCenterTimePicker').length > 0) { 640 $('.formCenterTimePicker').focusout(function () { 641 var text = $(this).val().toLowerCase(); 642 if (text != '' && (text.indexOf('am') < 0 && text.indexOf('pm') < 0)) { 643 text = $(this).val().trim() + ' AM'; 644 $(this).val(text); 645 } 646 }); 647 } 648 else { 649 $('.telerikTimePicker').each(function () { 650 if (typeof (cp) !== 'undefined') 651 cp.datetimepicker && cp.datetimepicker.createTimePicker(this, 652 { 653 format: 'h:i A' 654 }); 655 }); 656 } 657} 658 659// Registers event handlers for form. 660function registerFormPrintEvents() { 661 $('#btnFormContinue').click(function (event) { 662 event.preventDefault(); 663 664 var frm = document.aspnetForm; 665 var formID = extractFormIDFromURL(location.href); 666 var $form = $(document.aspnetForm); 667 668 // Change target/action to confirmation page.
669 frm.action = '/FormCenter/Confirmation?formID=' + formID; 670 671 $form.trigger("submit"); 672 }); 673} 674 675// Registers event handlers for form. 676function registerFormEvents() { 677 // Remove troublemakers (prevent the jQuery submit handler from ever firing, and not needed for this screen anyways). 678 document.aspnetForm.removeAttribute('onsubmit'); 679 document.aspnetForm.onsubmit = null; 680 681 var $form = $(document.aspnetForm); 682 683 // TODO: Plug this into other validation. 684 var wantCopyAddr, $wantCopyAddrLI; 685 var wantCopy = document.getElementById('wantCopy'); 686 687 if (wantCopy) { 688 wantCopyAddr = document.getElementById('wantCopyAddress'); 689 $wantCopyAddrLI = $(wantCopyAddr.parentNode.parentNode); 690 691 $(wantCopy).change(function (event) { 692 if (this.checked) 693 $wantCopyAddrLI.show(); 694 else 695 $wantCopyAddrLI.hide(); 696 }); 697 } 698 699 /* #2378*/ 700 $(document).keydown(function (event) { 701 if (event.keyCode === 13 && 702 event.target.tagName === 'INPUT' && 703 event.target.id !== 'btnFormSubmit' && 704 event.target.tagName !== 'TEXTAREA' && 705 event.target.tagName !== 'SELECT' && 706 event.target.getAttribute('data-enable-enter-keypress') !== 'true') { 707 event.preventDefault(); 708 return false; 709 } 710 if (event.keyCode === 32 && 711 event.target.tagName === 'A' && 712 event.target.getAttribute('role') === 'button') { 713 $(event.target).trigger('click'); 714 event.preventDefault(); 715 return false; 716 } 717 }); 718 719 $form.submit(function () { 720 // Run validation, stop data submission if necessary. 721 if (!formValidate()) { 722 enableDisableSubmit(true); 723 return false; 724 } 725 726 if (isNull(redirectNewWindow, '').trimEnd() != '') 727 window.open(redirectNewWindow); 728 729 // Field types requiring special serialization code (radio/check/file). 730 // The deserialization of dictionaries from forms in MVC 2 is somewhat sensitive. 731 serializeSpecialFields(); 732 return true; 733 }); 734 735 $('#btnFormSubmit').click(function (event) { 736 event.preventDefault(); 737 if (formValidate()) { 738 processSubmit(handleSubmitClick); 739 } 740 }); 741 742 $('#btnFormPrint').click(function (event) { 743 event.preventDefault(); 744 printForm(false); 745 }); 746 747 $('#btnFormSubmitPrint').click(function (event) { 748 event.preventDefault(); 749 if (formValidate()) { 750 processSubmit(handleSubmitPrintClick); 751 } 752 }); 753 754 $('#btnCalculateTotals').click(function (e) { 755 e.preventDefault(); 756 757 submitCheckboxHandler(); 758 submitRadioHandler(); 759 760 if (formValidate()) { 761 var $form = $(document.aspnetForm); 762 763 $.ajax({ 764 url: '/FormCenter/Home/CalculateTotal?formID=' + extractFormIDFromURL(location.href), 765 type: 'POST', 766 data: $(document.aspnetForm).serializeArray(), 767 success: function (response) { 768 openCpModal({ 769 title: FormCenterHomeScriptResources.CalculateTotals, 770 className: 'modalCalculateTotal', 771 isFrontEnd: window.location.href.indexOf('/Admin/FormCenter') == -1, 772 htmlContent: response 773 }); 774 }, 775 error: function (xhr, textStatus, exception) { 776 alert('Error: ' + xhr.statusText + '\nStatus: ' + xhr.status); 777 } 778 }); 779 } 780 }); 781 782 $('#btnProceedToCheckOut').click(function (e) { 783 proceedToCheckOut(e); 784 }); 785 786 if ($('.submissionConfirmationOk').length > 0) 787 { 788 $('.submissionConfirmationOk').unbind('click').click(function () { 789 $('.submitForm').show(); 790 $('.submissionConfirmation').hide(); 791 !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights(); 792 }) 793 } 794} 795 796function onRecaptchaLoadCallback() { 797 window.gRecaptchaClientId = grecaptcha.render('inline-recaptcha', { 798 'sitekey': document.querySelector('#inline-recaptcha').dataset.sitekey, 799 'badge': 'inline', 800 'size': 'invisible' 801 }); 802} 803 804function setRecaptchaResponse(token) { 805 if (!token) { 806 return; 807 } 808 809 var responseFields = document.querySelectorAll('[name="g-recaptcha-response"]'); 810 for (var i = 0; i < responseFields.length; i++) { 811 responseFields[i].value = token; 812 } 813} 814 815function processSubmit(callback) { 816 const recaptcha = document.querySelector('.recaptcha'); 817 if (!recaptcha) { 818 callback(); 819 return; 820 } 821 822 grecaptcha.ready(function() { 823 grecaptcha.execute(window.gRecaptchaClientId, { action: 'submit' }).then(function(token) { 824 setRecaptchaResponse(token); 825 callback(); 826 }); 827 }); 828} 829 830function enableDisableSubmit(enable) { 831 if (enable) { 832 if ($('#btnFormSubmitPrint').length > 0) { 833 $('#btnFormSubmitPrint').removeClass('inactive'); 834 $('#btnFormSubmitPrint').click(function (event) { 835 handleSubmitPrintClick(); 836 }); 837 } 838 if ($('#btnFormSubmit').length > 0) { 839 $('#btnFormSubmit').removeClass('inactive'); 840 $('#btnFormSubmit').click(function (event) { 841 event.preventDefault(); 842 if (formValidate()) { 843 closeModalDialog('editItemBehavior'); 844 processSubmit(handleSubmitClick); 845 } 846 }); 847 } 848 } else { 849 if ($('#btnFormSubmitPrint').length > 0) { 850 $('#btnFormSubmitPrint').addClass("inactive"); 851 $('#btnFormSubmitPrint').unbind(); 852 } 853 if ($('#btnFormSubmit').length > 0) { 854 $('#btnFormSubmit').addClass("inactive"); 855 $('#btnFormSubmit').unbind(); 856 } 857 } 858} 859 860function handleSubmitClick() { 861 enableDisableSubmit(false); 862 863 var frm = document.aspnetForm; 864 865 frm.action = FormCenterHomeJS.submissionURL; 866 867 var $form = $(frm); 868 869 var formID = extractFormIDFromURL(location.href); 870 871 submitForm($form, false, true, formID); 872} 873 874function handleSubmitPrintClick() { 875 enableDisableSubmit(false); 876 printForm(true); 877} 878 879function proceedToCheckOut(e) { 880 e.preventDefault(); 881 882 serializeSpecialFields(); 883 884 if (formValidate()) { 885 var savedProgressID = parseInt($('#hdnSavedProgressID').val(), 10); 886 887 var submitUrl = '/FormCenter/Home/ProceedToCheckOut?formID=' + extractFormIDFromURL(location.href); 888 889 if (!isNaN(savedProgressID)) {
890 submitUrl = submitUrl + '&savedProgressID=' + savedProgressID; 891 } 892 893 var $form = $(document.aspnetForm); 894 $form.attr('action', submitUrl); 895 $form.submit(); 896 } 897} 898 899function getModalDialogObjects() { 900 return { 901 iframe: document.getElementById('liveEditDialog'), 902 windowElement: $('.modalContainerCP')[0], 903 behavior: $find('editItemBehavior'), 904 titleElement: $('.modalTitle')[0] 905 }; 906} 907 908function getBooleanValue(value) { 909 switch (value.toLowerCase()) { 910 case "true": case "yes": case "1": return true; 911 case "false": case "no": case "0": case null: return false; 912 default: return Boolean(string); 913 } 914} 915 916// Validates current form. 917function formValidate() { 918 var assignFocus = true; 919 var ERROR_MSG = FormCenterHomeScriptResources.InvalidEmailAddressFormat2; 920 var wantCopy = document.getElementById('wantCopy'); 921 922 if (wantCopy) { 923 wantCopyAddr = document.getElementById('wantCopyAddress'); 924 $wantCopyAddrLI = $(wantCopyAddr.parentNode.parentNode); 925 926 if ($wantCopyAddrLI.is(":visible") && wantCopyAddr.value != "") { 927 if (!emailValidate(wantCopyAddr.value)) { 928 errorShow(ERROR_MSG); 929 return false; 930 } 931 } 932 if (wantCopy.checked == false)//if the checkbox is not checked then empty the emailaddress textbox 933 document.getElementById('wantCopyAddress').value = ""; 934 } 935 else { 936 //if the checkbox is not checked then empty the emailaddress textbox 937 var wantCopyAddress = document.getElementById('wantCopyAddress'); 938 if (wantCopyAddress) 939 document.getElementById('wantCopyAddress').value = ""; 940 } 941 942 if (typeof formValidators.keys !== 'undefined') { 943 var liCurrent = $('li.current'); 944 var step = "1"; 945 if (liCurrent.length > 0) { 946 step = liCurrent.attr('id').replace('liStep', ''); 947 } 948 949 var wizardStep = $('#wizard' + step); 950 951 if (wizardStep.length > 0) { 952 wizardStep = wizardStep[0]; 953 } 954 955 var checkForInappropriateWords = new Array(); 956 957 for (var i = 0, len = formValidators.keys.length; i < len; i++) { 958 var key = formValidators.keys[i]; 959 960 if (wizardStep == null || wizardStep.length == 0 || (wizardStep != null && wizardStep.contains(formValidators[key].elem
960Container))) { 961 if (!formValidators[key].validate(assignFocus, checkForInappropriateWords)) 962 assignFocus = false; 963 } 964 } 965 966 if (validateInappropriateWords(checkForInappropriateWords)) { 967 assignFocus = false; 968 } 969 } 970 971 return assignFocus; 972} 973 974function validateInappropriateWords(checkForInappropriateWords) { 975 var data = {}; 976 var j = 0; 977 var inappropriateWordsFound = false; 978 979 for (j = 0; j < checkForInappropriateWords.length; j++) { 980 data[checkForInappropriateWords[j].id.toString()] = checkForInappropriateWords[j].elemInput.value.trim(); 981 } 982 983 var results = HasInappropriateWordsMultiple(data); 984 985 for (j = 0; j < checkForInappropriateWords.length; j++) { 986 if (results[checkForInappropriateWords[j].id.toString()] == true) { 987 checkForInappropriateWords[j].handleInappropriateWords(inappropriateWordsFound == false); 988 989 inappropriateWordsFound = true; 990 } 991 } 992 993 return inappropriateWordsFound; 994} 995 996// Displays error message if email validation failed 997function errorShow(message) { 998 var elemContainer = $('.anonEmail'); 999 elemContainer.addClass('error'); 1000 1001 if (elemContainer.find('.explanation').length == 0) { 1002 var errorElemMsg = document.createElement('p'); 1003 errorElemMsg.className = 'explanation'; 1004 errorElemMsg.innerHTML = message; 1005 elemContainer.append(errorElemMsg); 1006 } 1007} 1008 1009// Determines if URL contains print querystring. 1010function containsPrint(url) { 1011 return url.search(/(&|\?)print\=yes(&.*|)$/i) > -1; 1012} 1013 1014 1015// Extracts CategoryID identifier from URL specified. 1016function extractCategoryIDFromURL(url) { 1017 1018 url = url.toLowerCase(); 1019 var indexOfForm = url.lastIndexOf("/formcenter/"); 1020 if (indexOfForm > -1) { 1021 //extract the categoryurl 1022 var formURL = url.substr(indexOfForm + 12); 1023 1024 1025 //check whether u have formid appended 1026 1027 if (formURL.indexOf("/") > -1) 1028 formURL = formURL.substr(0, formURL.indexOf("/")); 1029 //check wheter the url has categoryName 1030 var indexOfHypen = formURL.lastIndexOf("-"); 1031 var categoryID = 0; 1032 if (indexOfHypen > -1) 1033 categoryID = formURL.substr(indexOfHypen + 1); 1034 else 1035 categoryID = formURL; 1036 return categoryID; 1037 } 1038 else 1039 return null; 1040} 1041 1042 1043// Extracts form identifier from URL specified. 1044function extractFormIDFromURL(url) { 1045 return parseInt($('#hdnFormID').val(), 10); 1046 1047 //there is some query string appended if so remove those 1048 if (url.indexOf("/?") > -1) { 1049 url = url.substr(0, url.indexOf("/?")); 1050 } 1051 1052 url = url.toLowerCase(); 1053 var indexOfForm = url.lastIndexOf("/formcenter/"); 1054 if (indexOfForm > -1) { 1055 //extract the url 1056 var formURL = url.substr(indexOfForm + 12); 1057 1058 if (formURL.indexOf("/") > -1) { 1059 formURL = formURL.substr(formURL.indexOf("/") + 1); 1060 //check wheter the url has categoryName 1061 var indexOfHypen = formURL.lastIndexOf("-"); 1062 var formID = 0; 1063 if (indexOfHypen > -1) 1064 formID = formURL.substr(indexOfHypen + 1); 1065 else if (formURL == "") 1066 return null; 1067 else 1068 formID = formURL; 1069 1070 return formID; 1071 } 1072 else 1073 return null; 1074 } 1075 else 1076 return null; 1077} 1078 1079// Attaches expand/collapse handlers to section headers. 1080function attachCategoryVisibilityTogglers() {
1081 $('#FormCenterContent .contentMain').click(function (event) { 1082 var target = event.target; 1083 1084 if (/^lnkLess[0-9]*$/.test(target.id)) { 1085 // Form details should shrink. 1086 lessInfo(parseInt(target.id.substr(7), 10)); 1087 event.preventDefault(); 1088 } 1089 else if (/^lnkMore[0-9]*$/.test(target.id)) { 1090 // Form details should expand. 1091 moreInfo(parseInt(target.id.substr(7), 10)); 1092 event.preventDefault(); 1093 } 1094 }); 1095} 1096 1097// Called by form submittal to handle radio buttons for serialization. 1098function submitRadioHandler() { 1099 var names = []; 1100 var values = {}; 1101 $checkBoxSelector = null; 1102 $webCheckBox = $('div.formWrap ol.cpForm input[type=radio]'); 1103 $mobileCheckBox = $('.mobileGuts input[type=radio]'); 1104 1105 if ($webCheckBox.length != 0 && $mobileCheckBox.length == 0) 1106 $checkBoxSelector = $webCheckBox; 1107 1108 if ($webCheckBox.length == 0 && $mobileCheckBox.length != 0) 1109 $checkBoxSelector = $mobileCheckBox; 1110 if ($checkBoxSelector != null) { 1111 // Get list of radio inputs and their values. 1112 $checkBoxSelector.each(function () { 1113 if (!names.contains(this.name)) { 1114 names.push(this.name); 1115 values[this.name] = ''; 1116 } 1117 1118 if (this.checked) 1119 values[this.name] = this.value; 1120 }) 1121 } 1122 1123 // Map collected data to hidden inputs submitted to server. 1124 for (var i = 0, len = names.length; i < len; i++) { 1125 var inputName = names[i]; 1126 var id = (inputName.match(/_/g) || []).length == 2 ? inputName.substring(inputName.indexOf('_') + 1) : inputName; 1127 document.getElementById(id).value = values[inputName]; 1128 } 1129} 1130 1131// Called by form submittal to handle checkboxes for serialization. 1132function submitCheckboxHandler() { 1133 var names = []; 1134 var values = {}; 1135 $checkBoxSelector = null; 1136 $webCheckBox = $('div.formWrap ol.cpForm input[type=checkbox]'); 1137 $mobileCheckBox = $('.mobileGuts input[type=checkbox]'); 1138 1139 if ($webCheckBox.length != 0 && $mobileCheckBox.length == 0) 1140 $checkBoxSelector = $webCheckBox; 1141 1142 if ($webCheckBox.length == 0 && $mobileCheckBox.length != 0) 1143 $checkBoxSelector = $mobileCheckBox; 1144 1145 // Get list of checkbox inputs and their values. 1146 if ($checkBoxSelector != null) { 1147 $checkBoxSelector.each(function () { 1148 if (!names.contains(this.name)) { 1149 names.push(this.name); 1150 values[this.name] = []; 1151 } 1152 1153 if (this.checked) { 1154 var val = this.value.replace(/target="__blank"/g, 'target="_blank"'); 1155 val = val.replace(/\,/g, '_comma_'); 1156 if (val.trim() == '') 1157 val = '_empty_value_'; 1158 values[this.name].push(val); 1159 1160 } 1161 }); 1162 } 1163 1164 // Map collected data to hidden inputs submitted to server. 1165 for (var i = 0, len = names.length; i < len; i++) 1166 document.getElementById(names[i]).value = values[names[i]].join(','); 1167} 1168 1169function submitDateTimeHandler() { 1170 var names = []; 1171 var values = []; 1172 1173 var $datePickers, $timePickers; 1174 if ($('.formCenterDatePicker').length > 0 || $('.formCenterTimePicker').length > 0) { 1175 $datePickers = $('.formCenterDatePicker'); 1176 $timePickers = $('.formCenterTimePicker'); 1177 } 1178 else { 1179 $datePickers = $('.telerikDatePicker'); 1180 $timePickers = $('.telerikTimePicker'); 1181 } 1182 1183 $datePickers.each(function () { 1184 if (!names.contains(this.name)) { 1185 names.push(this.name); 1186 values[this.name] = [this.value]; 1187 } 1188 else { 1189 values[this.name].push(this.value); 1190 } 1191 }); 1192 1193 $timePickers.each(function () { 1194 if (!names.contains(this.name)) { 1195 names.push(this.name); 1196 values[this.name] = ['', '', this.value]; 1197 } 1198 else { 1199 if (values[this.name].length == 1) { 1200 values[this.name].push(''); 1201 } 1202 values[this.name].push(this.value); 1203 } 1204 }); 1205 1206 for (var i = 0, len = names.length; i < len; i++) 1207 document.getElementById(names[i]).value = values[names[i]].join(); 1208} 1209 1210$(function () { 1211 $('#aspnetForm,form[name=aspnetForm]').attr('enctype', "multipart/form-data"); 1212 $('#aspnetForm,form[name=aspnetForm]').addClass('submitForm'); 1213}); 1214; 1215 1216/// <reference path="../../../../Scripts/json2.js" /> 1217/// <reference path="../../../../Scripts/HtmlExtensionSupport.js" /> 1218/// <reference path="../../../../Common/GlobalJSFunctionsDetail.js" /> 1219/// <reference path="../../../../Assets/Scripts/InappropriateWords.js" /> 1220/// <reference path="Home.js" /> 1221 1222// Overridden on a per-form basis. Retrieves validator information for submission validation. 1223//function getFormValidatorData() { 1224// return []; 1225//} 1226 1227var FormCenterHomeScriptResources = GetJson("/FormCenter/Localization"); 1228var originalTextColorRadio; 1229var originalTextColorCheckBox; 1230 1231$.getScript("/Assets/Scripts/InappropriateWords.js"); 1232 1233// Used to properly localize strings. 1234String.prototype.format = function () { 1235 var args = arguments; 1236 return this.replace(/{(\d+)}/g, function (match, number) { 1237 return typeof args[number] != 'undefined' 1238 ? args[number] 1239 : match 1240 ; 1241 }); 1242}; 1243 1244 1245// Performs validation for a form field. 1246function FieldValidator(elemInput, id, fieldType, isInternal, isRequired, formatValidation, formatValidationCustom, minA
1246nswer, maxAnswer, maxLength) { 1247 var self = this; 1248 this.elemInputIsArray = $.isArray(elemInput); 1249 1250 if (this.elemInputIsArray) { 1251 for (var i = 0, len = elemInput.length; i < len; i++) { 1252 if (typeof (elemInput[i]) == "string") 1253 elemInput[i] = document.getElementById(elemInput[i]); 1254 } 1255 1256 if (elemInput.length > 0 && elemInput[0]) { 1257 this.elemContainer = elemInput[0].parentNode.parentNode.parentNode.parentNode; 1258 this.elemInput = elemInput; 1259 } 1260 } 1261 else { 1262 if (typeof (elemInput) == "string") 1263 elemInput = document.getElementById(elemInput); 1264 1265 if (elemInput) { 1266 if (fieldType === FieldTypes.DatePicker) 1267 this.elemContainer = elemInput.parentNode.parentNode.parentNode.parentNode; 1268 else 1269 this.elemContainer = elemInput.parentNode.parentNode; 1270 this.elemInput = elemInput; 1271 } 1272 } 1273 1274 this.enabled = true; 1275 this.$elemContainer = $(this.elemContainer); 1276 this.fieldType = fieldType; 1277 if (this.fieldType === FieldTypes.FileUpload) { 1278 //When validating <input type="file" />, we need to update the elemInput reference since it is created a new one when failing inside validateFileUpload method - LC 1279 var validateInputFileUpload = function () { 1280 var $this = $(this); 1281 if (!validateMultiFileUpload($this[0], true)) { 1282 alert("The file you are trying to upload is not an allowed file type or has an invalid file name. These are the accepted characters: A-z 0-9 ~ ! ( ) - + = [ ] { } , . _"); 1283 self.elemInput.value = null; 1284 self.elemInput.focus(); 1285 } 1286 }; 1287 $(this.elemInput).attr("change", "").removeAttr("onChange").unbind("change").change(validateInputFileUpload); 1288 } 1289 this.id = id; 1290 this.isInternal = isInternal; 1291 this.isRequired = isRequired; 1292 this.formatValidation = formatValidation; 1293 this.formatValidationCustom = formatValidationCustom; 1294 this.elemErrorNote = null; 1295 this.minAnswer = minAnswer; 1296 this.maxAnswer = maxAnswer; 1297 this.maxLength = maxLength; 1298 this.focusElementIndex = 0; 1299 this.alreadySetFocus = false; 1300 var isRequiredInfoLableDisplayed = false; 1301 if (this.isRequired && !isRequiredInfoLableDisplayed) { 1302 $('#liRequiredFieldInfo').show(); 1303 isRequiredInfoLableDisplayed = true; 1304 } 1305} 1306 1307// Static. Creates a single validation object from an options object. 1308FieldValidator.createSingle = function (options) { 1309 return new FieldValidator( 1310 options.elemInput, 1311 options.id, 1312 options.fieldType, 1313 options.isInternal, 1314 options.isRequired, 1315 options.formatValidation, 1316 options.formatValidationCustom, 1317 options.minAnswer, 1318 options.maxAnswer, 1319 options.maxLength); 1320}; 1321 1322// Static. Creates array of validation objects from array of option objects. 1323FieldValidator.createMulti = function (optionsArray) { 1324 var key = null; 1325 1326 var ret = { 1327 keys: [], 1328 add: function (validator) { 1329 var key = validator.id; 1330 this[key] = validator; 1331 this.keys.push(key); 1332 } 1333 }; 1334 1335 for (var i = 0, len = optionsArray.length; i < len; i++) 1336 ret.add(FieldValidator.createSingle(optionsArray[i])); 1337 1338 return ret; 1339}; 1340 1341// Internal. Used by validation() to ensure the input does not exceed the max length. 1342FieldValidator.prototype.validateMaxLength = function (errorMsg) { 1343 var ERROR_MSG = FormCenterHomeScriptResources.MaxLengthErrorMessage.format(this.maxLength); 1344 if (this.maxLength == null) 1345 return true; 1346 var cleanValue = this.elemInput.value.trim(); 1347 if (cleanValue != null && cleanValue.length > this.maxLength) { 1348 errorMsg.push(ERROR_MSG); 1349 return false; 1350 } 1351 return true; 1352}; 1353 1354// Internal. Used by validate() to ensure user-enterable fields are phone numbers (of NANP format). 1355FieldValidator.prototype.validatePhone = function (errorMsg) { 1356 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidPhoneNumberFormat); 1357 var origLen = errorMsg.length; 1358 1359 switch (this.fieldType) { 1360 case FieldTypes.ShortAnswer: 1361 case FieldTypes.LongAnswer: 1362 case FieldTypes.Password: 1363 var cleanValue = this.elemInput.value.trim(); 1364 if (cleanValue != '' && !phoneValidate(cleanValue, intCountryCode)) 1365 errorMsg.push(ERROR_MSG); 1366 break; 1367 } 1368
1369 // Return false if validation check failed (number of errors changed). 1370 return origLen == errorMsg.length; 1371} 1372 1373// Internal. Used by validate() to ensure user-enterable fields are postal codes. 1374FieldValidator.prototype.validatePostal = function (errorMsg) { 1375 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidPostalCode); 1376 var origLen = errorMsg.length; 1377 1378 switch (this.fieldType) { 1379 case FieldTypes.ShortAnswer: 1380 case FieldTypes.LongAnswer: 1381 case FieldTypes.Password: 1382 var cleanValue = this.elemInput.value.trim(); 1383 1384 if (cleanValue != '' && !isZipCode(cleanValue, intCountryCode)) 1385 errorMsg.push(ERROR_MSG); 1386 1387 break; 1388 } 1389 1390 // Return false if validation check failed (number of errors changed). 1391 return origLen == errorMsg.length; 1392} 1393 1394// Internal. Used by validate() to ensure user-enterable fields are email addresses. 1395FieldValidator.prototype.validateEmail = function (errorMsg) { 1396 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidEmailAddressFormat2); 1397 var origLen = errorMsg.length; 1398 1399 switch (this.fieldType) { 1400 case FieldTypes.ShortAnswer: 1401 case FieldTypes.LongAnswer: 1402 case FieldTypes.Password: 1403 case FieldTypes.ReplyEmail: 1404 var cleanValue = this.elemInput.value.trim(); 1405 1406 if (cleanValue != '' && !emailValidate(cleanValue)) 1407 errorMsg.push(ERROR_MSG); 1408 1409 break; 1410 } 1411 1412 // Return false if validation check failed (number of errors changed). 1413 return origLen == errorMsg.length; 1414} 1415function getNumericThousandsSeparator() { 1416 var dummy = new Number(11111111); 1417 var thousandSep = dummy.toLocaleString().replace(/1/g, ''); 1418 return (thousandSep.length > 0 ? thousandSep.charAt(0) : ','); 1419} 1420// Internal. Used by validate() to ensure user-enterable fields match custom expression. 1421FieldValidator.prototype.validateCustom = function (expr, errorMsg) { 1422 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidGenericField); 1423 var origLen = errorMsg.length; 1424 1425 var customRegExp = new RegExp(expr); 1426 1427 switch (this.fieldType) { 1428 case FieldTypes.ShortAnswer: 1429 case FieldTypes.LongAnswer: 1430 case FieldTypes.Password: 1431 var cleanValue = this.elemInput.value.trim(); 1432 1433 if (cleanValue != '' && (!customRegExp.test(cleanValue))) 1434 errorMsg.push(ERROR_MSG); 1435 1436 break; 1437 } 1438 1439 // Return false if validation check failed (number of errors changed). 1440 return origLen == errorMsg.length; 1441} 1442 1443// Internal. Used by validate() to ensure user-enterable fields are letters only. 1444FieldValidator.prototype.validateLetters = function (errorMsg) { 1445 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.LettersOnlyField); 1446 var origLen = errorMsg.length; 1447 1448 var letterRegExp = /^[a-zA-Z ]+$/; 1449 1450 switch (this.fieldType) { 1451 case FieldTypes.ShortAnswer: 1452 case FieldTypes.LongAnswer: 1453 case FieldTypes.Password: 1454 var cleanValue = this.elemInput.value.trim(); 1455 1456 if (cleanValue != '' && (!letterRegExp.test(cleanValue))) 1457 errorMsg.push(ERROR_MSG); 1458 1459 break; 1460 } 1461 1462 // Return false if validation check failed (number of errors changed). 1463 return origLen == errorMsg.length; 1464} 1465 1466// Internal. Used by validate() to ensure user-enterable fields are numeric (numbers, decimal separators, and group separators allowed). 1467FieldValidator.prototype.validateNumeric = function (errorMsg) { 1468 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.NumericOnlyField); 1469 var origLen = errorMsg.length; 1470 1471 var numericRegExp = new RegExp("^(([0-9]+?[0-9%G]+?[0-9](|%D[0-9]+))|([0-9]*(|%D[0-9]+)))$" 1472 .replace(/%G/g, RegExp.metaEscape(getNumericThousandsSeparator())) 1473 .replace(/%D/g, RegExp.metaEscape(getNumericDecimalSeparator()))); 1474 1475 switch (this.fieldType) { 1476 case FieldTypes.ShortAnswer: 1477 case FieldTypes.LongAnswer: 1478 case FieldTypes.Password: 1479 var cleanValue = this.elemInput.value.trim(); 1480 1481 if (cleanValue != '' && (!numericRegExp.test(cleanValue))) 1482 errorMsg.push(ERROR_MSG); 1483 1484 break; 1485 } 1486 1487 // Return false if validation check failed (number of errors changed). 1488 return origLen == errorMsg.length; 1489} 1490 1491FieldValidator.prototype.validateCurrency = function (errorMsg) { 1492 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.CurrencyOnlyField); 1493 var origLen = errorMsg.length; 1494 1495 var value = this.elemInput.value.trim(); 1496 1497 if (!this.isValidMoney(value)) { 1498 errorMsg.push(ERROR_MSG);; 1499 } 1500
1501 // Return false if validation check failed (nubmer of errors changed). 1502 return origLen == errorMsg.length; 1503} 1504 1505FieldValidator.prototype.isValidMoney = function (value) { 1506 if (value && value != '') 1507 return /^\$?\s*\d+(,\d{3})*(\.\d{1,2})?$/.test(value); 1508 else 1509 return true; 1510}; 1511 1512//#region Date Validation 1513 1514FieldValidator.prototype.validateDate = function (errorMsg) { 1515 var origLen = errorMsg.length; 1516 1517 var date = $(this.elemInput[0]).val(); 1518 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidDate); 1519 1520 if (!this.isValidDate(date, this.isRequired)) { 1521 errorMsg.push(ERROR_MSG); 1522 } 1523 1524 // Return false if validation check failed (nubmer of errors changed). 1525 return origLen == errorMsg.length; 1526} 1527 1528FieldValidator.prototype.validateTime = function (errorMsg) { 1529 var origLen = errorMsg.length; 1530 1531 var time = $(this.elemInput[0]).val(); 1532 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidTime); 1533 1534 if (!this.isValidTime(time, this.isRequired)) { 1535 errorMsg.push(ERROR_MSG); 1536 } 1537 1538 // Return false if validation check failed (nubmer of errors changed). 1539 return origLen == errorMsg.length; 1540} 1541 1542FieldValidator.prototype.validateDateTime = function (errorMsg) { 1543 var origLen = errorMsg.length; 1544 1545 var date = $(this.elemInput[0]).val(); 1546 1547 var time = $(this.elemInput[1]).val(); 1548 1549 var validDate = this.isValidDate(date, this.isRequired); 1550 1551 var validTime = this.isValidTime(time, this.isRequired); 1552 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidDateTime); 1553 1554 if (!validDate && !validTime) { 1555 if (!this.alreadySetFocus) { 1556 this.focusElementIndex = 0; 1557 this.alreadySetFocus = true; 1558 } 1559 errorMsg.push(ERROR_MSG); 1560 } 1561 else if (!validDate) { 1562 if (!this.alreadySetFocus) { 1563 this.focusElementIndex = 0; 1564 this.alreadySetFocus = true; 1565 } 1566 errorMsg.push(ERROR_MSG); 1567 } 1568 else if (!validTime) { 1569 if (!this.alreadySetFocus) { 1570 this.focusElementIndex = 1; 1571 this.alreadySetFocus = true; 1572 } 1573 errorMsg.push(ERROR_MSG); 1574 } 1575 1576 // Return false if validation check failed (nubmer of errors changed). 1577 return origLen == errorMsg.length; 1578} 1579 1580FieldValidator.prototype.validateDateSpan = function (errorMsg) { 1581 var origLen = errorMsg.length; 1582 1583 var date = $(this.elemInput[0]).val(); 1584 1585 var dateSpan = $(this.elemInput[1]).val(); 1586 1587 if (!this.isValidDate(date, this.isRequired)) { 1588 if (!this.alreadySetFocus) { 1589 this.focusElementIndex = 0; 1590 this.alreadySetFocus = true; 1591 } 1592 errorMsg.push(FormCenterHomeScriptResources.InvalidStartDate); 1593 } 1594 if (!this.isValidDate(dateSpan, this.isRequired)) { 1595 if (!this.alreadySetFocus) { 1596 this.focusElementIndex = 1; 1597 this.alreadySetFocus = true; 1598 } 1599 errorMsg.push(FormCenterHomeScriptResources.InvalidEndDate); 1600 } 1601 if (!this.isValidDateRange(date, dateSpan, this.isRequired, this.isRequired)) { 1602 if (!this.alreadySetFocus) { 1603 this.focusElementIndex = 0; 1604 this.alreadySetFocus = true; 1605 } 1606 errorMsg.push(FormCenterHomeScriptResources.InvalidDateSpan); 1607 } 1608 1609 // Return false if validation check failed (nubmer of errors changed). 1610 return origLen == errorMsg.length; 1611} 1612 1613FieldValidator.prototype.validateTimeSpan = function (errorMsg) { 1614 var origLen = errorMsg.length; 1615 1616 var time = $(this.elemInput[0]).val(); 1617 1618 var timeSpan = $(this.elemInput[1]).val(); 1619 1620 if (!this.isValidTime(time, this.isRequired)) { 1621 if (!this.alreadySetFocus) { 1622 this.focusElementIndex = 0; 1623 this.alreadySetFocus = true; 1624 } 1625 errorMsg.push(FormCenterHomeScriptResources.InvalidStartTime); 1626 } 1627 1628 if (!this.isValidTime(timeSpan, this.isRequired)) { 1629 if (!this.alreadySetFocus) { 1630 this.focusElementIndex = 1; 1631 this.alreadySetFocus = true; 1632 } 1633 errorMsg.push(FormCenterHomeScriptResources.InvalidEndTime); 1634 } 1635 1636 if (!this.isValidTimeRange(time, timeSpan, this.isRequired, this.isRequired)) { 1637 if (!this.alreadySetFocus) { 1638 this.focusElementIndex = 0; 1639 this.alreadySetFocus = true; 1640 } 1641 errorMsg.push(FormCenterHomeScriptResources.InvalidTimeSpan); 1642 } 1643
1644 // Return false if validation check failed (nubmer of errors changed). 1645 return origLen == errorMsg.length; 1646} 1647 1648FieldValidator.prototype.validateDateTimeSpan = function (errorMsg) { 1649 var origLen = errorMsg.length; 1650 1651 var date = $(this.elemInput[0]).val(); 1652 1653 var dateSpan = $(this.elemInput[1]).val(); 1654 1655 var time = $(this.elemInput[2]).val(); 1656 1657 var timeSpan = $(this.elemInput[3]).val(); 1658 1659 var validDate = this.isValidDate(date, this.isRequired); 1660 1661 var validTime = this.isValidTime(time, this.isRequired); 1662 1663 if (!validDate && !validTime) { 1664 if (!this.alreadySetFocus) { 1665 this.focusElementIndex = 0; 1666 this.alreadySetFocus = true; 1667 } 1668 errorMsg.push(FormCenterHomeScriptResources.InvalidStartDateTime); 1669 } 1670 else if (!validDate) { 1671 if (!this.alreadySetFocus) { 1672 this.focusElementIndex = 0; 1673 this.alreadySetFocus = true; 1674 } 1675 errorMsg.push(FormCenterHomeScriptResources.InvalidStartDate); 1676 } 1677 else if (!validTime) { 1678 if (!this.alreadySetFocus) { 1679 this.focusElementIndex = 2; 1680 this.alreadySetFocus = true; 1681 } 1682 errorMsg.push(FormCenterHomeScriptResources.InvalidStartTime); 1683 } 1684 1685 var validSpanDate = this.isValidDate(dateSpan, this.isRequired); 1686 1687 var validSpanTime = this.isValidTime(timeSpan, this.isRequired); 1688 1689 if (!validSpanDate && !validSpanTime) { 1690 if (!this.alreadySetFocus) { 1691 this.focusElementIndex = 1; 1692 this.alreadySetFocus = true; 1693 } 1694 errorMsg.push(FormCenterHomeScriptResources.InvalidEndDateTime); 1695 } 1696 else if (!validSpanDate) { 1697 if (!this.alreadySetFocus) { 1698 this.focusElementIndex = 1; 1699 this.alreadySetFocus = true; 1700 } 1701 errorMsg.push(FormCenterHomeScriptResources.InvalidEndDate); 1702 } 1703 else if (!validSpanTime) { 1704 if (!this.alreadySetFocus) { 1705 this.focusElementIndex = 3; 1706 this.alreadySetFocus = true; 1707 } 1708 errorMsg.push(FormCenterHomeScriptResources.InvalidEndTime); 1709 } 1710 var isDayBeforeMonth = getDateFormat().toLocaleLowerCase() == "dd/mm/yyyy" ? true : false; 1711 if (!this.isValidDateTimeRange(getDateFromInput(this.elemInput[0], isDayBeforeMonth), getDateFromInput(this.elemInput[1], isDayBeforeMonth), this.isRequired, this.isRequired, time, timeSpan, this.isRequired, this.isRequired)) { 1712 if (!this.alreadySetFocus) { 1713 this.focusElementIndex = 1; 1714 this.alreadySetFocus = true; 1715 } 1716 errorMsg.push(FormCenterHomeScriptResources.InvalidDateTimeSpan); 1717 } 1718 1719 // Return false if validation check failed (nubmer of errors changed). 1720 return origLen == errorMsg.length; 1721} 1722 1723FieldValidator.prototype.isValidDate = function (date, dateRequired) { 1724 var objDate = new dateValidator(); 1725 1726 return objDate.dateValidateNew(date, dateRequired, ''); 1727} 1728 1729FieldValidator.prototype.isValidTime = function (time, timeRequired) { 1730 var objDate = new dateValidator(); 1731 1732 var amIndex = time.toLowerCase().indexOf('am'); 1733 var pmIndex = time.toLowerCase().indexOf('pm'); 1734 1735 if (amIndex != -1) { 1736 time = time.substring(0, amIndex).replace(" ", ""); 1737 1738 if (time.trim() === "") { 1739 return false; 1740 } 1741 } 1742 else if (pmIndex != -1) { 1743 time = time.substring(0, pmIndex).replace(" ", ""); 1744 1745 if (time.trim() === "") { 1746 return false; 1747 } 1748 } 1749 1750 return objDate.timeValidate(time, timeRequired, ''); 1751} 1752 1753FieldValidator.prototype.isValidTimeRange = function (startTime, endTime, startTimeRequired, endTimeRequired) { 1754 var objDate = new dateValidator(); 1755 1756 objDate.ysnAllowTimeOnly = true; 1757 objDate.dtiStartTime = this.stripAMPM(startTime); 1758 objDate.ysnStartTimeRequired = startTimeRequired; 1759 objDate.dtiEndTime = this.stripAMPM(endTime); 1760 objDate.ysnEndTimeRequired = endTimeRequired; 1761 objDate.ysnDatesAreEqual = true; 1762 objDate.strStartAMPM = this.getAMPMString(startTime); 1763 objDate.strEndAMPM = this.getAMPMString(endTime); 1764 objDate.timesAlreadyValidated = true; 1765 1766 return objDate.timeOrderValidate(); 1767 1768} 1769 1770FieldValidator.prototype.isValidDateRange = function (startDate, endDate, startDateRequired, endDateRequired) { 1771 var objDate = new dateValidator(); 1772 objDate.setStartDate(checkDateFormatReturnUSString(startDate, false)); 1773 objDate.setEndDate(checkDateFormatReturnUSString(endDate, false)); 1774 objDate.setStartDateRequired(startDateRequired); 1775 objDate.setEndDateRequired(endDateRequired); 1776 objDate.datesAlreadyValidated = true; 1777 1778 return objDate.dateOrderValidateNew(); 1779} 1780 1781FieldValidator.prototype.isValidDateTimeRange = function (startDate, endDate, startDateRequired, endDateRequired, startTime, endTime, startTimeRequired, endTimeRequired) { 1782 var objDate = new dateValidator(); 1783 1784 1785 objDate.setStartDate(checkDateFormatReturnUSString(startDate, false)); 1786 objDate.setEndDate(checkDateFormatReturnUSString(endDate, false)); 1787 objDate.setStartDateRequired(startDateRequired); 1788 objDate.setEndDateRequired(endDateRequired); 1789 objDate.ysnAllowEqualDates = true; 1790 objDate.datesAlreadyValidated = true; 1791 1792 var validDateOrder = objDate.dateOrderValidateNew(); 1793 1794 objDate.strStartAMPM = this.getAMPMString(startTime); 1795 objDate.strEndAMPM = this.getAMPMString(endTime);
1796 objDate.ysnAllowTimeOnly = true; 1797 objDate.ysnAllowEqualTimes = !objDate.ysnDatesAreEqual; 1798 objDate.dtiStartTime = this.stripAMPM(startTime); 1799 objDate.ysnStartTimeRequired = startTimeRequired; 1800 objDate.dtiEndTime = this.stripAMPM(endTime); 1801 objDate.ysnEndTimeRequired = endTimeRequired; 1802 objDate.timesAlreadyValidated = true; 1803 1804 var validTimeOrder = objDate.timeOrderValidate(); 1805 1806 return validDateOrder && validTimeOrder; 1807} 1808 1809FieldValidator.prototype.stripAMPM = function (time) { 1810 var amIndex = time.toLowerCase().indexOf('am'); 1811 var pmIndex = time.toLowerCase().indexOf('pm'); 1812 1813 if (amIndex != -1) { 1814 time = time.substring(0, amIndex).replace(" ", ""); 1815 } 1816 else if (pmIndex != -1) { 1817 time = time.substring(0, pmIndex).replace(" ", ""); 1818 } 1819 1820 return time; 1821} 1822 1823FieldValidator.prototype.getAMPMString = function (time) { 1824 var amIndex = time.toLowerCase().indexOf('am'); 1825 var pmIndex = time.toLowerCase().indexOf('pm'); 1826 1827 var AMPM = ''; 1828 1829 if (amIndex != -1) { 1830 AMPM = time.substring(amIndex).replace(" ", ""); 1831 } 1832 else if (pmIndex != -1) { 1833 AMPM = time.substring(pmIndex).replace(" ", ""); 1834 } 1835 return AMPM; 1836} 1837 1838//#endregion Date Validation 1839 1840//checkbox validation done for min and max answer selcted 1841FieldValidator.prototype.checkBoxValidation = function (errorMsg) { 1842 var origLen = errorMsg.length; 1843 if (this.fieldType == FieldTypes.Checkboxes && ((this.minAnswer != "" && this.minAnswer != undefined) || (this.maxAnswer != "" && this.maxAnswer != undefined))) { 1844 var i = 0, len = this.elemInput.length; 1845 var checkedCount = 0; 1846 for (; i < len; i++) { 1847 if (this.elemInput[i].checked) 1848 checkedCount++; 1849 } 1850 //validation for checkbox min max fields 1851 if (this.minAnswer != "" && this.minAnswer != undefined) { 1852 if (checkedCount < parseInt(this.minAnswer, 10)) // the message is not localized on purpose as this has text and dynamic value 1853 errorMsg.push("This field must have at least " + parseInt(this.minAnswer, 10) + " options selected"); 1854 } 1855 1856 if (origLen == errorMsg.length && this.maxAnswer != "" && this.maxAnswer != undefined) { 1857 if (checkedCount > parseInt(this.maxAnswer, 10)) // the message is not localized on purpose as this has text and dynamic value 1858 errorMsg.push("This field can have at most " + parseInt(this.maxAnswer, 10) + " options selected"); 1859 } 1860 } 1861 1862 // Return false if validation check failed (number of errors changed). 1863 return origLen == errorMsg.length; 1864}; 1865 1866// Internal. Used by validate() to ensure required fields are set. 1867FieldValidator.prototype.validateRequired = function (errorMsg) { 1868 var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.RequiredField);//FormCenterHomeScriptResources.RequiredField; 1869 var origLen = errorMsg.length; 1870 switch (this.fieldType) { 1871 case FieldTypes.ShortAnswer: 1872 case FieldTypes.LongAnswer: 1873 case FieldTypes.ReplyEmail: 1874 case FieldTypes.Password: 1875 case FieldTypes.FileUpload: 1876 case FieldTypes.CodeSnippet: 1877 case FieldTypes.InputLink: 1878 case FieldTypes.DatePicker: 1879 case FieldTypes.InputImage: 1880 if (this.elemInput != 'undefined' && this.elemInput.value != undefined) { 1881 if (this.elemInput.value.trim() == '') 1882 errorMsg.push(ERROR_MSG); 1883 } 1884 break; 1885 case FieldTypes.Checkboxes: 1886 case FieldTypes.RadioButtons: 1887 var i = 0, len = this.elemInput.length; 1888 1889 for (; i < len; i++) { 1890 if (this.elemInput[i].checked) 1891 break; 1892 } 1893 1894 if (i == len) 1895 errorMsg.push(ERROR_MSG); 1896 1897 break; 1898 case FieldTypes.Dropdown: 1899 case FieldTypes.FormLink: 1900 if (this.elemInput.selectedIndex <= 0) 1901 errorMsg.push(ERROR_MSG); 1902 1903 break; 1904 case FieldTypes.DateTime: 1905 var i = 0, len = this.elemInput.length; 1906 1907 for (; i < len; i++) { 1908 if (this.elemInput[i].value.trim() == '') { 1909 errorMsg.push(ERROR_MSG); 1910 this.focusElementIndex = i; 1911 break; 1912 } 1913 } 1914 } 1915 // Return false if validation check failed (number of errors changed). 1916 return origLen == errorMsg.length; 1917}; 1918 1919// Performs validation for field and updates format if necessary. 1920FieldValidator.prototype.validate = function (assignFocusOnFailure, checkForInappropriateWords) { 1921 var errorMsg = []; 1922 1923 // Element not present OR disabled, pass (skipped). 1924 if (this.elemInput == null || !this.enabled) 1925 return true; 1926 1927 if (!this.isRequired || (this.isRequired && this.validateRequired(errorMsg))) { 1928 //checkbox validation done for min and max answer selected 1929 if (this.checkBoxValidation(errorMsg)) { 1930 switch (this.formatValidation) { 1931 case FieldValidation.Letters: 1932 this.validateLetters(errorMsg); 1933 break; 1934 case FieldValidation.Numeric: 1935 this.validateNumeric(errorMsg); 1936 break; 1937 case FieldValidation.Currency: 1938 this.validateCurrency(errorMsg); 1939 break; 1940 case FieldValidation.PhoneNumber: 1941 this.validatePhone(errorMsg); 1942 break; 1943 case FieldValidation.PostalCode: 1944 this.validatePostal(errorMsg); 1945 break; 1946 case FieldValidation.EmailAddress: 1947 this.validateEmail(errorMsg); 1948 break; 1949 case FieldValidation.RegEx: 1950 this.validateCustom(this.formatValidationCustom, errorMsg); 1951 break; 1952 case FieldValidation.Date: 1953 this.validateDate(errorMsg); 1954 break; 1955 case FieldValidation.Time: 1956 this.validateTime(errorMsg); 1957 break; 1958 case FieldValidation.DateTime: 1959 this.validateDateTime(errorMsg); 1960 break; 1961 case FieldValidation.DateSpan: 1962 this.validateDateSpan(errorMsg); 1963 break; 1964 case FieldValidation.TimeSpan: 1965 this.validateTimeSpan(errorMsg); 1966 break; 1967 case FieldValidation.DateTimeSpan: 1968 this.validateDateTimeSpan(errorMsg); 1969 break; 1970 } 1971 } 1972 } 1973 if (this.fieldType === FieldTypes.DatePicker && this.elemInput.value.trim() != '') { 1974 //validate date picker value (based on telerik mvc datePicker) 1975 var datepicker = $(this.elemInput).data("tDatePicker"); 1976 if ($(this.elemInput).hasClass('t-state-error') || datepicker.parse(this.elemInput.value.trim()) == null) 1977 errorMsg.push("Invalid date format"); 1978 } 1979 if (this.fieldType === FieldTypes.ShortAnswer || this.fieldType === FieldTypes.LongAnswer) {
1980 var validator = this; 1981 1982 if (checkForInappropriateWords != null && typeof (checkForInappropriateWords.push) == 'function') { 1983 checkForInappropriateWords.push(validator); 1984 } else { 1985 if (HasInappropriateWords(this.elemInput.value.trim())) { 1986 $(this.elemInput).addClass('t-state-error'); 1987 errorMsg.push(FormCenterHomeScriptResources.InappropriateWords); 1988 } 1989 } 1990 } 1991 1992 if (FeatureToggles.isActive("CMS.FormCenter.EnableServerSideValidationsForSubmissions") 1993 && this.fieldType === FieldTypes.FileUpload 1994 && this.elemInput.value.trim() != '') { 1995 if (Math.round((this.elemInput.files[0].size / 1024)) > 20480) 1996 errorMsg.push("Files cannot be larger than 20 MB."); 1997 } 1998 1999 this.validateMaxLength(errorMsg); 2000 2001 if (errorMsg.length > 0 && $(this.elemInput).is(":visible")) { 2002 this.errorShow(errorMsg); 2003 2004 if (assignFocusOnFailure) { 2005 this.focusErrorElement(); 2006 } 2007 2008 return false; 2009 } else { 2010 this.errorClear(); 2011 return true; 2012 } 2013 2014}; 2015 2016// Performs validation for admin edit internal only fields and updates format if necessary. 2017FieldValidator.prototype.validateInternal = function (assignFocusOnFailure, checkForInappropriateWords) { 2018 if (this.isInternal) { 2019 var errorMsg = []; 2020 2021 // Element not present OR disabled, pass (skipped). 2022 if (this.elemInput == null || !this.enabled) 2023 return true; 2024 2025 if (!this.isRequired || (this.isRequired && this.validateRequired(errorMsg))) { 2026 //checkbox validation done for min and max answer selected 2027 if (this.checkBoxValidation(errorMsg)) { 2028 switch (this.formatValidation) { 2029 case FieldValidation.Letters: 2030 this.validateLetters(errorMsg); 2031 break; 2032 case FieldValidation.Numeric: 2033 this.validateNumeric(errorMsg); 2034 break; 2035 case FieldValidation.Currency: 2036 this.validateCurrency(errorMsg); 2037 break; 2038 case FieldValidation.PhoneNumber: 2039 this.validatePhone(errorMsg); 2040 break; 2041 case FieldValidation.PostalCode: 2042 this.validatePostal(errorMsg); 2043 break; 2044 case FieldValidation.EmailAddress: 2045 this.validateEmail(errorMsg); 2046 break; 2047 case FieldValidation.RegEx: 2048 this.validateCustom(this.formatValidationCustom, errorMsg); 2049 break; 2050 case FieldValidation.Date: 2051 this.validateDate(errorMsg); 2052 break; 2053 case FieldValidation.Time: 2054 this.validateTime(errorMsg); 2055 break; 2056 case FieldValidation.DateTime: 2057 this.validateDateTime(errorMsg); 2058 break; 2059 case FieldValidation.DateSpan: 2060 this.validateDateSpan(errorMsg); 2061 break; 2062 case FieldValidation.TimeSpan: 2063 this.validateTimeSpan(errorMsg); 2064 break; 2065 case FieldValidation.DateTimeSpan: 2066 this.validateDateTimeSpan(errorMsg); 2067 break; 2068 } 2069 } 2070 } 2071 if (this.fieldType === FieldTypes.DatePicker && this.elemInput.value.trim() != '') { 2072 //validate date picker value (based on telerik mvc datePicker) 2073 var datepicker = $(this.elemInput).data("tDatePicker"); 2074 if ($(this.elemInput).hasClass('t-state-error') || datepicker.parse(this.elemInput.value.trim()) == null) 2075 errorMsg.push("Invalid date format"); 2076 } 2077 if (this.fieldType === FieldTypes.ShortAnswer || this.fieldType === FieldTypes.LongAnswer) { 2078 var validator = this; 2079 2080 if (checkForInappropriateWords != null && typeof (checkForInappropriateWords.push) == 'function') { 2081 checkForInappropriateWords.push(validator); 2082 } else { 2083 if (HasInappropriateWords(this.elemInput.value.trim())) { 2084 $(this.elemInput).addClass('t-state-error'); 2085 errorMsg.push(FormCenterHomeScriptResources.InappropriateWords); 2086 } 2087 } 2088 } 2089 2090 this.validateMaxLength(errorMsg); 2091 2092 if (errorMsg.length > 0 && $(this.elemInput).is(":visible")) { 2093 this.errorShow(errorMsg); 2094 2095 if (assignFocusOnFailure) { 2096 this.focusErrorElement(); 2097 } 2098 2099 return false; 2100 } else { 2101 this.errorClear(); 2102 return true; 2103 } 2104 } 2105 else { 2106 return true; 2107 } 2108}; 2109 2110FieldValidator.prototype.handleInappropriateWords = function (focus) { 2111 var errorMsg = []; 2112 $(this.elemInput).addClass('t-state-error'); 2113 errorMsg.push(FormCenterHomeScriptResources.InappropriateWords); 2114 this.errorShow(errorMsg); 2115 if (focus) { 2116 this.focusErrorElement(); 2117 } 2118}; 2119
2120FieldValidator.prototype.focusErrorElement = function () { 2121 var scrollIntoView = function (element) { 2122 var offset = $(element).offset(); 2123 var elementTop = offset.top; 2124 // Add a 50px padding to the top of the element, just for aesthetics 2125 $(document).scrollTop(elementTop - 150); 2126 }; 2127 2128 if (this.elemInputIsArray) { 2129 if ($(this.elemInput).is(":visible")) { 2130 if (this.elemInput.length > this.focusElementIndex) { 2131 this.elemInput[this.focusElementIndex].focus(); 2132 } 2133 else { 2134 this.elemInput[0].focus(); 2135 } 2136 scrollIntoView(this.elemInput[0]); 2137 } 2138 this.alreadySetFocus = false; 2139 this.focusElementIndex = 0; 2140 } 2141 else { 2142 if ($(this.elemInput).is(":visible")) { 2143 this.elemInput.focus(); 2144 scrollIntoView(this.elemInput); 2145 } 2146 } 2147} 2148 2149// Shows error message for field. Called by validate() if field value fails validation. 2150FieldValidator.prototype.errorShow = function (messages) { 2151 if (this.elemErrorNote) 2152 this.errorClear(); 2153 2154 // Element not defined, cannot perform operation. 2155 if (this.elemInput == null) 2156 return; 2157 2158 this.$elemContainer.addClass('error'); 2159 this.elemErrorNote = []; 2160 2161 $('ol li.error div').addClass('selfClear'); 2162 2163 if (this.elemInput != undefined) { 2164 if (this.elemInput["0"] != undefined) { 2165 //Check current element is radio 2166 if (this.elemInput["0"].type == "radio" & !(this.$elemContainer.closest('li').hasClass('error'))) { 2167 this.$elemContainer.closest('li').addClass('error'); 2168 originalTextColorRadio = this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color; 2169 this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color = "#800000"; 2170 } 2171 else //Check current element is checkbox 2172 if (this.elemInput["0"].type == "checkbox" & !(this.$elemContainer.closest('li').hasClass('error'))) { 2173 this.$elemContainer.closest('li').addClass('error'); 2174 originalTextColorCheckBox = this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color; 2175 this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color = "#800000"; 2176 } 2177 } 2178 } 2179 2180 for (var i = 0, len = messages.length; i < len; i++) { 2181 var errorElemMsg = document.createElement('p'); 2182 2183 errorElemMsg.className = 'explanation'; 2184 2185 var multiSelectable = this.elemInput[0] !== undefined && this.elemInput.tagName !== "SELECT"; 2186 if (multiSelectable) { 2187 errorElemMsg.id = 'errorMsg' + this.elemInput[0].id; 2188 } 2189 else { 2190 errorElemMsg.id = 'errorMsg' + this.elemInput.id; 2191 } 2192 2193 errorElemMsg.innerHTML = messages[i]; 2194 2195 if (this.elemInput != undefined) { 2196 if (this.elemInput["0"] != undefined) { 2197 if (this.elemInput["0"].type == "radio" || this.elemInput["0"].type == "checkbox") { 2198 errorElemMsg.style.backgroundColor = "#940E0D" 2199 errorElemMsg.style.color = "#FFFFFF"; 2200 errorElemMsg.style.fontWeight = "bold" 2201 errorElemMsg.style.lineHeight = "1.2" 2202 errorElemMsg.style.width = "94%" 2203 errorElemMsg.style.margin = ".5em 0 0" 2204 errorElemMsg.style.padding = ".5em" 2205 } 2206 } 2207 } 2208 2209 this.elemContainer.appendChild(errorElemMsg); 2210 2211 this.elemErrorNote.push(errorElemMsg); 2212 } 2213 !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights(); 2214}; 2215 2216// Clears error message for field. Called by validate() if field value passes validation. 2217FieldValidator.prototype.errorClear = function () { 2218 if (this.elemInput != undefined) { 2219 if (this.elemInput["0"] != undefined) { 2220 var i = 0, len = this.elemInput.length; 2221 for (; i < len; i++) { 2222 if (this.elemInput[i].checked) 2223 break; 2224 } 2225 2226 if (i != len) { 2227 if (this.elemInput["0"].type == "radio") { 2228 this.$elemContainer.closest('li').removeClass('error'); 2229 this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color = originalTextColorRadio; 2230 } 2231 else if (this.elemInput["0"].type == "checkbox") { 2232 this.$elemContainer.closest('li').removeClass('error'); 2233 this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color = originalTextColorCheckBox; 2234 } 2235 } 2236 } 2237 } 2238 if (this.elemErrorNote == null) 2239 return; 2240 else if (this.elemInput == null) 2241 return; 2242 2243 if (this.elemErrorNote.length > 0) { 2244 var errorParent = this.elemErrorNote[0].parentNode; 2245 2246 for (var i = 0, len = this.elemErrorNote.length; i < len; i++) 2247 errorParent.removeChild(this.elemErrorNote[i]); 2248 2249 this.elemErrorNote = null; 2250 } 2251 2252 this.$elemContainer.removeClass('error'); 2253 !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights();
2254}; 2255 2256FieldValidator.prototype.getErrorMessage = function (errorTemplateMsg) { 2257 var $fieldElemContainer = $(this.elemContainer); 2258 2259 if (!$fieldElemContainer.hasClass('formFieldContainer')) 2260 { 2261 $fieldElemContainer = $fieldElemContainer.parents('.formFieldContainer'); 2262 } 2263 2264 var $fieldLabelElem = $fieldElemContainer.find('.labelForFieldElement'); 2265 var fieldLabel = ''; 2266 2267 if ($fieldLabelElem.length > 0) 2268 { 2269 fieldLabel = $fieldLabelElem.text().replace(/\*/g, ''); 2270 } 2271 else 2272 { 2273 $fieldLabelElem = $fieldElemContainer.find('legend'); 2274 if ($fieldLabelElem.length > 0) 2275 { 2276 fieldLabel = $fieldLabelElem.text().replace(/\*/g, ''); 2277 } 2278 } 2279 2280 var errorMsg = errorTemplateMsg.format(fieldLabel); 2281 2282 return errorMsg; 2283} 2284; 2285/// <reference path="../../../../Scripts/json2.js"/> 2286/// <reference path="../../../../Scripts/HtmlExtensionSupport.js"/> 2287/// <reference path="../../../../Common/GlobalJSFunctionsDetail.js" /> 2288/// <reference path="Home.js" /> 2289 2290// Configurable in debug console. Controls behavior of FieldConditionsRunner.log(). 2291var condRunnerHideLogDupes = true; 2292 2293// Missing methods for IE 2294if (!Element.prototype.matches) { 2295 Element.prototype.matches = 2296 Element.prototype.msMatchesSelector || 2297 Element.prototype.webkitMatchesSelector; 2298} 2299 2300if (!Element.prototype.closest) { 2301 Element.prototype.closest = function (s) { 2302 var el = this; 2303 2304 do { 2305 if (Element.prototype.matches.call(el, s)) return el; 2306 el = el.parentElement || el.parentNode; 2307 } while (el !== null && el.nodeType === 1); 2308 return null; 2309 }; 2310} 2311 2312////////// Helper Functions /////////////// 2313 2314$("*").focus(function () { 2315 var inputs = $("input[type=text][cp5ph=true], textarea[cp5ph=true]"); 2316 if (inputs != null) { 2317 for (var i = 0; i < inputs.length; i++) { 2318 var elementName = inputs[i].getAttribute('id'); 2319 if (elementName != null) { 2320 var top = $('#' + elementName).offset().top; 2321 var left = $('#' + elementName).offset().left; 2322 if (top != -2 && left != -2) 2323 $('#ph_' + elementName).offset({ left: (left + 5), top: (top + 5) }); 2324 } 2325 } 2326 } 2327}); 2328 2329// Helper that handles replacement of special characters. 2330// * value - variable to handle characters of. 2331function HandleCharacters(value) { 2332 return value.replace(/,/g, '_d'); 2333} 2334 2335if (Array.prototype.any == null && !$.isFunction(Array.prototype.any)) { 2336 // Returns true if callback condition returns true for any items in array. 2337 // * callback - Callback function with single argument for current index. The 'this' reference points to the array. 2338 Array.prototype.any = function (callback) { 2339 if (this == null) 2340 return false; 2341 2342 for (var i = 0, len = this.length; i < len; i++) { 2343 if (callback.call(this, i)) 2344 return true; 2345 } 2346 2347 return false; 2348 } 2349} 2350 2351if (Array.prototype.all == null && !$.isFunction(Array.prototype.all)) { 2352 // Returns true if callback condition returns true for all items in array. 2353 // * callback - Callback function with single argument for current index. The 'this' reference points to the array. 2354 Array.prototype.all = function (callback) { 2355 if (this == null) 2356 return false; 2357 2358 for (var i = 0, len = this.length; i < len; i++) { 2359 if (!callback.call(this, i)) 2360 return false; 2361 } 2362 2363 return true; 2364 }; 2365} 2366 2367if (Error.argNull == null || !$.isFunction(Error.argNull)) { 2368 // Static helper that creates error when null argument that should not be null is encountered. 2369 // * argName - Name of problematic null argument. 2370 Error.argNull = function (argName) { 2371 return new ReferenceError(argName + " cannot be null"); 2372 } 2373} 2374 2375// Overridden on a per-form basis. Retrieves validator information for submission validation. 2376// * validators - Validator dictionary. 2377function getFormConditionData() { 2378 return []; 2379} 2380 2381// Prints useful debugging information for FieldConditionsRunner.run() results. Use as done callback. 2382// Note: When minifiying the JavaScript, this function can/should be removed. 2383// * logs - Log generated by run(). 2384function debugCondRunnerLogResults(logs) { 2385 if (logs == null) 2386 throw new Error.argNull("logs"); 2387 2388 console.log("## run() started at " + (new Date()) + " ##"); 2389 2390 for (var i = 0, iLen = logs.length; i < iLen; i++) { 2391 var log = logs[i]; 2392 var resultEx = log.isMet ? " (met)" : " (not met)"; 2393 2394 console.log( 2395 "field: " + log.id + 2396 ", condIndex: " + log.condIndex + 2397 ", action: " + ConditionActions.getName(log.actType) + 2398 ", result: " + ConditionRunnerActResult.getName(log.result) + resultEx); 2399 2400 if (log.needRestart) 2401 console.log("-- restart --"); 2402 } 2403 2404 console.log("## run() ended ##"); 2405 console.log("\t"); 2406} 2407 2408// Helper that repositions line siblings by re-assigning left/middle/right classes. 2409// * liSiblingList - Array of LI elements for a form line. 2410function repositionLineSiblings(liSiblingList) { 2411 if (liSiblingList == null) 2412 throw new Error.argNull("liSiblingList"); 2413 2414 var sibling, $sibling; 2415 var len = liSiblingList.length; 2416 2417 if (len > 0) { 2418 var operableNodes = []; 2419 2420 for (var i = 0; i < len; i++) { 2421 sibling = liSiblingList[i]; 2422 $sibling = $(sibling); 2423 2424 if (!$sibling.hasClass('hidden')) 2425 operableNodes.push($sibling); 2426 } 2427 2428 len = operableNodes.length; 2429 2430 if (len > 0) { 2431 operableNodes[0].removeClass('middle right').addClass('left'); 2432 2433 var j = 1; 2434 2435 for (; j < len - 1; j++) 2436 operableNodes[j].removeClass('left right').addClass('middle'); 2437 2438 if (j < len) 2439 operableNodes[j].removeClass('left middle').addClass('right'); 2440 } 2441 } 2442} 2443 2444// Helper that gets sibling field LI elements for a line field LI element. 2445// * liElem - The LI element for a form field to get line siblings LIs for. 2446function getLineSiblings(liElem) { 2447 2448 if (liElem == null && (window.location.href).toString().toLowerCase().indexOf("print") != -1) 2449 return ""; 2450 2451 if (liElem == null) 2452 throw new Error.argNull("liElem"); 2453 2454 var nodeList = []; 2455 var startNode = liElem; 2456 2457 // Get start of line. 2458 while (startNode && !$(startNode).hasClass('lineStart')) 2459 startNode = previousElementSibling(startNode); 2460 2461 // Get end of line. 2462 if (startNode) { 2463 var endNode = startNode; 2464 var $endNode = null; 2465 2466 while (endNode != null) { 2467 $endNode = $(endNode); 2468 2469 if ($endNode.hasClass('lineEnd')) 2470 break; 2471 2472 endNode = nextElementSibling(endNode); 2473 } 2474 } 2475 2476 if (startNode && endNode) { 2477 var nodeEnum = startNode; 2478 2479 while (true) { 2480 nodeList.push(nodeEnum); 2481 2482 if (nodeEnum == endNode) 2483 break; 2484 2485 nodeEnum = nextElementSibling(nodeEnum); 2486 } 2487 } 2488 2489 return nodeList; 2490} 2491 2492////////// Enumerations /////////////////// 2493 2494// Condition actions. 2495var ConditionActions = { 2496 None: 0, 2497 Show: 1, 2498 Hide: 2, 2499 Require: 3, 2500 RedirectTo: 4, 2501 getName: function (value) { 2502 for (var k in ConditionActions) { 2503 if (ConditionActions[k] == value) 2504 return k; 2505 } 2506 2507 return null; 2508 } 2509}; 2510 2511// Condition comparison types. 2512var ConditionComparison = { 2513 None: 0, 2514 GreaterThan: 1, 2515 LessThan: 2, 2516 EqualTo: 3, 2517 NotEqualTo: 4, 2518 Contains: 5, 2519 Available: 6, 2520 Unavailable: 7, 2521 Between: 8, 2522 getName: function (value) { 2523 for (var k in ConditionComparison) { 2524 if (ConditionComparison[k] == value) 2525 return k; 2526 } 2527 2528 return null; 2529 } 2530}; 2531 2532// Condition runner action results. 2533var ConditionRunnerActResult = { 2534 None: 0, 2535 SuccessImplicit: 1, 2536 SuccessExplicit: 2, 2537 SkipDuplicate: 3, 2538 SkipContradiction: 4, 2539 getName: function (value) { 2540 for (var k in ConditionRunnerActResult) { 2541 if (ConditionRunnerActResult[k] == value) 2542 return k; 2543 } 2544 2545 return null; 2546 } 2547}; 2548
2549////////// FieldCondition Class /////////// 2550 2551// Internal. Creates instance of FieldCondition class. 2552// * parent - Parent FieldConditions instance. 2553// * condInfo - Object containing properties {compType, compValue, actElemInput, actID, actType, actFieldType, actURL, actURLNewWindow}. 2554function FieldCondition(parent, condInfo) { 2555 if (parent == null) 2556 throw new Error.argNull("parent"); 2557 else if (condInfo == null) 2558 throw new Error.argNull("condInfo"); 2559 2560 $.extend(this, condInfo); 2561 2562 // Set instance parent. 2563 this.parent = parent; 2564 2565 // Process actElemInput argument. 2566 var actElemInput = this.actElemInput; 2567 this.actElemInputIsArray = $.isArray(actElemInput); 2568 2569 if (this.actElemInputIsArray) { 2570 for (var i = 0, len = actElemInput.length; i < len; i++) { 2571 if (typeof (actElemInput[i]) == "string") 2572 actElemInput[i] = document.getElementById(actElemInput[i]); 2573 } 2574 2575 if (actElemInput.length > 0 && actElemInput[0]) { 2576 this.actElemContainer = actElemInput[0].closest('.formFieldContainer'); 2577 this.actElemInput = actElemInput; 2578 } 2579 } 2580 else { 2581 if (typeof (actElemInput) == "string") 2582 actElemInput = document.getElementById(actElemInput); 2583 2584 if (actElemInput) { 2585 this.actElemContainer = actElemInput.closest('.formFieldContainer'); 2586 this.actElemInput = actElemInput; 2587 } 2588 } 2589 2590 // Get shared container. 2591 this.$actElemContainer = $(this.actElemContainer); 2592} 2593 2594// Static. Creates multiple instances from list of condition information. 2595FieldCondition.createMulti = function (parent, condList) { 2596 if (parent == null) 2597 throw new Error.argNull("parent"); 2598 else if (condList == null) 2599 throw new Error.argNull("condList"); 2600 2601 var ret = []; 2602 2603 for (var i = 0, len = condList.length; i < len; i++) 2604 ret.push(new FieldCondition(parent, condList[i])); 2605 2606 return ret; 2607} 2608 2609// Checks if condition is met and performs any necessary action. 2610// * updateUI - Determines if UI is updated after check. Treated as true if null/unspecified. 2611FieldCondition.prototype.check = function (updateUI) { 2612 // TODO: Handle checkboxes/radios/dropdowns when Akila gets that done on back-end. 2613 var thisValue = []; 2614 var compValue = this.compValue; 2615 var isMet = false; 2616 2617 switch (this.actFieldType) { 2618 case FieldTypes.Checkboxes: 2619 for (var i = 0, len = this.actElemInput.length; i < len; i++) { 2620 if (this.actElemInput[i].checked) 2621 thisValue.push(this.actElemInput[i].value.replace(/\,/g, '_comma_')); 2622 } 2623 break; 2624 case FieldTypes.RadioButtons: 2625 for (var i = 0, len = this.actElemInput.length; i < len; i++) { 2626 if (this.actElemInput[i].checked) { 2627 thisValue = [this.actElemInput[i].value]; 2628 break; 2629 } 2630 } 2631 break; 2632 case FieldTypes.DateTime: 2633 var tempArray = new Array(); 2634 for (var i = 0, len = this.actElemInput.length; i < len; i++) { 2635 tempArray.push([this.actElemInput[i].value]) 2636 } 2637 thisValue = [tempArray.join(',')]; 2638 break; 2639 default: 2640 thisValue = [this.actElemInput.value]; 2641 } 2642 2643 var extractMoneyValue = function (v) { 2644 var stringBeginsWith = function (val, beginString) { 2645 return val.substring(0, beginString.length) === beginString 2646 } 2647 if (v && v != '') { 2648 if (stringBeginsWith(v, '$')) { 2649 return v.substring(1).replace(',', ''); 2650 } 2651 } 2652 return v.replace(',', ''); 2653 }; 2654 2655 2656 var isNum = function (val) { 2657 var extracted = extractMoneyValue(val); 2658 return parseFloat(extracted) === +extracted; 2659 }; 2660 2661 var checkAgainst = function (compValue) { 2662 switch (this.compType) { 2663 case ConditionComparison.GreaterThan: 2664 return thisValue.any(function (index) { 2665 if (isNum(this[index]) && isNum(HandleCharacters(compValue))) { 2666 return parseFloat(extractMoneyValue(this[index])) > parseFloat(extractMoneyValue(HandleCharacters(compValue))); 2667 } 2668 return false; 2669 }); 2670 case ConditionComparison.LessThan: 2671 return thisValue.any(function (index) { 2672 if (isNum(this[index]) && isNum(HandleCharacters(compValue))) { 2673 return parseFloat(extractMoneyValue(this[index])) < parseFloat(extractMoneyValue(HandleCharacters(compValue))); 2674 } 2675 return false; 2676 }); 2677 case ConditionComparison.EqualTo: 2678 if (this.actFieldType == FieldTypes.DateTime) { 2679 if (this.actIsDateTimeSpan) { 2680 return this.checkDateEqualSpan(thisValue[0], compValue); 2681 } 2682 else { 2683 return this.checkDateEqualTo(thisValue[0], compValue); 2684 } 2685 } 2686 else { 2687 return thisValue.any(function (index) { 2688 return (isNull(HandleCharacters(this[index]), '') == isNull(HandleCharacters(compValue), '')); 2689 });
2690 } 2691 case ConditionComparison.NotEqualTo: 2692 return thisValue.any(function (index) { return (isNull(this[index], '').toUpperCase() != isNull(HandleCharacters(compValue), '').toUpperCase()); }); 2693 break; 2694 case ConditionComparison.Contains: 2695 var containsExp = new RegExp(RegExp.metaEscape(HandleCharacters(compValue)), 'i'); 2696 2697 return thisValue.any(function (index) { 2698 return containsExp.test(this[index]); 2699 }); 2700 case ConditionComparison.Unavailable: 2701 return this.$actElemContainer.hasClass('unavailable'); 2702 case ConditionComparison.Available: 2703 return !this.$actElemContainer.hasClass('unavailable'); 2704 case ConditionComparison.Between: 2705 return this.checkDateBetween(thisValue[0], compValue); 2706 return; 2707 case ConditionComparison.None: 2708 default: 2709 return true; 2710 } 2711 }; 2712 2713 switch (this.actFieldType) { 2714 case FieldTypes.Checkboxes: 2715 var compArr = compValue.split(','); 2716 2717 isMet = true; 2718 2719 for (var i = 0, len = compArr.length; i < len; i++) { 2720 2721 if (!checkAgainst.call(this, compArr[i])) { 2722 isMet = false; 2723 break; 2724 } 2725 } 2726 break; 2727 default: 2728 isMet = checkAgainst.call(this, compValue); 2729 } 2730 2731 if (updateUI) 2732 this.doAction(isMet); 2733 2734 return isMet; 2735}; 2736 2737// Performs changes to applying field based on condition action and comparison result. 2738FieldCondition.prototype.doAction = function (isMet) { 2739 var validator = (this.parent.validators ? this.parent.validators[this.parent.id] : null); 2740 2741 switch (this.actType) { 2742 case ConditionActions.Show: 2743 this.doActionShow(isMet, validator); 2744 break; 2745 case ConditionActions.Hide: 2746 this.doActionHide(isMet, validator); 2747 break; 2748 case ConditionActions.Require: 2749 this.doActionRequire(isMet, validator); 2750 break; 2751 case ConditionActions.RedirectTo: 2752 this.doActionRedirect(isMet, validator); 2753 break; 2754 } 2755}; 2756 2757FieldCondition.prototype.doActionShow = function (isMet, validator) { 2758 if (isMet) { 2759 this.parent.$elemContainer.removeClass('hidden'); 2760 this.parent.$elemContainer.removeClass('unavailable'); 2761 2762 // Update classes assigned to fields (e.g. since what was "left" may now be hidden and a new "left" is needed). 2763 repositionLineSiblings(getLineSiblings(this.parent.elemContainer)); 2764 2765 if (this.parent.$elemContainer.find('label > span') != null && this.parent.$elemContainer.find('label > span').length > 0) 2766 $('#liRequiredFieldInfo').show(); 2767 2768 if (validator) 2769 validator.enabled = true; 2770 } 2771 else { 2772 this.parent.$elemContainer.addClass('hidden'); 2773 this.parent.$elemContainer.addClass('unavailable'); 2774 2775 // Update classes assigned to fields (e.g. since what was "left" may now be hidden and a new "left" is needed). 2776 repositionLineSiblings(getLineSiblings(this.parent.elemContainer)); 2777 2778 if (validator) 2779 validator.enabled = false; 2780 } 2781}; 2782 2783FieldCondition.prototype.doActionHide = function (isMet, validator) { 2784 if (isMet) { 2785 this.parent.$elemContainer.addClass('hidden'); 2786 this.parent.$elemContainer.addClass('unavailable'); 2787 2788 // Update classes assigned to fields (e.g. since what was "left" may now be hidden and a new "left" is needed). 2789 repositionLineSiblings(getLineSiblings(this.parent.elemContainer)); 2790 2791 if (validator) 2792 validator.enabled = false; 2793 } 2794 else { 2795 this.parent.$elemContainer.removeClass('hidden'); 2796 this.parent.$elemContainer.removeClass('unavailable'); 2797 2798 // Update classes assigned to fields (e.g. since what was "left" may now be hidden and a new "left" is needed). 2799 repositionLineSiblings(getLineSiblings(this.parent.elemContainer)); 2800 2801 if (validator) 2802 validator.enabled = true; 2803 } 2804}; 2805 2806FieldCondition.prototype.doActionRequire = function (isMet, validator) { 2807 if (isMet) { 2808 this.parent.$elemReq.removeClass('hidden'); 2809 2810 if (validator == null) { 2811 validator = new FieldValidator(this.parent.elemInput, this.parent.id, this.parent.fieldType, this.parent.isInternal, true, FieldValidation.Any); 2812 this.parent.validators.add(validator); 2813 } 2814 2815 this.parent.$elemContainer.find('label.labelForFieldElement > span').show(); 2816 $('#liRequiredFieldInfo').show(); 2817 if (validator) 2818 validator.isRequired = true; 2819 } 2820 else { 2821 this.parent.$elemReq.addClass('hidden'); 2822 this.parent.$elemContainer.find('label.labelForFieldElement > span').hide(); 2823 2824 if (validator) 2825 validator.isRequired = false; 2826 } 2827}; 2828 2829FieldCondition.prototype.doActionRedirect = function (isMet, validator) { 2830 // TODO: Some point alter this to pass in references for submitRedirect/redirectNewWindow. Not ideal at moment to ref. global vars. 2831 var submitRedirect = document.getElementById('submitRedirect'); 2832 2833 redirectNewWindow = null; 2834 submitRedirect.value = ''; 2835 2836 if (isMet) { 2837 if (this.actURLNewWindow) { 2838 redirectNewWindow = this.actURL; 2839 submitRedirect.value = ''; 2840 } 2841 else 2842 submitRedirect.value = this.actURL; 2843 } 2844}; 2845 2846// Attachs event handler to field to monitor changes. 2847// * condRunner - FieldConditionsRunner instance to attach. 2848// Note: Calling more than once will have no effect. 2849FieldCondition.prototype.attachRunner = function (condRunner) { 2850 if (condRunner == null) 2851 throw new Error.argNull("condRunner"); 2852 2853 // Do not try to bind this if it is an internal field condition and we are not running internal field 2854 // conditions. 2855 if (this.parent.isInternal && !condRunner.runInternal) 2856 return; 2857 2858 if ($.data(this.actElemInput, "runner_chghook") == null) { 2859 var changeHook = function (event) { 2860 condRunner.run(true); 2861 !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights();
2862 }; 2863 $.data(this.actElemInput, "runner_chghook", changeHook); 2864 $(this.actElemInput).change(changeHook); 2865 } 2866}; 2867 2868// Removes event handler that monitors changes. 2869// Note: Calling more than once will have no effect. 2870FieldCondition.prototype.detachRunner = function () { 2871 var changeHook = $.data(this.actElemInput, "runner_chghook"); 2872 2873 if (changeHook) { 2874 $(this.actElemInput).unbind('change', changeHook); 2875 $.removeData(this.actElemInput, "runner_chghook"); 2876 } 2877}; 2878 2879FieldCondition.prototype.checkDateCommon = function (thisValue, compValue) { 2880 var defaultDate = '1/1/70'; 2881 var defualtDateObj = new Date(defaultDate); 2882 2883 var compArr = compValue.split(','); 2884 var valueArr = thisValue.split(','); 2885 2886 var hasTimeOfDayStart = false; 2887 var hasTimeOfDayEnd = false; 2888 2889 var compareStartDate; 2890 var compareEndDate; 2891 2892 if (compArr[0] == '') { 2893 compareStartDate = new Date(defaultDate + ' ' + compArr[2]); 2894 } 2895 else { 2896 compareStartDate = new Date(compArr[0] + ' ' + compArr[2]); 2897 } 2898 2899 if (compArr[1] == '') { 2900 compareEndDate = new Date(defaultDate + ' ' + compArr[3]); 2901 } 2902 else { 2903 compareEndDate = new Date(compArr[1] + ' ' + compArr[3]); 2904 } 2905 2906 var validStartDate = new Date(defaultDate); 2907 var validEndDate = new Date(defaultDate); 2908 var timeOfDayStart = ''; 2909 var timeOfDayEnd = ''; 2910 2911 if (valueArr.length == 4) { 2912 if (valueArr[0] == '') { 2913 validStartDate = new Date(defaultDate + ' ' + valueArr[2]); 2914 } 2915 else { 2916 validStartDate = new Date(valueArr[0] + ' ' + valueArr[2]); 2917 } 2918 2919 timeOfDayStart = this.getAMPMString(valueArr[2]); 2920 2921 if (timeOfDayStart != '') 2922 hasTimeOfDayStart = true; 2923 2924 if (valueArr[1] == '') { 2925 validEndDate = new Date(defaultDate + ' ' + valueArr[3]); 2926 } 2927 else { 2928 validEndDate = new Date(valueArr[1] + ' ' + valueArr[3]); 2929 } 2930 2931 timeOfDayEnd = this.getAMPMString(valueArr[3]); 2932 2933 if (timeOfDayEnd != '') 2934 hasTimeOfDayEnd = true; 2935 } 2936 else if (valueArr.length == 2) { 2937 timeOfDayStart = this.getAMPMString(valueArr[0]); 2938 2939 if (timeOfDayStart == '') { 2940 if (valueArr[0] != '') { 2941 validStartDate = new Date(valueArr[0]); 2942 hasTimeOfDayStart = true; 2943 } 2944 } 2945 else { 2946 validStartDate = new Date(defaultDate + ' ' + valueArr[0]); 2947 hasTimeOfDayStart = true; 2948 } 2949 2950 timeOfDayEnd = this.getAMPMString(valueArr[1]); 2951 2952 if (timeOfDayEnd == '') { 2953 if (valueArr[1] != '') { 2954 validEndDate = new Date(valueArr[1]); 2955 hasTimeOfDayEnd = true; 2956 } 2957 } 2958 else { 2959 validEndDate = new Date(defaultDate + ' ' + valueArr[1]); 2960 hasTimeOfDayEnd = true; 2961 } 2962 } 2963 2964 return { 2965 validStartDate: validStartDate, 2966 compareStartDate: compareStartDate, 2967 compareEndDate: compareEndDate, 2968 hasTimeOfDayStart: hasTimeOfDayStart, 2969 validEndDate: validEndDate, 2970 hasTimeOfDayEnd: hasTimeOfDayEnd 2971 }; 2972}; 2973 2974FieldCondition.prototype.checkDateBetween = function (thisValue, compValue) { 2975 var checkDateCommonData = this.checkDateCommon(thisValue, compValue); 2976 2977 return (checkDateCommonData.validStartDate.getTime() >= checkDateCommonData.compareStartDate.getTime() && checkDateCommonData.validStartDate.getTime() <= checkDateCommonData.compareEndDate.getTime() && checkDateCommonData.hasTimeOfDayStart) 2978 && (checkDateCommonData.validEndDate.getTime() <= checkDateCommonData.compareEndDate.getTime() && checkDateCommonData.validEndDate.getTime() >= checkDateCommonData.compareStartDate.getTime() && checkDateCommonData.hasTimeOfDayEnd); 2979}; 2980 2981FieldCondition.prototype.checkDateEqualSpan = function (thisValue, compValue) { 2982 var checkDateCommonData = this.checkDateCommon(thisValue, compValue); 2983 2984 return (checkDateCommonData.validStartDate.getTime() == checkDateCommonData.compareStartDate.getTime() && checkDateCommonData.hasTimeOfDayStart) 2985 && (checkDateCommonData.validEndDate.getTime() == checkDateCommonData.compareEndDate.getTime() && checkDateCommonData.hasTimeOfDayEnd); 2986}; 2987 2988FieldCondition.prototype.checkDateEqualTo = function (thisValue, compValue) { 2989 var defaultDate = '1/1/70'; 2990 var defualtDateObj = new Date(defaultDate); 2991 2992 var compArr = compValue.split(','); 2993 var valueArr = thisValue.split(','); 2994 2995 var compareDate; 2996 2997 var hasTimeOfDay = false; 2998 2999 if (compArr[0] == '') { 3000 compareDate = new Date(defaultDate + ' ' + compArr[2]); 3001 } 3002 else { 3003 compareDate = new Date(compArr[0] + ' ' + compArr[2]); 3004 } 3005 3006 var validDate = new Date(defaultDate); 3007 var timeOfDay = ''; 3008 3009 if (valueArr.length == 1) { 3010 timeOfDay = this.getAMPMString(valueArr[0]); 3011 3012 if (timeOfDay == '') { 3013 if (valueArr[0] != '') { 3014 validDate = new Date(valueArr[0]); 3015 hasTimeOfDay = true; 3016 } 3017 } 3018 else { 3019 hasTimeOfDay = true; 3020 validDate = new Date(valueArr[0]); 3021 } 3022 } 3023 else if (valueArr.length == 2) { 3024 timeOfDay = this.getAMPMString(valueArr[1]); 3025 3026 if (timeOfDay != '') 3027 hasTimeOfDay = true; 3028 3029 if (valueArr[0] != '') { 3030 validDate = new Date((valueArr[0] + ' ' + valueArr[1] + ' ').replace(/\-/g, '/')); 3031 } 3032 else { 3033 validDate = new Date((defaultDate + ' ' + valueArr[0] + ' ').replace(/\-/g, '/')); 3034 } 3035 } 3036 3037 return validDate.getTime() == compareDate.getTime() && hasTimeOfDay; 3038}; 3039 3040FieldCondition.prototype.getAMPMString = function (time) { 3041 var amIndex = time.indexOf('AM'); 3042 var pmIndex = time.indexOf('PM'); 3043 3044 var timeOfDay = ''; 3045 3046 // First see if the time is military time... if so we need to convert it to AM/PM so the rest 3047 // of this function will return the proper value. 3048 3049 if (amIndex === -1 && pmIndex === -1) { 3050 time = militaryTimeToStandard(time); 3051 amIndex = time.indexOf('AM'); 3052 pmIndex = time.indexOf('PM'); 3053 } 3054 3055 if (amIndex != -1) { 3056 timeOfDay = time.substring(amIndex).replace(" ", ""); 3057 } 3058 else if (pmIndex != -1) { 3059 timeOfDay = time.substring(pmIndex).replace(" ", ""); 3060 } 3061 3062 return timeOfDay; 3063}; 3064 3065function militaryTimeToStandard(militaryTime) { 3066 var colonIndex = militaryTime.indexOf(':'); 3067 var hours = ''; 3068 var min = ''; 3069 3070 if (colonIndex === -1) { 3071 hours = militaryTime.substring(0, 2); 3072 min = militaryTime.substring(2, 4); 3073 } else { 3074 var tokens = militaryTime.split(':'); 3075 hours = tokens[0]; 3076 min = tokens[1]; 3077 } 3078 3079 if (hours < 12) { 3080 ampm = 'AM'; 3081 } else { 3082 hours = hours - 12; 3083 ampm = 'PM'; 3084 } 3085 3086 return parseInt(hours) + ':' + ('00' + min).slice('-2') + ' ' + ampm; ß 3087} 3088 3089 3090////////// FieldConditions Class ////////// 3091 3092// Creates instance of FieldConditions class. 3093// * elemInput - Reference to DOM element of field with condition. May be a DOM element or string containing ID. May also be array of DOM elements or IDs. Multiple elements must share same parent. 3094// * id - The ID of the field with the condition. 3095// * fieldType - The field type of the field with the condition. 3096// * isInternal - Whether or not this condition is for internal-only fields. 3097// * condList - List (array) of zero or more condition clauses for the field. 3098// * validators - Validator dictionary. 3099function FieldConditions(options, validators) { 3100 if (options.elemInput == null) 3101 throw new Error.argNull("options.elemInput"); 3102 else if (options.id == null) 3103 throw new Error.argNull("id"); 3104 else if (options.fieldType == null) 3105 throw new Error.argNull("options.fieldType"); 3106 else if (options.condList == null) 3107 throw new Error.argNull("options.condList"); 3108 else if (validators == null) 3109 throw new Error.argNull("validators"); 3110 3111 this.elemInputIsArray = $.isArray(options.elemInput); 3112 3113 // Process elemInput argument. 3114 if (this.elemInputIsArray) { 3115 for (var i = 0, len = options.elemInput.length; i < len; i++) { 3116 if (typeof (options.elemInput[i]) == "string") 3117 options.elemInput[i] = document.getElementById(options.elemInput[i]); 3118 } 3119 3120 if (options.elemInput.length > 0 && options.elemInput[0]) { 3121 this.elemContainer = options.elemInput[0].closest('.formFieldContainer'); 3122 this.elemInput = options.elemInput; 3123 } 3124 } 3125 else { 3126 if (typeof (options.elemInput) == "string") 3127 options.elemInput = document.getElementById(options.elemInput); 3128 3129 if (options.elemInput) { 3130 this.elemContainer = options.elemInput.closest('.formFieldContainer'); 3131 this.elemInput = options.elemInput; 3132 } 3133 } 3134 3135 this.validators = validators; 3136 this.elemReq = document.getElementById('r_' + options.id); 3137 this.$elemContainer = $(this.elemContainer); 3138 this.$elemReq = $(this.elemReq); 3139 this.fieldType = options.fieldType; 3140 this.id = options.id; 3141 this.isInternal = options.isInternal; 3142 this.conditions = FieldCondition.createMulti(this, options.condList); 3143} 3144 3145// Static. Creates a single conditions object from an options object. 3146FieldConditions.createSingle = function (options, validators) { 3147 if (options == null) 3148 throw new Error.argNull("options"); 3149 else if (validators == null) 3150 throw new Error.argNull("validators"); 3151 3152 return new FieldConditions( 3153 options, 3154 validators); 3155}; 3156 3157// Static. Creates dictionary of conditions objects from array of option objects. 3158FieldConditions.createMulti = function (optionsArray, validators) { 3159 if (optionsArray == null) 3160 throw new Error.argNull("optionsArray"); 3161 else if (validators == null) 3162 throw new Error.argNull("validators"); 3163 3164 var ret = { keys: [] }; 3165 var key = null; 3166 3167 for (var i = 0, len = optionsArray.length; i < len; i++) { 3168 if (optionsArray[i].id != null) { 3169 key = optionsArray[i].id; 3170 ret[key] = FieldConditions.createSingle(optionsArray[i], validators); 3171 ret.keys.push(key); 3172 } 3173 } 3174 3175 return ret; 3176}; 3177 3178// Attachs event handler to field to monitor changes. 3179// * condRunner - FieldConditionsRunner instance to attach. 3180// Note: Calling more than once will have no effect. 3181FieldConditions.prototype.attachRunner = function (condRunner) { 3182 if (condRunner == null) 3183 throw new Error.argNull("condRunner"); 3184 3185 for (var i = 0, len = this.conditions.length; i < len; i++) 3186 this.conditions[i].attachRunner(condRunner); 3187};
3188 3189// Removes event handler that monitors changes. 3190// Note: Calling more than once will have no effect. 3191FieldConditions.prototype.detachRunner = function () { 3192 for (var i = 0, len = this.conditions.length; i < len; i++) 3193 this.conditions[i].detachRunner(); 3194}; 3195 3196////////// FieldConditionsRunner Class //// 3197 3198// Creates new instance of conditions runners for the field conditions objects provided. 3199// * allFieldConditions - Array of FieldConditions objects to execute checks for. 3200// * doneCallback - Method executed when run() completes. Recieves log information as argument. 3201// * autoAttach - Determines if allFieldConditions are automatically attached to this instance by the constructor. If null/unspecified, treated as true. 3202// * runInternal - Set to true to execute internal-only fields. 3203function FieldConditionsRunner(allFieldConditions, doneCallback, autoAttach, runInternal) { 3204 if (allFieldConditions == null) 3205 throw new Error.argNull("allFieldConditions"); 3206 else if (doneCallback == null) 3207 throw new Error.argNull("doneCallback"); 3208 3209 this.fieldConditions = allFieldConditions; 3210 this.doneCallback = doneCallback; 3211 this.runInternal = runInternal; 3212 3213 if (autoAttach == null || autoAttach) 3214 this.attachConditions(); 3215} 3216 3217// Static. Internal. Creates static information object for state tracking during execution. 3218FieldConditionsRunner.createFieldStateInfo = function () { 3219 var ret = {}; 3220 3221 ret[ConditionActions.None] = ConditionRunnerActResult.None; 3222 ret[ConditionActions.Show] = ConditionRunnerActResult.None; 3223 ret[ConditionActions.Hide] = ConditionRunnerActResult.None; 3224 ret[ConditionActions.Require] = ConditionRunnerActResult.None; 3225 ret[ConditionActions.RedirectTo] = ConditionRunnerActResult.None; 3226 3227 return ret; 3228}; 3229 3230// Attaches to FieldConditions/FieldCondition objects that runner will use. 3231FieldConditionsRunner.prototype.attachConditions = function () { 3232 for (var i = 0, iLen = this.fieldConditions.keys.length; i < iLen; i++) 3233 this.fieldConditions[this.fieldConditions.keys[i]].attachRunner(this); 3234}; 3235 3236// Detaches to FieldConditions/FieldCondition objects that runner may have used. 3237FieldConditionsRunner.prototype.detachConditions = function () { 3238 for (var i = 0, iLen = this.fieldConditions.keys.length; i < iLen; i++) 3239 this.fieldConditions[this.fieldConditions.keys[i]].detachRunner(this); 3240}; 3241 3242// Internal. Cleans up runner for use again. 3243FieldConditionsRunner.prototype.cleanup = function () { 3244 if (this.fieldConditionResults != null) { 3245 delete this.fieldConditionResults; 3246 delete this.fieldConditionLog; 3247 } 3248}; 3249 3250// Internal. Called by run() to log result for each condition. 3251FieldConditionsRunner.prototype.log = function (id, condIndex, actType, result, isMet, needRestart) { 3252 if (condRunnerHideLogDupes && result == ConditionRunnerActResult.SkipDuplicate) 3253 return; 3254 3255 this.fieldConditionLog.push({ 3256 id: id, 3257 condIndex: condIndex, 3258 actType: actType, 3259 result: result, 3260 isMet: isMet, 3261 needRestart: needRestart 3262 }); 3263}; 3264 3265// Internal. Sets whether or not the condition engine is executing. 3266FieldConditionsRunner.prototype.setRunning = function (value) { 3267 if (arguments.length == 0) 3268 this.isRunning = true; 3269 else 3270 this.isRunning = value; 3271}; 3272 3273// Gets whether or not the condition engine is executing. 3274FieldConditionsRunner.prototype.getRunning = function () { 3275 return this.isRunning; 3276}; 3277 3278// Internal. Tells condition execution task to reset cycle (done whenever something changes). 3279FieldConditionsRunner.prototype.setRestart = function (value) { 3280 if (arguments == null || arguments.length == 0) 3281 this.needRestart = true; 3282 else 3283 this.needRestart = value; 3284}; 3285 3286// Internal. Gets whether or not the runner needs to restart. 3287FieldConditionsRunner.prototype.getRestart = function () { 3288 return this.needRestart; 3289}; 3290 3291// Launches execution of conditions. 3292// * fromEvent - Should be set to true when triggerd from DOM events. 3293// NOTE: fromEvent may be a race condition but will be left for now while debugging (to simplify logs). 3294FieldConditionsRunner.prototype.run = function (fromEvent) { 3295 if (this.getRunning() && !fromEvent) 3296 this.setRestart(); 3297 else { 3298 this.setRunning(); 3299 3300 this.cleanup(); 3301 3302 this.runTask(); 3303 3304 this.doneCallback(this.fieldConditionLog); 3305 3306 this.setRunning(false); 3307 } 3308}; 3309 3310// Internal. Executes conditions. Should not be called while already running, so run() has sync mechanism for this.
3311// * runInternal - If true, conditions for internal conditions will be ran. 3312FieldConditionsRunner.prototype.runTask = function (runInternal) { 3313 var needRestart = true; 3314 3315 // Prepare objects for execution. 3316 this.fieldConditionLog = []; 3317 this.fieldConditionResults = []; 3318 this.setRedirectUrl = false; 3319 3320 // Populate state information. 3321 var condCondList = this.fieldConditions; 3322 var condListInfo = null; 3323 var condList = null; 3324 3325 for (var i = 0, iLen = condCondList.keys.length; i < iLen; i++) 3326 this.fieldConditionResults[condCondList[condCondList.keys[i]].id] = FieldConditionsRunner.createFieldStateInfo(); 3327 3328 // Number of restart actions (tracked to eventually kill infinite loops that should not happen). 3329 var numRestarts = 0; 3330 3331 // Start/restart actions. 3332 while (needRestart && (++numRestarts < 65535)) { 3333 needRestart = false; 3334 this.setRestart(needRestart); 3335 3336 for (var i = 0, iLen = condCondList.keys.length; i < iLen && !needRestart; i++) { 3337 condListInfo = condCondList[condCondList.keys[i]]; 3338 3339 // If we are on the front-end, we don't want to have anything to do with back-end (internal only) 3340 // conditions, they will cause javascript errors. 3341 if (!this.runInternal && condListInfo.isInternal == true) 3342 continue; 3343 3344 if (condListInfo.isInternal == false && document.URL.indexOf("Admin") > -1 && document.URL.indexOf("Submissions") > -1) 3345 continue; 3346 3347 condList = condListInfo.conditions; 3348 3349 for (var j = 0, jLen = condList.length; j < jLen && !needRestart; j++) { 3350 var cond = condList[j]; 3351 var results = this.fieldConditionResults[condListInfo.id]; 3352 var logState = ConditionRunnerActResult.None; 3353 3354 // Determine whether or not condition is met. 3355 var isMet = cond.check(false); 3356 3357 // This is because the effective action for a failed explicit Show is an implicit Hide (and vice versa). 3358 var effectiveActType = cond.actType; 3359 3360 // Determine if action is contradictory or duplicate and skip UI changes if so. 3361 switch (effectiveActType) { 3362 case ConditionActions.Show: 3363 // Show can collide with hide. 3364 var resultsHide = results[ConditionActions.Hide]; 3365 3366 if (resultsHide == ConditionRunnerActResult.SuccessExplicit || (resultsHide == ConditionRunnerActResult.SuccessImplicit && !isMet)) 3367 logState = ConditionRunnerActResult.SkipContradiction; 3368 3369 break; 3370 case ConditionActions.Hide: 3371 // Hide can collide with show. 3372 var resultsShow = results[ConditionActions.Show]; 3373 3374 if (resultsShow == ConditionRunnerActResult.SuccessExplicit || (resultsShow == ConditionRunnerActResult.SuccessImplicit && !isMet)) 3375 logState = ConditionRunnerActResult.SkipContradiction; 3376 3377 break; 3378 case ConditionActions.RedirectTo: 3379 // Redirects work differently since they span all fields. Extra contradiction detection needed. 3380 if (this.setRedirectUrl) 3381 logState = ConditionRunnerActResult.SkipContradiction; 3382 else if (isMet) 3383 this.setRedirectUrl = true; 3384 break; 3385 } 3386 3387 if (isMet && results[effectiveActType] == ConditionRunnerActResult.SuccessExplicit) 3388 logState = ConditionRunnerActResult.SkipDuplicate; 3389 else if (!isMet && results[effectiveActType] == ConditionRunnerActResult.SuccessExplicit) 3390 logState = ConditionRunnerActResult.SkipContradiction; 3391 else if (!isMet && results[effectiveActType] == ConditionRunnerActResult.SuccessImplicit) 3392 logState = ConditionRunnerActResult.SkipDuplicate; 3393 3394 if (logState == ConditionRunnerActResult.None) { 3395 // Determine log result. 3396 logState = isMet ? ConditionRunnerActResult.SuccessExplicit : ConditionRunnerActResult.SuccessImplicit; 3397 3398 // Update running state info. 3399 results[effectiveActType] = logState; 3400 3401 // Update form UI. 3402 cond.doAction(isMet); 3403 3404 // Restart task. 3405 this.setRestart(); 3406 needRestart = true; 3407 } 3408 3409 // Log result. 3410 this.log(condListInfo.id, j, cond.actType, logState, isMet, needRestart); 3411 3412 // Some other action could cause this to get set. 3413 if (this.getRestart()) 3414 needRestart = true; 3415 } 3416 } 3417 } 3418 3419 if (numRestarts >= 65535)
3420 console[console.warn ? "warn" : "log"]("Infinite Loop (heuristic-detected) in FieldConditionsRunner.runTask()"); 3421}; 3422; 3423// This file contains javascript functions for the "External Integration" field type. 3424// REQUIREMENTS: 3425// FieldSetDesigner.js 3426 3427// These values must match the values provided in CivicPlus.Entities.Modules.FormCenter.Enums.ExternalIntegrationCommandType 3428var ExternalIntegrationCommandType = { 3429 XMLCommand: 1, 3430 EchoCommand: 2 3431}; 3432 3433// Closure containing the client-side functionality for the External Integration field type. 3434// * externalIntegrationClass - The name of the CSS class that is used to identify external integration buttons. 3435function ExternalIntegration(externalIntegrationClassname, fieldSetDesigner) { 3436 this.cssClassname = externalIntegrationClassname; 3437 this.fieldSetDesigner = fieldSetDesigner; 3438 3439 this.hookEvents = function () { 3440 var my = this; 3441 if (my.cssClassname == null) 3442 throw 'No external integration button CSS class name has been specified.' 3443 3444 $('.' + this.cssClassname).click(function (event) { 3445 var fieldID = null; 3446 fieldID = event.target.id; 3447 my.sendRequest(fieldID); 3448 }); 3449 }; 3450 3451 this.sendRequest = function (fieldID) { 3452 var params = this.getFormData(); 3453 var formID = $('#Item_FormID').val(); 3454 var intFieldID = fieldID.replace('e_', ''); 3455 3456 var my = this; 3457 var sendData = { 3458 id: formID, 3459 fieldID: intFieldID, 3460 parameters: JSON.stringify(params) 3461 }; 3462 3463 $.ajax({ 3464 type: 'post', 3465 url: '/FormCenter/ExecuteExternalIntegrationCommand', 3466 data: sendData, 3467 success: function (data) { my.updateFormData(data, my); }, 3468 error: function (xhr, status, error) { alert('An error occurred while sending the request.'); }, 3469 beforeSend: function () { 3470 ajaxPostBackStart('Loading'); 3471 }, 3472 complete: function () { 3473 ajaxPostBackEnd(); 3474 } 3475 }); 3476 }; 3477 3478 // This function takes the values from the JSON result and sets the appropriate 3479 // form field values. 3480 this.updateFormData = function (responseFromController, externalIntegrationObject) { 3481 3482 if (responseFromController.error) { 3483 alert('An error occurred: ' + responseFromController.errorMessage); 3484 return; 3485 } 3486 3487 for (var i = 0, len = responseFromController.length; i < len; i++) { 3488 var param = responseFromController[i]; 3489 switch (responseFromController[i].Type) { 3490 case FieldTypes.ShortAnswer: 3491 externalIntegrationObject.updateShortAnswerField(param); 3492 break; 3493 case FieldTypes.LongAnswer: 3494 externalIntegrationObject.updateLongAnswerField(param); 3495 break; 3496 case FieldTypes.Checkboxes: 3497 externalIntegrationObject.updateCheckboxField(param); 3498 break; 3499 case FieldTypes.Dropdown: 3500 externalIntegrationObject.updateDropdownField(param); 3501 break; 3502 case FieldTypes.Password: 3503 externalIntegrationObject.updatePasswordField(param); 3504 break; 3505 case FieldTypes.RadioButtons: 3506 externalIntegrationObject.updateRadioField(param); 3507 break; 3508 case FieldTypes.DateTime: 3509 externalIntegrationObject.updateDateField(param); 3510 break; 3511 } 3512 } 3513 } 3514 3515 this.getFormData = function () { 3516 var params = []; 3517 3518 this.appendShortAnswerFields(params); 3519 this.appendCheckboxFields(params); 3520 this.appendRadioFields(params); 3521 this.appendDropdowns(params); 3522 this.appendTextAreaFields(params); 3523 this.appendPasswordFields(params); 3524 3525 return params; 3526 }; 3527 3528 this.createFieldValue = function (fieldID, type, value, externalName) { 3529 return { ID: fieldID, Type: type, Value: value, ExternalName: externalName}; 3530 }; 3531 3532 this.appendShortAnswerFields = function (params) { 3533 var my = this; 3534 $('input[id^="e_"][type="text"]').each(function (i) { 3535 var element = $(this); 3536 params.push(my.createFieldValue(element.attr('id'), FieldTypes.ShortAnswer, element.val(), my.externalSubmissionName(element))); 3537 }); 3538 }; 3539 3540 this.externalSubmissionName = function($element) { 3541 return $element.parents('*[data-external-submission-name]').attr('data-external-submission-name'); 3542 }; 3543 3544 this.updateShortAnswerField = function (param) { 3545 var id = param.ID; 3546 $('#' + param.ID).val(param.Value); 3547 } 3548 3549 this.appendCheckboxFields = function (params) { 3550 var my = this; 3551 $('input[id^="e_"][type="checkbox"]').each(function (index) { 3552 var item = $(this); 3553 var value = item.attr('value'); 3554 var checked = false; 3555 if (item.is(':checked')) { 3556 checked = true; 3557 } 3558 var fieldValue = my.createFieldValue(item.attr('id'), FieldTypes.Checkboxes, value, my.externalSubmissionName(item)); 3559 fieldValue.Checked = checked; 3560 params.push(fieldValue); 3561 }); 3562 }; 3563 3564 this.updateCheckboxField = function (param) { 3565 var id = param.ID; 3566 if (param.Checked == true) 3567 $('#' + param.ID).prop('checked', true); 3568 else 3569 $('#' + param.ID).prop('checked', false); 3570 }; 3571 3572 this.appendRadioFields = function (params) { 3573 var my = this; 3574 $('input[id^="e_"][type="radio"]').each(function (index) { 3575 var item = $(this); 3576 var value = item.attr('value'); 3577 var checked = false; 3578 if (item.is(':checked')) { 3579 checked = true; 3580 } 3581 var fieldValue = my.createFieldValue(item.attr('id'), FieldTypes.RadioButtons, value, my.externalSubmissionName(item)); 3582 fieldValue.Checked = checked; 3583 3584 params.push(fieldValue); 3585 }); 3586 }; 3587 3588 this.updateRadioField = function (param) { 3589 var id = param.ID; 3590 var value = param.Value; 3591 var button = $('input[id^="' + id + '"][value="' + value + '"]'); 3592 button.prop('checked', true); 3593 }; 3594 3595 this.appendDropdowns = function (params) { 3596 var my = this; 3597 $('select[id^="e_"]').each(function (index) { 3598 var item = $(this); 3599 params.push(my.createFieldValue(item.attr('id'), FieldTypes.Dropdown, item.val(), my.externalSubmissionName(item))); 3600 }); 3601 }; 3602 3603 this.updateDropdownField = function (param) { 3604 $('#' + param.ID).val(param.Value); 3605 } 3606 3607 this.appendTextAreaFields = function (params) { 3608 var my = this; 3609 $('textarea[id^="e_"]').each(function (index) { 3610 var element = $(this); 3611 3612 if (element.closest('li.LongAnswer').length > 0) { 3613 params.push(my.createFieldValue(element.attr('id'), FieldTypes.LongAnswer, element.text(), my.externalSubmissionName(element))); 3614 } 3615 }); 3616 }; 3617 3618 this.updateLongAnswerField = function (param) { 3619 $('#' + param.ID).text(param.Value); 3620 } 3621 3622 this.appendPasswordFields = function (params) { 3623 var my = this; 3624 $('input[id^="e_"][type="password"').each(function (i) { 3625 var element = $(this); 3626 params.push(my.createFieldValue(element.attr('id'), FieldTypes.Password, element.val(), my.externalSubmissionName(element))); 3627 }); 3628 } 3629 3630 this.updatePasswordField = function (param) { 3631 // We don't want to update password information with values returned from the remote service. 3632 return; 3633 } 3634 3635 this.updateDateField = function (param) { 3636 var my = this; 3637 var isSpan = (param.Value.indexOf(',') >= 0); 3638 3639 var dateID = param.ID + '_date'; 3640 var timeID = param.ID + '_time'; 3641 var endDateID = param.ID + '_dateSpan'; 3642 var endTimeID = param.ID + '_timeSpan'; 3643 3644 var updateDate = function (selector, val) { 3645 var datePicker = $('#' + selector); 3646 if (datePicker.length == 0) 3647 return; 3648 3649 datePicker.data('tDatePicker').value(val); 3650 }; 3651 3652 var updateTime = function (selector, val) { 3653 var timePicker = $('#' + selector); 3654 if (timePicker.length == 0) 3655 return; 3656 timePicker.data('tTimePicker').value(val); 3657 }; 3658 3659 if (isSpan) { 3660 var dateArray = param.Value.split(','); 3661 var startDate = new Date(dateArray[0]); 3662 var endDate = new Date(dateArray[1]); 3663 3664 updateDate(dateID, startDate); 3665 updateTime(timeID, startDate); 3666 3667 updateDate(endDateID, endDate); 3668 updateTime(endTimeID, endDate); 3669 } else { 3670 var startDate = new Date(param.Value); 3671 updateDate(dateID, startDate); 3672 updateTime(timeID, startDate); 3673 } 3674 } 3675}; 3676
3677// Calls subroutines used to initialize the ExternalIntegration javascript object. 3678ExternalIntegration.prototype.initialize = function () { 3679 this.hookEvents(); 3680}; 3681 3682var CP_DynamicForm_ExternalSubmissionFE = function($) { 3683 3684 var self = this; 3685 3686 3687 self.getExternalSubmissionData = function() { 3688 var $fieldContainers = $('.formFieldContainer'); 3689 var data = {}; 3690 $fieldContainers.each(function (index) { 3691 var $container = $(this); 3692 var externalSubmissionName = self.getExternalSubmissionName($container); 3693 var singleFieldData = self.getSingleFieldData($container); 3694 if (singleFieldData != null) { 3695 data[externalSubmissionName] = self.getSingleFieldData($container); 3696 } 3697 }); 3698 return data; 3699 }; 3700 3701 self.getExternalSubmissionName = function($container) { 3702 return $container.attr('data-external-submission-name'); 3703 }; 3704 3705 self.getSingleFieldData = function($container) { 3706 var self = this; 3707 var result = null; 3708 if ($container.hasClass('ShortAnswer')) { 3709 result = self.submissionDataShortAnswer($container); 3710 } else if ($container.hasClass('LongAnswer')) { 3711 result = self.submissionDataLongAnswer($container); 3712 } else if ($container.hasClass('Checkboxes')) { 3713 result = self.submissionDataCheckboxes($container); 3714 } else if ($container.hasClass('Dropdown')) { 3715 result = self.submissionDataDropdown($container); 3716 } else if ($container.hasClass('RadioButtons')) { 3717 result = self.submissionDataRadioButtons($container); 3718 } else if ($container.hasClass('ReplyEmail')) { 3719 result = self.submissionDataReplyEmail($container); 3720 } else if ($container.hasClass('DateTime')) { 3721 result = self.submissionDataDateTime($container); 3722 } else if ($container.hasClass('DateTimeSpan')) { 3723 result = self.submissionDataDateTimeSpan($container); 3724 } else if ($container.hasClass('Password')) { 3725 result = self.submissionDataPassword($container); 3726 } 3727 3728 return result; 3729 }; 3730 3731 // 3732 // There needs to be one function for each type of field that will be passed to 3733 // an external submission service. 3734 // 3735 3736 self.submissionDataShortAnswer = function($container) { 3737 return $('input[id^=e_]', $container).val(); 3738 }; 3739 3740 self.submissionDataLongAnswer = function($container) { 3741 return $('textarea', $container).html(); 3742 }; 3743 3744 self.submissionDataPassword = function($container) { 3745 return $('input[id^=e_]', $container).val(); 3746 }; 3747 3748 self.submissionDataCheckboxes = function($container) { 3749 var result = []; 3750 var $checkedItems = $('input[type=checkbox]:checked', $container); 3751 $checkedItems.each(function (index) { 3752 result.push($(this).attr('Value')); 3753 }); 3754 return result.join(); 3755 }; 3756 3757 self.submissionDataDropdown = function($container) { 3758 return $('select option:selected').val(); 3759 }; 3760 3761 self.submissionDataRadioButtons = function($container) { 3762 return $('input:radio:checked', $container).val(); 3763 }; 3764 3765 self.submissionDataReplyEmail = function($container) { 3766 return $('input[id^=e_]', $container).val(); 3767 }; 3768 3769 self.isDateTimeValueEmpty = function(val) { 3770 // The telerik controls sometimes have just "0" if the user does not 3771 // enter a value, so this function checks for both an empty value and for "0" 3772 if (val == null || val == '' || val == '0') 3773 return true; 3774 else 3775 return false; 3776 }; 3777 3778 self.submissionDataDateTime = function($container) { 3779 var $dateDiv = $('div.date', $container).not('.time')[0]; 3780 var $timeDiv = $('div.time', $container)[0]; 3781 3782 var date = $('input', $dateDiv).val(); 3783 var time = $('input', $timeDiv).val(); 3784 3785 return formatDateTime(date, time); 3786 }; 3787 3788 self.formatDateTime = function(date, time) { 3789 var dateEmpty = isDateTimeValueEmpty(date); 3790 var timeEmpty = isDateTimeValueEmpty(time); 3791 3792 if (dateEmpty && timeEmpty) 3793 return ''; 3794 else if (!dateEmpty && timeEmpty) 3795 return date; 3796 else if (dateEmpty && !timeEmpty) 3797 return time; 3798 else 3799 return date + ' ' + time; 3800 } 3801 3802 self.submissionDataDateTimeSpan = function($container) { 3803 var $startDateDiv = $('div.date', $container).not('.time')[0]; 3804 var $startTimeDiv = $('div.date.time', $container)[0]; 3805 var startDate = $('input', $startDateDiv).val(); 3806 var startTime = $('input', $startTimeDiv).val(); 3807 3808 var $endDateDiv = $('div.date', $container).not('.time')[1]; 3809 var $endTimeDiv = $('div.date.time', $container)[1]; 3810 var endDate = $('input', $endDateDiv).val(); 3811 var endTime = $('input', $endTimeDiv).val(); 3812 3813 var startDateTime = formatDateTime(startDate, startTime); 3814 var endDateTime = formatDateTime(endDate, endTime); 3815 3816 if (startDateTime == '' && endDateTime == '') 3817 return ''; 3818 3819 return startDateTime + ',' + endDateTime; 3820 }; 3821 3822 3823 return self; 3824}(jQuery); 3825 3826 3827var CP_DynamicForm_PrintSubmission = (function () { 3828 self.StatusCodes = { 3829 Loading: 1, 3830 Success: 2, 3831 Spam: 3, 3832 Timeout: 4 3833 }; 3834 3835 return self; 3836})(); 3837/// <reference path="../../../../Assets/Scripts/FrontEnd.js" /> 3838/// <reference path="../../../../Assets/Scripts/Authentication/PopupBasedAuthentication.js" /> 3839/// <reference path="../../../../Assets/Scripts/Store.js" /> 3840/// <reference path="../../../../Assets/Scripts/Authentication/Authentication.js" /> 3841/// <reference path="../../../../Assets/Scripts/Shared.js" /> 3842 3843window.FormCenter = window.FormCenter || {}; 3844 3845function SaveProgressClass() { 3846 var url; 3847} 3848
3849if (!window.FormCenter.SaveProgress) { 3850 window.FormCenter.SaveProgress = new SaveProgressClass(); 3851} 3852 3853SaveProgressClass.prototype.checkLoggedInStatus = function (event) { 3854 if (event != null) { 3855 event.preventDefault(); 3856 } 3857 3858 submitCheckboxHandler(); 3859 submitRadioHandler(); 3860 submitDateTimeHandler(); 3861 3862 if ($('[type="file"]').length > 0) { 3863 alert($('#hdnFileUploadWarning').val()); 3864 } 3865 3866 var $form = $(document.aspnetForm); 3867 3868 window.FormCenter.SaveProgress.url = null; 3869 3870 window.FormCenter.SaveProgress.url = $(this).data('redirect-url'); 3871 3872 var savedProgressID = $('#hdnSavedProgressID').val(); 3873 3874 var postUrl = '/FormCenter/Home/SaveProgress?formID=' + $('#hdnFormID').val(); 3875 3876 if (savedProgressID != null) { 3877 postUrl = postUrl + '&savedProgressID=' + savedProgressID; 3878 } 3879 3880 $.ajax({ 3881 url: postUrl, 3882 type: 'POST', 3883 contentType: 'application/x-www-form-urlencoded; charset=UTF-8', 3884 data: $(document.aspnetForm).serializeArray(), 3885 success: FormCenter.SaveProgress.savePostCallback, 3886 async: false, 3887 beforeSend: function () { 3888 ajaxPostBackStart('Loading'); 3889 }, 3890 complete: function () { 3891 ajaxPostBackEnd(); 3892 }, 3893 error: function (xhr, textStatus, exception) { 3894 alert('Error: ' + xhr.statusText + '\nStatus: ' + xhr.status); 3895 } 3896 }); 3897}; 3898 3899SaveProgressClass.prototype.savePostCallback = function(response) { 3900 if (response.Successful) { 3901 if (response.LoggedIn) { 3902 if (response.RedirectUrl != null) { 3903 window.FormCenter.SaveProgress.setStorageToShowMessage(); 3904 3905 window.location = response.RedirectUrl; 3906 } 3907 else { 3908 alert(response.Message); 3909 } 3910 } 3911 else { 3912 window.FormCenter.SaveProgress.setStorageToShowMessage(); 3913 window.FormCenter.SaveProgress.url = window.FormCenter.SaveProgress.url + '?savedProgressKey=' + response.Key; 3914 if (response.IsSamlLoginEnabled) { 3915 window.location = '/Admin/Saml/LogonRequest?RelayState=' + window.FormCenter.SaveProgress.url.substring(1); 3916 } 3917 else { 3918 popupSignIn(encodeURI(window.FormCenter.SaveProgress.url), '', FormCenter.SaveProgress.checkLoggedInStatusCallBack); 3919 } 3920 } 3921 } 3922 else { 3923 alert(response.Message); 3924 if (response.hasOwnProperty('FormUnavailable') && response.FormUnavailable) 3925 { 3926 window.location.href = '/FormCenter'; 3927 } 3928 } 3929}; 3930 3931SaveProgressClass.prototype.setStorageToShowMessage = function () { 3932 $.jStorage.set("showSavedMessage" + $('#hdnFormID').val(), true); 3933}; 3934 3935SaveProgressClass.prototype.checkLoggedInStatusCallBack = function () { 3936 3937}; 3938 3939SaveProgressClass.prototype.deleteProgress = function (event) { 3940 event.preventDefault(); 3941 3942 var postUrl = '/FormCenter/Home/DeleteSaveProgress?savedProgressID=' + $(this).attr('data-progressID'); 3943 3944 AJAX(postUrl, 'POST', null, FormCenter.SaveProgress.deleteProgressCallback, true, null, true); 3945}; 3946 3947SaveProgressClass.prototype.deleteProgressCallback = function(response) { 3948 if (response.Successful) { 3949 $('#savedProgressTr' + response.SavedProgressID).remove(); 3950 } 3951}; 3952 3953SaveProgressClass.prototype.init = function () { 3954 if ($.jStorage != null) { 3955 $('#saveFormProgress').unbind().bind({ 3956 click: FormCenter.SaveProgress.checkLoggedInStatus 3957 }); 3958 3959 $('.modern-button.deleteSavedProgress').unbind().bind({ 3960 click: FormCenter.SaveProgress.deleteProgress 3961 }); 3962 3963 var storageKey = "showSavedMessage" + $('#hdnFormID').val(); 3964 3965 var showSavedMessage = $.jStorage.get(storageKey, false); 3966 3967 if (showSavedMessage && window.location.search.indexOf("savedProgressID") > 0) { 3968 $.jStorage.deleteKey(storageKey); 3969 3970 if (window.location.search.indexOf("savedProgressID=-1") == -1) { 3971 alert($('#hdnSavedProgressMessage').val()); 3972 } 3973 } 3974 } 3975}; 3976
3977$(document).ready(FormCenter.SaveProgress.init); 3978; 3979window.pageHandleResponsive = true; 3980 3981$.when(window.Pages.rwdReady).done(function () { 3982 3983 toggleClassMedia("maxWidth600px", ".cpForm:media(this-max-width: 600px)"); 3984 toggleClassMedia("maxWidth515px", "#FormCenterContent:media(this-max-width: 515px)"); 3985 toggleClassMedia("maxWidth485px", "#FormCenterContent:media(this-max-width: 485px)"); 3986 toggleClassMedia("maxWidth440px", ".cpForm:media(this-max-width: 440px)"); 3987 toggleClassMedia("maxWidth395px", "#FormCenterContent:media(this-max-width: 395px)"); 3988 toggleClassMedia("maxWidth380px", ".cpForm:media(this-max-width: 380px)"); 3989}); 3990
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.