1$(document).ready(function () { 2 // Helper function to parse URL query parameters 3 function url_query (query) { 4 query = query.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]') 5 const expr = '[\\?&]' + query + '=([^&#]*)' 6 const regex = new RegExp(expr) 7 const results = regex.exec(window.location.href) 8 if (results !== null) { 9 return decodeURIComponent(results[1].replace(/\+/g, ' ')) 10 } else { 11 return false 12 } 13 } 14 15 // Check for avtalegiro success status in URL 16 const avtalegiroStatus = url_query('status') 17 if (avtalegiroStatus === 'ok') { 18 // Find the "Min profil" heading 19 const minProfilHeading = $('h2').filter(function () { 20 return $(this).text().trim() === 'Min profil' 21 }) 22 23 if (minProfilHeading.length > 0) { 24 // Check if message already exists to avoid duplicates 25 const parentContainer = minProfilHeading.parent() 26 let successMessageElement = parentContainer.find('.avtalegiro-success-message').first() 27 28 if (successMessageElement.length === 0) { 29 // Create the success message element 30 successMessageElement = $('<div>') 31 .addClass('avtalegiro-success-message alert alert-success alert-dismissible') 32 .html('Avtalegiro-registreringen er fullført!<br><small><strong>Merk:</strong> Det kan ta opptil 1 dag eller mer før registreringen vises i din profil. Dette skyldes at registreringen først mÃ¥ bekreftes av banken før den registreres i vÃ¥rt system.</small>') 33 34 // Add close button 35 const closeButton = $('<button>') 36 .attr({ 37 type: 'button', 38 class: 'close', 39 'aria-label': 'Lukk' 40 }) 41 .html('×') 42 .on('click', function () { 43 successMessageElement.fadeOut(300, function () { 44 successMessageElement.remove() 45 }) 46 }) 47 48 successMessageElement.prepend(closeButton) 49 50 // Insert the message before the heading 51 minProfilHeading.before(successMessageElement) 52 } else { 53 // If message already exists, just show it 54 successMessageElement.show() 55 } 56 57 // Clean up URL by removing the status parameter 58 let cleanUrl = window.location.href 59 // Remove ?status=ok or &status=ok 60 cleanUrl = cleanUrl.replace(/[?&]status=ok(&|$)/, function (match, after) { 61 return after === '&' ? '&' : '' 62 }) 63 // Clean up trailing ? or & 64 cleanUrl = cleanUrl.replace(/[?&]$/, '') 65 // Fix ?& to ? 66 cleanUrl = cleanUrl.replace(/\?&/, '?') 67 68 if (cleanUrl !== window.location.href) { 69 window.history.replaceState({}, document.title, cleanUrl) 70 } 71 } else {
72 // Check for corporate heading layout (hero-corporate__text) 73 const heroCorporateText = $('.hero-corporate__text').first() 74 if (heroCorporateText.length > 0) { 75 // Check if message already exists to avoid duplicates 76 let successMessageElement = heroCorporateText.find('.avtalegiro-success-message').first() 77 78 if (successMessageElement.length === 0) { 79 // Create the success message element 80 successMessageElement = $('<div>') 81 .addClass('avtalegiro-success-message alert alert-success alert-dismissible') 82 .html('Avtalegiro-registreringen er fullført!<br><small><strong>Merk:</strong> Det kan ta opptil 1 dag eller mer før registreringen vises i din profil. Dette skyldes at registreringen først mÃ¥ bekreftes av banken før den registreres i vÃ¥rt system.</small>') 83 84 // Add close button 85 const closeButton = $('<button>') 86 .attr({ 87 type: 'button', 88 class: 'close', 89 'aria-label': 'Lukk' 90 }) 91 .html('×') 92 .on('click', function () { 93 successMessageElement.fadeOut(300, function () { 94 successMessageElement.remove() 95 }) 96 }) 97 98 successMessageElement.prepend(closeButton) 99 100 // Insert the message at the end of the hero-corporate__text div 101 heroCorporateText.append(successMessageElement) 102 } else { 103 // If message already exists, just show it 104 successMessageElement.show() 105 } 106 107 // Clean up URL by removing the status parameter 108 let cleanUrl = window.location.href 109 // Remove ?status=ok or &status=ok 110 cleanUrl = cleanUrl.replace(/[?&]status=ok(&|$)/, function (match, after) { 111 return after === '&' ? '&' : '' 112 }) 113 // Clean up trailing ? or & 114 cleanUrl = cleanUrl.replace(/[?&]$/, '') 115 // Fix ?& to ? 116 cleanUrl = cleanUrl.replace(/\?&/, '?') 117 118 if (cleanUrl !== window.location.href) { 119 window.history.replaceState({}, document.title, cleanUrl) 120 } 121 } else { 122 // Fallback to existing successMessageFormEvent if neither "Min profil" heading nor corporate heading found 123 const successMessageElement = $('#successMessageFormEvent') 124 if (successMessageElement.length > 0) { 125 // Set the success message 126 successMessageElement.html('Avtalegiro-registreringen er fullført!<br><small><strong>Merk:</strong> Det kan ta opptil 1 dag eller mer før registreringen vises i din profil. Dette skyldes at registreringen først mÃ¥ bekreftes av banken før den registreres i vÃ¥rt system.</small>') 127 128 // Make it dismissible by adding a close button if it doesn't exist 129 if (successMessageElement.find('.close').length === 0) { 130 successMessageElement.addClass('alert alert-success alert-dismissible') 131 const closeButton = $('<button>') 132 .attr({ 133 type: 'button', 134 class: 'close', 135 'aria-label': 'Lukk' 136 }) 137 .html('×') 138 .on('click', function () { 139 successMessageElement.fadeOut(300, function () { 140 successMessageElement.remove() 141 }) 142 }) 143 successMessageElement.prepend(closeButton) 144 } 145 146 // Show the message 147 successMessageElement.show() 148 149 // Clean up URL by removing the status parameter 150 let cleanUrl = window.location.href 151 // Remove ?status=ok or &status=ok 152 cleanUrl = cleanUrl.replace(/[?&]status=ok(&|$)/, function (match, after) { 153 return after === '&' ? '&' : '' 154 }) 155 // Clean up trailing ? or & 156 cleanUrl = cleanUrl.replace(/[?&]$/, '') 157 // Fix ?& to ? 158 cleanUrl = cleanUrl.replace(/\?&/, '?') 159 160 if (cleanUrl !== window.location.href) { 161 window.history.replaceState({}, document.title, cleanUrl) 162 } 163 } 164 } 165 } 166 } 167 168 // Check for avtalegiro error or cancel status in URL 169 const avtalegiroErrorStatus = url_query('status') 170 if (avtalegiroErrorStatus === 'cancel' || avtalegiroErrorStatus === 'error' || avtalegiroErrorStatus === 'Error' || avtalegiroErrorStatus === 'Cancel') { 171 // If we are on the corporate welcome page, show an info message that faktura will be used 172 const heroCorporateTextError = $('.hero-corporate__text').first() 173 if (heroCorporateTextError.length > 0) { 174 let errorMessageElement = heroCorporateTextError.find('.avtalegiro-error-message').first() 175 176 if (errorMessageElement.length === 0) { 177 errorMessageElement = $('<div>') 178 .addClass('avtalegiro-error-message alert alert-warning alert-dismissible') 179 .html('Avtalegiro-registreringen ble ikke fullført. <br><small>Faktura vil bli brukt som standard betalingsmÃ¥te for medlemskapet ditt.</small>') 180 181 const closeButton = $('<button>') 182 .attr({ 183 type: 'button', 184 class: 'close', 185 'aria-label': 'Lukk' 186 }) 187 .html('×') 188 .on('click', function () { 189 errorMessageElement.fadeOut(300, function () { 190 errorMessageElement.remove() 191 }) 192 }) 193
194 errorMessageElement.prepend(closeButton) 195 heroCorporateTextError.append(errorMessageElement) 196 } else { 197 errorMessageElement.show() 198 } 199 } 200 201 // Clean up URL by removing status and actNo parameters 202 let cleanUrl = window.location.href 203 // Remove ?status=... or &status=... 204 cleanUrl = cleanUrl.replace(/[?&]status=(cancel|error|Error|Cancel)(&|$)/i, function (match, statusValue, after) { 205 return after === '&' ? '&' : '' 206 }) 207 // Remove ?actNo=... or &actNo=... 208 cleanUrl = cleanUrl.replace(/[?&]actNo=[^&]*/g, '') 209 // Clean up trailing ? or & 210 cleanUrl = cleanUrl.replace(/[?&]$/, '') 211 // Fix ?& to ? 212 cleanUrl = cleanUrl.replace(/\?&/, '?') 213 214 if (cleanUrl !== window.location.href) { 215 window.history.replaceState({}, document.title, cleanUrl) 216 } 217 } 218 219 const redirectUrl = $('div[data-redirect-page-url]').data('redirect-page-url') 220 if (redirectUrl) { 221 window.location.replace(redirectUrl) 222 } 223 224 const loginModalControl = $('div.onlyLoginModalControl') 225 if (loginModalControl.length > 0) { $('.login-button').click() } 226 227 const redirectLogin = $('div[data-redirect-login]').data('redirect-login') 228 if (redirectLogin) { 229 $('a.loginModalControl').click(function (e) { 230 e.preventDefault() 231 $('.login-button').click() 232 }) 233 } 234 235 const signUpForm = $("#registerEvent input[name='signUpForm']").val() 236 237 if (signUpForm === 'true') { 238 $("#registerEvent select[name='medlemstype']").change(function () { 239 if ($(this).val() == 'Student (fulltid)' || $(this).val() == 'Arbeidssøkende') { 240 $('.workingForm').hide() 241 242 if ($(this).val() == 'Arbeidssøkende') { 243 $('#labelAddress').text('Privatadresse*') 244 $('#labelPostnumber').text('Postnummer*') 245 } else { 246 $('#labelAddress').text('Privatadresse') 247 $('#labelPostnumber').text('Postnummer') 248 } 249 } else if ($(this).val() == 'Er i jobb') { 250 $('.workingForm').show() 251 $('#labelAddress').text('Privatadresse*') 252 $('#labelPostnumber').text('Postnummer*') 253 } 254 255 $('#registerEvent :input').not("select[name='medlemstype']").trigger('change') 256 }) 257 } 258 259 /* Used for the form in register event/seminar page and in the form in the minside page */ 260 261 $('#successMessageFormEvent').hide() 262 $('#failMessageFormEvent').hide() 263 264 $('span.requiredField').hide() 265 $('span.privatField').hide() 266 $('#invoiceAlert').hide() 267 268 $('#registerEvent').on('submit', function (e) { 269 const submitButton = $(this).find('button[type="submit"]') 270 e.preventDefault() 271 272 // Remove required attribute and disable invoice central fields if invoice_send_central is not selected 273 const invoiceOption = $(this).find("input[name='invoiceOption']:checked").val() 274 if (invoiceOption !== 'invoice_send_central') { 275 $('#invoiceCentralFields input[required]').each(function () { 276 $(this).removeAttr('required') 277 $(this).prop('required', false) 278 $(this).prop('disabled', true) 279 }) 280 } else { 281 // Re-enable if invoice_send_central is selected 282 $('#invoiceCentralFields input[required]').each(function () { 283 $(this).prop('disabled', false) 284 }) 285 } 286 287 const formData = $(this).serialize() 288 289 const serviceUrl = $("#registerEvent input[name='registerService']").val() 290 291 const failMessage = "Beklager, her skjedde det en feil.<br>Hvis det skjer igjen, ta kontakt med oss<br>på <a href='mailto: [email protected]'>[email protected]</a>" 292 const fieldMissing = 'Felt mangler' 293 294 let dataOK = true 295 const $form = $(this) 296 const currentPaymentMethod = $form.find("input[name='paymentMethod']:checked").val() 297 $('span.requiredField').each(function (idx, it) { 298 const $field = $(it).parent().find('select, input') 299 // Only validate fields that actually have the required attribute 300 const isRequired = $field.prop('required') || $field.attr('required') !== undefined 301 // Skip validation if field is disabled, hidden, or not required 302 const isDisabled = $field.prop('disabled') || $field.closest('.hidden').length > 0 || $field.closest('fieldset.hidden').length > 0 303 const shouldSkip = !isRequired || isDisabled 304 305 if (!shouldSkip && (($field.filter('select').val() == '') || ($field.filter('input').val() == ''))) { 306 dataOK = false 307 $(it).show() 308 $('#failMessageFormEvent').text('Følgende felt mangler.') 309 $('#failMessageFormEvent').show() 310 } else { 311 $(it).hide() 312 $('#failMessageFormEvent').hide() 313 } 314 }) 315 316 let signUpMedlem = $(this).find("input[name='signUpForm']").val() 317 signUpMedlem = signUpMedlem && (signUpMedlem == 'true') 318 319 const er_i_jobb = $(this).find("select[name='medlemstype']").val() 320 321 let signUpEvent = $(this).find("input[name='signUpEvent']").val() 322 signUpEvent = signUpEvent && (signUpEvent == 'true') 323 324 // Allow students and Arbeidsledig whitout check radio button
325 const invoiceSelected = ($("input[name='invoiceOption']").length > 0) ? $(this).find("input[name='invoiceOption']:checked").val() : 'none' 326 if (((signUpMedlem && (er_i_jobb == 'Er i jobb' || er_i_jobb == '')) || (signUpEvent)) && (invoiceSelected == undefined)) { 327 dataOK = false 328 $('#invoiceAlert').show() 329 $('#failMessageFormEvent').text('Følgende felt mangler.') 330 $('#failMessageFormEvent').show() 331 } else { 332 $('#invoiceAlert').hide() 333 $('#failMessageFormEvent').hide() 334 } 335 336 if (((signUpMedlem && (er_i_jobb == 'Er i jobb' || er_i_jobb == 'Arbeidssøkende')) || (signUpEvent)) && (invoiceSelected == 'invoice_send_private')) { 337 const address = $(this).find("input[name='address']").val() || '' 338 const postnumber = $(this).find("input[name='postnumber']").val() || '' 339 const city = $(this).find("input[name='city']").val() || '' 340 341 if (address == '') { 342 dataOK = false 343 $("input[name='address']").parent().find('span.privatField').show() 344 } else { 345 $("input[name='address']").parent().find('span.privatField').hide() 346 } 347 if (postnumber == '') { 348 dataOK = false 349 $("input[name='postnumber']").parent().find('span.privatField').show() 350 } else { 351 $("input[name='postnumber']").parent().find('span.privatField').hide() 352 } 353 if (city == '') { 354 dataOK = false 355 $("input[name='city']").parent().find('span.privatField').show() 356 } else { 357 $("input[name='city']").parent().find('span.privatField').hide() 358 } 359 360 if (!signUpEvent) { 361 // Validate payment method (required when private is selected) 362 const paymentMethod = $(this).find("input[name='paymentMethod']:checked").val() 363 if (!paymentMethod) { 364 dataOK = false 365 $('#failMessageFormEvent').text('Følgende felt mangler.') 366 $('#failMessageFormEvent').show() 367 } 368 369 if (!dataOK) { 370 $('#failMessageFormEvent').text('Følgende felt mangler.') 371 $('#failMessageFormEvent').show() 372 } 373 } 374 } else { 375 $("input[name='address']").parent().find('span.privatField').hide() 376 $("input[name='postnumber']").parent().find('span.privatField').hide() 377 $("input[name='city']").parent().find('span.privatField').hide() 378 } 379 380 if ($("#registerEvent select[name='medlemstype']").val() == 'Er i jobb' || $("#registerEvent select[name='medlemstype']").val() == 'Arbeidssøkende') { 381 $('span.privatField').each(function (idx, it) { 382 if (($(it).parent().find('select').val() == '') || ($(it).parent().find('input').val() == '')) { 383 dataOK = false 384 $(it).show() 385 $('#failMessageFormEvent').text('Følgende felt mangler.') 386 $('#failMessageFormEvent').show() 387 } else { 388 $(it).hide() 389 $('#failMessageFormEvent').hide() 390 } 391 }) 392 } else { 393 $('span.privatFieldStudent').each(function (idx, it) { 394 if (($(it).parent().find('select').val() == '') || ($(it).parent().find('input').val() == '')) { 395 dataOK = false 396 $(it).show() 397 $('#failMessageFormEvent').text('Følgende felt mangler.') 398 $('#failMessageFormEvent').show() 399 } else { 400 $(it).hide() 401 $('#failMessageFormEvent').hide() 402 } 403 }) 404 } 405 406 submitButton.prop('disabled', true) 407 submitButton.css('cursor', 'wait') 408 409 if (dataOK) { 410 withRecaptchaToken(function (token) { 411 const dataToSend = token ? `${formData}&g-recaptcha-response=${encodeURIComponent(token)}` : formData 412 $.ajax({
413 url: serviceUrl, 414 method: 'POST', 415 dataType: 'json', 416 data: dataToSend, 417 success: function (data) { 418 if (data.statusMessage === 'success') { 419 // Handle avtalegiro redirect if avtalegiro data is present 420 if (data.avtalegiro) { 421 submitAvtalegiroForm(data.avtalegiro) 422 return 423 } 424 425 const welcomeFormHeader = document.getElementById('welcome-form-header') 426 if (welcomeFormHeader) { 427 $('#sign-up-header').hide() 428 $('#welcome-form-header').show() 429 $('#registerEvent').hide() 430 welcomeFormHeader.scrollIntoView({ behavior: 'smooth', block: 'center' }) 431 $('#welcomeForm').show() 432 $('#welcomeForm input').each(function () { 433 $(this).removeAttr('disabled') 434 }) 435 } else { 436 $('#failMessageFormEvent').hide() 437 $('#invoiceAlert').hide() 438 439 const redirectPage = data.linkRedirect 440 if (redirectPage) { 441 window.location.replace(redirectPage) 442 } else { 443 window.location.reload() 444 $(document).scrollTop(0) 445 } 446 } 447 } 448 449 if (data.statusMessage == 'fail') { 450 $('#btn-failure-box').click() 451 $('#failMessageFormEvent').hide() 452 $('#invoiceAlert').hide() 453 $('#successMessageFormEvent').hide() 454 submitButton.prop('disabled', false) 455 submitButton.css('cursor', 'pointer') 456 } 457 }, 458 error: function (xhr, status, error) { 459 $('#btn-failure-box').click() 460 $('#failMessageFormEvent').hide() 461 $('#invoiceAlert').hide() 462 $('#successMessageFormEvent').hide() 463 submitButton.prop('disabled', false) 464 submitButton.css('cursor', 'pointer') 465 } 466 }) 467 }) 468 } else { 469 $('#successMessageFormEvent').hide() 470 $('#failMessageFormEvent').text(fieldMissing) 471 $('#failMessageFormEvent').show() 472 submitButton.prop('disabled', false) 473 submitButton.css('cursor', 'pointer') 474 } 475 }) 476 477 $('#welcomeForm').on('submit', function (e) { 478 const submitButtons = $(this).find('button[type="submit"]') 479 submitButtons.prop('disabled', true) 480 submitButtons.css('cursor', 'wait') 481 e.preventDefault() 482 483 const fireButtonId = e.originalEvent.submitter.getAttribute('data-id') 484 485 const signUpFormData = $('#registerEvent').serialize() 486 const formData = $(this).serialize() 487 488 const serviceUrl = $("#registerEvent input[name='registerService']").val() 489 490 const baseData = `${signUpFormData}&${formData}&skipWelcomeForm=${fireButtonId === 'skip-current-information'}` 491 492 withRecaptchaToken(function (token) { 493 const dataToSend = token ? `${baseData}&g-recaptcha-response=${encodeURIComponent(token)}` : baseData 494 $.ajax({ 495 url: serviceUrl, 496 method: 'POST', 497 dataType: 'json', 498 data: dataToSend, 499 success: function (data) { 500 if (data.statusMessage === 'success') { 501 // Handle avtalegiro redirect if avtalegiro data is present 502 if (data.avtalegiro) { 503 submitAvtalegiroForm(data.avtalegiro) 504 return 505 } 506 507 $('#failMessageFormEvent').hide() 508 $('#invoiceAlert').hide() 509 510 const redirectPage = data.linkRedirect 511 if (redirectPage) { 512 window.location.replace(redirectPage) 513 } else { 514 window.location.reload() 515 $(document).scrollTop(0) 516 } 517 } 518 519 if (data.statusMessage === 'fail') { 520 $('#btn-failure-box').click() 521 $('#failMessageFormEvent').hide() 522 $('#invoiceAlert').hide() 523 $('#successMessageFormEvent').hide() 524 submitButtons.prop('disabled', false) 525 submitButtons.css('cursor', 'pointer') 526 } 527 }, 528 error: function (xhr, status, error) { 529 $('#btn-failure-box').click() 530 $('#failMessageFormEvent').hide() 531 $('#invoiceAlert').hide() 532 $('#successMessageFormEvent').hide() 533 submitButtons.prop('disabled', false) 534 submitButtons.css('cursor', 'pointer') 535 } 536 }) 537 }) 538 }) 539 540 // Student Information 541 $('.studentForm').hide() 542 $("select[name='medlemstype']").change(function () { 543 if ($(this).val() == 'Student (fulltid)') { 544 $('.studentForm').show() 545 $('.studentRequired').prop('required', true) 546 } else { 547 $('.studentForm').val('') 548 $('.studentForm').hide() 549 $('.studentRequired').removeAttr('required') 550 $('.studentRequiredOther').removeAttr('required') 551 } 552 }) 553
554 $('#invoiceCentralFields').hide() 555 // Initialize: disable invoice central fields on page load if not selected 556 const initialInvoiceOption = $("input[name='invoiceOption']:checked").val() 557 if (initialInvoiceOption !== 'invoice_send_central') { 558 $('#invoiceCentralFields input[type="text"]').prop('disabled', true) 559 } 560 561 $("input[name='invoiceOption']").click(function () { 562 if ($(this).attr('value') == 'invoice_send_central') { 563 $('#invoiceCentralFields input[type="text"]').attr('required', true) 564 $('#invoiceCentralFields input[type="text"]').prop('required', true) 565 $('#invoiceCentralFields input[type="text"]').prop('disabled', false) 566 $('#invoiceCentralFields').show() 567 } else { 568 $('#invoiceCentralFields input[type="text"]').removeAttr('required') 569 $('#invoiceCentralFields input[type="text"]').prop('required', false) 570 $('#invoiceCentralFields input[type="text"]').prop('disabled', true) 571 $('#invoiceCentralFields').hide() 572 } 573 }) 574 575 $('#messageChangePassword').hide() 576 $('#changePasswordForm').on('submit', function (e) { 577 e.preventDefault() 578 579 const failMessageChange = "Beklager, her skjedde det en feil.<br>Hvis det skjer igjen, ta kontakt med oss<br>på <a href='mailto: [email protected]'>[email protected]</a>" 580 581 const formData = $(this).serialize() 582 583 const serviceUrl = $(this).find("input[name='changePasswordService']").val() 584 585 const pass1 = $(this).find("input[name='newPassword']").val() 586 const pass2 = $(this).find("input[name='newPasswordAgain']").val() 587 588 if (pass1.length < 6) { 589 $('#messageChangePassword').text('Passordet må være minst 6 bokstaver') 590 $('#messageChangePassword').show() 591 return false 592 } 593 594 if (pass1 != pass2) { 595 $('#messageChangePassword').text('Begge passordene må være like') 596 $('#messageChangePassword').show() 597 return false 598 } 599 600 $.ajax({ 601 url: serviceUrl, 602 method: 'POST', 603 dataType: 'json', 604 data: formData, 605 success: function (data) { 606 if (data.statusMessage == 'success') { 607 $('#messageChangePassword').text('Ditt passord er endret!') 608 $('#messageChangePassword').show() 609 } 610 611 if (data.statusMessage == 'fail') { 612 $('#messageChangePassword').append(failMessageChange) 613 $('#messageChangePassword').show() 614 } 615 }, 616 error: function (xhr, status, error) { 617 $('#messageChangePassword').append(failMessageChange) 618 $('#messageChangePassword').show() 619 } 620 }) 621 }) 622 623 $('#consentEvent').on('submit', function (e) { 624 e.preventDefault() 625 626 const formData = $(this).serialize() 627 628 const serviceUrl = $("#consentEvent input[name='consentService']").val() 629 630 $.ajax({ 631 url: serviceUrl, 632 method: 'POST', 633 dataType: 'json', 634 data: formData, 635 success: function (data) { 636 if (data.statusMessage == 'success') { 637 // window.location.replace(redirectAfterLogin); 638 $('#btn-confirmation-box').click() 639 // $("#successMessageFormEvent").show(); 640 $('#failMessageFormEvent').hide() 641 $('#invoiceAlert').hide() 642 // $('#registerEvent').trigger("reset"); 643 644 $('#modalOk').click(function () { 645 const redirectPage = data.linkRedirect 646 if (redirectPage) { 647 window.location.replace(redirectPage) 648 } else { 649 window.location.reload() 650 $(document).scrollTop(0) 651 } 652 }) 653 } 654 655 if (data.statusMessage == 'fail') { 656 // window.location.replace(redirectAfterLogin); 657 $('#btn-failure-box').click() 658 // $("#successMessageFormEvent").show(); 659 $('#failMessageFormEvent').hide() 660 $('#invoiceAlert').hide() 661 // $('#registerEvent').trigger("reset"); 662 663 $('#modalFailureOk').click(function () { 664 const redirectPage = data.linkRedirect 665 if (redirectPage) { 666 window.location.replace(redirectPage) 667 } else { 668 window.location.reload() 669 $(document).scrollTop(0) 670 } 671 }) 672 673 /* $("#failMessageFormEvent").html( data.error || failMessage ); 674 $("#failMessageFormEvent").show(); */ 675 $('#successMessageFormEvent').hide() 676 } 677 }, 678 error: function (xhr, status, error) { 679 // window.location.replace(redirectAfterLogin); 680 $('#btn-failure-box').click() 681 // $("#successMessageFormEvent").show(); 682 $('#failMessageFormEvent').hide() 683 $('#invoiceAlert').hide() 684 // $('#registerEvent').trigger("reset"); 685 686 $('#modalFailureOk').click(function () { 687 const redirectPage = data.linkRedirect 688 if (redirectPage) { 689 window.location.replace(redirectPage) 690 } else { 691 window.location.reload() 692 $(document).scrollTop(0) 693 } 694 }) 695 696 $('#successMessageFormEvent').hide() 697 /* $("#failMessageFormEvent").html(failMessage); 698 $("#failMessageFormEvent").show(); */ 699 } 700 }) 701 }) 702 703 cancelUserForm() 704 if (signUpForm == 'true') $('#registerEvent :input').trigger('change') 705 706 $('input:radio[name="invoiceOption"]').on('change', function () { 707 const value = $(this).val() 708 if (value === 'invoice_send_private') { 709 $('fieldset[data-id="invoice_send_private"]').show() 710 $('fieldset[data-id="invoice_send_private"] input:required').prop('disabled', false) 711 $('fieldset[data-id="invoice_send_company"]').hide() 712 $('fieldset[data-id="invoice_send_company"] input:required').prop('disabled', true) 713 } 714 715 if (value === 'invoice_send_company') { 716 $('fieldset[data-id="invoice_send_company"]').show() 717 $('fieldset[data-id="invoice_send_company"] input:required').prop('disabled', false) 718 $('fieldset[data-id="invoice_send_private"]').hide() 719 $('fieldset[data-id="invoice_send_private"] input:required').prop('disabled', true) 720 } 721 }) 722 723 phoneInputHandler() 724}) 725 726/** 727 * Generates a reCAPTCHA v3 token when the form exposes a site key, then runs the 728 * callback with the token. On pages without reCAPTCHA configured (no [data-site-key] 729 * element or grecaptcha unavailable) the callback runs immediately with no token, 730 * so event/course signups and profile updates are unaffected. 731 * @param {(token?: string) => void} callback 732 */ 733function withRecaptchaToken (callback) { 734 const siteKeyElement = document.querySelector('[data-site-key]') 735 const siteKey = siteKeyElement && siteKeyElement.getAttribute('data-site-key') 736 737 if (!siteKey || typeof grecaptcha === 'undefined') { 738 callback() 739 return 740 } 741 742 grecaptcha.ready(function () { 743 grecaptcha.execute(siteKey, { action: 'submit' }) 744 .then(function (token) { 745 callback(token) 746 }) 747 .catch(function () { 748 // On failure to obtain a token, submit without one; the server rejects it. 749 callback() 750 }) 751 }) 752} 753 754function cancelUserForm () { 755 const form = document.querySelector('#cancelUserForm') 756 if (!form) return 757 758 let serviceUrl 759 const element = form.querySelector('[name="cancelUserService"]') 760 if (element) { 761 serviceUrl = element.value 762 } else { 763 serviceUrl = undefined 764 } 765 766 let actNo 767 const elementActNo = form.querySelector('[name="actNo"]') 768 if (elementActNo) { 769 actNo = elementActNo.value 770 } else { 771 actNo = undefined 772 } 773 774 if (!serviceUrl || !actNo) return 775 776 // Adding the event to change the save history chosen option 777 const cancelSaveHistory = form.querySelector('.cancel-user-save-history') 778 const resetSaveHistory = function () { 779 const inputs = cancelSaveHistory.querySelectorAll('input') 780 if (inputs) {
781 inputs.forEach(function (input) { 782 input.setAttribute('checked', '') 783 }) 784 } 785 } 786 787 const inputs = cancelSaveHistory.querySelectorAll('input') 788 if (inputs) { 789 inputs.forEach(function (input) { 790 input.addEventListener('click', function () { 791 resetSaveHistory() 792 input.setAttribute('checked', 'checked') 793 }) 794 }) 795 } 796 797 form.addEventListener('submit', function (e) { 798 e.preventDefault() 799 800 let cancelCode 801 const elementCancelCode = form.querySelector('[name="cancelCode"]') 802 if (elementCancelCode) { 803 cancelCode = elementCancelCode.value 804 } else { 805 cancelCode = undefined 806 } 807 if (!cancelCode) return 808 809 let saveHistoryStr 810 const elementChecked = form.querySelector('.cancel-user-save-history input[checked="checked"]') 811 if (elementChecked) { 812 const value = elementChecked.value 813 if (value) { 814 const parts = value.split(',') 815 if (parts.length > 0) { 816 saveHistoryStr = parts[0] 817 } else { 818 saveHistoryStr = undefined 819 } 820 } else { 821 saveHistoryStr = undefined 822 } 823 } else { 824 saveHistoryStr = undefined 825 } 826 827 const saveHistory = saveHistoryStr === 'true' 828 829 fetch(`${serviceUrl}?actNo=${actNo}&cancelCode=${cancelCode}&saveHistory=${saveHistory}`) 830 .then(res => res.json()) 831 .then(data => { 832 const messageContainer = document.querySelector('#confirmation-box h4') 833 if (messageContainer) { 834 messageContainer.innerHTML = 'Du er nå meldt ut!' 835 } 836 const button = document.querySelector('#btn-confirmation-box') 837 if (button) { 838 button.click() 839 } 840 841 const modalOkButton = document.querySelector('#modalOk') 842 if (modalOkButton) { 843 modalOkButton.addEventListener('click', function () { 844 location.reload() 845 }) 846 } 847 }) 848 .catch(e => { 849 const failureButton = document.querySelector('#btn-failure-box') 850 if (failureButton) { 851 failureButton.click() 852 } 853 }) 854 }) 855} 856 857/** 858 * Submits the avtalegiro form with the provided data and redirects to the avtalegiro page 859 * @param {Object} avtalegiroData - The avtalegiro response data from the API 860 */ 861function submitAvtalegiroForm (avtalegiroData) { 862 if (!avtalegiroData) { 863 console.error('No avtalegiro data provided') 864 return 865 } 866 867 // Extract values from the response data (handling different possible field names) 868 // Use hardcoded defaults as per the form template 869 const companyName = avtalegiroData.companyName 870 const companyAccountNo = avtalegiroData.companyAccountNo 871 const kid = avtalegiroData.KID 872 const amountLimit = avtalegiroData.amountLimit 873 const returnUrl = avtalegiroData.returnUrl 874 875 // Create a form element 876 const form = document.createElement('form') 877 form.method = 'POST' 878 form.action = avtalegiroData.formAction 879 form.style.display = 'none' 880 881 // Create and append form fields 882 const fields = [ 883 { name: 'companyName', value: companyName }, 884 { name: 'companyAccountNo', value: companyAccountNo }, 885 { name: 'kid', value: kid }, 886 { name: 'amountLimit', value: amountLimit }, 887 { name: 'returnUrl', value: returnUrl }, 888 { name: 'notificationDisabled', value: 'true' } 889 ] 890 891 fields.forEach(field => { 892 const input = document.createElement('input') 893 input.type = 'hidden' 894 input.name = field.name 895 input.id = field.name 896 input.value = field.value 897 form.appendChild(input) 898 }) 899 900 // Append form to body and submit 901 document.body.appendChild(form) 902 form.submit() 903} 904 905/** 906 * Adds event listener to phone number to allow only 8 digits and numbers 907 */ 908function phoneInputHandler () { 909 const phoneNumber = document.querySelector('[type="tel"][pattern]') 910 911 if (!phoneNumber) return 912 913 phoneNumber.addEventListener('input', function () { 914 if (String(this.value).length > 8) this.value = String(this.value).slice(0, 8) 915 916 this.value = this.value.replace(/[^0-9]/g, '') 917 }) 918}
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.