PageSourceSearch

https://theskydeck.com/wp-content/themes/skydeck/library/js/scripts.js?ver=7.1.2

js theskydeck.com collected 2026-09-24 09:20:54 UTC 25,552 bytes, 672 lines download raw bytes

1/*
2Bones Scripts File
3Author: Caitlin DiMare-Oliver & Frank Korf
4
5This file should contain any js scripts you want to add to the site.
6Instead of calling it in the header or throwing it inside wp_head()
7this file will be called automatically in the footer so as not to
8slow the page load.
9
10*/
11
12$ = jQuery;
13ldm = {};
14
15
16/** =======================================================================
17    UTILITY FUNCTIONS
18======================================================================== */
19
20
21/* A fix for the iOS orientationchange zoom bug.
22  Script by @scottjehl, rebound by @wilto.
23  MIT License.
24  */
25(function(w){
26    // This fix addresses an iOS bug, so return early if the UA claims it's something else.
27    if( !( /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1 ) ){ return; }
28    var doc = w.document;
29    if( !doc.querySelector ){ return; }
30    var meta = doc.querySelector( "meta[name=viewport]" ),
31        initialContent = meta && meta.getAttribute( "content" ),
32        disabledZoom = initialContent + ",maximum-scale=1",
33        enabledZoom = initialContent + ",maximum-scale=10",
34        enabled = true,
35        x, y, z, aig;
36    if( !meta ){ return; }
37    function restoreZoom(){
38        meta.setAttribute( "content", enabledZoom );
39        enabled = true; }
40    function disableZoom(){
41        meta.setAttribute( "content", disabledZoom );
42        enabled = false; }
43    function checkTilt( e ){
44        aig = e.accelerationIncludingGravity;
45        x = Math.abs( aig.x );
46        y = Math.abs( aig.y );
47        z = Math.abs( aig.z );
48        // If portrait orientation and in one of the danger zones
49        if( !w.orientation && ( x > 7 || ( ( z > 6 && y < 8 || z < 8 && y > 6 ) && x > 5 ) ) ){
50            if( enabled ){ disableZoom(); } }
51        else if( !enabled ){ restoreZoom(); } }
52        w.addEventListener( "orientationchange", restoreZoom, false );
53        w.addEventListener( "devicemotion", checkTilt, false );
54})( this );
55
56
57// Utility Function to verify that we are on mobile
58isMobile = {
59  //Android: function(){return navigator.userAgent.match(/Android/i) ? true : false;},
60  Android: function(){return navigator.userAgent.match(/Android/i) ? true : false;},
61  BlackBerry: function(){return navigator.userAgent.match(/BlackBerry/i) ? true : false;},
62  iOS: function(){return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;},
63  Windows: function(){return navigator.userAgent.match(/IEMobile/i) ? true : false;},
64  any: function(){return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());},
65  tablet: function(){return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows()) && jQuery(window).width() > 767;}
66};
67isSmallMobile = { any: function(){return jQuery(window).width() < 767;} }
68
69/* -------------------------------------------
70    Mobile Menu Animation
71------------------------------------------- */
72function openNav() {
73    //document.getElementById("ldmSidenav").style.width = "100%";
74    var sidenav = document.getElementById("ldmSidenav");
75    sidenav.style.marginRight = "0%";
76    sidenav.removeAttribute("inert");
77    sidenav.setAttribute("aria-hidden", "false");
78    sidenav.tabIndex = "0";
79    // Clear aria-hidden that external scripts may have propagated to interactive descendants
80    sidenav.querySelectorAll('a[aria-hidden="true"], button[aria-hidden="true"]').forEach(function(el) {
81        el.removeAttribute('aria-hidden');
82    });
83    document.querySelector(".header__toggler").setAttribute("aria-expanded", "true");
84    document.querySelector("html").classList.add("overflow-hidden");
85
86    // Move focus to first nav item after transition starts
87    setTimeout(function() {
88        var firstItem = sidenav.querySelector('a[href], button:not([disabled])');
89        if (firstItem) { firstItem.focus(); }
90    }, 50);
91}
92function closeNav() {
93    //document.getElementById("ldmSidenav").style.width = "100%";
94    var sidenav = document.getElementById("ldmSidenav");
95    sidenav.style.marginRight = "-100%";
96    sidenav.setAttribute("inert", "");
97    var toggler = document.querySelector(".header__toggler");
98    if (toggler) { toggler.focus(); }
99    sidenav.setAttribute("aria-hidden", "true");
100    if (toggler) { toggler.setAttribute("aria-expanded", "false"); }
101    document.querySelector("html").classList.remove("overflow-hidden");
102	document.querySelector(".slide-menu .slider").style.height = '';
103}
104
105jQuery(document).ready(function($) {
106    //console.log("page loaded");
107        var menuLeft = $('#menu-left').slideMenu({
108            position: 'left',
109            keycodeClose: 0,
110            submenuLinkAfter: ' <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M342.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L274.7 256 105.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z"/></svg> ',
111            backLinkBefore: ' <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 278.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z"/></svg> '
112        });
113    });
114
115document.addEventListener('keydown', function(e) {
116    var toggler = document.querySelector('.header__toggler');
117    var isOpen  = toggler && toggler.getAttribute('aria-expanded') === 'true';
118
119    if (e.key === 'Escape') {
120        if (isOpen) {
121            closeNav();
122            toggler.focus();
123        }
124        return;
125    }
126
127    if (e.key === 'Tab' && isOpen) {
128        var sidenav = document.getElementById('ldmSidenav');
129        if (!sidenav) { return; }
130
131        // Use getBoundingClientRect so elements slid off-screen by CSS transform are excluded
132        var sidenavRect = sidenav.getBoundingClientRect();
133        var focusable = Array.prototype.slice.call(
134            sidenav.querySelectorAll('a[href], button:not([disabled])')
135        ).filter(function(el) {
136            var rect = el.getBoundingClientRect();
137            return rect.width > 0 && rect.height > 0 && rect.right > sidenavRect.left + 1
138                && el.getAttribute('aria-hidden') !== 'true';
139        });
140
141        if (!focusable.length) { return; }
142
143        e.preventDefault();
144
145        var idx = focusable.indexOf(document.activeElement);
146        var nextIdx;
147
148        if (idx === -1 && !e.shiftKey) {
149            // Active element is off-screen (e.g. parent item after submenu opens).
150            // Jump to the first visible item inside the slider (back link or first subitem).
151            var slider = sidenav.querySelector('.slider');
152            nextIdx = slider ? focusable.findIndex(function(el) { return slider.contains(el); }) : 0;
153            if (nextIdx === -1) { nextIdx = 0; }
154        } else if (e.shiftKey) {
155            nextIdx = idx <= 0 ? focusable.length - 1 : idx - 1;
156        } else {
157            nextIdx = idx >= focusable.length - 1 ? 0 : idx + 1;
158        }
159
160        var nextEl = focusable[nextIdx];
161        nextEl.focus({ preventScroll: true });
162
163        var scrollContainer = document.querySelector('.slide-menu');
164        if (scrollContainer && scrollContainer.contains(nextEl)) {
165            var elRect = nextEl.getBoundingClientRect();
166            var containerRect = scrollContainer.getBoundingClientRect();
167            if (elRect.bottom > containerRect.bottom) {
168                scrollContainer.scrollTop += elRect.bottom - containerRect.bottom + 4;
169            } else if (elRect.top < containerRect.top) {
170                scrollContainer.scrollTop -= containerRect.top - elRect.top + 4;
171            }
172        }
173    }
174});
175
176
177
178// Check if #page-header exists on the page
179const pageHeader = document.getElementById('page-header');
180if (pageHeader) {
181    /* -------------------------------------------
182    Sticky Nav (Intersection Observer API) (NEW)
183    ------------------------------------------- */ 
184
185    // Find the header
186    const header = document.querySelector('header');
187    const headerBottom = document.querySelector('header .bottom-bar');
188
189    // Find the first block
190    const pageStart = document.querySelector('#page-content');
191    const firstBlock = pageStart.firstElementChild;
192
193    //Callback function
194    const obsCallback = function(entries) {
195        const [entry] = entries;
196        if (!entry.isIntersecting) {
197            header.classList.add('sticky-nav');
198            headerBottom.classList.add("white-bg");
199            headerBottom.classList.remove("secondary-bg");
200        }
201        else {
202            header.classList.remove('sticky-nav');
203            headerBottom.classList.add("secondary-bg");
204            headerBottom.classList.remove("white-bg");
205        }
206    };
207
208    //Callback function
209    const obsCallbackOpacity = function(e) {
210        const [entry2] = e;
211        if (!entry2.isIntersecting) {
212            header.classList.add('opacity');
213        }
214        else {
215            header.classList.remove('opacity');
216        }
217    };
218
219    // Object
220    const obsOptions = {
221        root: null,
222        threshold: 0,
223    };
224
225    // Intersection Observer API
226    observer = new IntersectionObserver(obsCallback, obsOptions);
227
228    observer.observe(firstBlock);
229
230    observerOpacity = new IntersectionObserver(obsCallbackOpacity, obsOptions);
231
232    observerOpacity.observe(header);
233}
234
235
236// as the page loads, call these scripts
237jQuery(document).ready(function($) {
238
239/** =======================================================================
240    DOCUMENT READY FUNCTIONS
241======================================================================== */
242
243
244    /* -------------------------------------------
245    Search Animation
246    ------------------------------------------- */ 
247
248    $('button.toggle-search').on("click",function(){
249        $(this).toggleClass('active');
250    });
251
252
253// Check if <div id="webcam-feed"> exists on the page
254const webcamFeed = document.getElementById('webcam-feed');
255if (webcamFeed) {
256
257    /* -------------------------------------------
258    Webcam Toggle Buttons
259    ------------------------------------------- */
260    const eastView = document.querySelector('#feed-east');
261    const northView = document.querySelector('#feed-north');
262    const westView = document.querySelector('#feed-west');
263    const webcamToggleEast = document.querySelectorAll('.east-view');
264    const webcamToggleNorth = document.querySelectorAll('.north-view');
265    const webcamToggleWest = document.querySelectorAll('.west-view');
266
267    if (webcamToggleEast) {
268        webcamToggleEast.forEach(function (button) {
269            button.addEventListener('click', function () {
270                eastView.classList.add('east-view');
271                eastView.classList.remove('d-none');
272                northView.classList.add('d-none');
273                westView.classList.add('d-none');
274                // remove active class from all other buttons and add it to all the buttons with this class
275                webcamToggleNorth.forEach(function (btn) {
276                    btn.classList.remove('active');
277                });
278                webcamToggleWest.forEach(function (btn) {
279                    btn.classList.remove('active');
280                });
281                button.classList.add('active');
282            });
283        });
284    }
285
286    if (webcamToggleNorth) {
287        webcamToggleNorth.forEach(function (button) {
288            button.addEventListener('click', function () {
289                eastView.classList.add('d-none');
290                westView.classList.add('d-none');
291                northView.classList.add('north-view');
292                northView.classList.remove('d-none');
293                // remove active class from all other buttons and add it to all the buttons with this class
294                webcamToggleEast.forEach(function (btn) {
295                    btn.classList.remove('active');
296                });
297                webcamToggleWest.forEach(function (btn) {
298                    btn.classList.remove('active');
299                });
300                button.classList.add('active');
301            });
302        });
303    }
304
305    if (webcamToggleWest) {
306        webcamToggleWest.forEach(function (button) {
307            button.addEventListener('click', function () {
308                westView.classList.add('west-view');
309                westView.classList.remove('d-none');
310                northView.classList.add('d-none');
311                eastView.classList.add('d-none');
312                // remove active class from all other buttons and add it to all the buttons with this class
313                webcamToggleNorth.forEach(function (btn) {
314                    btn.classList.remove('active');
315                });
316                webcamToggleEast.forEach(function (btn) {
317                    btn.classList.remove('active');
318                });
319                button.classList.add('active');
320            });
321        });
322    }
323}
324    /* -------------------------------------------
325    stop embed video when modal is closed
326    ------------------------------------------- */
327
328    // Stop video when modal is closed
329    $('#basicModal').on('hidden.bs.modal', function (e) {
330        // Get the iframe element containing the video
331        var iframe = $(this).find('iframe');
332        // Get the video's source URL
333        var src = iframe.attr('src');
334        // Set the video's source URL to an empty string to stop the video
335        iframe.attr('src', '');
336        // Set the video's source URL back to the original URL to prepare for the next time the modal is opened
337        iframe.attr('src', src);
338    });
339
340    /* -------------------------------------------
341    Slick Slider
342    ------------------------------------------- */
343
344    $('#hero .bg-slider').slick({
345        slidesToShow: 1,
346        slidesToScroll: 1,
347        arrows: false,
348        autoplay: true,
349        prevArrow: '<span class="slick-prev"><i class="fa fa-caret-left"></i></span>',
350        nextArrow: '<span class="slick-next"><i class="fa fa-caret-right"></i></span>',
351        appendDots: '.slider-controls',
352        fade: true,
353        speed: 1000,
354        dots: true,
355    });
356
357    $('#content-image.events .outer-box .inner-box-slide').slick({
358        slidesToShow: 1,
359        slidesToScroll: 1,
360        arrows: true,
361        autoplay: true,
362        speed: 500,
363        autoplaySpeed: 2500,
364        adaptiveHeight: false,
365        dots: false,
366    });
367
368
369
370
371
372
373 
374}); /* end of as page load scripts */
375
376
377
378
379
380/* ------------------------------------------------------------------------------
381Append all buttons that point to the tickets website to add a svg icon afterwards
382------------------------------------------------------------------------------ */
383
384// Get all the links on the page
385var links = document.getElementsByTagName('a');
386
387// Iterate through each link and check if href contains "tickets.theskydeck.com"
388for (var i = 0; i < links.length; i++) {
389    var link = links[i];
390    
391    // Check if the href attribute contains "tickets.theskydeck.com"
392    if (link.href && (link.href.indexOf("tickets.theskydeck.com") !== -1)) {
393        // Add the class 'tickets' to the link
394        link.classList.add('primary', 'tickets');
395        
396        // Check if the link has the class wp-block-button__link
397        if (link.classList.contains('wp-block-button__link')) {
398            // Add the class 'btn' to the link
399            link.classList.add('btn');
400        }
401
402        // Create an SVG element
403        var svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
404        svgElement.setAttribute("viewBox", "0 0 18 19");
405        svgElement.setAttribute("fill", "none");
406
407        // Create a path element within the SVG
408        var pathElement = document.createElementNS("http://www.w3.org/2000/svg", "path");
409        pathElement.setAttribute("d", "M17.863 7.38544L15.9282 5.45032C15.7482 5.27031 15.4782 5.27031 15.2982 5.45032C14.9833 5.76534 14.6233 5.90035 14.1734 5.90035C13.3185 5.90035 12.5986 5.1803 12.5986 4.32525C12.5986 3.92022 12.7785 3.51519 13.0485 3.20017C13.1385 3.11017 13.1835 3.02016 13.1835 2.88515C13.1835 2.75014 13.1385 2.66014 13.0485 2.57013L11.1137 0.635009C10.9337 0.454997 10.6638 0.454997 10.4838 0.635009L7.8741 3.24518L9.31393 4.68527C9.49311 4.86528 9.49311 5.1353 9.31393 5.31531C9.13154 5.49693 8.8672 5.49773 8.684 5.31531L7.24417 3.87522L0.134985 10.9857C-0.0449948 11.1657 -0.0449948 11.4357 0.134985 11.6157L2.06976 13.5508C2.24974 13.7308 2.51971 13.7308 2.69969 13.5508C3.01465 13.2358 3.37461 13.1008 3.82456 13.1008C4.67946 13.1008 5.39938 13.8209 5.39938 14.6759C5.39938 15.0809 5.2194 15.486 4.94943 15.801C4.76945 15.981 4.76945 16.251 4.94943 16.431L6.88421 18.3661C7.05214 18.5341 7.32693 18.5542 7.51414 18.3661L14.6233 11.2557L13.1835 9.8156C13.0043 9.63559 13.0043 9.36557 13.1835 9.18556C13.3635 9.00555 13.6334 9.00555 13.8134 9.18556L15.2533 10.6256L17.863 8.01548C18.0421 7.83708 18.0486 7.57108 17.863 7.38544ZM12.4636 8.46551C12.2812 8.64713 12.0168 8.64793 11.8336 8.46551L10.0338 6.6654C9.85467 6.48538 9.85467 6.21537 10.0338 6.03535C10.2138 5.85534 10.4838 5.85534 10.6638 6.03535L12.4636 7.83547C12.6435 8.01548 12.6435 8.2855 12.4636 8.46551Z");
410        pathElement.setAttribute("fill", "#fff");
411
412        // Append the path element to the SVG
413        svgElement.appendChild(pathElement);
414
415        // Append the SVG element after the link text
416        link.appendChild(svgElement);
417    }
418}
419
420// Make header sticky on scroll
421document.addEventListener("DOMContentLoaded", function () {
422    const header = document.querySelector("header"); // Select the header element
423    const stickyClass = "sticky"; // Class to add when header becomes sticky
424    const offset = 75; // Scroll offset to trigger sticky behavior
425    const docBody = document.querySelector("body"); // Select the body element
426
427    window.addEventListener("scroll", function () {
428        if (window.scrollY >= offset) {
429            header.classList.add(stickyClass);
430            docBody.classList.add("sticky-header");
431        } else {
432            header.classList.remove(stickyClass);
433            docBody.classList.remove("sticky-header");
434        }
435    });
436
437    initializeMobileMenu();
438});
439
440
441function initializeMobileMenu() {
442    function initializeDropdowns() {
443        const dropdownToggles = document.querySelectorAll('.slide-menu .slider .mobile-nav .dropdown-toggle.nav-link');
444        dropdownToggles.forEach(toggle => {
445            toggle.addEventListener('click', function (e) {
446                // Get the associated dropdown menu
447                const dropdownId = this.getAttribute('id');
448                const dropdownMenu = document.querySelector(`.dropdown-menu[aria-labelledby="${dropdownId}"]`);
449
450                if (dropdownMenu) {
451                    const menuHeight = dropdownMenu.offsetHeight;
452                    const slider = document.querySelector('.slide-menu .slider');
453                    if (slider) {
454                        slider.style.height = menuHeight + 'px';
455                    }
456                }
457            });
458        });
459    }
460
461    // Function to initialize slide menu controls
462    function initializeSlideMenuControls() {
463        const slideMenuControls = document.querySelectorAll('.slide-menu-control');
464        slideMenuControls.forEach(control => {
465            control.addEventListener('click', function (e) {
466                const slider = document.querySelector('.slide-menu .slider');
467                if (slider) {
468                    slider.style.height = '';
469                }
470            });
471        });
472    }
473
474    // Initial attempt to initialize
475    initializeDropdowns();
476    initializeSlideMenuControls();
477
478    // Set up a mutation observer to watch for changes in the DOM
479    const observer = new MutationObserver(function (mutations) {
480        mutations.forEach(function (mutation) {
481            if (mutation.addedNodes.length) {
482                // Check if the added nodes contain our target elements
483                const hasDropdownToggles = document.querySelectorAll('.slide-menu .slider .mobile-nav .dropdown-toggle.nav-link').length > 0;
484                if (hasDropdownToggles) {
485                    initializeDropdowns();
486                    initializeSlideMenuControls();
487                }
488            }
489        });
490    });
491
492    // Start observing the document body for changes
493    observer.observe(document.body, {
494        childList: true,
495        subtree: true
496    });
497
498    // Also try initializing after a short delay to ensure dynamic content is loaded
499    setTimeout(() => {
500        initializeDropdowns();
501        initializeSlideMenuControls();
502    }, 1000);
503}
504
505// If URL has /es/ path, add class to body
506let isSpanish = false;
507if (window.location.pathname.includes("/es/")) {
508    document.body.classList.add("spanish");
509    isSpanish = true;
510}
511
512function setSliderContentHeight(selector1, selector2, breakpoint) {
513    let maxHeight = 0;
514    windowWidth = window.innerWidth;
515
516    // Reset height if device is desktop/laptop landscape
517    if (windowWidth < breakpoint) {
518        document.querySelectorAll(selector2).forEach(container => {
519            container.style.height = "";
520        });
521
522    // Set height of all slides to the tallest slide
523    } else {
524
525        // Find tallest .new_slider__content-left across all slides
526        document.querySelectorAll(selector1).forEach(el => {
527            const height = el.offsetHeight;
528            if (height > maxHeight) maxHeight = height;
529
530        });
531
532        // Set height to all .new_slider__content based on tallest .new_slider__content-left
533        document.querySelectorAll(selector2).forEach(container => {
534            container.style.height = `${maxHeight}px`;
535        });
536        
537    }
538
539}
540
541jQuery(function($) {
542
543  // Make sure GF’s JS is there
544  if (typeof gform === 'undefined' || typeof gform.addFilter === 'undefined') {
545    return;
546  }
547
548  gform.addFilter('gform_datepicker_options_pre_init', function(optionsObj, formId, fieldId) {
549
550    var allowedForms = [12, 13, 14, 15]; // <-- change to your real IDs
551    formId = parseInt(formId, 10);
552
553    if (allowedForms.indexOf(formId) === -1) {
554      return optionsObj; // not one of the target forms
555    }
556
557    // Preserve any existing beforeShow, just in case GF or addons use it
558    var originalBeforeShow = optionsObj.beforeShow;
559
560    optionsObj.beforeShow = function(input, inst) {
561      var $input      = $(input);
562      var $datepicker = $('#ui-datepicker-div');
563
564      // Find the Bootstrap modal that contains this field
565      var $modal = $input.closest('.modal'); // adjust selector if needed
566      if ($modal.length) {
567        $datepicker.appendTo($modal);
568      }
569
570      // Position the datepicker under the input, inside the modal
571      setTimeout(function() {
572        if ($.ui && $.ui.position) {
573          $datepicker.position({
574            my: 'left top',
575            at: 'left bottom',
576            of: $input
577          });
578        } else {
579          // Fallback if position() isn't available
580          var offset = $input.offset();
581          $datepicker.css({
582            position: 'absolute',
583            top: offset.top + $input.outerHeight(),
584            left: offset.left
585          });
586        }
587      }, 0);
588
589      // Call any original beforeShow if it existed
590      if (typeof originalBeforeShow === 'function') {
591        return originalBeforeShow(input, inst);
592      }
593    };
594
595    return optionsObj;
596  });
597
598});
599
600jQuery(function($) {
601
602  if (typeof gform === 'undefined' || typeof gform.addFilter === 'undefined') {
603    return;
604  }
605
606  gform.addFilter('gform_datepicker_options_pre_init', function(optionsObj, formId, fieldId) {
607
608    var allowedForms = [12, 13, 14, 15];
609    formId = parseInt(formId, 10);
610
611    if (allowedForms.indexOf(formId) === -1) {
612      return optionsObj;
613    }
614
615    var originalBeforeShow = optionsObj.beforeShow;
616
617    optionsObj.beforeShow = function(input, inst) {
618      var $input      = $(input);
619      var $datepicker = $('#ui-datepicker-div');
620
621      // Find modal + modal-content
622      var $modal      = $input.closest('.modal');
623      var $container  = $modal.find('.modal-content').first();
624
625      if ($container.length) {
626        // Make sure datepicker lives inside modal content
627        if (!$datepicker.parent().is($container)) {
628          $datepicker.appendTo($container);
629        }
630
631        // Ensure container is positioning context
632        if ($container.css('position') === 'static') {
633          $container.css('position', 'relative');
634        }
635
636        setTimeout(function() {
637          // Offsets relative to document
638          var inputOffset     = $input.offset();
639          var containerOffset = $container.offset();
640
641          // Position relative to modal-content
642          var top  = inputOffset.top - containerOffset.top + $input.outerHeight();
643          var left = inputOffset.left - containerOffset.left;
644
645          var dpWidth        = $datepicker.outerWidth();
646          var containerWidth = $container.innerWidth();
647
648          // Clamp horizontally to stay inside modal
649          var padding = 10;
650          var maxLeft = containerWidth - dpWidth - padding;
651
652          if (left < padding) left = padding;
653          if (left > maxLeft) left = maxLeft;
654
655          $datepicker.css({
656            position: 'absolute',
657            top: top + 'px',
658            left: left + 'px',
659            zIndex: 9999
660          });
661        }, 0);
662      }
663
664      if (typeof originalBeforeShow === 'function') {
665        return originalBeforeShow(input, inst);
666      }
667    };
668
669    return optionsObj;
670  });
671
672});

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.