PageSourceSearch

https://www.modelaircraft.org/themes/custom/nt_ama/js/nt_ama.js?v=10.6.17

js modelaircraft.org collected 2026-09-24 09:05:52 UTC 22,603 bytes, 687 lines download raw bytes

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.