PageSourceSearch

https://www.firstmarquisofmontrosesociety.co.uk/wp-content/plugins/creatomatic-lightbox/script.js?ver=101

js firstmarquisofmontrosesociety.co.uk collected 2026-10-02 22:48:15 UTC 4,712 bytes, 151 lines download raw bytes

1jQuery(document).ready(function($){
2  /*  Creatomatic Lightbox  */
3
4  // Append the lightbox container once to the body
5  $('body').append(`
6    <div class="creato-lightbox-overlay">
7      <div class="creato-lightbox-content">
8        <div class="creato-lightbox-slider"></div>
9        <span class="creato-lightbox-close"><i class="fas fa-times"></i></span>
10      </div>
11    </div>
12  `);
13
14  const $overlay = $('.creato-lightbox-overlay');
15  const $slider = $('.creato-lightbox-slider');
16
17  /* Strip WordPress size suffix from image filenames */
18  function stripSizeSuffix(src) {
19    return src.replace(/-\d+x\d+(?=\.(jpg|jpeg|png|gif))/i, '');
20  }
21
22  /* Generate slide markup for image or iframe */
23  function getSlideMarkup($el) {
24    if ($el.data('featherlight') === 'iframe') {
25      const src = $el.attr('href') || $el.data('src') || $el.data('featherlight-src');
26      
27      
28      // Dodgy url
29      if (!isSafeUrl(src))
30        return;
31      
32      const width = $el.data('featherlight-iframe-width') || '100%';
33      const height = $el.data('featherlight-iframe-height') || '500';
34      const frameborder = $el.data('featherlight-iframe-frameborder') || '0';
35      const allow = $el.data('featherlight-iframe-allow') || 'autoplay; encrypted-media';
36      const allowfullscreen = $el.data('featherlight-iframe-allowfullscreen') ? 'allowfullscreen' : '';
37
38      return `
39        <div class="creato-slide">
40          <div class="iframe-container">
41            <iframe src="${src}" width="${width}" height="${height}" frameborder="${frameborder}" allow="${allow}" ${allowfullscreen}></iframe>
42          </div>
43        </div>
44      `;
45    }
46
47    let imgSrc = $el.is('img') ? $el.attr('src')
48      : $el.is('a') ? $el.attr('href')
49      : $el.find('img').attr('src');
50    
51    // Dodgy image url
52    if(!isSafeImageUrl(imgSrc))
53      return false;
54
55    return `
56      <div class="creato-slide">
57        <img src="${imgSrc}" />
58      </div>
59    `;
60  }
61
62  
63
64  /* Close lightbox */
65  function closeLightbox() {
66    $overlay.fadeOut(() => {
67      if ($slider.hasClass('slick-initialized')) {
68        $slider.slick('unslick');
69      }
70      $slider.empty();
71    });
72  }
73
74  /* Links directly to images (with Slick Slider) */
75  const featherlightSelector = 'a[href$=".jpg"], a[href$=".jpeg"], a[href$=".png"], a[href$=".gif"], a[data-featherlight="iframe"]';
76
77  
78  $(document).on('click', featherlightSelector, function (e) {
79    e.preventDefault();
80
81    const $clicked = $(this);
82    const imgSrc = $clicked.attr('href');
83    //const alt = $clicked.find('img').attr('alt') || '';
84
85    // Create the slide for the clicked image
86    const slide = getSlideMarkup($clicked);
87
88    // Prepare the slider with this single image (or others if part of a gallery)
89    $slider.empty().append(slide);  // Start with the clicked image
90
91    // Check if there are any other images within the same gallery to add
92    const $gallery = $clicked.closest('.wp-block-gallery, .sc-agent-property-section, .creato-lightbox-gallery, .woocommerce-product-gallery__wrapper, .gallery, .single-property-page-gallery, .single-property-gallery');
93    const $images = $gallery.find('a[href$=".jpg"], a[href$=".jpeg"], a[href$=".png"], a[href$=".gif"], a[data-featherlight="iframe"]');
94
95    const slides = [];
96    let initialIndex = 0;
97
98    $images.each(function (i) {
99      const $el = $(this);
100      const slide = getSlideMarkup($el);
101      if (!slide) return;
102
103      if ($el[0] === $clicked[0]) {
104        initialIndex = i;
105      }
106
107      slides.push(slide);
108    });
109
110    $slider.empty().append(slides.join(''));
111
112    // Initialize the Slick slider
113    $slider.slick({
114      dots: true,
115      arrows: true,
116      initialSlide: initialIndex,  // Start at the clicked image
117      prevArrow: '<button type="button" class="creato-slick-prev"><i class="fas fa-chevron-left"></i></button>',
118      nextArrow: '<button type="button" class="creato-slick-next"><i class="fas fa-chevron-right"></i></button>',
119    });
120
121    // Show the overlay with the lightbox
122    $overlay.fadeIn();
123  });
124
125  /* Close button */
126  $('.creato-lightbox-close').on('click', closeLightbox);
127
128  /* Close on outside click */
129  $overlay.on('click', function (e) {
130    if (
131      !$(e.target).closest('.creato-lightbox-content img').length &&
132      !$(e.target).closest('.creato-slick-prev').length &&
133      !$(e.target).closest('.creato-slick-next').length
134    ) {
135      closeLightbox();
136    }
137  });
138  
139  
140    
141
142  // The flaw with featherlight, it never sanitized urls for iframes or images etc
143  function isSafeUrl(url) {
144    return /^(https?:)?\/\/[^\s]+$/.test(url);
145  }
146
147  function isSafeImageUrl(url) {
148    return /^https?:\/\/.+\.(jpg|jpeg|png|gif)$/i.test(url);
149  }
150  
151});

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.