PageSourceSearch

https://www.securitymagazine.com/javascripts/application.js?v=1790233200

js securitymagazine.com collected 2026-09-24 08:26:57 UTC 15,780 bytes, 524 lines download raw bytes

1// Place your application-specific JavaScript functions and classes here
2// This file is automatically included by javascript_include_tag :defaults
3;
4/**
5 * listen for afterMenu right away and set a cookie when its ready
6 */
7$(document).one("epub.afterMenu", function () {
8  $.cookie("epubAfterMenu", true, { path: "/" });
9});
10
11$(function () {
12  if ($("#related-categories").length > 0) {
13    require(["components/expandable-nav"], function (ExpandableNav) {
14      new ExpandableNav("#related-categories", {
15        defaultVisibleItems: 4,
16      });
17    });
18  }
19});
20
21if ($(".page-search-index").length > 0) {
22  require([
23    "pickerdate",
24    "css!/javascripts/vendor/pickadatejs/themes/classic",
25    "css!/javascripts/vendor/pickadatejs/themes/classic.date",
26  ], function (pickadate) {
27    $(function () {
28      $("#filter_start_date, #filter_end_date").pickadate({
29        max: new Date(),
30        formatSubmit: "mm/dd/yyyy",
31        hiddenName: true,
32        selectYears: true,
33        onStart: function () {
34          this.set("select", null);
35        },
36      });
37    });
38  });
39}
40
41require(["jquery", "components/add-this-toolbox"], function (
42  $,
43  AddThisToolbox
44) {
45  $(function () {
46    var services = [
47      { name: "print" },
48      { name: "email" },
49      { name: "facebook", type: "counter" },
50      { name: "twitter" },
51      { name: "linkedin", type: "counter" },
52      { name: "more" },
53    ];
54
55    $(".addthis-toolbox").each(function () {
56      new AddThisToolbox(this, {
57        services: services,
58      });
59    });
60  });
61});
62
63$(function() {
64  const mainHeader = document.querySelector(".main-header");
65
66  if (mainHeader && !mainHeader.classList.contains("event-microsite")) {
67    require([
68      "jquery",
69      "mobile-nav",
70      "nav-quick-return",
71      "quick-search",
72      "user-actions",
73    ], function ($, MobileNav, NavQuickReturn, QuickSearch) {
74      let config = {};
75
76      // Diff order and config of Mobile Menu for v2 redesign
77      // TODO: Refactor once all sites are on v2
78      if (window.homeVersionV2Enabled) {
79        config = {
80          triggerID: "#hamburger-nav-link,#search-nav-link",
81          addBeforeMenu: [
82            ".main-nav--horizontal:not(.main-nav--horizontal--quick-return) #user-actions",
83            "#user-actions",
84            "#quick-search",
85            "#subscribe-mobile-nav-link",
86          ],
87          addAfterMenu: ["#directory-nav", "#cart-social-wrapper"],
88          mmenuConfigAddon: {
89            classNames: {
90              fixedElements: {
91                fixedTop: "main-header--quick-return",
92              },
93            },
94          },
95          mmenu: {
96            offCanvas: {
97              position: "right",
98            },
99          },
100        };
101      } else {
102        config = {
103          addBeforeMenu: [
104            "#quick-search",
105            "#user-actions",
106            "#subscribe-mobile-nav-link",
107          ],
108          addAfterMenu: ["#directory-nav", "#cart-link", "#social-links"],
109          mmenuConfigAddon: {
110            classNames: {
111              fixedElements: {
112                fixedTop: "main-header--quick-return",
113              },
114            },
115          },
116        };
117      }
118
119      new MobileNav(".main-nav--horizontal", config);
120      
121      new NavQuickReturn(".main-header", {
122        mediaQuery: "screen and (max-width: 1200px)",
123        appendCloneTo: ".mmenu-placeholder",
124      });
125
126      new NavQuickReturn(".main-nav--horizontal");
127
128      new QuickSearch("#quick-search");
129    });
130  }
131});
132
133require([
134  "jquery",
135  "follow-scroll",
136  "sponsored-content-help",
137  "selectize",
138  "bundle/scrolldepth.bundle",
139], function (
140  $,
141  FollowScroll,
142  SponsoredContentHelp,
143  selectize,
144  ScrollDepthWrapper
145) {
146  $(function () {
147    new ScrollDepthWrapper.default();
148
149    if (!window.homeVersionV2Enabled) {
150      new FollowScroll("#homepage-left-column", {
151        bottomPosition: function () {
152          return $("#main-footer").offset().top;
153        },
154        mediaQuery: "screen and (min-width: 950px)",
155      });
156
157      new FollowScroll("#main-sidebar", {
158        bottomPosition: function () {
159          return $("#main-footer").offset().top;
160        },
161      });
162
163      new FollowScroll("#featured-home-contents", {
164        bottomPosition: function () {
165          return $("#main-footer").offset().top;
166        },
167      });
168    }
169
170    if (!Modernizr.csstransitions) {
171      $(".main-nav--horizontal").on(
172        {
173          mouseenter: function mainNavMouseEnter() {
174            $(this).find(".level2").show();
175          },
176          mouseleave: function mainNavMouseLeave() {
177            $(this).find(".level2").hide();
178          },
179        },
180        ".level1-li"
181      );
182    }
183
184    $("#subscribe-now").on(
185      "click.subscribe-now",
186      ".subscribe-now__subscribe-link",
187      function openSubscribeNowDropdown(e) {
188        e.preventDefault();
189        var $nav = $(this).next(".subscribe-now__nav");
190        // Animation Fallback if No CSS3 Transition Support
191        if (!Modernizr.csstransitions) {
192          $nav.slideToggle();
193        } else {
194          $nav.toggleClass("js-animate--flip-open");
195        }
196      }
197    );
198
199    $("#home-subscribe-cta").on(
200      "click.home-subscribe-cta",
201      ".home-subscribe-cta__subscribe-link",
202      function openSubscribeNowDropdown(e) {
203        e.preventDefault();
204        var $nav = $(this).next(".home-subscribe-cta__nav");
205        // Animation Fallback if No CSS3 Transition Support
206        if (!Modernizr.csstransitions) {
207          $nav.slideToggle();
208        } else {
209          $nav.toggleClass("js-animate--flip-open");
210        }
211      }
212    );
213
214    // Hide Apprenticeship Reviews Directories breadcrumbs
215    if ($(".breadcrumbs").length) {
216      const breadcrumb = $(".breadcrumbs").text();
217      if (breadcrumb.indexOf("Apprenticeship") > 0) {
218        $(".breadcrumbs").hide();
219      }
220    }
221
222    if ($("#sponsored-content").length) {
223      new SponsoredContentHelp("#sponsored-content");
224    }
225    if ($("#home-sponsored-content").length) {
226      new SponsoredContentHelp("#home-sponsored-content", {
227        component: ".sponsored-content-list",
228      });
229    }
230    if ($("#sponsored-content-widget").length) {
231      new SponsoredContentHelp("#sponsored-content-widget", {
232        component: ".sponsored-content-widget",
233      });
234    }
235    if ($("#topic-sponsored-article").length) {
236      new SponsoredContentHelp("#topic-sponsored-article", {
237        component: ".sponsored-content-widget",
238      });
239    }
240
241    // Replace select fields with improved UI
242    // Cache to var to use API
243    // Implemented using workaround https://github.com/brianreavis/selectize.js/issues/744
244    $("select").each(function () {
245      // The 'if' makes sure that selectize does not get added to the drop downs
246      // in the calendar search for select year.
247      if (!$(this).hasClass("picker__select--year")) {
248        $(this).selectize();
249      }
250    });
251    $(window).on("pageshow", function () {
252      var $location = $("#location");
253      if ($location.length) {
254        var $select = $location.selectize();
255        var selectize = $select[0].selectize;
256        if (selectize) {
257          selectize.clear(); // Clears the selected value on page load
258        }
259      }
260    });
261  
262    // Checkout Page: Update the country and state custom select fields,
263    // on the change event of the native select fields. This is
264    // for when the shipping address is the same as billing.
265
266    $("#bill_country_id").on("change", function () {
267      var value = $(this).val();
268      var selectize = $("#ship_country_id")[0].selectize;
269      selectize.setValue(value);
270    });
271
272    $("#bill_state_id").on("change", function () {
273      var value = $(this).val();
274      var selectize = $("#ship_state_id")[0].selectize;
275      selectize.setValue(value);
276    });
277
278    // jQuery validation will ignore hidden elements,
279    // since we are using Selectize to replace select fields,
280    // we must set validation to ignore hidden fields with the exception
281    // of selectize controlled hidden fields
282    $.validator.setDefaults({
283      ignore:
284        ":hidden:not([class~=selectized]),:hidden > .selectized, .selectize-control .selectize-input input",
285    });
286
287    /*
288      This corrects a bug on the navigation for tablet devices where a click on the
289      parent link was going directly to the link and not expanding the level2 nav
290      items.  This prevents default in cases where the level2 nav is not currently
291      visible.
292    */
293    $(".main-nav--horizontal").on("click", ".link2", function (evt) {
294      if ($(this).siblings(".level2").height() == 0) {
295        evt.preventDefault();
296      }
297    });
298
299    // Detect RFP form changes and show red dot on submit
300    const RFPChange = localStorage.getItem("rfpchange");
301    if (RFPChange === "true") {
302      $(".badge-dot-edit").show();
303    }
304    $(".rfp-form input, .rfp-form select, .rfp-form textarea").on(
305      "input",
306      function () {
307        $(".badge-dot-edit").show();
308      }
309    );
310    $(".rfp-add-supplier-button").click(function () {
311      localStorage.setItem("rfpchange", "true");
312      $(".badge-dot-edit").show();
313    });
314    $(".rfp-form__button-container input").click(function () {
315      localStorage.removeItem("rfpchange");
316    });
317  });
318});
319
320// Initialize all the brightcove video lists we find that have the following markup
321//
322// <div
323//  data-playlist-id=""
324//  data-player-url=""
325//  data-open-in-new-window=""
326//  data-width=""
327//  data-height=""
328//  data-video-logo=""
329//  data-video-play-arrow=""
330//  data-randomize-videos=""
331//  data-show-long-descriptions=""
332//  data-max-videos-visible="">
333// </div>
334//
335//
336require(["jquery"], function ($) {
337  $(function () {
338    $("div[data-playlist-id]").each(function () {
339      var videoDiv = $(this);
340      // If we don't find any, this won't ever be pulled in
341      require([
342        "bundle/brightcove-video-list.bundle",
343      ], function (videoBrightCoveGallery) {
344        var playlist_id = videoDiv.data("playlist-id");
345        var player_url = videoDiv.data("player-url");
346        var width = videoDiv.data("width");
347        var height = videoDiv.data("height");
348        var openInNewWindow = videoDiv.data("open-in-new-window");
349        var randomizeVideos = videoDiv.data("randomize-videos");
350        var showLongDescriptions = videoDiv.data("show-long-descriptions");
351        var video_logo = videoDiv.data("video-logo");
352        var video_play_arrow = videoDiv.data("video-play-arrow");
353        var max_videos_visible = videoDiv.data("max-videos-visible");
354        var max_thumbnails_visible = videoDiv.data("max-thumbnails-visible");
355        var autoplay = videoDiv.data("autoplay");
356        var carousel = videoDiv.data("carousel");
357        var token =
358          videoDiv.data("token") ||
359          "BCpkADawqM1CSLkNMXl4noZnUFKfkqq30qsaWUzd5MZ8UFUmwKL7KzrYLM-Z9C_5OJG351h5c1ZBtJFULAf6Jp_hmftcuqTx93AFdiL1lNh6YaeVgKAS5unUTZ0";
360
361        var videoList = new videoBrightCoveGallery.default(
362          videoDiv,
363          playlist_id,
364          token,
365          player_url,
366          {
367            width: width,
368            height: height,
369            openInNewWindow: openInNewWindow,
370            randomizeVideos: randomizeVideos,
371            showLongDescriptions: showLongDescriptions,
372            video_logo: video_logo,
373            max_videos_visible: max_videos_visible,
374            max_thumbnails_visible: max_thumbnails_visible,
375            carousel: carousel,
376          },
377          {
378            autoplay: autoplay,
379          }
380        );
381      });
382    });
383  });
384});
385
386window.addEventListener("load", function (event) {
387  require([
388    "jquery",
389    "bundle/olytics-dfp.bundle",
390    "bundle/dfp-ads.bundle",
391    "bundle/modify-dfp-targeting.bundle",
392    "bundle/geolocation.bundle",
393  ], function ($, olyticsDFPInit, GoogleTagSetup, ModifyDfpTargeting, Geolocation) {
394    // wrapper function for ad initialization
395    const init_ads = () => {
396      /**
397       * A better way of ensuring that window.olytics is completely
398       * ready. Relying on the load of olyticsImport script revealed an
399       * async issue.
400       */
401      const checkForOlyticsHandler = setInterval(function () {
402        if (
403          typeof window.olytics !== "undefined" &&
404          "ready" in window.olytics
405        ) {
406          window.olytics.ready(olyticsInit);
407        }
408      }, 200);
409
410      const olyticsGiveupHandler = setTimeout(function () {
411        if (
412          typeof window.olytics !== "undefined" &&
413          "ready" in window.olytics
414        ) {
415          clearTimeout(olyticsGiveupHandler);
416          return;
417        }
418        clearInterval(checkForOlyticsHandler);
419        dfpInit();
420      }, 1500);
421
422      function dfpInit() {
423        var href = window.location.href;
424        var shouldCollapse = !(
425          href.includes(".stage.epublishing.com") || href.includes(":3000")
426        );
427
428        window.dfpAds = new GoogleTagSetup.default(targeting, {
429          refreshChangeCorrelator: true,
430          collapse: shouldCollapse,
431          slotRenderEnded: function (evt, slot) {
432            if (typeof slot === "undefined") return;
433
434            var $slot = $("#" + slot.id);
435            var $frame = $($slot.find("iframe").prop("contentDocument"));
436
437            if (!$frame.length && shouldCollapse) return $slot.remove();
438
439            $frame.on("load", function () {
440              if ($frame.find("canvas,img").length) return;
441
442              shouldCollapse && $slot.remove();
443            });
444          },
445        });
446      }
447
448      function olyticsInit() {
449        /**
450         * kick off olytics DFP
451         */
452        clearInterval(checkForOlyticsHandler);
453        clearTimeout(olyticsGiveupHandler);
454        window.olytics.loadDfpSegments();
455
456        window.olyticsDfpSegments = function (segments) {
457          /**
458           * olytics is looking for this global function as its callback
459           * segments from `loadDfpSegments` are sent to this function
460           */
461          new olyticsDFPInit.default(segments, {
462            awaitMobileNav: true,
463            initDFP: function (mergedTargeting) {
464              targeting = ModifyDfpTargeting.modifyDfpTargeting(
465                mergedTargeting,
466                {
467                  reg_user: "email",
468                }
469              );
470
471              dfpInit();
472            },
473          });
474        };
475      }
476    };
477
478    if (typeof window.OneTrust == 'undefined') return init_ads();
479
480    // run ads for everyone outside eu, otherwise wait for consent, checking every second
481    Geolocation.default(
482      () => {
483        // check for affirmative consent every second
484        const check_interval = setInterval(() => {
485          if (!document.cookie.includes("C0004%3A1")) return;
486
487          clearInterval(check_interval);
488          init_ads();
489        }, 1000);
490      },
491      () => {
492        // run ads until they opt out everywhere else
493        if (document.cookie.includes("C0004%3A0")) return;
494
495        init_ads();
496      }
497    );
498  });
499});
500
501require(["jquery"], function ($) {
502  $(document).ready(function () {
503    if (
504      $("body").data("controller") == "events" &&
505      $("body").data("action") == "category"
506    ) {
507      $(".live-and-upcoming__see-full-description").on("click", function () {
508        $button = $(this);
509        const eventID = $button.data("eventId");
510
511        $("#classification-title__description--truncated-" + eventID).toggle();
512        $("#classification-title__description--full-" + eventID).toggle();
513
514        const SEE_FULL = "See Full Description";
515        const COLLAPSE = "Collapse Full Description";
516        if ($button.text() === SEE_FULL) {
517          $button.text(COLLAPSE);
518        } else {
519          $button.text(SEE_FULL);
520        }
521      });
522    }
523  });
524});

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.