PageSourceSearch

https://tickets.blackstockmarket.co.uk/hotwatercomedyclub/website/scripts/integrate.js

js blackstockmarket.co.uk collected 2026-09-25 04:01:01 UTC 16,907 bytes, 458 lines download raw bytes

1// IE11 polyfill
2if (!String.prototype.endsWith) {
3    String.prototype.endsWith = function (search, thisLen) {
4        if (thisLen === undefined || thisLen > this.length) {
5            thisLen = this.length;
6        }
7        return this.substring(thisLen - search.length, thisLen) === search;
8    };
9}
10
11function safeSlice(s, startIndex, length) {
12    return typeof s === "string" ? s.slice(startIndex, length) : "";
13}
14
15var spekResizeIFrame = function () {
16    var iframe = document.getElementById('SpektrixIFrame');
17    var count = 0;
18
19    try {
20        var src = iframe.contentWindow.frames[0].location;
21
22        var parts = src.search.split('=');
23        var height = Number(parts[1]);
24        if (isNaN(height)) {
25            throw "NaN";
26        } else {
27            if (typeof (spektrixMinHeight) !== 'undefined') {
28                if (spektrixMinHeight > height) {
29                    iframe.style.height = spektrixMinHeight + 'px';
30                    return;
31                }
32            }
33
34            iframe.style.height = height + 'px';
35        }
36    } catch (e) {
37        // try again if something went wrong (there are plenty of timing issues!)
38        if (count < 10) {
39            setTimeout(spekResizeIFrame, 50);
40            count++;
41        }
42    }
43};
44
45var spekPollIFrame = function () {
46    spekResizeIFrame();
47
48    var iframe = document.getElementById('SpektrixIFrame');
49
50    if (iframe.addEventListener) {
51        iframe.addEventListener('load', spekResizeIFrame, false);
52    } else {
53        iframe.attachEvent('onload', spekResizeIFrame);
54    }
55};
56
57var spekHandleResizeExactMessage = function (e) {
58    if (e && e.data && safeSlice(e.data, 0, 12) === "resizeExact:") {
59        var iframe = document.getElementById('SpektrixIFrame');
60        var height = Number(e.data.slice(12));
61        if (!isNaN(height)) {
62            iframe.style.height = height + 'px';
63            iframe.contentWindow.postMessage('resizeDone', '*');
64            spekScheduleViewportSync();
65        }
66    }
67};
68
69var spekHandleResizeMessage = function (e) {
70    // Handle resize messages
71    if (e && e.data && safeSlice(e.data, 0, 7) === "resize:") {
72        var iframe = document.getElementById('SpektrixIFrame');
73        var height = Number(e.data.slice(7));
74        if (isNaN(height)) {
75            throw "NaN";
76        } else {
77            if (typeof (spektrixMinHeight) !== 'undefined') {
78                if (spektrixMinHeight > height) {
79                    iframe.style.height = spektrixMinHeight + 'px';
80                    iframe.contentWindow.postMessage('resizeDone', '*');
81                    spekScheduleViewportSync();
82                    return;
83                }
84            }
85            iframe.style.height = height + 'px';
86            iframe.contentWindow.postMessage('resizeDone', '*');
87            spekScheduleViewportSync();
88        }
89    }
90};
91
92var spekCheckForClickOutsideCalendar = function (e) {
93    var spekIFrame = document.getElementById('SpektrixIFrame');
94    spekIFrame.contentWindow.postMessage('hideDropdownCalendar', '*');
95};
96
97var spekHandleCalendarMessage = function (e) {
98    /* Handle calendar messages */
99    if (e && e.data && safeSlice(e.data, 0, 21) === "dropdowncalendarshown") {
100        if (document.addEventListener) {
101            document.addEventListener('mousedown', spekCheckForClickOutsideCalendar, false);
102        } else {
103            document.attachEvent('onmousedown', spekCheckForClickOutsideCalendar);
104        }
105    }
106    if (e && e.data && safeSlice(e.data, 0, 22) === "dropdowncalendarhidden") {
107        if (document.removeEventListener) {
108            document.removeEventListener('mousedown', spekCheckForClickOutsideCalendar, false);
109        } else {
110            document.detachEvent('onmousedown', spekCheckForClickOutsideCalendar);
111        }
112    }
113};
114
115function getParameterByName(name, url) {
116    if (!url) url = window.location.href;
117    name = name.replace(/[\[\]]/g, "\\$&");
118    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
119        results = regex.exec(url);
120    if (!results) return null;
121    if (!results[2]) return '';
122    return decodeURIComponent(results[2].replace(/\+/g, " "));
123}
124
125function removeParameterByName(name, url) {
126    var rtn = url.split("?")[0],
127        param,
128        params_arr = [],
129        queryString = (url.indexOf("?") !== -1) ? url.split("?")[1] : "";
130    if (queryString !== "") {
131        params_arr = queryString.split("&");
132        for (var i = params_arr.length - 1; i >= 0; i -= 1) {
133            param = params_arr[i].split("=")[0];
134            if (param === name) {
135                params_arr.splice(i, 1);
136            }
137        }
138
139        if (params_arr.length !== 0) {
140            rtn = rtn + "?" + params_arr.join("&");
141        }
142    }
143    return rtn;
144}
145
146// see https://stackoverflow.com/questions/736513/how-do-i-parse-a-url-into-hostname-and-path-in-javascript
147var getLocation = function (href) {
148    var location = document.createElement("a");
149    location.href = href;
150    return location;
151};
152
153var handleRedirects = function () {
154    var iframe = document.getElementById('SpektrixIFrame');
155    var parentUrl = window.location.href;
156    if (/[?&]SpektrixPasswordlessToken=/.test(parentUrl) && /[?&]SpektrixRedirectUrl=/.test(parentUrl)) {
157
158        var newSrc = getParameterByName('SpektrixRedirectUrl') + '?SpektrixPasswordlessToken=' 
158+ getParameterByName('SpektrixPasswordlessToken');
159
160        var url = getLocation(newSrc);
161        if (!url.hostname.endsWith(".spektrix.com")) {
162            return;
163        }
164
165        parentUrl = removeParameterByName('SpektrixRedirectUrl', parentUrl);
166        parentUrl = removeParameterByName('SpektrixPasswordlessToken', parentUrl);
167
168        if (window.history !== undefined && window.history.pushState !== undefined) {
169            // this changes the url without reloading the page but only works with Html 5
170            window.history.pushState({}, document.title, parentUrl);
171        }
172
173        if (iframe.src !== newSrc) { // Do redirect
174            iframe.src = newSrc;
175        }
176    }
177};
178
179var spekOriginalIframeStyles = null;
180var spekFullscreenActive = false;
181var spekFixedOverlayCandidates = [];
182var spekFixedOverlayCacheDirty = true;
183var spekFixedOverlayObserver = null;
184
185function spekRefreshFixedOverlayCandidates() {
186    if (!document.body) {
187        spekFixedOverlayCandidates = [];
188        return;
189    }
190    var candidates = [];
191    var all = document.body.getElementsByTagName('*');
192    for (var i = 0; i < all.length; i++) {
193        var el = all[i];
194        var cs = window.getComputedStyle ? window.getComputedStyle(el) : null;
195        if (cs && cs.position === 'fixed') {
196            candidates.push(el);
197        }
198    }
199    spekFixedOverlayCandidates = candidates;
200    spekFixedOverlayCacheDirty = false;
201}
202
203function spekStartFixedOverlayObserver() {
204    if (spekFixedOverlayObserver || typeof MutationObserver === 'undefined' || !document.body) {
205        return;
206    }
207    spekFixedOverlayObserver = new MutationObserver(function () {
208        spekFixedOverlayCacheDirty = true;
209        spekScheduleViewportSync();
210    });
211    spekFixedOverlayObserver.observe(document.body, {
212        childList: true,
213        subtree: true,
214        attributes: true,
215        attributeFilter: ['style', 'class']
216    });
217}
218
219var spekSyncViewport = function () {
220    var iframe = document.getElementById('SpektrixIFrame');
221    if (!iframe || !iframe.contentWindow || typeof iframe.contentWindow.postMessage !== "function") {
222        return;
223    }
224
225    if (spekFixedOverlayCacheDirty && !spekFullscreenActive) {
226        spekRefreshFixedOverlayCandidates();
227    }
228
229    var rect = iframe.getBoundingClientRect();
230    var viewportWidth = window.innerWidth || document.documentElement.clientWidth;
231    var viewportHeight = window.innerHeight || document.documentElement.clientHeight;
232
233    var topInset = 0;
234    var bottomInset = 0;
235    var leftInset = 0;
236    var rightInset = 0;
237
238    if (!spekFullscreenActive) {
239        for (var i = 0; i < spekFixedOverlayCandidates.length; i++) {
240        var el = spekFixedOverlayCandidates[i];
241        if (!el || el === iframe) {
242            continue;
243        }
244        var elConnected = el.isConnected;
245        if (elConnected === false || (elConnected === undefined && !document.documentElement.contains(el))) {
246            continue;
247        }
248        var cs = window.getComputedStyle ? window.getComputedStyle(el) : null;
249        if (cs && (cs.display === 'none' || cs.visibility === 'hidden' || cs.position !== 'fixed')) {
250            continue;
251        }
252        var r = el.getBoundingClientRect();
253        if (r.width <= 0 || r.height <= 0) {
254            continue;
255        }
256
257        // Only treat an element as edge-attached chrome if its near edge sits
258        // within a small tolerance of a viewport edge. This excludes centred
259        // modals, cookie banners, full-screen overlays, etc.
260        var edgeEpsilon = 2;
261        var touchesTop = r.top <= edgeEpsilon;
262        var touchesBottom = r.bottom >= viewportHeight - edgeEpsilon;
263        var touchesLeft = r.left <= edgeEpsilon;
264        var touchesRight = r.right >= viewportWidth - edgeEpsilon;
265        if (!touchesTop && !touchesBottom && !touchesLeft && !touchesRight) {
266            continue;
267        }
268
269        // Skip full-width elements from triggering left/right insets
270        var verticalScrollbarWidth = Math.max(0, viewportWidth - document.documentElement.clientWidth);
271        var horizontalScrollbarHeight = Math.max(0, viewportHeight - document.documentElement.clientHeight);
272        var widthTolerance = edgeEpsilon + verticalScrollbarWidth;
273        var heightTolerance = edgeEpsilon + horizontalScrollbarHeight;
274
275        var fullWidth = (touchesLeft || touchesRight) && (viewportWidth - r.width) <= widthTolerance;
276        if (fullWidth) {
277            touchesLeft = false;
278            touchesRight = false;
279        }
280
281        // Skip full-height elements from triggering top/bottom insets
282        var fullHeight = (touchesTop || touchesBottom) && (viewportHeight - r.height) <= heightTolerance;
283        if (fullHeight) {
284            touchesTop = false;
285            touchesBottom = false;
286        }
287
288        if (!touchesTop && !touchesBottom && !touchesLeft && !touchesRight) {
289            continue;
290        }
291
292        var horizontallyIntersectsIframe = r.right > rect.left && r.left < rect.right;
293        var verticallyIntersectsIframe = r.bottom > rect.top && r.top < rect.bottom;
294
295        // Top/bottom insets only matter if the element actually overlaps the
296        // iframe horizontally (a fixed bar above/below the iframe column).
297        // Left/right insets only matter if it overlaps the iframe vertically.
298        var topCandidate = touchesTop && horizontallyIntersectsIframe;
299        var bottomCandidate = touchesBottom && horizontallyIntersectsIframe;
300        var leftCandidate = touchesLeft && verticallyIntersectsIframe;
301        var rightCandidate = touchesRight && verticallyIntersectsIframe;
302        if (!topCandidate && !bottomCandidate && !leftCandidate && !rightCandidate) {
303            continue;
304        }
305
306        // Among the edges the element is attached to, pick the one with the
307        // smallest gap from the corresponding far edge — i.e. the edge it most
308        // plausibly anchors to. Ties are resolved deterministically in the
309        // order top, bottom, left, right.
310        var bestEdge = null;
311        var bestDist = Infinity;
312        if (topCandidate) {
313            bestEdge = 'top';
314            bestDist = r.top;
315        }
316        if (bottomCandidate) {
317            var dB = viewportHeight - r.bottom;
318            if (dB < bestDist) { bestEdge = 'bottom'; bestDist = dB; }
319        }
320        if (leftCandidate) {
321            var dL = r.left;
322            if (dL < bestDist) { bestEdge = 'left'; bestDist = dL; }
323        }
324        if (rightCandidate) {
325            var dR = viewportWidth - r.right;
326            if (dR < bestDist) { bestEdge = 'right'; bestDist = dR; }
327        }
328
329        if (bestEdge === 'top') {
330            if (r.bottom > topInset) topInset = r.bottom;
331        } else if (bestEdge === 'bottom') {
332            var b = viewportHeight - r.top;
333            if (b > bottomInset) bottomInset = b;
334        } else if (bestEdge === 'left') {
335            if (r.right > leftInset) leftInset = r.right;
336        } else if (bestEdge === 'right') {
337            var rt = viewportWidth - r.left;
338            if (rt > rightInset) rightInset = rt;
339        }
340    }
341    }
342
343    if (topInset < 0) topInset = 0;
344    if (bottomInset < 0) bottomInset = 0;
345    if (leftInset < 0) leftInset = 0;
346    if (rightInset < 0) rightInset = 0;
347    if (topInset > viewportHeight) topInset = viewportHeight;
348    if (bottomInset > viewportHeight) bottomInset = viewportHeight;
349    if (leftInset > viewportWidth) leftInset = viewportWidth;
350    if (rightInset > viewportWidth) rightInset = viewportWidth;
351
352    var adjustedViewportHeight = viewportHeight - topInset - bottomInset;
353    var adjustedViewportWidth = viewportWidth - leftInset - rightInset;
354    if (adjustedViewportHeight < 0) adjustedViewportHeight = 0;
355    if (adjustedViewportWidth < 0) adjustedViewportWidth = 0;
356
357    iframe.contentWindow.postMessage({
358        type: 'sync_view_port',
359        viewport: {
360            top: rect.top - topInset,
361            left: rect.left - leftInset,
362            width: rect.width,
363            height: rect.height,
364            viewportWidth: adjustedViewportWidth,
365            viewportHeight: adjustedViewportHeight
366        }
367    }, '*');
368};
369
370var spekHandleFullscreenMessage = function (e) {
371    if (e && e.data && safeSlice(e.data, 0, 11) === "fullscreen:") {
372        var iframe = document.getElementById('SpektrixIFrame');
373        if (!iframe) return;
374        var expanded = e.data.slice(11) === 'true';
375
376        if (expanded) {
377            if (spekOriginalIframeStyles === null) {
378                spekOriginalIframeStyles = iframe.getAttribute('style') || '';
379            }
380            iframe.style.cssText = 'position:fixed;inset:0;width:100vw;height:100vh;z-index:2147483647;border:none;';
381            spekFullscreenActive = true;
382            spekScheduleViewportSync();
383        } else {
384            iframe.setAttribute('style', spekOriginalIframeStyles || '');
385            spekOriginalIframeStyles = null;
386            spekFullscreenActive = false;
387            spekScheduleViewportSync();
388        }
389    }
390};
391
392if (typeof (window.postMessage) !== "undefined") {
393    if (window.addEventListener) {
394        window.addEventListener('message', spekHandleResizeMessage, false);
395        window.addEventListener('message', spekHandleResizeExactMessage, false);
396        window.addEventListener('message', spekHandleCalendarMessage, false);
397        window.addEventListener('message', spekHandleFullscreenMessage, false);
398    } else {
399        window.attachEvent('onmessage', spekHandleResizeMessage);
400        window.attachEvent('onmessage', spekHandleResizeExactMessage);
401        window.attachEvent('onmessage', spekHandleCalendarMessage);
402        window.attachEvent('onmessage', spekHandleFullscreenMessage);
403    }
404} else if (window.addEventListener) {
405    window.addEventListener('load', spekPollIFrame, false);
406} else {
407    window.attachEvent('onload', spekPollIFrame);
408}
409
410var spekRequestAnimationFrame =
411    window.requestAnimationFrame ||
412    window.msRequestAnimationFrame ||
413    function (callback) {
414        return window.setTimeout(callback, 16);
415    };
416var spekViewportSyncScheduled = false;
417
418function spekScheduleViewportSync() {
419    if (spekViewportSyncScheduled) {
420        return;
421    }
422
423    spekViewportSyncScheduled = true;
424    spekRequestAnimationFrame(function () {
425        spekViewportSyncScheduled = false;
426        spekSyncViewport();
427    });
428}
429
430function spekHandleViewportLayoutChange() {
431    spekRefreshFixedOverlayCandidates();
432    spekStartFixedOverlayObserver();
433    spekScheduleViewportSync();
434}
435
436if (typeof (window.postMessage) !== "undefined") {
437    if (window.addEventListener) {
438        window.addEventListener('scroll', spekScheduleViewportSync, true);
439        window.addEventListener('resize', spekHandleViewportLayoutChange, false);
440        window.addEventListener('load', spekHandleViewportLayoutChange, false);
441    } else {
442        window.attachEvent('onscroll', spekScheduleViewportSync);
443        window.attachEvent('onresize', spekHandleViewportLayoutChange);
444        window.attachEvent('onload', spekHandleViewportLayoutChange);
445    }
446}
447
448// the code below is the equivalent to jQuery's document.ready which executes before window load/onload
449// this allows changing the iframe's src as soon as the dom elements are ready
450if (window.addEventListener) {
451    window.addEventListener("DOMContentLoaded", handleRedirects, false);
452} else {
453    document.attachEvent("onreadystatechange", function () {
454        if (document.readyState === "complete") {
455            handleRedirects();
456        }
457    });
458}

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.