1/** 2 * SLS Player Registration Form JavaScript 3 */ 4 5jQuery(document).ready(function($) { 6 'use strict'; 7 8 // Form submission handler 9 $('#sls-registration-form').on('submit', function(e) { 10 e.preventDefault(); 11 12 var $form = $(this); 13 var $submitBtn = $form.find('button[type="submit"]'); 14 var $messages = $('#form-messages'); 15 16 // Show loading state 17 $form.addClass('loading'); 18 $submitBtn.prop('disabled', true).text('Processing...'); 19 20 // Clear previous messages 21 $messages.removeClass('success error info').hide(); 22 23 // Validate form 24 if (!validateForm($form)) { 25 $form.removeClass('loading'); 26 $submitBtn.prop('disabled', false).text('Submit Registration'); 27 return; 28 } 29 30 // Prepare form data 31 var formData = new FormData(this); 32 33 // Convert date of birth from dd/mm/yyyy to Y-m-d format for backend 34 var dobInput = formData.get('date_of_birth'); 35 if (dobInput) { 36 var dateObj = parseDDMMYYYY(dobInput); 37 if (dateObj) { 38 var year = dateObj.getFullYear(); 39 var month = String(dateObj.getMonth() + 1).padStart(2, '0'); 40 var day = String(dateObj.getDate()).padStart(2, '0'); 41 formData.set('date_of_birth', year + '-' + month + '-' + day); 42 } 43 } 44 45 formData.append('action', 'sls_submit_registration'); 46 formData.append('nonce', sls_ajax.nonce); 47 48 // Submit form via AJAX 49 $.ajax({ 50 url: sls_ajax.ajax_url, 51 type: 'POST', 52 data: formData, 53 processData: false, 54 contentType: false, 55 success: function(response) { 56 $form.removeClass('loading'); 57 $submitBtn.prop('disabled', false).text('Submit Registration'); 58 59 if (response.success) { 60 if (response.data.confirmation_page) { 61 // Show confirmation page 62 showConfirmationPage(response.data.data); 63 } else if (response.data.redirect_url) { 64 // Redirect to payment 65 setTimeout(function() { 66 window.location.href = response.data.redirect_url; 67 }, 2000); 68 } else { 69 showMessage('success', response.data.message); 70 // Reset form after successful submission 71 setTimeout(function() { 72 $form[0].reset(); 73 $form.find('.photo-preview').empty(); 74 }, 3000); 75 } 76 } else { 77 showMessage('error', response.data || 'An error occurred. Please try again.'); 78 } 79 }, 80 error: function(xhr, status, error) { 81 $form.removeClass('loading'); 82 $submitBtn.prop('disabled', false).text('Submit Registration'); 83 showMessage('error', 'Network error. Please check your connection and try again.'); 84 } 85 }); 86 }); 87 88 // Photo upload handler 89 $('#player_photo').on('change', function() { 90 var file = this.files[0]; 91 var $preview = $('#photo-preview'); 92 93 if (file) { 94 // Validate file type 95 var allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif']; 96 if (!allowedTypes.includes(file.type)) { 97 showMessage('error', 'Please select a valid image file (JPG, PNG, GIF)'); 98 this.value = ''; 99 return; 100 } 101 102 // Validate file size (3MB) 103 if (file.size > 3145728) { 104 showMessage('error', 'File size must be less than 3MB'); 105 this.value = ''; 106 return; 107 } 108 109 // Show preview 110 var reader = new FileReader(); 111 reader.onload = function(e) { 112 $preview.html('<img src="' + e.target.result + '" alt="Photo Preview">'); 113 };
114 reader.readAsDataURL(file); 115 116 // Upload file 117 uploadPhoto(file); 118 } else { 119 $preview.empty(); 120 } 121 }); 122 123 // Form reset handler 124 $('button[type="reset"]').on('click', function() { 125 $('#photo-preview').empty(); 126 $('#form-messages').hide(); 127 clearFormErrors(); 128 129 // Reset reCAPTCHA if enabled 130 if (sls_ajax.recaptcha_site_key && typeof grecaptcha !== 'undefined') { 131 grecaptcha.reset(); 132 } 133 }); 134 135 // Real-time validation 136 $('input[required], select[required]').on('blur', function() { 137 validateField($(this)); 138 }); 139 140 // Initialize datepicker for date of birth 141 $('#date_of_birth').datepicker({ 142 dateFormat: 'dd/mm/yy', 143 changeMonth: true, 144 changeYear: true, 145 yearRange: '1900:' + new Date().getFullYear(), 146 maxDate: 0, // Cannot select future dates 147 onSelect: function(dateText, inst) { 148 clearFieldError($(this)); 149 // Trigger age calculation 150 $(this).trigger('change'); 151 } 152 }); 153 154 // Validate date of birth on blur 155 $('#date_of_birth').on('blur', function() { 156 var $field = $(this); 157 var value = $field.val().trim(); 158 159 if (value.length > 0) { 160 if (!isValidDDMMYYYY(value)) { 161 showFieldError($field, 'Please enter a valid date in DD/MM/YYYY format'); 162 } else { 163 // Check if date is not in the future 164 var dateObj = parseDDMMYYYY(value); 165 if (dateObj) { 166 var today = new Date(); 167 today.setHours(0, 0, 0, 0); 168 if (dateObj > today) { 169 showFieldError($field, 'Date of birth cannot be in the future'); 170 } 171 } 172 } 173 } 174 }); 175 176 // Tel input live validation to clear previous errors 177 $('input[type="tel"]').on('input', function() { 178 var $field = $(this); 179 var value = $field.val().trim(); 180 181 clearFieldError($field); 182 183 if (!value.length) { 184 return; 185 } 186 187 if (!isValidPhone(value)) { 188 showFieldError($field, 'Please enter a valid phone number'); 189 } 190 }); 191 192 // Registration type change handler 193 $('#registration_type').on('change', function() { 194 updateRegistrationAmount(); 195 }); 196 197 // Initialize 198 updateRegistrationAmount(); 199 200 /** 201 * Validate entire form 202 */ 203 function validateForm($form) { 204 var isValid = true; 205 var $requiredFields = $form.find('input[required], select[required], textarea[required]'); 206 207 $requiredFields.each(function() { 208 if (!validateField($(this))) { 209 isValid = false; 210 } 211 }); 212 213 // Validate email format 214 var $email = $form.find('input[type="email"]'); 215 if ($email.length && $email.val()) { 216 if (!isValidEmail($email.val())) { 217 showFieldError($email, 'Please enter a valid email address'); 218 isValid = false; 219 } 220 } 221 222 // Validate phone format 223 $form.find('input[type="tel"]').each(function() { 224 var $phoneField = $(this); 225 var phoneValue = $phoneField.val().trim(); 226 if (phoneValue.length && !isValidPhone(phoneValue)) { 227 showFieldError($phoneField, 'Please enter a valid phone number'); 228 isValid = false; 229 } 230 }); 231 232 // Validate date of birth format (dd/mm/yyyy) 233 var $dobField = $form.find('#date_of_birth'); 234 if ($dobField.length) { 235 var dobValue = $dobField.val().trim(); 236 if ($dobField.prop('required') && !dobValue) { 237 showFieldError($dobField, 'Date of birth is required'); 238 isValid = false; 239 } else if (dobValue.length > 0) { 240 if (!isValidDDMMYYYY(dobValue)) { 241 showFieldError($dobField, 'Please enter a valid date in DD/MM/YYYY format'); 242 isValid = false;
243 } else { 244 // Check if date is not in the future 245 var dateObj = parseDDMMYYYY(dobValue); 246 if (dateObj) { 247 var today = new Date(); 248 today.setHours(0, 0, 0, 0); 249 if (dateObj > today) { 250 showFieldError($dobField, 'Date of birth cannot be in the future'); 251 isValid = false; 252 } 253 } 254 } 255 } 256 } 257 258 // Validate reCAPTCHA if enabled 259 if (sls_ajax.recaptcha_site_key) { 260 var recaptchaResponse = grecaptcha.getResponse(); 261 if (!recaptchaResponse) { 262 var $recaptcha = $form.find('.g-recaptcha'); 263 var $recaptchaError = $form.find('.recaptcha-error'); 264 if ($recaptchaError.length) { 265 $recaptchaError.show(); 266 } else { 267 $recaptcha.after('<span class="recaptcha-error" style="color: red; display: block;">Please complete the reCAPTCHA verification.</span>'); 268 } 269 isValid = false; 270 } else { 271 $form.find('.recaptcha-error').hide(); 272 } 273 } 274 275 return isValid; 276 } 277 278 /** 279 * Validate individual field 280 */ 281 function validateField($field) { 282 var value = $field.val().trim(); 283 var isValid = true; 284 285 // Clear previous errors 286 clearFieldError($field); 287 288 if ($field.prop('required') && !value) { 289 showFieldError($field, 'This field is required'); 290 isValid = false; 291 } 292 293 if (isValid && $field.attr('type') === 'tel' && value && !isValidPhone(value)) { 294 showFieldError($field, 'Please enter a valid phone number'); 295 isValid = false; 296 } 297 298 // Validate date of birth format 299 if (isValid && $field.attr('id') === 'date_of_birth' && value) { 300 if (!isValidDDMMYYYY(value)) { 301 showFieldError($field, 'Please enter a valid date in DD/MM/YYYY format'); 302 isValid = false; 303 } else { 304 var dateObj = parseDDMMYYYY(value); 305 if (dateObj) { 306 var today = new Date(); 307 today.setHours(0, 0, 0, 0); 308 if (dateObj > today) { 309 showFieldError($field, 'Date of birth cannot be in the future'); 310 isValid = false; 311 } 312 } 313 } 314 } 315 316 return isValid; 317 } 318 319 /** 320 * Show field error 321 */ 322 function showFieldError($field, message) { 323 $field.addClass('error'); 324 $field.closest('.form-group').addClass('error'); 325 326 var $errorDiv = $field.siblings('.error-message'); 327 if ($errorDiv.length === 0) { 328 $errorDiv = $('<div class="error-message"></div>'); 329 $field.after($errorDiv); 330 } 331 $errorDiv.text(message); 332 } 333 334 /** 335 * Clear field error 336 */ 337 function clearFieldError($field) { 338 $field.removeClass('error'); 339 $field.closest('.form-group').removeClass('error'); 340 $field.siblings('.error-message').remove(); 341 } 342 343 /** 344 * Clear all form errors 345 */ 346 function clearFormErrors() { 347 $('.form-group').removeClass('error'); 348 $('.error-message').remove(); 349 $('input, select, textarea').removeClass('error'); 350 } 351 352 /** 353 * Validate email format 354 */ 355 function isValidEmail(email) { 356 var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 357 return emailRegex.test(email); 358 } 359 360 /** 361 * Validate phone format 362 */ 363 function isValidPhone(phone) { 364 var trimmed = phone.trim(); 365 366 if (!trimmed.length) { 367 return true; 368 } 369 370 var allowedChars = /^\+?[0-9\s().-]+$/; 371 if (!allowedChars.test(trimmed)) { 372 return false;
373 } 374 375 if ((trimmed.match(/\+/g) || []).length > 1) { 376 return false; 377 } 378 379 if (trimmed.indexOf('+') > 0) { 380 return false; 381 } 382 383 var digitCount = trimmed.replace(/\D/g, '').length; 384 return digitCount >= 7 && digitCount <= 15; 385 } 386 387 /** 388 * Upload photo 389 */ 390 function uploadPhoto(file) { 391 var formData = new FormData(); 392 formData.append('file', file); 393 formData.append('action', 'sls_upload_player_photo'); 394 formData.append('nonce', sls_ajax.nonce); 395 396 $.ajax({ 397 url: sls_ajax.ajax_url, 398 type: 'POST', 399 data: formData, 400 processData: false, 401 contentType: false, 402 success: function(response) { 403 if (response.success) { 404 // Store photo URL in hidden field 405 $('<input>').attr({ 406 type: 'hidden', 407 name: 'photo_url', 408 value: response.data.url 409 }).appendTo('#sls-registration-form'); 410 411 showMessage('success', 'Photo uploaded successfully'); 412 } else { 413 showMessage('error', response.data || 'Photo upload failed'); 414 } 415 }, 416 error: function() { 417 showMessage('error', 'Photo upload failed. Please try again.'); 418 } 419 }); 420 } 421 422 /** 423 * Update registration amount display 424 */ 425 function updateRegistrationAmount() { 426 var $typeSelect = $('#registration_type'); 427 var selectedType = $typeSelect.val(); 428 var amounts = { 429 'new': 5000, 430 'renewal': 3000, 431 'junior': 2000 432 }; 433 434 if (amounts[selectedType]) { 435 var $amountDisplay = $typeSelect.siblings('.amount-display'); 436 if ($amountDisplay.length === 0) { 437 $amountDisplay = $('<div class="amount-display" style="margin-top: 5px; font-weight: bold; color: #2b4079;"></div>'); 438 $typeSelect.after($amountDisplay); 439 } 440 $amountDisplay.text('Amount: LKR ' + amounts[selectedType].toLocaleString()); 441 } 442 } 443 444 /** 445 * Show confirmation page 446 */ 447 function showConfirmationPage(data) { 448 var confirmationHtml = generateConfirmationHtml(data); 449 450 // Hide the form and show confirmation 451 $('.sls-registration-container').html(confirmationHtml); 452 453 // Add event handlers for confirmation buttons 454 $('#back-to-form').on('click', function() { 455 location.reload(); 456 }); 457 458 $('#terms-conditions').on('change', function() { 459 $('#confirm-registration').prop('disabled', !this.checked); 460 }); 461 462 $('#confirm-registration').on('click', function() { 463 if (!$('#terms-conditions').is(':checked')) { 464 return; 465 } 466 confirmRegistration(); 467 }); 468 } 469 470 /** 471 * Generate confirmation HTML 472 */ 473 function generateConfirmationHtml(data) { 474 var html = '<div class="sls-confirmation-container">'; 475 html += '<div class="sls-confirmation-header">'; 476 html += '<h2>Please review and confirm the following.</h2>'; 477 html += '</div>'; 478 html += '<div class="sls-confirmation-content">'; 479 480 // Personal Details 481 html += '<div class="confirmation-row">'; 482 html += '<div class="confirmation-label">First Name:</div>'; 483 html += '<div class="confirmation-value">' + (data.first_name || '') + '</div>'; 484 html += '</div>'; 485 486 html += '<div class="confirmation-row">'; 487 html += '<div class="confirmation-label">Middle Name:</div>'; 488 html += '<div class="confirmation-value">' + (data.middle_name || '') + '</div>'; 489 html += '</div>'; 490 491 html += '<div class="confirmation-row">'; 492 html += '<div class="confirmation-label">Surname:</div>'; 493 html += '<div class="confirmation-value">' + (data.surname || '') + '</div>'; 494 html += '</div>'; 495 496 // Address Information 497 html += '<div class="confirmation-row">'; 498 html += '<div class="confirmation-label">Address 1:</div>'; 499 html += '<div class="confirmation-value">' + (data.address_1 || '') + '</div>'; 500 html += '</div>'; 501 502 html += '<div class="confirmation-row">'; 503 html += '<div class="confirmation-label">Address 2:</div>'; 504 html += '<div class="confirmation-value">' + (data.address_2 || '') + '</div>'; 505 html += '</div>'; 506 507 html += '<div class="confirmation-row">'; 508 html += '<div class="confirmation-label">City:</div>'; 509 html += '<div class="confirmation-value">' + (data.city || '') + '</div>'; 510 html += '</div>'; 511 512 // Date of Birth (calculate age) 513 if (data.date_of_birth) { 514 var dob = new Date(data.date_of_birth); 515 var now = new Date(); 516 var age = now.getFullYear() - dob.getFullYear(); 517 var monthDiff = now.getMonth() - dob.getMonth(); 518 if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < dob.getDate())) { 519 age--; 520 } 521 var months = (now.getFullYear() - dob.getFullYear()) * 12 + (now.getMonth() - dob.getMonth()); 522 if (now.getDate() < dob.getDate()) months--; 523 524 // Format date for display (convert Y-m-d to dd/mm/yyyy) 525 var dobDate = new Date(data.date_of_birth);
526 var displayDate = String(dobDate.getDate()).padStart(2, '0') + '/' + 527 String(dobDate.getMonth() + 1).padStart(2, '0') + '/' + 528 dobDate.getFullYear(); 529 530 html += '<div class="confirmation-row">'; 531 html += '<div class="confirmation-label">Date of Birth:</div>'; 532 html += '<div class="confirmation-value">' + displayDate + ' (' + age + ' years ' + (months % 12) + ' months)</div>'; 533 html += '</div>'; 534 } 535 536 // html += '<div class="confirmation-row">'; 537 // html += '<div class="confirmation-label">Age Group:</div>'; 538 // html += '<div class="confirmation-value">' + (data.age_group || '') + '</div>'; 539 // html += '</div>'; 540 541 html += '<div class="confirmation-row">'; 542 html += '<div class="confirmation-label">Player Category:</div>'; 543 html += '<div class="confirmation-value">' + (data.player_category || '') + '</div>'; 544 html += '</div>'; 545 546 html += '<div class="confirmation-row">'; 547 html += '<div class="confirmation-label">School / Institution:</div>'; 548 html += '<div class="confirmation-value">' + (data.school_institi || '') + '</div>'; 549 html += '</div>'; 550 551 html += '<div class="confirmation-row">'; 552 html += '<div class="confirmation-label">Coached By:</div>'; 553 html += '<div class="confirmation-value">' + (data.coached_by || '') + '</div>'; 554 html += '</div>'; 555 556 html += '<div class="confirmation-row">'; 557 html += '<div class="confirmation-label">Rankdin ID:</div>'; 558 html += '<div class="confirmation-value">' + (data.rankdin_id || '') + '</div>'; 559 html += '</div>'; 560 561 html += '<div class="confirmation-row">'; 562 html += '<div class="confirmation-label">WSF Spin Number:</div>'; 563 html += '<div class="confirmation-value">' + (data.wsfspinnumber || '') + '</div>'; 564 html += '</div>'; 565 566 html += '<div class="confirmation-row">'; 567 html += '<div class="confirmation-label">Contact Number 1 - Mobile:</div>'; 568 html += '<div class="confirmation-value">' + (data.contact_number_1 || '') + '</div>'; 569 html += '</div>'; 570 571 html += '<div class="confirmation-row">'; 572 html += '<div class="confirmation-label">Contact Number 2 - Mobile:</div>'; 573 html += '<div class="confirmation-value">' + (data.contact_number_2 || '') + '</div>'; 574 html += '</div>'; 575 576 // html += '<div class="confirmation-row">'; 577 // html += '<div class="confirmation-label">Land Line:</div>'; 578 // html += '<div class="confirmation-value">' + (data.contact_number_3 || '') + '</div>'; 579 // html += '</div>'; 580 581 html += '<div class="confirmation-row">'; 582 html += '<div class="confirmation-label">Email:</div>'; 583 html += '<div class="confirmation-value">' + (data.email || '') + '</div>'; 584 html += '</div>'; 585 586 html += '</div>'; 587 html += '<div class="sls-terms-section">'; 588 html += '<div class="sls-checkbox-group">'; 589 html += '<input type="checkbox" id="terms-conditions" name="terms_conditions">'; 590 html += '<label for="terms-conditions">I have read and agreed to the <a href="https://srilankasquash.lk/SRILANKASQUASHPAYMENTPOLICY.pdf" target="_blank" rel="noopener noreferrer">Terms & Conditions</a></label>'; 591 html += '</div>'; 592 html += '</div>'; 593 html += '<div class="confirmation-actions">'; 594 html += '<button type="button" id="back-to-form" class="btn btn-back">Back</button>'; 595 html += '<button type="button" id="confirm-registration" class="btn btn-confirm" disabled>Confirm</button>'; 596 html += '</div>'; 597 html += '</div>'; 598 599 return html; 600 } 601 602 /** 603 * Confirm registration 604 */ 605 function confirmRegistration() { 606 var $confirmBtn = $('#confirm-registration'); 607 $confirmBtn.prop('disabled', true).text('Processing...'); 608 609 $.ajax({ 610 url: sls_ajax.ajax_url, 611 type: 'POST', 612 data: { 613 action: 'sls_confirm_registration', 614 nonce: sls_ajax.nonce 615 }, 616 success: function(response) { 617 if (response.success) { 618 if (response.data.redirect_url) { 619 // Redirect to payment 620 window.location.href = response.data.redirect_url; 621 } else { 622 showMessage('success', response.data.message); 623 } 624 } else { 625 $confirmBtn.prop('disabled', !$('#terms-conditions').is(':checked')).text('Confirm'); 626 showMessage('error', response.data || 'An error occurred. Please try again.'); 627 } 628 }, 629 error: function() { 630 $confirmBtn.prop('disabled', !$('#terms-conditions').is(':checked')).text('Confirm'); 631 showMessage('error', 'Network error. Please try again.'); 632 } 633 }); 634 } 635 636 /** 637 * Show message 638 */ 639 function showMessage(type, message) { 640 var $messages = $('#form-messages'); 641 $messages.removeClass('success error info') 642 .addClass(type) 643 .html(message) 644 .show(); 645 646 // Auto-hide success messages 647 if (type === 'success') { 648 setTimeout(function() { 649 $messages.fadeOut(); 650 }, 5000); 651 } 652 653 // Scroll to message 654 $('html, body').animate({ 655 scrollTop: $messages.offset().top - 100 656 }, 500); 657 } 658 659 /** 660 * Format phone number as user types 661 */ 662 $('#phone').on('input', function() { 663 var value = this.value.replace(/\D/g, ''); 664 var formattedValue = value.replace(/(\d{3})(\d{3})(\d{4})/, '$1-$2-$3'); 665 if (value.length <= 10) { 666 this.value = formattedValue; 667 } 668 }); 669 670 /** 671 * Age group auto-selection based on date of birth 672 */ 673 $('#date_of_birth').on('change', function() { 674 var dobValue = $(this).val().trim(); 675 if (dobValue && isValidDDMMYYYY(dobValue)) { 676 var dob = parseDDMMYYYY(dobValue); 677 if (dob) { 678 var today = new Date(); 679 var age = today.getFullYear() - dob.getFullYear(); 680 var monthDiff = today.getMonth() - dob.getMonth(); 681 682 if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < dob.getDate())) { 683 age--; 684 } 685 686 var ageGroup = ''; 687 if (age < 12) { 688 ageGroup = 'under-12'; 689 } else if (age >= 12 && age <= 15) { 690 ageGroup = '12-15'; 691 } else if (age >= 16 && age <= 18) { 692 ageGroup = '16-18'; 693 } else if (age >= 19 && age <= 25) { 694 ageGroup = '19-25'; 695 } else { 696 ageGroup = '26-plus'; 697 } 698 699 $('#age_group').val(ageGroup); 700 } 701 } 702 }); 703 704 /** 705 * Validate dd/mm/yyyy format 706 */ 707 function isValidDDMMYYYY(value) { 708 if (!value) { 709 return false;
710 } 711 712 // Check format: dd/mm/yyyy 713 var datePattern = /^(\d{2})\/(\d{2})\/(\d{4})$/; 714 var match = value.match(datePattern); 715 716 if (!match) { 717 return false; 718 } 719 720 var day = parseInt(match[1], 10); 721 var month = parseInt(match[2], 10); 722 var year = parseInt(match[3], 10); 723 724 // Basic range checks 725 if (month < 1 || month > 12) { 726 return false; 727 } 728 if (day < 1 || day > 31) { 729 return false; 730 } 731 if (year < 1900 || year > new Date().getFullYear()) { 732 return false; 733 } 734 735 // Create date object to validate (handles leap years, etc.) 736 var dateObj = new Date(year, month - 1, day); 737 if (dateObj.getFullYear() !== year || 738 dateObj.getMonth() !== (month - 1) || 739 dateObj.getDate() !== day) { 740 return false; 741 } 742 743 return true; 744 } 745 746 /** 747 * Parse dd/mm/yyyy string to Date object 748 */ 749 function parseDDMMYYYY(value) { 750 if (!value) { 751 return null; 752 } 753 754 // Check format: dd/mm/yyyy 755 var datePattern = /^(\d{2})\/(\d{2})\/(\d{4})$/; 756 var match = value.match(datePattern); 757 758 if (!match) { 759 return null; 760 } 761 762 var day = parseInt(match[1], 10); 763 var month = parseInt(match[2], 10); 764 var year = parseInt(match[3], 10); 765 766 var dateObj = new Date(year, month - 1, day); 767 768 // Verify the date is valid 769 if (dateObj.getFullYear() !== year || 770 dateObj.getMonth() !== (month - 1) || 771 dateObj.getDate() !== day) { 772 return null; 773 } 774 775 return dateObj; 776 } 777});
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.