PageSourceSearch

https://karadenizreisen.de/wp-content/plugins/smg-technology/public/js/smg-urania-iframe-gallery.js?ver=7.1

js karadenizreisen.de collected 2026-10-07 05:19:52 UTC 6,467 bytes, 180 lines download raw bytes

1/**
2 * URANIA Iframe Gallery – postMessage listener
3 *
4 * URANIA (the hotelview / booking engine) is embedded as an iframe inside
5 * QUADRA pages via the [smg_travelbox] shortcode.  When a user taps a hotel
6 * image gallery inside the iframe, URANIA sends a postMessage to the parent
7 * window with the event name "uraniaOpenGallery" and an array of image URLs.
8 *
9 * This script runs on the parent (WordPress / QUADRA) side:
10 *   1. Listens for the "uraniaOpenGallery" postMessage from the iframe.
11 *   2. Opens a full-screen lightbox gallery on the parent page.
12 *   3. Supports prev / next navigation, keyboard (Esc, arrows) and touch swipe.
13 *
14 * The corresponding sender lives in URANIA's Angular component:
15 *   HotelviewTabContentMediaComponent.openLightbox()
16 *   → window.parent.postMessage(JSON.stringify({
17 *       event: 'uraniaOpenGallery',
18 *       payload: [imageUrl, ...],
19 *       activeIndex: <number>
20 *     }), '*');
21 */
22(function () {
23  'use strict';
24
25  var CLS = 'smg-urania-gallery';
26
27  var gallery = {
28    images: [],
29    currentIndex: 0,
30    overlay: null,
31    imageEl: null,
32    counterEl: null,
33    prevBtn: null,
34    nextBtn: null,
35    spinnerEl: null,
36    touchStartX: 0,
37    touchEndX: 0,
38    preloadCache: {}
39  };
40
41  function preloadImage(url) {
42    if (gallery.preloadCache[url]) return;
43    var img = new Image();
44    img.src = url;
45    gallery.preloadCache[url] = img;
46  }
47
48  function preloadAdjacent(index) {
49    var len = gallery.images.length;
50    if (len <= 1) return;
51    preloadImage(gallery.images[(index + 1) % len]);
52    preloadImage(gallery.images[(index - 1 + len) % len]);
53  }
54
55  function createGallery() {
56    if (gallery.overlay) return;
57
58    var overlay = document.createElement('div');
59    overlay.className = CLS;
60    overlay.setAttribute('role', 'dialog');
61    overlay.setAttribute('aria-modal', 'true');
62    overlay.setAttribute('aria-label', 'Bildergalerie');
63    overlay.innerHTML =
64      '<div class="' + CLS + '__backdrop"></div>' +
65      '<button class="' + CLS + '__close" type="button" aria-label="Schließen">&times;</button>' +
66      '<button class="' + CLS + '__prev" type="button" aria-label="Vorheriges Bild">&#10094;</button>' +
67      '<button class="' + CLS + '__next" type="button" aria-label="Nächstes Bild">&#10095;</button>' +
68      '<div class="' + CLS + '__content">' +
69        '<div class="' + CLS + '__spinner"></div>' +
70        '<img class="' + CLS + '__image" src="" alt="Galeriebild" />' +
71      '</div>' +
72      '<div class="' + CLS + '__counter"></div>';
73
74    document.body.appendChild(overlay);
75
76    gallery.overlay = overlay;
77    gallery.imageEl = overlay.querySelector('.' + CLS + '__image');
78    gallery.counterEl = overlay.querySelector('.' + CLS + '__counter');
79    gallery.prevBtn = overlay.querySelector('.' + CLS + '__prev');
80    gallery.nextBtn = overlay.querySelector('.' + CLS + '__next');
81    gallery.spinnerEl = overlay.querySelector('.' + CLS + '__spinner');
82
83    gallery.imageEl.addEventListener('load', function () {
84      gallery.imageEl.classList.add('is-loaded');
85      gallery.spinnerEl.style.display = 'none';
86    });
87
88    overlay.querySelector('.' + CLS + '__backdrop').addEventListener('click', close);
89    overlay.querySelector('.' + CLS + '__close').addEventListener('click', close);
90    gallery.prevBtn.addEventListener('click', prev);
91    gallery.nextBtn.addEventListener('click', next);
92
93    var content = overlay.querySelector('.' + CLS + '__content');
94    content.addEventListener('touchstart', function (e) {
95      gallery.touchStartX = e.changedTouches[0].screenX;
96    }, { passive: true });
97    content.addEventListener('touchend', function (e) {
98      gallery.touchEndX = e.changedTouches[0].screenX;
99      var diff = gallery.touchStartX - gallery.touchEndX;
100      if (Math.abs(diff) > 50) {
101        if (diff > 0) { next(); } else { prev(); }
102      }
103    }, { passive: true });
104  }
105
106  function showImage(index) {
107    if (index < 0 || index >= gallery.images.length) return;
108    gallery.currentIndex = index;
109
110    gallery.imageEl.classList.remove('is-loaded');
111    gallery.spinnerEl.style.display = '';
112
113    gallery.imageEl.src = gallery.images[index];
114    gallery.imageEl.alt = 'Bild ' + (index + 1) + ' von ' + gallery.images.length;
115    gallery.counterEl.textContent = (index + 1) + ' / ' + gallery.images.length;
116    gallery.prevBtn.style.display = gallery.images.length > 1 ? '' : 'none';
117    gallery.nextBtn.style.display = gallery.images.length > 1 ? '' : 'none';
118
119    if (gallery.preloadCache[gallery.images[index]] && gallery.preloadCache[gallery.images[index]].complete) {
120      gallery.imageEl.classList.add('is-loaded');
121      gallery.spinnerEl.style.display = 'none';
122    }
123
124    preloadAdjacent(index);
125  }
126
127  function open(images, activeIndex) {
128    createGallery();
129    gallery.images = images;
130    showImage(activeIndex || 0);
131    gallery.overlay.classList.add('is-open');
132    document.body.style.overflow = 'hidden';
133    gallery.overlay.querySelector('.' + CLS + '__close').focus();
134  }
135
136  function close() {
137    if (!gallery.overlay) return;
138    gallery.overlay.classList.remove('is-open');
139    document.body.style.overflow = '';
140  }
141
142  function prev() {
143    var idx = gallery.currentIndex > 0 ? gallery.currentIndex - 1 : gallery.images.length - 1;
144    showImage(idx);
145  }
146
147  function next() {
148    var idx = gallery.currentIndex < gallery.images.length - 1 ? gallery.currentIndex + 1 : 0;
149    showImage(idx);
150  }
151
152  document.addEventListener('keydown', function (e) {
153    if (!gallery.overlay || !gallery.overlay.classList.contains('is-open')) return;
154    if (e.key === 'Escape') { close(); }
155    else if (e.key === 'ArrowLeft') { prev(); }
156    else if (e.key === 'ArrowRight') { next(); }
157  });
158
159  /**
160   * Listen for postMessage from the URANIA iframe.
161   *
162   * Expected message format (JSON-stringified):
163   *   { event: "uraniaOpenGallery", payload: string[], activeIndex: number }
164   *
165   * `payload` contains image URLs from URANIA's HotelviewTabContentMediaComponent
166   * (the hotel image gallery). Each URL points to the 800px variant of the image.
167   */
168  window.addEventListener('message', function (e) {
169    var data;
170    try {
171      data = typeof e.data === 'string' ? JSON.parse(e.data) : e.data;
172    } catch (_) {
173      return;
174    }
175
176    if (data && data.event === 'uraniaOpenGallery' && Array.isArray(data.payload) && data.payload.length > 0) {
177      open(data.payload, data.activeIndex || 0);
178    }
179  });
180})();

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.