PageSourceSearch

https://dcri.org/themes/contrib/som/js/global.js?v=10.6.17

js dcri.org collected 2026-10-02 03:26:13 UTC 10,097 bytes, 288 lines download raw bytes

1/**
2 * @file
3 * Global utilities.
4 *
5 */
6(function ($, Drupal) {
7  "use strict";
8
9  // Drupal.behaviors.som = {
10  //   attach: function (context, settings) {
11  //     var position = $(window).scrollTop();
12  //     $(window).scroll(function () {
13  //       if ($(this).scrollTop() > 50) {
14  //         $("body").addClass("scrolled");
15  //       } else {
16  //         $("body").removeClass("scrolled");
17  //       }
18  //       var scroll = $(window).scrollTop();
19  //       if (scroll > position) {
20  //         $("body").addClass("scrolldown");
21  //         $("body").removeClass("scrollup");
22  //       } else {
23  //         $("body").addClass("scrollup");
24  //         $("body").removeClass("scrolldown");
25  //       }
26  //       position = scroll;
27  //     });
28  //   },
29  // };
30
31  Drupal.behaviors.som = {
32    attach: function (context, settings) {
33      $(document).ready(function () {
34
35        $.each( $(".masonry"), function() {
36          var masonrySelector = $(this);
37          var masonryOptions = {
38            itemSelector: ".masonry .views-row",
39            horizontalOrder: true,
40          };
41
42          if (masonrySelector.hasClass("format-tile")) {
43            let grid = masonrySelector.find(".view");
44            grid.masonry(masonryOptions);
45          }
46
47          // blog view buttons toggle
48          $(".blog-tile-button").on("click", function () {
49            let $masonry = $(this)
50              .parents(".blog-format-switcher")
51              .siblings(".masonry");
52            let $grid = $masonry.find(".view");
53            let isMasonryActive = Masonry.data($($grid)[0])
54              ? Masonry.data($($grid)[0]).options.initLayout
55              : false;
56
57            $masonry.addClass("format-tile").removeClass("format-list");
58
59            if (!isMasonryActive) {
60              $grid.masonry(masonryOptions); // re-initialize
61            }
62          });
63
64          $(".blog-list-button").on("click", function () {
65            let $masonry = $(this)
66              .parents(".blog-format-switcher")
67              .siblings(".masonry");
68            let $grid = $masonry.find(".view");
69            let isMasonryActive = Masonry.data($($grid)[0])
70              ? Masonry.data($($grid)[0]).options.initLayout
71              : false;
72
73            $masonry.addClass("format-list").removeClass("format-tile");
74
75            if (isMasonryActive) {
76              $grid.masonry("destroy"); // destroy
77            }
78          });
79        });
80
81        // Replace the Search button with an icon in Stories unfiltered view exposed filter
82        $("#edit-submit-stories-view").replaceWith(
83          '<button class="btn" type="submit" id="edit-submit-stories-view"><i class="fa fa-search"></i></button>'
84        );
85        $("#edit-keyword").attr("placeholder", "Search");
86
87        // Open the accordion if linked from URL
88        if (window.location.hash != "") {
89          var accordionItemID = window.location.hash;
90          $(accordionItemID).collapse("show");
91
92          $("html, body").animate(
93            { scrollTop: $(accordionItemID).offset().top - 80 },
94            500,
95            "linear"
96          );
97        }
98
99        // Labs sidebar mobile collapse button behavior
100        $("#labs-sidebar-additional").on("show.bs.collapse", function () {
101          var $button = $('[data-bs-target="#labs-sidebar-additional"]');
102          $button.find(".expand-text").addClass("d-none");
103          $button.find(".collapse-text").removeClass("d-none");
104          $button.find(".expand-icon").addClass("d-none");
105          $button.find(".collapse-icon").removeClass("d-none");
106          $button.attr("aria-expanded", "true");
107        });
108
109        $("#labs-sidebar-additional").on("hide.bs.collapse", function () {
110          var $button = $('[data-bs-target="#labs-sidebar-additional"]');
111          $button.find(".expand-text").removeClass("d-none");
112          $button.find(".collapse-text").addClass("d-none");
113          $button.find(".expand-icon").removeClass("d-none");
114          $button.find(".collapse-icon").addClass("d-none");
115          $button.attr("aria-expanded", "false");
116        });
117      });
118
119      function a11yClick(event) {
120        if (event.type === "click") {
121          return true;
122        } else if (event.type === "keypress") {
123          var code = event.charCode || event.keyCode;
124          if (code === 32 || code === 13) {
125            return true;
126          }
127        } else {
128          return false;
129        }
130      }
131
132      // Sidebar menu behavior
133      var sideNavCaret = $(".sidebar-menu .caret");
134      var sideNavCaretCurrent = $(".sidebar-menu .active.has-submenu > .caret");
135
136      // Initially add correct expanded attributes for caret on load
137      sideNavCaretCurrent.attr("aria-expanded", "true");
138      sideNavCaretCurrent.next(".submenu").css("display", "block");
139
140      // Toggle attributes and animations
141      sideNavCaret.on("click keypress", function (e) {
142        if (a11yClick(e) === true) {
143          const _d = $(this).next(".submenu");
144          _d.slideToggle();
145          var _s = $(this).attr("aria-expanded");
146          $(this).toggleClass("expanded");
147          if (_s == "false") {
148            $(this).attr("aria-expanded", "true");
149          } else {
150            $(this).attr("aria-expanded", "false");
151          }
152        }
153      });
154    },
155  };
156
157  Drupal.behaviors.add_screenreader_menu_actions = {
158    attach: function () {
159      var $mm_itemToggle = $(
160        "#block-mainnavigation .navbar-nav > .nav-item > .dropdown-toggle"
161      );
162      var $mm_item = $("#block-mainnavigation .navbar-nav > .nav-item");
163
164      // Keyboard toggle
165      $mm_itemToggle.attr("aria-haspopup", "true");
166      $mm_itemToggle.bind("click", function () {
167        var expandedState = $(this).attr("aria-expanded");
168        if (expandedState == "true") {
169          $(this).next().attr("aria-hidden", "true");
170        } else {
171          $(this).next().attr("aria-hidden", "false");
172        }
173      });
174      // mouse hover
175      $mm_item.bind("mouseenter", function () {
176        if (window.matchMedia("(min-width: 992px)").matches) {
177          $(this).find("> button").attr("aria-expanded", "true");
178          $(this).find("> ul").addClass("show").attr("aria-hidden", "false");
179        }
180      });
181      $mm_item.bind("mouseleave", function () {
182        if (window.matchMedia("(min-width: 992px)").matches) {
183          $(this).find("> button").attr("aria-expanded", "false");
184          $(this).find("> ul").removeClass("show").attr("aria-hidden", "true");
185        }
186      });
187    },
188  };
189
190  Drupal.behaviors.polite_sticky_header = {
191    attach: function (context, settings) {
192      var $header = $('.header', context);
193      var $body = $('body');
194      var headerHeight = 0;
195      var lastScrollTop = 0;
196      var scrollThreshold = 50; // Minimum scroll distance before triggering
197      var isSticky = false;
198      var isHidden = false;
199      var scrollTimeout;
200
201      // Initialize header height and sticky state
202      function initHeader() {
203        headerHeight = $header.outerHeight();
204        // Don't add padding initially - only when header becomes sticky
205      }
206
207            // Update header state based on scroll position and direction
208      function updateHeaderState() {
209        var scrollTop = $(window).scrollTop();
210        var scrollDelta = scrollTop - lastScrollTop;
211
212        // Only trigger if scroll distance is significant
213        if (Math.abs(scrollDelta) < scrollThreshold) {
214          return;
215        }
216
217        // Determine scroll direction
218        var isScrollingDown = scrollDelta > 0;
219        var isScrollingUp = scrollDelta < 0;
220
221        // Handle sticky positioning - snap immediately when scrolling down past header height
222        if (scrollTop > headerHeight && !isSticky) {
223          $header.addClass('header--sticky');
224          $body.addClass('header-sticky-active').css('padding-top', headerHeight + 'px');
225          isSticky = true;
226          isHidden = false;
227
228          // Enable transitions after a brief delay to allow immediate positioning
229          setTimeout(function() {
230            $header.addClass('header--transitions-enabled');
231          }, 50);
232        } else if (scrollTop <= headerHeight && isSticky) {
233          // Calculate seamless position when scrolling back up within header height
234          var scrollDifference = scrollTop - headerHeight;
235          var headerOffset = Math.max(0, scrollDifference);
236
237          // Position header based on scroll difference
238          $header.css('top', headerOffset + 'px');
239
240          // If we've scrolled all the way back to the top, return to normal flow
241          if (scrollTop <= 0) {
242            $header.removeClass('header--sticky header--hidden header--visible header--transitions-enabled').css('top', '');
243            $body.removeClass('header-sticky-active').css('padding-top', '0');
244            isSticky = false;
245            isHidden = false;
246            return;
247          }
248        }
249
250        // Handle show/hide animations with smooth transitions when sticky
251        if (isSticky) {
252          if (isScrollingUp && isHidden) {
253            // Show header with smooth transition when scrolling up
254            $header.removeClass('header--hidden').addClass('header--visible');
255            isHidden = false;
256          } else if (isScrollingDown && !isHidden) {
257            // Hide header with smooth transition when scrolling down
258            $header.removeClass('header--visible').addClass('header--hidden');
259            isHidden = true;
260          }
261        }
262
263        lastScrollTop = scrollTop;
264      }
265
266      // Throttled scroll handler
267      function handleScroll() {
268        if (scrollTimeout) {
269          clearTimeout(scrollTimeout);
270        }
271        scrollTimeout = setTimeout(updateHeaderState, 10);
272      }
273
274      // Initialize on page load
275      $(document).ready(function() {
276        initHeader();
277
278        // Handle window resize
279        $(window).on('resize', function() {
280          initHeader();
281        });
282
283        // Handle scroll events
284        $(window).on('scroll', handleScroll);
285      });
286    },
287  };
288})(jQuery, Drupal);

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.