1// var nbsp = 160; // non-breaking space char 2var node_text = 3; // DOM text node-type 3var emptyString = /^\s*$/ ; 4var global_valfield; // retain valfield for timer thread 5 6// -------------------------------------------- 7// trim 8// Trim leading/trailing whitespace off string 9// -------------------------------------------- 10 11function trim(str) 12{ 13 return str.replace(/^\s+|\s+$/g, ''); 14} 15 16 17// -------------------------------------------- 18// setfocus 19// Delayed focus setting to get around IE bug 20// -------------------------------------------- 21 22function setFocusDelayed() 23{ 24 global_valfield.focus(); 25} 26 27function setfocus(valfield) 28{ 29 // save valfield in global variable so value retained when routine exits 30 global_valfield = valfield; 31 setTimeout( 'setFocusDelayed()', 100 ); 32} 33 34 35// -------------------------------------------- 36// msg 37// Display warn/error message in HTML element. 38// commonCheck routine must have previously been called 39// -------------------------------------------- 40 41function msg(fld, // id of element to display message in 42 msgtype, // class to give element ("warn" or "error") 43 message) // string to display 44{ 45 console.log(fld); 46 // setting an empty string can give problems if later set to a 47 // non-empty string, so ensure a space present. (For Mozilla and Opera one could 48 // simply use a space, but IE demands something more, like a non-breaking space.) 49 var dispmessage; 50 if (emptyString.test(message)) 51 dispmessage = ''; 52 else 53 dispmessage = message; 54 var elem = document.getElementById(fld); 55 // console.log(dispmessage); 56 // elem.firstChild.nodeValue = dispmessage; 57 jQuery('#'+fld).text(dispmessage); 58 59 elem.className = msgtype; // set the CSS class to adjust appearance of message 60} 61 62// -------------------------------------------- 63// commonCheck 64// Common code for all validation routines to: 65// (a) check for older / less-equipped browsers 66// (b) check if empty fields are required 67// Returns true (validation passed), 68// false (validation failed) or 69// proceed (don't know yet) 70// -------------------------------------------- 71 72var proceed = 2; 73 74function commonCheck(valfield, infofield, required) 75{ 76 if (!document.getElementById) { 77 return true; 78 } 79 80 var elem = document.getElementById(infofield); 81 if (elem == null) { 82 return true; 83 } 84 85 if (emptyString.test(valfield.value)) { 86 if (required) { 87 msg(infofield, "errorNode", "Required"); 88 jQuery('#' + infofield).show(); 89 jQuery(valfield).css('border', '1px solid #FF0000'); 90 return false; 91 } else { 92 msg(infofield, "warn", ""); 93 jQuery('#' + infofield).hide(); 94 jQuery(valfield).css('border', ''); 95 return true; 96 } 97 } 98 99 jQuery('#' + infofield).hide(); 100 return proceed; 101} 102 103// -------------------------------------------- 104// greenLight 105// Simply removes red borders assuming all is ok 106// Returns void 107// -------------------------------------------- 108 109function greenLight (valfield) // element to be green lit 110{ 111 jQuery(valfield).css('border', '1px solid #008000'); 112} 113 114// -------------------------------------------- 115// redLight 116// Simply makes border red 117// Returns void 118// -------------------------------------------- 119 120function redLight (valfield) // element to be red lit 121{ 122 jQuery(valfield).css('border', '1px solid #FF0000'); 123} 124 125// -------------------------------------------- 126// validateEmailAddress 127// Validate if e-mail address 128// Returns true if so (and also if could not be executed because of old browser) 129// -------------------------------------------- 130 131function validateEmailAddress (valfield, // element to be validated 132 infofield, // id of element to receive info/error msg 133 required) // true if required 134{ 135 if (required) { 136 var stat = commonCheck (valfield, infofield, required); 137 if (stat !== proceed) return stat; 138 } 139 var tfld = trim(valfield.value); // value of field with whitespace trimmed off 140 if (required || tfld.length > 0) { 141 var email = /^[^@]+@[^@.]+\.[^@]*\w\w$/; 142 if (!email.test(tfld)) { 143 msg(infofield, "errorNode", "Invalid email"); 144 jQuery('#' + infofield).show(); 145 // setfocus(valfield); 146 redLight(valfield); 147 return false;
148 } 149 150 var email2 = /^[A-Za-z][\w.-]+@\w[\w.-]+\.[\w.-]*[A-Za-z][A-Za-z]$/; 151 if (!email2.test(tfld)) { 152 msg(infofield, "errorNode", "Malformed email"); 153 jQuery('#' + infofield).show(); 154 redLight(valfield); 155 return false; 156 } 157 } else { 158 msg (infofield, "errorNode", ""); 159 } 160 greenLight(valfield); 161 return true; 162} 163 164// -------------------------------------------- 165// validatePhone 166// Validate telephone number 167// Returns true if so (and also if could not be executed because of old browser) 168// Permits spaces, hyphens, brackets and leading + 169// -------------------------------------------- 170 171function validatePhone (valfield, // element to be validated 172 infofield, // id of element to receive info/error msg 173 required) // true if required 174{ 175 if (required) { 176 var stat = commonCheck (valfield, infofield, required); 177 if (stat !== proceed) return stat; 178 } 179 180 var tfld = trim(valfield.value); // value of field with whitespace trimmed off 181 if (required || tfld.length > 0) { 182 var phone1 = /^\+?[0-9 .()-]+[0-9]$/ ; 183 if (!phone1.test(tfld)) { 184 msg (infofield, "errorNode", "Invalid phone"); 185 jQuery('#' + infofield).show(); 186 // setfocus(valfield); 187 redLight(valfield); 188 return false; 189 } 190 191 //Checks for 555 area codes (movie phones) 192 var filteredPhone = valfield.value.replace(/[^0-9]/g, ""); 193 var moviePhone = /^(555)(.*)$/; 194 if (moviePhone.test(filteredPhone)) { 195 msg (infofield, "errorNode", "Invalid area code"); 196 jQuery('#' + infofield).show(); 197 // setfocus(valfield); 198 redLight(valfield); 199 return false; 200 } 201 202 var numdigits = 0; 203 for (var j=0; j<tfld.length; j++) 204 if (tfld.charAt(j)>='0' && tfld.charAt(j)<='9') numdigits++; 205 206 if (numdigits<7) { 207 msg (infofield, "errorNode", "Only " + numdigits + " digits: please correct."); 208 jQuery('#' + infofield).show(); 209 // setfocus(valfield); 210 redLight(valfield); 211 return false; 212 } 213 214 if (numdigits>14) { 215 msg (infofield, "errorNode", asterisk + numdigits + " digits?"); 216 jQuery('#' + infofield).show(); 217 redLight(valfield); 218 return false; 219 } else { 220 if (numdigits<10) { 221 msg (infofield, "errorNode", asterisk + numdigits + " digits: no area code?"); 222 jQuery('#' + infofield).show(); 223 redLight(valfield); 224 return false; 225 } else { 226 msg (infofield, "errorNode", ""); 227 jQuery('#' + infofield).hide(); 228 } 229 } 230 } 231 greenLight(valfield); 232 return true; 233} 234 235// -------------------------------------------- 236// validateAge 237// Validate person's age 238// Returns true if OK 239// -------------------------------------------- 240 241function validateAge (valfield, // element to be validated 242 infofield, // id of element to receive info/error msg 243 required) // true if required 244{ 245 var stat = commonCheck (valfield, infofield, required); 246 if (stat !== proceed) { 247 if (!required) { 248 jQuery('#' + infofield).hide(); 249 greenLight(valfield); 250 } 251 return stat; 252 } 253 254 var tfld = trim(valfield.value); 255 var ageRE = /^[0-9]{1,3}$/ 256 if (!ageRE.test(tfld)) { 257 msg (infofield, "errorNode", "Invalid age"); 258 jQuery('#' + infofield).show(); 259 redLight(valfield); 260 // setfocus(valfield); 261 return false; 262 } 263 264 if (tfld>125) { 265 msg (infofield, "errorNode", "Invalid age"); 266 jQuery('#' + infofield).show(); 267 redLight(valfield); 268 } else { 269 if (tfld<9) { 270 msg (infofield, "errorNode", "Invalid age"); 271 jQuery('#' + infofield).show(); 272 redLight(valfield); 273 } else { 274 msg (infofield, "errorNode", ""); 275 jQuery('#' + infofield).hide(); 276 greenLight(valfield); 277 } 278 } 279 280 return true; 281} 282 283// -------------------------------------------- 284// validateZip 285// Validate zipcode 286// Returns true if OK 287// -------------------------------------------- 288 289function validateZip(valfield, infofield, required) 290{ 291 var stat = commonCheck(valfield, infofield, required); 292 if (stat !== proceed) return stat; 293 294 var zfld = trim(valfield.value); 295 var zipRE = /^[0-9]{5}$/; 296 297 // Optional zip fields are valid when left blank. If supplied, they must
298 // still contain exactly five digits. 299 if (!required && zfld.length === 0) { 300 msg(infofield, "errorNode", ""); 301 jQuery('#' + infofield).hide(); 302 greenLight(valfield); 303 return true; 304 } 305 306 if (!zipRE.test(zfld)) { 307 msg(infofield, "errorNode", "Invalid zip"); 308 jQuery('#' + infofield).show(); 309 redLight(valfield); 310 return false; 311 } 312 313 msg(infofield, "errorNode", ""); 314 jQuery('#' + infofield).hide(); 315 greenLight(valfield); 316 return true; 317} 318 319function validateIntZip (valfield, // element to be validated 320 infofield, // id of element to receive info/error msg 321 required) // true if required 322{ 323 if (required) { 324 var stat = commonCheck (valfield, infofield, required); 325 if (stat !== proceed) return stat; 326 } 327 var zfld = trim(valfield.value); 328 var ageRE = /^[a-zA-Z0-9\s\-]{1,15}$/ 329 if (required || zfld.length > 0) { 330 if (!ageRE.test(zfld)) { 331 msg (infofield, "errorNode", "Invalid zip"); 332 jQuery('#' + infofield).show(); 333 redLight(valfield); 334 return false; 335 } 336 } 337 msg (infofield, "errorNode", ""); 338 jQuery('#' + infofield).hide(); 339 greenLight(valfield); 340 return true; 341} 342 343// *** -------------------------------------------- 344// validateName 345// Validate the input tag for Name 346// Returns true if OK 347// -------------------------------------------- 348 349function validateName(valfield, // element to be validated 350 infofield, // id of element to receive info/error msg 351 required ) 352{ 353 if (required) { 354 var stat = commonCheck (valfield, infofield, required); 355 if (stat !== proceed) return stat; 356 } 357 var tfld = trim(valfield.value); 358 if (required || tfld.length > 0) { 359 if(tfld.length < 2) { 360 msg(infofield,"errorNode", "Must be at least 2 characters"); 361 jQuery('#' + infofield).show(); 362 // setfocus(valfield); 363 redLight(valfield); 364 return false; 365 } 366 } 367 msg (infofield, "errorNode", ""); 368 jQuery('#' + infofield).hide(); 369 greenLight(valfield); 370 return true; 371} 372 373// *** -------------------------------------------- 374// validateSchedulerDate 375// Validate the CTC Scheduler dateSelect 376// Returns true if OK 377// -------------------------------------------- 378 379function validateSchedulerDate(valfield, infofield, required) 380{ 381 var radioName = 'ctc_scheduler_date'; 382 var isoRegex = /^\d{4}-\d{2}-\d{2}$/; 383 384 var $selected = jQuery('input[name="' + radioName + '"]:checked'); 385 var $dateField = jQuery('.dayBtn-datepicker').first(); 386 var schedulerConfig = getSchedulerConfig(); 387 var holidays = schedulerConfig.holidays || []; 388 389 if (!$selected.length) { 390 if (required) { 391 msg(infofield, "errorNode", "Required"); 392 jQuery('#' + infofield).show(); 393 redLight(jQuery('input[name="' + radioName + '"]')); 394 return false; 395 } 396 397 msg(infofield, "errorNode", ""); 398 jQuery('#' + infofield).hide(); 399 return true; 400 } 401 402 var isCustomOption = $selected.closest('.dayBtn-picker').length > 0; 403 404 if (isCustomOption) { 405 var dateVal = $dateField.val(); 406 407 if (!dateVal) { 408 msg(infofield, "errorNode", "Please select a date"); 409 jQuery('#' + infofield).show(); 410 redLight($dateField); 411 return false; 412 } 413 414 if (!isoRegex.test(dateVal)) { 415 msg(infofield, "errorNode", "Invalid date"); 416 jQuery('#' + infofield).show(); 417 redLight($dateField); 418 return false; 419 } 420 421 var isHoliday = holidays.indexOf(dateVal) !== -1; 422 423 if (isHoliday) { 424 msg(infofield, "errorNode", "Selected date is unavailable"); 425 jQuery('#' + infofield).show(); 426 redLight($dateField); 427 return false; 428 } 429 430 if (!getScheduleWindowForDate(dateVal)) { 431 msg(infofield, "errorNode", "Selected date is unavailable"); 432 jQuery('#' + infofield).show(); 433 redLight($dateField); 434 return false;
435 } 436 437 msg(infofield, "errorNode", ""); 438 jQuery('#' + infofield).hide(); 439 greenLight($dateField); 440 return true; 441 } 442 443 var value = $selected.val(); 444 445 if (!isoRegex.test(value)) { 446 msg(infofield, "errorNode", "Invalid date"); 447 jQuery('#' + infofield).show(); 448 redLight($selected); 449 return false; 450 } 451 452 msg(infofield, "errorNode", ""); 453 jQuery('#' + infofield).hide(); 454 greenLight($selected); 455 return true; 456} 457 458function validateSchedulerTime(valfield, infofield, required) 459{ 460 var radioName = 'ctc_scheduler_time'; 461 var $selected = jQuery('input[name="' + radioName + '"]:checked'); 462 var $all = jQuery('input[name="' + radioName + '"]'); 463 464 if (!$selected.length) { 465 if (required) { 466 msg(infofield, "errorNode", "Required"); 467 jQuery('#' + infofield).show(); 468 redLight($all); 469 return false; 470 } 471 472 msg(infofield, "errorNode", ""); 473 jQuery('#' + infofield).hide(); 474 return true; 475 } 476 477 if ($selected.prop('disabled')) { 478 msg(infofield, "errorNode", "Please select an available time"); 479 jQuery('#' + infofield).show(); 480 redLight($all); 481 return false; 482 } 483 484 msg(infofield, "errorNode", ""); 485 jQuery('#' + infofield).hide(); 486 greenLight($selected); 487 return true; 488} 489 490var schedulerFallbackConfig = null; 491var schedulerNearbyAvailabilityExhausted = false; 492 493 494function safeParseSchedulerJson(rawValue, fallbackValue) { 495 if (typeof rawValue === 'undefined' || rawValue === null || rawValue === '') { 496 return fallbackValue; 497 } 498 499 if (typeof rawValue === 'object') { 500 return rawValue; 501 } 502 503 try { 504 return JSON.parse(rawValue); 505 } catch (e) { 506 return fallbackValue; 507 } 508} 509 510function readSchedulerConfigFromElement($element, attrNames) { 511 if (!$element || !$element.length) { 512 return null; 513 } 514 515 return { 516 holidays: safeParseSchedulerJson($element.attr(attrNames.holidays), []), 517 schedule: safeParseSchedulerJson($element.attr(attrNames.schedule), {}), 518 specialSchedule: safeParseSchedulerJson($element.attr(attrNames.specialSchedule), {}) 519 }; 520} 521 522function getFallbackSchedulerConfig() { 523 if (schedulerFallbackConfig !== null) { 524 return schedulerFallbackConfig; 525 } 526 527 var $group = jQuery('.dayBtn-group').first(); 528 schedulerFallbackConfig = readSchedulerConfigFromElement($group, { 529 holidays: 'data-holidays', 530 schedule: 'data-schedule', 531 specialSchedule: 'data-special-schedule' 532 }) || { 533 holidays: [], 534 schedule: {}, 535 specialSchedule: {} 536 }; 537 538 return schedulerFallbackConfig; 539} 540 541function getSelectedFacilitySchedulerConfig() { 542 var $select = jQuery('select[name="facilityChoice"]').first(); 543 544 if (!$select.length || !$select.val() || $select.val() === '0') { 545 return null; 546 } 547 548 var $option = $select.find('option:selected').first(); 549 550 if (!$option.length) { 551 return null; 552 } 553 554 if ($option.attr('data-scheduler-config') !== '1') { 555 if (getSchedulerMode() === 'homepage') { 556 return { 557 holidays: [], 558 schedule: {}, 559 specialSchedule: {} 560 }; 561 } 562 563 return null; 564 } 565 566 return readSchedulerConfigFromElement($option, { 567 holidays: 'data-scheduler-holidays', 568 schedule: 'data-scheduler-schedule', 569 specialSchedule: 'data-scheduler-special-schedule' 570 }); 571} 572 573function getSchedulerConfig() { 574 return getSelectedFacilitySchedulerConfig() || getFallbackSchedulerConfig(); 575} 576 577function getSchedulerController() { 578 return jQuery('.ctc-scheduler-controller').first(); 579} 580 581function getSchedulerMode() { 582 var $controller = getSchedulerController(); 583 return $controller.length ? String($controller.attr('data-ctc-scheduler-mode') || '') : ''; 584} 585 586function getSchedulerWrapper() { 587 var $controller = getSchedulerController(); 588 589 if ($controller.length) { 590 var $wrapper = $controller.closest('.ctcscheduler_mainWrapper'); 591 if ($wrapper.length) { 592 return $wrapper; 593 } 594 } 595 596 return jQuery('.ctcscheduler_mainWrapper').first(); 597} 598 599function initializeSchedulerWrapperState() { 600 var mode = getSchedulerMode(); 601 var $wrapper = getSchedulerWrapper(); 602 603 if (!$wrapper.length) { 604 return; 605 } 606 607 $wrapper 608 .removeClass('ctc-scheduler-mode-homepage ctc-scheduler-mode-lp') 609 .addClass(mode === 'homepage' ? 'ctc-scheduler-mode-homepage' : (mode === 'lp' ? 'ctc-scheduler-mode-lp' : '')); 610 611 if (mode === 'lp') { 612 jQuery('#scheduler_shortname_selector').hide(); 613 } else if (mode === 'homepage') { 614 jQuery('#scheduler_shortname_selector').show(); 615 } 616} 617 618function getFacilitySchedulerStatusFromOption($option) { 619 if (!$option || !$option.length) { 620 return null; 621 } 622 623 if ($option.attr('data-scheduler-config') !== '1') { 624 return { 625 schedulerEnabled: '0', 626 holdAdmits: false, 627 noHours: true, 628 missingSchedulerConfig: true 629 }; 630 } 631 632 return { 633 schedulerEnabled: $option.attr('data-scheduler-enabled'), 634 holdAdmits: $option.attr('data-scheduler-hold-admits') === '1',
635 noHours: $option.attr('data-scheduler-no-hours') === '1' 636 }; 637} 638 639function isFacilitySchedulerStatusAvailable(status) { 640 if (!status) { 641 return false; 642 } 643 644 if (String(status.schedulerEnabled || '') !== '1') { 645 return false; 646 } 647 648 return !status.holdAdmits && !status.noHours; 649} 650 651function isFacilityOptionSchedulerAvailable($option) { 652 return isFacilitySchedulerStatusAvailable(getFacilitySchedulerStatusFromOption($option)); 653} 654 655function getSelectedFacilitySchedulerStatus() { 656 var $select = jQuery('select[name="facilityChoice"]').first(); 657 658 if (!$select.length || !$select.val() || $select.val() === '0') { 659 return null; 660 } 661 662 return getFacilitySchedulerStatusFromOption($select.find('option:selected').first()); 663} 664 665function shouldShowSchedulerUnavailableMessage() { 666 if (getSchedulerMode() !== 'homepage') { 667 return false; 668 } 669 670 if (schedulerNearbyAvailabilityExhausted) { 671 return true; 672 } 673 674 var status = getSelectedFacilitySchedulerStatus(); 675 676 if (!status) { 677 return false; 678 } 679 680 return !isFacilitySchedulerStatusAvailable(status); 681} 682 683function getNearbyFacilityOptions() { 684 var $select = jQuery('select[name="facilityChoice"]').first(); 685 686 if (!$select.length) { 687 return jQuery(); 688 } 689 690 return $select.find('option[data-scheduler-nearby="1"]').slice(0, 5); 691} 692 693function selectNearbyFacilityWithAvailability() { 694 schedulerNearbyAvailabilityExhausted = false; 695 696 if (getSchedulerMode() !== 'homepage') { 697 return false; 698 } 699 700 var $select = jQuery('select[name="facilityChoice"]').first(); 701 var $nearbyOptions = getNearbyFacilityOptions(); 702 703 if (!$select.length || !$nearbyOptions.length) { 704 return false; 705 } 706 707 var $selected = $select.find('option:selected').first(); 708 709 if (!$selected.length || $selected.attr('data-scheduler-nearby') !== '1') { 710 return false; 711 } 712 713 if (isFacilityOptionSchedulerAvailable($selected)) { 714 return false; 715 } 716 717 var selectedOption = null; 718 719 $nearbyOptions.each(function() { 720 var $option = jQuery(this); 721 722 if (selectedOption === null && isFacilityOptionSchedulerAvailable($option)) { 723 selectedOption = this; 724 } 725 }); 726 727 if (selectedOption) { 728 $select.prop('selectedIndex', selectedOption.index); 729 return true; 730 } 731 732 schedulerNearbyAvailabilityExhausted = true; 733 return false; 734} 735 736function isSchedulerCurrentlyUnavailable() { 737 var $wrapper = getSchedulerWrapper(); 738 return $wrapper.length && $wrapper.hasClass('ctc-scheduler-unavailable'); 739} 740 741function updateSchedulerUnavailableState() { 742 var $wrapper = getSchedulerWrapper(); 743 744 if (!$wrapper.length) { 745 return false; 746 } 747 748 var unavailable = shouldShowSchedulerUnavailableMessage(); 749 $wrapper 750 .toggleClass('ctc-scheduler-unavailable', unavailable) 751 .toggleClass('ctc-scheduler-nearby-unavailable', unavailable && schedulerNearbyAvailabilityExhausted); 752 753 if (unavailable) { 754 clearSchedulerSelections(); 755 } 756 757 return unavailable; 758} 759 760function writeSchedulerConfigToDateControls(config) { 761 var $group = jQuery('.dayBtn-group').first(); 762 var $dateField = jQuery('.dayBtn-datepicker').first(); 763 764 if (!$group.length) { 765 return; 766 } 767 768 var holidaysJson = JSON.stringify(config.holidays || []); 769 var scheduleJson = JSON.stringify(config.schedule || {}); 770 var specialScheduleJson = JSON.stringify(config.specialSchedule || {}); 771 772 $group 773 .attr('data-holidays', holidaysJson) 774 .attr('data-schedule', scheduleJson) 775 .attr('data-special-schedule', specialScheduleJson) 776 .data('holidays', config.holidays || []) 777 .data('schedule', config.schedule || {}) 778 .data('special-schedule', config.specialSchedule || {}); 779 780 $dateField 781 .attr('data-holidays', holidaysJson) 782 .attr('data-schedule', scheduleJson) 783 .attr('data-special-schedule', specialScheduleJson) 784 .data('holidays', config.holidays || []) 785 .data('schedule', config.schedule || {}) 786 .data('special-schedule', config.specialSchedule || {}); 787} 788 789function getTodayIsoDate() { 790 var today = new Date(); 791 return ( 792 today.getFullYear() + '-' + 793 String(today.getMonth() + 1).padStart(2, '0') + '-' + 794 String(today.getDate()).padStart(2, '0') 795 ); 796} 797 798function addDaysToIsoDate(isoDate, daysToAdd) { 799 var parts = String(isoDate).split('-'); 800 var d = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10)); 801 d.setDate(d.getDate() + daysToAdd); 802 803 return ( 804 d.getFullYear() + '-' + 805 String(d.getMonth() + 1).padStart(2, '0') + '-' + 806 String(d.getDate()).padStart(2, '0') 807 ); 808} 809 810function formatSchedulerDateLabel(isoDate) { 811 var parts = String(isoDate).split('-'); 812 var d = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10)); 813 814 return d.toLocaleDateString('en-US', { 815 weekday: 'short', 816 month: 'short', 817 day: 'numeric' 818 }); 819} 820 821function getSelectedSchedulerDate() { 822 var $selectedDateRadio = jQuery('input[name="ctc_scheduler_date"]:checked'); 823 var $customDateField = jQuery('.dayBtn-datepicker').first(); 824 825 if (!$selectedDateRadio.length) { 826 return ''; 827 } 828 829 if ($selectedDateRadio.closest('.dayBtn-picker').length) { 830 return $customDateField.val() || ''; 831 } 832 833 return $selectedDateRadio.val() || ''; 834} 835 836function isoToMonthDayKey(isoDate) { 837 var parts = String(isoDate).split('-'); 838 if (parts.length !== 3) { 839 return ''; 840 } 841 842 return parseInt(parts[1], 10) + '/' + parseInt(parts[2], 10) + '/' + parseInt(parts[0], 10); 843} 844 845function isoToDayKey(isoDate) { 846 var parts = String(isoDate).split('-'); 847 if (parts.length !== 3) { 848 return ''; 849 } 850 851 var d = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10)); 852 var keys = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; 853 return keys[d.getDay()]; 854} 855 856function parse24HourTimeToMinutes(value) { 857 var match = String(value).match(/^(\d{1,2}):(\d{2})$/); 858 if (!match) { 859 return null; 860 } 861 862 var hour = parseInt(match[1], 10); 863 var minute = parseInt(match[2], 10); 864 865 if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { 866 return null; 867 } 868 869 return (hour * 60) + minute; 870} 871 872function parseSchedulerTimeToMinutes(timeValue) { 873 var match = String(timeValue).match(/^(\d{1,2}):(\d{2}) ([AP]M)$/); 874 if (!match) { 875 return null; 876 } 877 878 var hour = parseInt(match[1], 10); 879 var minute = parseInt(match[2], 10); 880 var meridiem = match[3]; 881 882 if (meridiem === 'AM') { 883 if (hour === 12) { 884 hour = 0; 885 } 886 } else { 887 if (hour !== 12) { 888 hour += 12; 889 } 890 } 891 892 return (hour * 60) + minute; 893} 894 895function getScheduleWindowForDateFromConfig(isoDate, config) { 896 config = config || { 897 holidays: [], 898 schedule: {}, 899 specialSchedule: {} 900 }; 901 902 var mdKey = isoToMonthDayKey(isoDate); 903 var dayKey = isoToDayKey(isoDate); 904 var window = null; 905 906 if (config.schedule && config.schedule[dayKey]) { 907 window = config.schedule[dayKey]; 908 } 909 910 if (config.specialSchedule && Object.prototype.hasOwnProperty.call(config.specialSchedule, mdKey)) { 911 var specialWindow = config.specialSchedule[mdKey]; 912 913 if ( 914 jQuery.isArray(specialWindow) && 915 specialWindow.length === 2 && 916 specialWindow[0] !== '' && 917 specialWindow[1] !== '' 918 ) { 919 window = specialWindow; 920 } else { 921 window = null; 922 } 923 } 924 925 if (config.holidays && config.holidays.indexOf(isoDate) !== -1) { 926 return null; 927 } 928 929 return window; 930} 931 932function getScheduleWindowForDate(isoDate) { 933 return getScheduleWindowForDateFromConfig(isoDate, getSchedulerConfig()); 934} 935 936function getNextSchedulerDates(count, config) { 937 var dates = []; 938 var $dateField = jQuery('.dayBtn-datepicker').first(); 939 var maxDate = $dateField.attr('max') || ''; 940 var cursor = getTodayIsoDate(); 941 var daysChecked = 0; 942 943 while (dates.length < count && daysChecked < 62) { 944 cursor = addDaysToIsoDate(cursor, 1); 945 daysChecked++; 946 947 if (maxDate && cursor > maxDate) { 948 break; 949 } 950 951 if (getScheduleWindowForDateFromConfig(cursor, config)) { 952 dates.push({
953 value: cursor, 954 display: formatSchedulerDateLabel(cursor) 955 }); 956 } 957 } 958 959 return dates; 960} 961 962function clearSchedulerSelections() { 963 jQuery('input[name="ctc_scheduler_date"]').prop('checked', false); 964 jQuery('.dayBtn-datepicker').val(''); 965 jQuery('input[name="ctc_scheduler_time"]').prop('checked', false); 966 967 resetCustomDateOption(false); 968 969 msg('ctc_scheduler_dateError', "errorNode", ""); 970 jQuery('#ctc_scheduler_dateError').hide(); 971 msg('ctc_scheduler_timeError', "errorNode", ""); 972 jQuery('#ctc_scheduler_timeError').hide(); 973} 974 975function refreshSchedulerDateButtons(config) { 976 var $group = jQuery('.dayBtn-group').first(); 977 var $dateButtons = $group.find('label.dayBtn').not('.dayBtn-picker'); 978 var dates = getNextSchedulerDates(2, config); 979 980 $dateButtons.each(function(index) { 981 var $button = jQuery(this); 982 var $input = $button.find('input[type="radio"]').first(); 983 var $span = $button.find('span').first(); 984 var dateInfo = dates[index]; 985 986 if (dateInfo) { 987 $input.val(dateInfo.value).prop('disabled', false).prop('checked', false); 988 $button.removeClass('disabled'); 989 $span.text(dateInfo.display); 990 } else { 991 $input.val('').prop('disabled', true).prop('checked', false); 992 $button.addClass('disabled'); 993 $span.text(index === 0 ? 'No dates available' : ''); 994 } 995 }); 996} 997 998function refreshSchedulerForSelectedFacility(clearSelections, autoSelectNearby) { 999 if (autoSelectNearby) { 1000 selectNearbyFacilityWithAvailability(); 1001 } else { 1002 schedulerNearbyAvailabilityExhausted = false; 1003 } 1004 1005 var config = getSchedulerConfig(); 1006 1007 writeSchedulerConfigToDateControls(config); 1008 refreshSchedulerDateButtons(config); 1009 1010 if (clearSelections) { 1011 clearSchedulerSelections(); 1012 } 1013 1014 if (updateSchedulerUnavailableState()) { 1015 return; 1016 } 1017 1018 updateSchedulerTimeAvailability(); 1019} 1020 1021function resetCustomDateOption(selectPicker) { 1022 var $group = jQuery('.dayBtn-group').first(); 1023 var $pickerLabel = $group.find('.dayBtn-picker').first(); 1024 var $radio = $pickerLabel.find('input[type="radio"]'); 1025 var $span = $pickerLabel.find('span'); 1026 var $dateInput = $group.find('.dayBtn-datepicker').first(); 1027 1028 if (typeof selectPicker === 'undefined') { 1029 selectPicker = true; 1030 } 1031 1032 $dateInput.val(''); 1033 $radio.val('other').prop('checked', selectPicker); 1034 $span.text('Pick another date'); 1035} 1036 1037var schedulerClosedTodayAlertShown = false; 1038 1039function updateSchedulerTimeAvailability() { 1040 var selectedDate = getSelectedSchedulerDate(); 1041 var $timeInputs = jQuery('input[name="ctc_scheduler_time"]'); 1042 1043 if (isSchedulerCurrentlyUnavailable()) { 1044 schedulerClosedTodayAlertShown = false; 1045 $timeInputs.prop('checked', false).prop('disabled', true).closest('.timeBtn').addClass('disabled'); 1046 return; 1047 } 1048 1049 if (!selectedDate) { 1050 schedulerClosedTodayAlertShown = false; 1051 $timeInputs.each(function() { 1052 jQuery(this) 1053 .prop('disabled', false) 1054 .prop('checked', false) 1055 .closest('.timeBtn') 1056 .removeClass('disabled'); 1057 }); 1058 return; 1059 } 1060 1061 var window = getScheduleWindowForDate(selectedDate); 1062 1063 var today = new Date(); 1064 var todayIso = 1065 today.getFullYear() + '-' + 1066 String(today.getMonth() + 1).padStart(2, '0') + '-' + 1067 String(today.getDate()).padStart(2, '0'); 1068 1069 var isToday = (selectedDate === todayIso); 1070 var currentMinutes = (today.getHours() * 60) + today.getMinutes(); 1071 1072 var openMinutes = null; 1073 var closeMinutes = null; 1074 1075 if (window && window.length === 2) { 1076 openMinutes = parse24HourTimeToMinutes(window[0]); 1077 closeMinutes = parse24HourTimeToMinutes(window[1]); 1078 } 1079 1080 $timeInputs.each(function() { 1081 var $input = jQuery(this); 1082 var timeMinutes = parseSchedulerTimeToMinutes($input.val()); 1083 var disableThis = false; 1084 1085 if (openMinutes === null || closeMinutes === null || timeMinutes === null) { 1086 disableThis = true; 1087 } else { 1088 if (timeMinutes < openMinutes || timeMinutes >= closeMinutes) { 1089 disableThis = true; 1090 } 1091 1092 if (isToday && timeMinutes <= currentMinutes) { 1093 disableThis = true; 1094 } 1095 } 1096 1097 $input.prop('disabled', disableThis); 1098 $input.closest('.timeBtn').toggleClass('disabled', disableThis); 1099 1100 if (disableThis && $input.is(':checked')) { 1101 $input.prop('checked', false); 1102 } 1103 }); 1104 1105 if (isToday && (openMinutes === null || closeMinutes === null)) { 1106 if (!schedulerClosedTodayAlertShown) { 1107 schedulerClosedTodayAlertShown = true; 1108 alert('This location is closed today.'); 1109 } 1110 } else { 1111 schedulerClosedTodayAlertShown = false;
1112 } 1113} 1114 1115jQuery(document).on('click', '.dayBtn-picker', function(e) { 1116 e.preventDefault(); 1117 1118 var $pickerBtn = jQuery(this); 1119 var $group = $pickerBtn.closest('.dayBtn-group'); 1120 var $radio = $pickerBtn.find('input[type="radio"]'); 1121 var $dateInput = $group.find('.dayBtn-datepicker').first(); 1122 1123 $radio.prop('checked', true).trigger('change'); 1124 1125 if ($dateInput.length) { 1126 if (typeof $dateInput[0].showPicker === 'function') { 1127 $dateInput[0].showPicker(); 1128 } else { 1129 $dateInput.trigger('focus').trigger('click'); 1130 } 1131 } 1132}); 1133 1134jQuery(document).on('change', '.dayBtn-datepicker', function() { 1135 var $dateInput = jQuery(this); 1136 var selectedDate = $dateInput.val(); 1137 var infofield = 'ctc_scheduler_dateError'; 1138 var schedulerConfig = getSchedulerConfig(); 1139 var holidays = schedulerConfig.holidays || []; 1140 var minDate = $dateInput.attr('min') || ''; 1141 var maxDate = $dateInput.attr('max') || ''; 1142 var $group = $dateInput.closest('.dayBtn-group'); 1143 var $pickerLabel = $group.find('.dayBtn-picker').first(); 1144 var $radio = $pickerLabel.find('input[type="radio"]'); 1145 var $span = $pickerLabel.find('span'); 1146 1147 if (!selectedDate) { 1148 return; 1149 } 1150 1151 var isoRegex = /^\d{4}-\d{2}-\d{2}$/; 1152 1153 if (!isoRegex.test(selectedDate)) { 1154 msg(infofield, "errorNode", "Invalid date"); 1155 jQuery('#' + infofield).show(); 1156 redLight($dateInput); 1157 resetCustomDateOption(); 1158 updateSchedulerTimeAvailability(); 1159 return; 1160 } 1161 1162 if (minDate && selectedDate < minDate) { 1163 msg(infofield, "errorNode", "Invalid date"); 1164 jQuery('#' + infofield).show(); 1165 redLight($dateInput); 1166 resetCustomDateOption(); 1167 updateSchedulerTimeAvailability(); 1168 return; 1169 } 1170 1171 if (maxDate && selectedDate > maxDate) { 1172 msg(infofield, "errorNode", "Invalid date"); 1173 jQuery('#' + infofield).show(); 1174 redLight($dateInput); 1175 resetCustomDateOption(); 1176 updateSchedulerTimeAvailability(); 1177 return; 1178 } 1179 1180 var parts = selectedDate.split('-'); 1181 var year = parseInt(parts[0], 10); 1182 var month = parseInt(parts[1], 10); 1183 var day = parseInt(parts[2], 10); 1184 1185 var d = new Date(year, month - 1, day); 1186 1187 if ( 1188 d.getFullYear() !== year || 1189 d.getMonth() !== (month - 1) || 1190 d.getDate() !== day 1191 ) { 1192 msg(infofield, "errorNode", "Invalid date"); 1193 jQuery('#' + infofield).show(); 1194 redLight($dateInput); 1195 resetCustomDateOption(); 1196 updateSchedulerTimeAvailability(); 1197 return; 1198 } 1199 1200 var isHoliday = holidays.indexOf(selectedDate) !== -1; 1201 1202 if (isHoliday) { 1203 msg(infofield, "errorNode", "Selected date is unavailable"); 1204 jQuery('#' + infofield).show(); 1205 redLight($dateInput); 1206 resetCustomDateOption(); 1207 updateSchedulerTimeAvailability(); 1208 return; 1209 } 1210 1211 var window = getScheduleWindowForDate(selectedDate); 1212 if (!window) { 1213 msg(infofield, "errorNode", "Selected date is unavailable"); 1214 jQuery('#' + infofield).show(); 1215 redLight($dateInput); 1216 resetCustomDateOption(); 1217 updateSchedulerTimeAvailability(); 1218 return; 1219 } 1220 1221 var displayDate = d.toLocaleDateString('en-US', { 1222 weekday: 'short', 1223 month: 'short', 1224 day: 'numeric' 1225 }); 1226 1227 $radio.val(selectedDate).prop('checked', true).trigger('change'); 1228 $span.text(displayDate); 1229 1230 msg(infofield, "errorNode", ""); 1231 jQuery('#' + infofield).hide(); 1232 greenLight($dateInput); 1233 1234 updateSchedulerTimeAvailability(); 1235}); 1236 1237function validateYesNo(valfield, infofield, required) 1238{ 1239 var radioName = ''; 1240 1241 if (valfield && typeof valfield.length !== 'undefined' && valfield.length > 0 && valfield[0] && valfield[0].name) { 1242 radioName = valfield[0].name; 1243 } else if (valfield && valfield.name) { 1244 radioName = valfield.name; 1245 } 1246 1247 if (!radioName) { 1248 msg(infofield, "errorNode", "Invalid selection"); 1249 jQuery('#' + infofield).show(); 1250 return false;
1251 } 1252 1253 var $selected = jQuery('input[name="' + radioName + '"]:checked'); 1254 var $all = jQuery('input[name="' + radioName + '"]'); 1255 1256 if (!$selected.length) { 1257 if (required) { 1258 msg(infofield, "errorNode", "Required"); 1259 jQuery('#' + infofield).show(); 1260 redLight($all); 1261 return false; 1262 } 1263 1264 msg(infofield, "errorNode", ""); 1265 jQuery('#' + infofield).hide(); 1266 return true; 1267 } 1268 1269 var value = String($selected.val()).toLowerCase(); 1270 1271 if (value !== 'yes' && value !== 'no') { 1272 msg(infofield, "errorNode", "Invalid selection"); 1273 jQuery('#' + infofield).show(); 1274 redLight($all); 1275 return false; 1276 } 1277 1278 msg(infofield, "errorNode", ""); 1279 jQuery('#' + infofield).hide(); 1280 greenLight($selected); 1281 return true; 1282} 1283 1284function isUsingInsuranceYes() 1285{ 1286 return jQuery('input[name="using_insurance"]:checked').val() === 'yes'; 1287} 1288 1289function getInsuranceEligibilityOption() 1290{ 1291 return jQuery('input[name="insurance_eligibility_option"]:checked').val() || ''; 1292} 1293 1294function isInsuranceSSNRequired() 1295{ 1296 return isUsingInsuranceYes() && getInsuranceEligibilityOption() === 'ssn'; 1297} 1298 1299function isInsuranceDetailsRequired() 1300{ 1301 return isUsingInsuranceYes() && getInsuranceEligibilityOption() === 'insurance_details'; 1302} 1303 1304function clearInsuranceEligibilityErrors() 1305{ 1306 ['insurance_eligibility_optionError', 'insurance_ssnError', 'insurance_provider_nameError', 'insurance_member_idError'].forEach(function(errorId) { 1307 if (document.getElementById(errorId)) { 1308 msg(errorId, 'errorNode', ''); 1309 jQuery('#' + errorId).hide(); 1310 } 1311 }); 1312 greenLight(jQuery('input[name="insurance_eligibility_option"]')); 1313 greenLight(jQuery('#insurance_ssn')); 1314 greenLight(jQuery('#insurance_provider_name')); 1315 greenLight(jQuery('#insurance_member_id')); 1316} 1317 1318function resetInsuranceEligibilityFields(clearOption) 1319{ 1320 if (clearOption) { 1321 jQuery('input[name="insurance_eligibility_option"]').prop('checked', false); 1322 } 1323 jQuery('#insurance_ssn').val(''); 1324 jQuery('#insurance_provider_name').val(''); 1325 jQuery('#insurance_member_id').val(''); 1326 clearInsuranceEligibilityErrors(); 1327} 1328 1329function updateInsuranceEligibilityFields(clearHiddenValues) 1330{ 1331 var useInsurance = isUsingInsuranceYes(); 1332 var option = getInsuranceEligibilityOption(); 1333 1334 jQuery('#insuranceEligibilityRow').toggle(useInsurance); 1335 jQuery('#insuranceEligibilitySSNFields').toggle(useInsurance && option === 'ssn'); 1336 jQuery('#insuranceEligibilityDetailFields').toggle(useInsurance && option === 'insurance_details'); 1337 1338 jQuery('#insurance_ssn').attr('aria-required', useInsurance && option === 'ssn' ? 'true' : 'false'); 1339 jQuery('#insurance_provider_name').attr('aria-required', useInsurance && option === 'insurance_details' ? 'true' : 'false'); 1340 jQuery('#insurance_member_id').attr('aria-required', useInsurance && option === 'insurance_details' ? 'true' : 'false'); 1341 1342 if (!useInsurance) { 1343 resetInsuranceEligibilityFields(true); 1344 return; 1345 } 1346 1347 if (clearHiddenValues) { 1348 if (option !== 'ssn') { 1349 jQuery('#insurance_ssn').val(''); 1350 msg('insurance_ssnError', 'errorNode', ''); 1351 jQuery('#insurance_ssnError').hide(); 1352 greenLight(jQuery('#insurance_ssn')); 1353 } 1354 if (option !== 'insurance_details') { 1355 jQuery('#insurance_provider_name').val(''); 1356 jQuery('#insurance_member_id').val(''); 1357 msg('insurance_provider_nameError', 'errorNode', ''); 1358 msg('insurance_member_idError', 'errorNode', ''); 1359 jQuery('#insurance_provider_nameError, #insurance_member_idError').hide(); 1360 greenLight(jQuery('#insurance_provider_name')); 1361 greenLight(jQuery('#insurance_member_id')); 1362 } 1363 } 1364} 1365 1366function formatInsuranceSSNValue(value) 1367{ 1368 var digits = String(value || '').replace(/[^0-9]/g, '').slice(0, 9); 1369 1370 if (digits.length > 5) { 1371 return digits.slice(0, 3) + '-' + digits.slice(3, 5) + '-' + digits.slice(5); 1372 } 1373 1374 if (digits.length > 3) { 1375 return digits.slice(0, 3) + '-' + digits.slice(3); 1376 } 1377 1378 return digits; 1379} 1380 1381function validateInsuranceEligibilityOption(required) 1382{ 1383 if (!required) { 1384 msg('insurance_eligibility_optionError', 'errorNode', ''); 1385 jQuery('#insurance_eligibility_optionError').hide(); 1386 return true; 1387 } 1388 1389 var option = getInsuranceEligibilityOption(); 1390 if (option !== 'ssn' && option !== 'insurance_details' && option !== 'none') { 1391 msg('insurance_eligibility_optionError', 'errorNode', 'Required'); 1392 jQuery('#insurance_eligibility_optionError').show();
1393 redLight(jQuery('input[name="insurance_eligibility_option"]')); 1394 return false; 1395 } 1396 1397 msg('insurance_eligibility_optionError', 'errorNode', ''); 1398 jQuery('#insurance_eligibility_optionError').hide(); 1399 greenLight(jQuery('input[name="insurance_eligibility_option"]')); 1400 return true; 1401} 1402 1403function validateInsuranceSSN(valfield, infofield, required) 1404{ 1405 var stat = commonCheck(valfield, infofield, required); 1406 if (stat !== proceed) return stat; 1407 1408 var value = trim(valfield.value); 1409 if (!required && value.length === 0) { 1410 msg(infofield, 'errorNode', ''); 1411 jQuery('#' + infofield).hide(); 1412 greenLight(valfield); 1413 return true; 1414 } 1415 1416 if (!/^\d{3}-\d{2}-\d{4}$/.test(value)) { 1417 msg(infofield, 'errorNode', 'Invalid SSN'); 1418 jQuery('#' + infofield).show(); 1419 redLight(valfield); 1420 return false; 1421 } 1422 1423 msg(infofield, 'errorNode', ''); 1424 jQuery('#' + infofield).hide(); 1425 greenLight(valfield); 1426 return true; 1427} 1428 1429function validateInsuranceProviderName(valfield, infofield, required) 1430{ 1431 var stat = commonCheck(valfield, infofield, required); 1432 if (stat !== proceed) return stat; 1433 1434 var value = trim(valfield.value); 1435 if (!required && value.length === 0) { 1436 msg(infofield, 'errorNode', ''); 1437 jQuery('#' + infofield).hide(); 1438 greenLight(valfield); 1439 return true; 1440 } 1441 1442 if (!/^[A-Za-z0-9 .&'\-]{2,80}$/.test(value)) { 1443 msg(infofield, 'errorNode', 'Invalid provider name'); 1444 jQuery('#' + infofield).show(); 1445 redLight(valfield); 1446 return false; 1447 } 1448 1449 msg(infofield, 'errorNode', ''); 1450 jQuery('#' + infofield).hide(); 1451 greenLight(valfield); 1452 return true; 1453} 1454 1455function validateInsuranceMemberId(valfield, infofield, required) 1456{ 1457 var stat = commonCheck(valfield, infofield, required); 1458 if (stat !== proceed) return stat; 1459 1460 var value = trim(valfield.value); 1461 if (!required && value.length === 0) { 1462 msg(infofield, 'errorNode', ''); 1463 jQuery('#' + infofield).hide(); 1464 greenLight(valfield); 1465 return true; 1466 } 1467 1468 if (!/^[A-Za-z0-9 \-_]{2,40}$/.test(value)) { 1469 msg(infofield, 'errorNode', 'Invalid member ID'); 1470 jQuery('#' + infofield).show(); 1471 redLight(valfield); 1472 return false; 1473 } 1474 1475 msg(infofield, 'errorNode', ''); 1476 jQuery('#' + infofield).hide(); 1477 greenLight(valfield); 1478 return true; 1479} 1480 1481 1482function validateProfessionalText(valfield, infofield, required) 1483{ 1484 var stat = commonCheck(valfield, infofield, required); 1485 if (stat !== proceed) return stat; 1486 1487 var value = trim(valfield.value); 1488 if (!required && value.length === 0) { 1489 msg(infofield, 'errorNode', ''); 1490 jQuery('#' + infofield).hide(); 1491 greenLight(valfield); 1492 return true; 1493 } 1494 1495 if (!/^[A-Za-z0-9 .,&'()\-\/]{2,100}$/.test(value)) { 1496 msg(infofield, 'errorNode', 'Invalid company name'); 1497 jQuery('#' + infofield).show(); 1498 redLight(valfield); 1499 return false; 1500 } 1501 1502 msg(infofield, 'errorNode', ''); 1503 jQuery('#' + infofield).hide(); 1504 greenLight(valfield); 1505 return true; 1506} 1507 1508function validateInsuranceEligibilityFields() 1509{ 1510 if (!jQuery('#insuranceEligibilityRow').length) { 1511 return true; 1512 } 1513 1514 updateInsuranceEligibilityFields(false); 1515 1516 if (!isUsingInsuranceYes()) { 1517 clearInsuranceEligibilityErrors(); 1518 return true; 1519 } 1520 1521 var errs = 0; 1522 if (!validateInsuranceEligibilityOption(true)) errs++; 1523 1524 if (isInsuranceSSNRequired()) { 1525 if (!validateInsuranceSSN(document.getElementById('insurance_ssn'), 'insurance_ssnError', true)) errs++; 1526 } else if (isInsuranceDetailsRequired()) { 1527 if (!validateInsuranceProviderName(document.getElementById('insurance_provider_name'), 'insurance_provider_nameError', true)) errs++; 1528 if (!validateInsuranceMemberId(document.getElementById('insurance_member_id'), 'insurance_member_idError', true)) errs++; 1529 } 1530 1531 return errs === 0; 1532} 1533 1534jQuery(document).on('change', 'input[name="using_insurance"]', function() { 1535 updateInsuranceEligibilityFields(true); 1536}); 1537 1538jQuery(document).on('change', 'input[name="insurance_eligibility_option"]', function() { 1539 updateInsuranceEligibilityFields(true); 1540 validateInsuranceEligibilityOption(isUsingInsuranceYes()); 1541}); 1542 1543jQuery(document).on('input', '#insurance_ssn', function() { 1544 this.value = formatInsuranceSSNValue(this.value); 1545}); 1546 1547jQuery(document).on('input', '#insurance_provider_name', function() { 1548 this.value = this.value.replace(/[^A-Za-z0-9 .&'\-]/g, '').slice(0, 80); 1549}); 1550 1551jQuery(document).on('input', '#insurance_member_id', function() { 1552 this.value = this.value.replace(/[^A-Za-z0-9 \-_]/g, '').slice(0, 40); 1553}); 1554 1555jQuery(function() { 1556 updateInsuranceEligibilityFields(false); 1557}); 1558 1559jQuery(document).on('change', 'input[name="ctc_scheduler_date"]', function() { 1560 updateSchedulerTimeAvailability(); 1561}); 1562 1563jQuery(document).on('change', 'select[name="facilityChoice"]', function() { 1564 refreshSchedulerForSelectedFacility(true, false); 1565}); 1566 1567jQuery(function() { 1568 initializeSchedulerWrapperState(); 1569 refreshSchedulerForSelectedFacility(true, true); 1570}); 1571 1572// *** -------------------------------------------- 1573// validateSelect
1574// Validate the input tag for Relationship 1575// Returns true if OK 1576// -------------------------------------------- 1577 1578function validateSelect(valfield, // element to be validated 1579 infofield, // id of element to receive info/error msg 1580 required ) 1581{ 1582 var stat = commonCheck (valfield, infofield, required); 1583 if (stat !== proceed) return stat; 1584 1585 var selection = valfield.value; 1586 if(selection === '0' && required) { 1587 msg(infofield,"errorNode", "Required"); 1588 jQuery('#' + infofield).show(); 1589 // setfocus(valfield); 1590 redLight(valfield); 1591 return false; 1592 } else { 1593 msg (infofield, "errorNode", ""); 1594 jQuery('#' + infofield).hide(); 1595 greenLight(valfield); 1596 return true; 1597 } 1598 msg (infofield, "errorNode", ""); 1599 jQuery('#' + infofield).hide(); 1600 greenLight(valfield); 1601 return true; 1602} 1603 1604// *** -------------------------------------------- 1605// validateTimeToCall 1606// Validate the input tag for TimeToCall 1607// Returns true if OK 1608// -------------------------------------------- 1609 1610function validateTimeToCall(valfield, // element to be validated 1611 infofield, // id of element to receive info/error msg 1612 required ) 1613{ 1614 var stat = commonCheck (valfield, infofield, required); 1615 if (stat !== proceed) return stat; 1616 1617 var selection = valfield.value; 1618 if(selection === '0' && required === true) { 1619 msg(infofield,"errorNode", "Required"); 1620 jQuery('#' + infofield).show(); 1621 redLight(valfield); 1622 return false; 1623 } else { 1624 msg (infofield, "errorNode", ""); 1625 jQuery('#' + infofield).hide(); 1626 greenLight(valfield); 1627 return true; 1628 } 1629} 1630 1631function validateDOB(valfield, infofield, required) 1632{ 1633 var stat = commonCheck(valfield, infofield, required); 1634 if (stat !== proceed) return stat; 1635 1636 var value = trim(valfield.value); 1637 var dobRegex = /^(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])\/\d{4}$/; 1638 1639 if (!dobRegex.test(value)) { 1640 msg(infofield, "errorNode", "Invalid date"); 1641 jQuery('#' + infofield).show(); 1642 redLight(valfield); 1643 return false; 1644 } 1645 1646 var parts = value.split('/'); 1647 var month = parseInt(parts[0], 10); 1648 var day = parseInt(parts[1], 10); 1649 var year = parseInt(parts[2], 10); 1650 1651 var d = new Date(year, month - 1, day); 1652 1653 if ( 1654 d.getFullYear() !== year || 1655 d.getMonth() !== (month - 1) || 1656 d.getDate() !== day 1657 ) { 1658 msg(infofield, "errorNode", "Invalid date"); 1659 jQuery('#' + infofield).show(); 1660 redLight(valfield); 1661 return false; 1662 } 1663 1664 msg(infofield, "errorNode", ""); 1665 jQuery('#' + infofield).hide(); 1666 greenLight(valfield); 1667 return true; 1668} 1669 1670jQuery(document).on('input', '#dob', function () { 1671 var value = this.value.replace(/[^\d]/g, '').slice(0, 8); 1672 1673 if (value.length >= 5) { 1674 value = value.slice(0, 2) + '/' + value.slice(2, 4) + '/' + value.slice(4); 1675 } else if (value.length >= 3) { 1676 value = value.slice(0, 2) + '/' + value.slice(2); 1677 } 1678 1679 this.value = value; 1680}); 1681 1682function validateComments(valfield, infofield, required) 1683{ 1684 var stat = commonCheck (valfield, infofield, required); 1685 if (stat !== proceed) return stat; 1686 msg (infofield, "errorNode", ""); 1687 jQuery('#' + infofield).hide(); 1688 greenLight(valfield); 1689 return true; 1690} 1691 1692function validateOnSubmit() { 1693 let errs = 0; 1694 var sfwfaRequired = getSFWFAValidation(); 1695 1696 if (sfwfaRequired.length === 0) { 1697 console.log("Val array is empty."); 1698 return; 1699 } 1700 1701 for (let i = 0; i < sfwfaRequired.length; i++) { 1702 const valField = sfwfaRequired[i]; 1703 const functionName = valField[1]; 1704 1705 if (typeof window[functionName] === 'function') { 1706 const field = document.forms['SFWFA_main_form'][valField[0]]; 1707 const errorField = valField[2]; 1708 const req = valField[3]; 1709 1710 if (!window[functionName](field, errorField, req)) errs += 1; 1711 } else { 1712 console.log("No formval function " + functionName); 1713 } 1714 } 1715 1716 if (typeof validateInsuranceEligibilityFields === 'function' && !validateInsuranceEligibilityFields()) { 1717 errs += 1; 1718 } 1719 1720 if (errs >= 1) { 1721 alert('There are fields which need correction before sending'); 1722 jQuery('html, body').animate({scrollTop: (jQuery('#SFWFA_main_form').offset().top - 300)}, 1000); 1723 } 1724 1725 if (errs > 0) { 1726 return false;
1727 } else { 1728 return true; 1729 } 1730} 1731 1732function show(id) { 1733 if (document.getElementById(id).style.display == 'none') { 1734 document.getElementById(id).style.display = ''; 1735 } 1736} 1737 1738function hide(id) { 1739 document.getElementById(id).style.display = 'none'; 1740} 1741 1742document.onload = function() { 1743 document.getElementById('inquiringAbout').onchange(); 1744}
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.