1 2(function ($, Drupal, drupalSettings) { 3 4 "use strict"; 5 6 /** 7 * Container for easy storage and retrieval of variables in the DOM 8 * 9 * Configurable Javascript is available with drupalSettings (the successor to Drupal 7's Drupal.settings). 10 * However, to make drupalSettings available to our JavaScript file: we have to declare a dependency on it. 11 * 12 * @requires drupalSettings as dependency nt_ama.libraries.yml 13 * @see https://www.drupal.org/node/2274843#configurable 14 * @see nt_ama/js/README.md 15 * @type {{object}} 16 */ 17 drupalSettings.nt_ama = { 18 'config': { 19 'sample_variable': true 20 } 21 }; 22 23 /** 24 * Behavior to responsive tables 25 * 26 * @see http://css-tricks.com/examples/ResponsiveTables/responsive.php 27 */ 28 Drupal.behaviors.ntAmaResponsiveTables = { 29 attach: function (context, settings) { 30 // Using the new 'once' API 31 once('ntAmaResponsiveTables', '.main-layout .region-content table', context).forEach(function (element) { 32 // Wrapping the element with jQuery to maintain jQuery method compatibility 33 var $element = $(element); 34 35 if ($element.hasClass('ui-datepicker-calendar') || $element.hasClass('no-responsive-table') || $element.hasClass('simple-responsive-table')) { 36 return; 37 } 38 39 $element.ngResponsiveTables({ 40 smallPaddingCharNo: 13, 41 mediumPaddingCharNo: 18, 42 largePaddingCharNo: 30 43 }); 44 }); 45 } 46 }; 47 48 49 /** 50 * Disable built-in date picker on Edge browsers 51 * @type {{attach: Drupal.behaviors.ntAmaDateFields.attach}} 52 */ 53 Drupal.behaviors.ntAmaDateFields = { 54 attach: function (context, settings) { 55 56 // Fixes for date field in all browsers 57 $("[type='date'], input.date-input", context).attr('type', 'date-picker').attr('placeholder', 'mm/dd/yyyy').datepicker({ 58 dateFormat: 'mm/dd/yy', 59 constrainInput: true, 60 }).inputmask("mm/dd/yyyy"); 61 } 62 }; 63 64 /** 65 * Make My Account submenu a child of the My Account menu item 66 * @type {{attach: Drupal.behaviors.ntAmaMyAccountSubmen.attach}} 67 */ 68 Drupal.behaviors.ntAmaMyAccountSubmen = { 69 attach: function (context, settings) { 70 $('nav.menu--my-account-submenu ul', context).detach().appendTo('#block-headeractionlinks > ul > li.my-account'); 71 } 72 }; 73 74 /** 75 * Behavior to open/close search header 76 * 77 */ 78 Drupal.behaviors.ntAmaOpenSearchHeader = { 79 attach: function (context, settings) { 80 $('.menu--header-action-links .search a', context).off('click').click(function (event) { 81 event.preventDefault(); 82 if ($(this).parent('li').hasClass('close')) { 83 $('.ama-header-search').removeClass('open'); 84 $(this).parent('li').removeClass('close'); 85 } 86 else { 87 $('.ama-header-search').addClass('open'); 88 $(this).parent('li').addClass('close'); 89 } 90 }); 91 92 // Search icon on mobile 93 once('amaSearchIcon', '.ama-search-icon .field--name-body a', context).forEach(function (element) { 94 var $element = $(element); // Wrap with jQuery 95 $element.click(function (event) { 96 event.preventDefault(); 97 if ($element.hasClass('close')) { 98 $('.ama-header-search').removeClass('open'); 99 $element.removeClass('close'); 100 } 101 else { 102 $('.ama-header-search').addClass('open'); 103 $element.addClass('close'); 104 } 105 }); 106 }); 107 } 108 }; 109 110 /** 111 * Behavior to handler collapsible/collapsed on view header 112 * 113 */ 114 Drupal.behaviors.ntAmaHandlerCollapibleViewHeader = { 115 attach: function (context, settings) { 116 var elements = once('viewHeaderCollapsible', '.view-header .collapsible', context); 117 $(elements).click(function (event) { 118 event.preventDefault(); 119 $(this).toggleClass('collapsed'); 120 $(this).parents('.view').find('.view-content').slideToggle('400'); 121 }); 122 } 123 }; 124 125 /** 126 * Behavior to handler donate type 127 * 128 */ 129 Drupal.behaviors.ntAmaHandlerDonateForm = { 130 attach: function (context, settings) { 131 var val; 132 var total; 133 $('.donate-type .fee-other').on('click', function (event) { 134 ntAmaDonateTotal(); 135 $(this).parents('.donate-type').find('.radio-button').prop('checked', false); 136 }); 137 138 $('.donate-type .fee-other').on('blur', function (event) { 139 ntAmaDonateTotal(); 140 if ($(this).val() != '') { 141 $(this).addClass('fill'); 142 } 143 else { 144 $(this).removeClass('fill'); 145 } 146 }); 147 148 $(".donate-type .fee-other").keypress(function (e) { 149 var key = String.fromCharCode(!e.charCode ? e.which : e.charCode); 150 var string = $(this).val() + key; 151 var regex = new RegExp('^[0-9]+[.]?([0-9])*$'); 152 if (!regex.test(string)) { 153 return false;
154 } 155 }); 156 157 const elements = once('amaDonate', '.ama-donate .radio-button', context); 158 $(elements).change(function () { 159 $(this).parents('.donate-type').find('.fee-other').val(''); 160 $(this).parents('.donate-type').find('.fee-other').removeClass('fill'); 161 ntAmaDonateTotal(); 162 }); 163 164 function ntAmaDonateTotal() { 165 var sum = 0; 166 $('.donate-form .radio-button').each(function (index) { 167 if ($(this).prop('checked') === true) { 168 val = $(this).val().replace(/[^\d.]/g, ''); 169 sum = parseFloat(sum) + parseFloat(val); 170 } 171 }); 172 173 $('.donate-form .fee-other').each(function (index) { 174 if ($(this).val() != '') { 175 val = $(this).val(); 176 sum = parseFloat(sum) + parseFloat(val); 177 } 178 }); 179 180 if (sum != 0) { 181 $('.donate-form .total-value').val(sum); 182 $('.donate-form .total .value').html('$' + sum); 183 } 184 } 185 } 186 }; 187 188 /** 189 * Behavior to handler walk of fame form 190 * 191 */ 192 Drupal.behaviors.ntAmaHandlerWalkOfFameForm = { 193 attach: function (context, settings) { 194 var elements = once('amaWalkOfFameForm', '.ama-walk-of-fame-form .radio-button', context); 195 $(elements).change(function () { 196 var current = $(this).attr('name'); 197 ntAmaHandlerWalkOfFameFormEngraving(current); 198 $(".ama-walk-of-fame-form .radio-button:checked").each(function (index) { 199 if ($(this).attr('name') != current) { 200 $(this).prop('checked', false).attr('checked', false); 201 } 202 }); 203 }); 204 205 $(".clear").click(function (e) { 206 e.preventDefault(); 207 $(this).parents('form')[0].reset(); 208 }); 209 210 /** 211 * Add or remove css class to engraving 212 * @param name 213 */ 214 function ntAmaHandlerWalkOfFameFormEngraving(name) { 215 switch (name) { 216 case 'name_fee': 217 $('.engraving .container, .item-picture').addClass('name-fee'); 218 $('.engraving .container, .item-picture').removeClass('code-fee'); 219 $('.engraving .container, .item-picture').removeClass('reminder-fee'); 220 break; 221 case 'code_fee': 222 $('.engraving .container, .item-picture').addClass('code-fee'); 223 $('.engraving .container, .item-picture').removeClass('name-fee'); 224 $('.engraving .container, .item-picture').removeClass('reminder-fee'); 225 break; 226 case 'reminder_fee': 227 $('.engraving .container, .item-picture').addClass('reminder-fee'); 228 $('.engraving .container, .item-picture').removeClass('name-fee'); 229 $('.engraving .container, .item-picture').removeClass('code-fee'); 230 break; 231 } 232 } 233 } 234 }; 235 236 /** 237 * Behavior to limit characters to only numbers on input 238 * 239 */ 240 Drupal.behaviors.ntAmaHandlerInputOnlyNumbers = { 241 attach: function (context, settings) { 242 $("input.only-numbers").keypress(function (e) { 243 if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) { 244 return false; 245 } 246 }); 247 } 248 }; 249 250 /** 251 * Behavior to limit characters to only alpha numric on input 252 * 253 */ 254 Drupal.behaviors.ntAmaHandlerInputAlphaNumeric = { 255 attach: function (context, settings) { 256 $("body").on('keydown', '.alphanumeric', function (e) { 257 var a = e.key; 258 if (a.length == 1) return /[a-z]|[0-9]/i.test(a); 259 return true; 260 }); 261 } 262 }; 263 264 /** 265 * Behavior to club finder 266 * 267 */ 268 Drupal.behaviors.ntAmaClubFinder = { 269 attach: function (context, settings) { 270 if ($("#edit-reset").length > 0) { 271 $("#edit-reset").parents('form').addClass('form-reset'); 272 } 273 274 $('#edit-submit-club-finder-listing').click(function (event) { 275 var city = $('.ama-club-finder .view-filters .city'); 276 var code = $('.ama-club-finder .view-filters .postal-code'); 277 var state = $('.ama-club-finder .view-filters .state'); 278 var distance_value = $('.ama-club-finder .view-filters .distance-value'); 279 var distance_from = $('.ama-club-finder .view-filters .distance-from'); 280 var distance_from_default = $('.ama-club-finder .view-filters .distance-from option:last'); 281 282 if ((!distance_from.val() || distance_from.val() == '-') && code.val()) { 283 distance_from.val('160.16191'); 284 } 285 }); 286 } 287 }; 288 289 // Class to add animations for fixed header. 290 Drupal.behaviors.ntAmaFixedRegionHeader = { 291 attach: function (context, settings) { 292 const maxScroll = 200; 293 const maxWidth = 215; 294 const minWidth = 140; 295 const toolbarElement = document.querySelector('#toolbar-administration'); 296 const toolbarHeight = toolbarElement ? toolbarElement.offsetHeight : 0; 297 298 function updateLogoSize() { 299 const scrollY = window.scrollY; 300 const adjustedScroll = Math.max(scrollY - toolbarHeight, 0); 301 const scrollRatio = Math.min(adjustedScroll / maxScroll, 1); 302 const width = maxWidth - (scrollRatio * (maxWidth - minWidth)); 303 document.documentElement.style.setProperty('--logo-width', `${width}px`); 304 } 305 306 window.addEventListener('scroll', updateLogoSize); 307 updateLogoSize(); 308 } 309 }; 310 311 Drupal.behaviors.ntAmaTouchScreens = { 312 attach: function (context, settings) { 313 var el = document.getElementsByClassName('level-0')[0]; 314 el.addEventListener("touchstart", handleStart, false); 315 function handleStart() { 316 $('body').addClass('other-touchscreen'); 317 $('.tb-megamenu-item.dropdown', context).on('mouseout', function (e) { 318 $('.level-0 > li').removeClass('open-ms'); 319 }); 320 $('.tb-megamenu-item.dropdown', context).on('mouseover', function (e) { 321 var link = $(this); 322 link.addClass('open-ms'); 323 }); 324 $('.tb-megamenu-item.dropdown', context).on('touchstart', function (e) { 325 'use strict'; 326 var link = $(this); 327 if (link.hasClass('open')) { 328 window.location.href = $(this).find('a').attr('href'); 329 return true; 330 } else { 331 link.addClass('open'); 332 $('.level-0 > a').removeClass('tb-megamenu-clicked'); 333 $(this).find('a.dropdown-toggle').addClass('tb-megamenu-clicked'); 334 $('.level-0 > li').not(this).removeClass('open'); 335 e.preventDefault(); 336 return false;
337 } 338 }); 339 } 340 handleStart(); 341 } 342 }; 343 344 Drupal.behaviors.ntAmaMSTouchScreens = { 345 attach: function (context, settings) { 346 function handleMSStart() { 347 $('.tb-megamenu-item.dropdown', context).on('click', function (e) { 348 'use strict'; 349 var link = $(this); 350 if (link.hasClass('open-ms')) { 351 window.location.href = $(this).find('a').attr('href'); 352 return true; 353 } else { 354 $('.level-0 li').each(function () { $(this).removeClass('open-ms'); }); 355 $('.level-0 a').each(function () { $(this).removeClass('tb-megamenu-clicked'); }); 356 link.addClass('open open-ms'); 357 $(this).find('a.dropdown-toggle').addClass('tb-megamenu-clicked'); 358 e.preventDefault(); 359 return false; 360 } 361 }); 362 } 363 if (window.navigator.pointerEnabled && navigator.maxTouchPoints > 1) { 364 $('body').addClass('ms-surface'); 365 var elms = document.getElementsByClassName('level-0')[0]; 366 elms.addEventListener("click", handleMSStart, false); 367 handleMSStart(); 368 } 369 } 370 }; 371 372 /** 373 * Behavior used to limit megamenu submenu height. 374 * 375 */ 376 Drupal.behaviors.ntAmaTBMegaMenuHeight = { 377 attach: function (context, settings) { 378 379 limitMegaMenuHeight(); 380 381 $(window).resize(function () { 382 limitMegaMenuHeight(); 383 }); 384 } 385 }; 386 387 function limitMegaMenuHeight() { 388 var currentHeight, 389 $window = $(window), 390 windowWidth = $window.width(), 391 windowHeight = $window.height(), 392 headerHeight = $('#header-outer-wrapper').outerHeight() + 35; 393 394 if ($('body').hasClass('toolbar-fixed')) { 395 headerHeight += 78; 396 } 397 398 if (windowWidth > 1024) { 399 $('.tb-megamenu .dropdown-menu').each(function () { 400 currentHeight = 0; 401 currentHeight += $(this).outerHeight(); 402 currentHeight += headerHeight; 403 404 if (windowHeight < currentHeight) { 405 $(this).css({ 'overflow-y': 'scroll', 'max-height': 'calc(100vh - ' + headerHeight + 'px)' }); 406 } 407 else { 408 $(this).css({ 'overflow-y': 'visible', 'max-height': 'none' }); 409 } 410 }); 411 } 412 } 413 414 // Class to hide flying sites in club detail page if flying site not has information 415 Drupal.behaviors.ntAmaClubDetailPage = { 416 attach: function (context, settings) { 417 $('.ama-node.club-detail .attached .item-list .item').each(function (index) { 418 if ($(this).children().length == 1) { 419 $(this).addClass('empty'); 420 } 421 }) 422 } 423 }; 424 425 // Class to hide flying sites in club detail page if flying site not has information 426 Drupal.behaviors.ntAmaStudentFormAutoPupolateEndDate = { 427 attach: function (context, settings) { 428 $('.add-student-form .start-date').change(function () { 429 var start_date_value = $('.add-student-form .start-date').val(); 430 var start_date = new Date(start_date_value); 431 var endDate = new Date(start_date); 432 433 endDate.setDate(endDate.getDate() + 60); 434 var dd = endDate.getDate(); 435 var mm = endDate.getMonth() + 1; 436 var y = endDate.getFullYear(); 437 var formattedDate = mm + '/' + dd + '/' + y; 438 $('.add-student-form .end_date').val(formattedDate); 439 }); 440 } 441 }; 442 443 /** 444 * Behavior to close menu responsive 445 * 446 */ 447 Drupal.behaviors.ntAmaCloseMobileMenu = { 448 attach: function (context, settings) { 449 once('ntAmaCloseMobileMenu', '#off-canvas .mm-navbar', context).forEach(function (element) { 450 $(element).append('<a class="toggle responsive-menu-toggle-icon" href="#off-canvas"></a>'); 451 }); 452 453 $('#off-canvas .mm-listview .join', context).detach().appendTo('.mm-panels'); 454 455 $(context).find('#off-canvas .mm-navbar .toggle').click(function (event) { 456 event.preventDefault(); 457 if ($('#off-canvas').hasClass('mm-opened')) { 458 var API = $("#off-canvas").data("mmenu"); 459 API.close(); 460 } 461 }); 462 } 463 }; 464 465 /** 466 * Behavior to elements with same height 467 * 468 */ 469 Drupal.behaviors.ntAmaElementsEqualHeights = { 470 attach: function (context, settings) { 471 elementsEqualHeights('.ama-finder form'); 472 } 473 }; 474 475 /** 476 * Behavior to add class to wrapper field in ama profile view 477 * 478 */ 479 Drupal.behaviors.ntAmaProfile = { 480 attach: function (context, settings) { 481 $('.view-ama-profile .no-member').closest('.ama-number').addClass('hide'); 482 } 483 }; 484 485 /** 486 * Behavior to customization in club roster 487 * 488 */ 489 Drupal.behaviors.ntAmaClubRoster = { 490 attach: function (context, settings) { 491 var hash = window.location.hash; 492 var hash_id = getNumericPart(hash); 493 if (($(hash).length < 1) && (hash_id > 1)) { 494 var table_type = (hash.indexOf('lapsed') > 0) ? 'lapsed' : 'current'; 495 var hash_name_pattern = '#row-' + table_type + '-'; 496 hash = hash_name_pattern + (hash_id - 1); 497 // I see we are deleting some rows through JS 498 if ($(hash).length < 0) { 499 hash = hash_name_pattern + (hash_id - 2); 500 } 501 } 502 else if (hash && ($('.ama-club-roster-form').length > 0) && ($(hash).length < 1)) { 503 hash = '.ama-club-roster-form'; 504 } 505 506 // Scroll to the element in roster 507 if ($(hash).length > 0) { 508 var diff = ($('header').outerHeight() == 0) ? 300 : $('header').outerHeight() * 2; 509 var element_position = $(hash).offset().top - diff; 510 $([document.documentElement, document.body]).animate({ 511 scrollTop: element_position 512 }, 1000); 513 } 514 // Once compatibility 515 once('roster-table-th', '.roster table thead th', context).forEach(function (element) { 516 if ($(element).find('.tablesort').length == 0) { 517 $(element).find('a').append('<span class="default-sort"></span>'); 518 } 519 $(element).append('<a class="toggle responsive-menu-toggle-icon" href="#off-canvas"></a>'); 520 }); 521 } 522 }; 523 524 // Image to css background. 525 Drupal.behaviors.ntAmaImageToBagground = { 526 attach: function (context, settings) { 527 var images = $('.img-to-bg img'); 528 images.each(function (i) { 529 var css_bg = 'url(' + $(this).attr('src') + ')'; 530 $(this).closest('.img-to-bg').css('background-image', css_bg); 531 }); 532 } 533 }; 534 535 // Remove block from css class. 536 Drupal.behaviors.ntAmaRemoveBlock = { 537 attach: function (context, settings) { 538 $('.ama-advertisers-remove-block .region-postscript-second .ama-partners').remove(); 539 $('.ama-model-aviation-remove-block .region-postscript-first .ama-bg-logo-title-summary-button').remove(); 540 } 541 }; 542 543 /** 544 * Returns numeric part of id used on club roster 545 */ 546 function getNumericPart(id) { 547 var $num = id.replace(/[^\d]+/, ''); 548 return $num; 549 } 550 551 function removeDuplicateRows($table) { 552 function getVisibleRowText($row) { 553 return $row.find('td:visible').text().toLowerCase(); 554 } 555 556 $table.find('tr').each(function (index, row) { 557 var $row = $(row); 558 $row.nextAll('tr').each(function (index, next) { 559 var $next = $(next); 560 if (getVisibleRowText($next) == getVisibleRowText($row)) 561 $next.remove(); 562 }) 563 }); 564 } 565 566 /** 567 * Behavior to close menu responsive 568 * 569 */ 570 Drupal.behaviors.ntAmaToggleUpdateEndDateFlyingSite = { 571 attach: function (context, settings) { 572 $('.trigger-update-end-date-flying-site-form', context).on("click", function () { 573 let thisForm = $(this).next('form[class^="update-end-date-flying-site-form"]'); 574 thisForm.addClass("nt-show-form"); 575 if (thisForm.hasClass("nt-show-form")) { 576 $(".nt-show-form").fadeIn(); 577 } 578 }); 579 580 $('form[id^="update-end-date-flying-site-form"] .cancel', context).click(function (event) { 581 event.preventDefault(); 582 let thisForm = $(this).parents('form[class^="update-end-date-flying-site-form"]'); 583 thisForm.removeClass("nt-show-form"); 584 if (thisForm.not(".nt-show-form")) { 585 thisForm.fadeOut(); 586 } 587 }); 588 } 589 }; 590 591 // Elements same height 592 function elementsEqualHeights(element) { 593 var currentTallest = 0, 594 currentRowStart = 0, 595 rowDivs = new Array(), 596 $el, 597 topPosition = 0; 598 599 $(element).each(function () { 600 601 $el = $(this); 602 603 topPosition = $el.offset().top; 604 605 if (currentRowStart != topPosition) { 606 607 // we just came to a new row. Set all the heights on the completed row 608 for (var currentDiv = 0; currentDiv < rowDivs.length; currentDiv++) { 609 rowDivs[currentDiv].height(currentTallest); 610 } 611 612 // set the variables for the new row 613 rowDivs.length = 0; // empty the array 614 currentRowStart = topPosition; 615 currentTallest = $el.height(); 616 rowDivs.push($el); 617 618 } 619 else { 620 // another div on the current row. Add it to the list and check if it's taller 621 rowDivs.push($el); 622 currentTallest = Math.max(currentTallest, $el.height()); 623 } 624 625 // do the last row 626 for (currentDiv = 0; currentDiv < rowDivs.length; currentDiv++) { 627 rowDivs[currentDiv].height(currentTallest); 628 } 629 }); 630 } 631 632 /** 633 * Make checkboxes behave like radio buttons. 634 * 635 */ 636 Drupal.behaviors.ntAmaCheckboxAsRadioOnCharterRenewal = { 637 attach: function (context, settings) { 638 $('.club-officer-positions-table-form input[type="checkbox"]', context).on('change', function () { 639 $('.club-officer-positions-table-form input[type="checkbox"]', context).not(this).each(function () { 640 $(this).prop('checked', false); 641 }); 642 }); 643 } 644 }; 645 646 /** 647 * Club Finder Form Loader 648 * 649 */ 650 Drupal.behaviors.clubFinderForm = { 651 attach: function (context, settings) { 652 $(document).ready(function () { 653 if ($('.ama-club-finder-form').length) { 654 $('.ama-club-finder-form .form--inline').animate({ opacity: 1 }, 300); 655 } 656 }); 657 } 658 }; 659 660 /* 661 * Add "is-active" class to parent 'a' elements of the active menu item. 662 * 663 */ 664 Drupal.behaviors.customBehavior = { 665 attach: function (context, settings) { 666 // Find the first element with the class "is-active" 667 let elementsActive = context.querySelector('.is-active'); 668 // Stop the loop in the first element of menu 669 while (elementsActive && elementsActive.getAttribute('href') !== '#mm-1') { 670 let elementsPanel = elementsActive.closest('.mm-panel'); 671 672 let elementsDivEnNavbar = elementsPanel?.querySelector('.mm-navbar__title'); 673 // Find all menu items 674 let menuAllItems = Array.from(context.querySelectorAll('.mm-panels .mm-listitem__text')); 675 // Find the parent of the first active element 676 let activeMenuItem = menuAllItems.find(menuItem => menuItem?.textContent.trim() === elementsDivEnNavbar?.textContent.trim()); 677 if (activeMenuItem) { 678 activeMenuItem.classList.add('is-active'); 679 elementsActive = context.querySelector('.is-active'); // Update elementsActive for the next iteration 680 } else { 681 break; // Break the loop if activeMenuItem is not found 682 } 683 } 684 } 685 }; 686 687})(jQuery, Drupal, drupalSettings);
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.