PageSourceSearch

https://www.xalatan.com/-/media/base-themes/components-theme/scripts/component-overlay.js

js xalatan.com collected 2026-09-26 11:41:32 UTC 17,282 bytes, 517 lines download raw bytes

1/* global mejs:false */
2/**
3 * open content in overlay
4 * @module overlay
5 * @param  {jQuery} $ Instance of jQuery
6 * @return {Object} List of overlay methods
7 */
8XA.component.overlay = function ($) {
9    /**
10    * This object stores all public api methods
11    * @type {Object.<Methods>}
12    * @memberOf module:overlay
13    * */
14    var api = {},
15        href = window.location.href,
16        host = location.host,
17        label,
18        overlayPlaceholder = false,
19        marginTop = 100,
20        focusableElementsString = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]',
21        firstTabStop,
22        lastTabStop,
23        overlayClickSource;
24    /**
25    * isPreviewMode check if page in preview mode
26    * @memberOf module:overlay
27    * @private
28    * @returns {Boolean} is page in a preview mode
29    */
30    function isPreviewMode() {
31        if (href.indexOf("sc_mode=preview") > -1) {
32            return true;
33        }
34        var $hdPageMode = $('#hdPageMode');
35
36        return $hdPageMode.length > 0 && $hdPageMode.attr('value') == 'preview';
37    }
38
39
40    /**
41     * isOverlayPage check if "#wrapper" element has class "overlay-page"
42     * @memberOf module:overlay
43     * @private
44     * @returns {Boolean} is #wrapper an overlay page
45     */
46    function isOverlayPage() {
47        return $('#wrapper').hasClass('overlay-page');
48    }
49    /**
50     * hasOverlayContent check if "overlay-source" 
51     * element present on a page
52     * @memberOf module:overlay
53     * @private
54     * @returns {Boolean} is overlay-source present on a page
55     */
56    function hasOverlayContent() {
57        return $(".overlay-source").length;
58    }
59    /**
60    * resizeOverlay resize overlay
61    * @memberOf module:overlay
62    * @param {jQuery<Object>} inner ".overlay-inner"
63    * @param {jQuery<Object>} content (".component-content"),
64    * @param {Object} options contains size of overlay 
65    * @param {number} [options.width] width of overlay
66    * @param {number} [options.height] height of overlay
67    * @param {string} [options.percent] units of width and height
68    * @alias module:overlay.resizeOverlay
69    */
70    api.resizeOverlay = function (inner, content, options) {
71        var unit = "px";
72        var css = {
73            "width": "",
74            "height": ""
75        };
76        var wh = $(window).height();
77
78        if (options.percent) {
79            unit = "%";
80            inner.addClass("overlay-percent");
81        } else {
82            inner.removeClass("overlay-percent");
83        }
84
85        if (options.width) {
86            css["width"] = options.width + unit;
87        }
88        if (options.height) {
89            css["height"] = options.height + unit;
90        }
91
92        css["max-height"] = (wh - marginTop - 0.1 * wh) + "px";
93
94        content.css(css);
95    }
96    /**
97    * getUrlVariables get variables provided in overlay url
98    * @memberOf module:overlay
99    * @param {String} url url of overlay content
100    * @private
101    * @returns {Object} list of get parameters
102    */
103    function getUrlVariables(url) {
104        var q = url.split('?')[1],
105            vars = [],
106            hash;
107
108        if (q != undefined) {
109            q = q.split('&');
110            for (var i = 0; i < q.length; i++) {
111                hash = q[i].split('=');
112                vars.push(hash[1]);
113                vars[hash[0]] = hash[1];
114            }
115        }
116
117        return vars;
118    }
119    /**
120    * getSize check if overlay has width or height in url 
121    * and set up this values  
122    * @memberOf module:overlay
123    * @param {String} vars variables from url of overlay content
124    * @private
125    * @returns {Object} sizes of overlay
126    */
127    function getSize(vars) {
128        var obj = {};
129
130        if (vars["width"] !== null) {
131            obj["width"] = vars["width"];
132        }
133
134        if (vars["height"] !== null) {
135            obj["height"] = vars["height"];
136        }
137
138        return obj;
139    }
140    /**
141    * checkInternal checks if overlay content is internal resource
142    * @memberOf module:overlay
143    * @param {String} url url of overlay content
144    * @private
145    * @returns {Boolean} true - content is internal| false - content is external
146    */
147    function checkInternal(url) {
148        if (url.indexOf(host) > -1) {
149            return true;
150        }
151        return false;
152    }
153    /**
154    * checkImage checks if overlay content is an image
155    * @memberOf module:overlay
156    * @param {String} url url of overlay content
157    * @private
158    * @returns {Boolean} true - content is an image| false - content not an a image
159    */
160    function checkImage(url) {
161        var ext = url.split("?")[0].split('.').pop();
162        if ($.inArray(ext, ['gif', 'png', 'jpg', 'jpeg']) > -1) {
163            return true;
164        }
165
166        return false;
167    }
168
169    /**
170    * loadOverlay creates overlay content and show it
171    * @memberOf module:overlay
172    * @param {String} url url of overlay
173    * @param {jQuery<DOMElement>} overlay overlay DOMElement
174    * @private
175    */
176    function loadOverlay(url, overlay) {
177        var content = overlay.find(".overlay-inner"),
178            overlayContent = overlay.find(".component-content"),
179            vars = getUrlVariables(url),
180            internalLink = checkInternal(url),
181            overlaySize = getSize(vars),
182            suffix;
183        overlayContent.addClass('overlayFullWidth');
184        content.removeAttr('style');
185        if (internalLink) {
186            if (checkImage(url)) {
187                content.empty().append($("<img>", { src: url }));
188                content.css(overlaySize);
189                overlayContent.removeClass('overlayFullWidth');
190                showOverlay(overlay);
191            } else if (url.indexOf("overlaytype=iframe") > -1) {
192                content.empty().append($("<iframe>", { src: url, style: "width: 100%; height: 100%" }));
193                content.css(overlaySize);
194                showOverlay(overlay);
195            } else {
196                if (isPreviewMode()) {
197                    suffix = "cf_overlay=1";
198                    url = url.replace("sitecore/shell/");
199                    url += (url.indexOf("?") == -1 ? "?" : "&") + suffix;
200                }
201
202                $.get(url, function (data) {
203                    var overlayData = $(data).before().first();
204
205                    api.resizeOverlay(content, overlayContent, {
206                        width: overlayData.attr("data-width"),
207                        height: overlayData.data("height"),
208                        percent: overlayData.data("percent")
209                    });
210
211                    content.empty().append(data);
212                    XA.init();
213                    showOverlay(overlay);
214                });
215            }
216        } else {
217            if (checkImage(url)) {
218                content.empty().append($("<img>", { src: url }));
219            } else {
220                content.empty().append($("<iframe >", { src: url, style: "width: 100%; height: 100%" }));
221            }
222            content.css(overlaySize);
223            showOverlay(overlay);
224        }
225
226    }
227    /**
228    * preShowOverlay sets opacity to 1 and shows overlay
229    * @memberOf module:overlay
230    * @param {jQuery<DOMElement>} overlay overlay DOMElement
231    * @private
232    */
233    function preShowOverlay(overlay) {
234        overlay.css({
235            "opacity": 1
236        }).show();
237    }
238    /**
239    * showOverlay makes overlay visible
240    * @memberOf module:overlay
241    * @param {jQuery<DOMElement>} overlay overlay DOMElement
242    * @private
243    * @returns {jQuery<DOMElement>} overlay overlay DOMElement
244    */
245
246    function showOverlay(overlay) {
247        var close, content;
248        overlay.show().animate({
249            opacity: 1
250        });
251
252        // hides wrapper data from screen readers
253        $("#wrapper").addClass("aria-hidden");
254
255        overlayClickSource = document.activeElement;
256
257        close = overlay.find(".overlay-close");
258        setTimeout(function () { close.focus(); }, 0);
259
260        content = overlay.find(".overlay-inner");
261        content.blur(function (args) {
262            args.preventDefault();
263            args.stopPropagation();
264            setTimeout(function () { close.focus() }, 0);
265        });
266
267        // Finds all focusable children
268        var focusableElements = content.find(focusableElementsString);
269
270        // Converts NodeList to Array
271        focusableElements = Array.prototype.slice.call(focusableElements);
272        firstTabStop = focusableElements[0];
273        lastTabStop = focusableElements[focusableElements.length - 1];
274
275        // Focus first
276        firstTabStop.focus();
277        return overlay;
278    }
279    /**
280     * hideOverlay hide overlay
281     * @memberOf module:overlay
282     * @private
283     */
284    function hideOverlay(overlay) {
285        $("#wrapper").removeClass("aria-hidden");
286        var content = overlay.find(".overlay-inner");
287
288        overlay.animate({ opacity: 0 },
289            function () {
290                overlay.hide();
291                content.empty();
292
293                if (mejs) {
294                    for (var p in mejs.players) {
295                        if ($("#" + mejs.players[p].id).parents(".overlay").length == 1) {
296                            $("#" + mejs.players[p].id + ' video').attr('src', '');
297                            mejs.players[p].remove();
298                            mejs.players.splice(p, 1);
299                        }
300                    }
301                }
302            }
303        );
304
305        return overlay;
306    }
307    /**
308     * createOverlay creates a markup for overlay and appends it to body 
309     * @memberOf module:overlay
310     * @private
311     */
312    function createOverlay() {
313        var overlay = "<div class='overlay-wrapper'>" +
314            "<div class='overlay component'>" +
315            "<div class='component-content' role='dialog'>" +
316            "<div class='overlay-inner'></div>" +
317            "<div class='overlay-close' role='button' aria-label='Close dialog'></div>" +
318            "</div>" +
319            "</div>" +
320            "</div>";
321
322        $("body").append(overlay);
323    }
324    /**
325     * Init form conditions under overlay content
326     * @memberOf module:overlay
327     * @private
328     */
329    function initFormConditions() {
330        setTimeout(function () {
331            if (window.$ && window.$.fn.init_formConditions) {
332                var forms = window.$(".overlay-inner form[data-sc-fxb]");
333                if (forms.length) {
334                    forms.each(function () {
335                        var formEl = window.$(this);
336                        var fromInitializer = window.$.fn.init_formConditions.bind(formEl);
337                        fromInitializer();
338                    }).parent().on("submit", "form[data-sc-fxb]", function () {
339                        var $submitBtns = window.$(this).find("input[type='submit'], button[type='submit']");
340                        if ($submitBtns.length) {
341                            $submitBtns.on("click", function () {
342                                return false;
343                            });
344                        }
345                    });
346                }
347            }
348        }, 0)
349
350    }
351
352    /**
353    * initInstance method prevent event propagation and call 
354    * ["preShowOverlay"]{@link module:overlay.preShowOverlay} and
355    * ["loadOverlay"]{@link module:overlay.loadOverlay} methods
356    * @memberOf module:overlay
357    * @method
358    * @param {jQuery} component Root DOM element of archive component wrapped by jQuery
359    * @param {jQuery<DOMElement>} overlay overlay DOMElement
360    * @param {jQuery<DOMElement>} overlayContent overlay content DOMElement 
361    * @alias module:overlay.initInstance
362    */
363    api.initInstance = function (component, overlay, overlayContent) {
364        component.on("click",
365            function (event) {
366                event.preventDefault();
367                event.stopPropagation();
368                preShowOverlay(overlay, overlayContent);
369
370                var uri = this.href;
371                loadOverlay(uri, overlay);
372
373                var href = this.href.split('/');
374                for (var i = 0; i <= href.length; i++) {
375                    label = href.pop();
376                    if (label.length == 0) {
377                        continue;
378                    }
379                    break;
380                }
381            });
382        // Init forms if they exist inside overlay
383        initFormConditions();
384        component.addClass("initialized");
385    }
386    /**
387    * init method makes preparation for overlay content, binds events
388    * for proper work of overlay and
389    * calls in a loop for each instance of overlay
390    * [".initInstance"]{@link module:Accordion.initInstance} method.
391    * @memberOf module:overlay
392    * @alias module:overlay.init
393    */
394    api.init = function () {
395        var overlayContent,
396            overlaySource,
397            overlayInner,
398            overlayCloseLink,
399            closeAction,
400            page,
401            overlay,
402            content;
403
404        if (!overlayPlaceholder && hasOverlayContent()) {
405            createOverlay();
406        }
407
408        if (isOverlayPage()) {
409
410            page = $(".overlay-page");
411            overlayContent = page.children(".component-content");
412            overlay = $("#spnOverlay");
413            content = overlayContent.children(".overlay-inner");
414
415            api.resizeOverlay(content, overlayContent, {
416                width: overlayContent.data("width"),
417                height: overlayContent.data("height"),
418                percent: overlayContent.data("percent")
419            });
420            overlayContent.on("click", function (event) {
421                if (event.target.type != 'submit') {
422                    event.stopPropagation();
423                }
424            });
425            page.on("click", function () {
426                if (isPreviewMode()) {
427                    location.href = location.href.replace("sc_mode=preview", "sc_mode=edit");
428                }
429            });
430        }
431        overlay = $(".overlay-wrapper > .overlay");
432        overlayContent = overlay.find(".component-content");
433        overlaySource = $(".overlay-source a:not(.initialized), a.overlay-source:not(.initialized)");
434        overlayInner = $(".overlay-inner");
435        overlayCloseLink = overlay.find(".overlay-close");
436
437        closeAction = function () {
438            hideOverlay(overlay);
439            overlayInner.off("blur");
440            setTimeout(function () {
441                if (overlayClickSource != null) {
442                    overlayClickSource.focus();
443                }
444            }, 0);
445        };
446
447        if (!overlayPlaceholder) {
448            overlayContent.on("click", function (event) {
449                if (event.target.type != 'submit') {
450                    event.stopPropagation();
451                }
452            });
453
454            overlay.on("click", function (event) {
455                if (event.target.type != 'submit') {
456                    closeAction();
457                }
458
459            });
460
461            overlayCloseLink.on("click", function (args) {
462                args.preventDefault();
463                closeAction();
464            });
465
466            $("body").keydown(function (e) {
467                // Check for TAB key press
468                if (e.keyCode === 9) {
469                    // SHIFT + TAB
470                    if (e.shiftKey) {
471                        if (document.activeElement === firstTabStop) {
472                            e.preventDefault();
473                            lastTabStop.focus();
474                        }
475
476                        // TAB
477                    } else if (document.activeElement === lastTabStop) {
478                        e.preventDefault();
479                        // firstTabStop.attr('tabindex', 0);
480                        firstTabStop.focus();
481                    }
482                }
483
484                // ESCAPE
485                if (e.keyCode === 27) {
486                    e.stopPropagation();
487                    closeAction();
488                }
489            });
490
491            $(window).on("resize", function () {
492                var height = $(window).height();
493                height = height - marginTop - 0.1 * height;
494                overlayContent.css("max-height", height + "px");
495            });
496
497            overlayPlaceholder = true;
498        }
499
500
501        overlaySource.each(function () {
502            api.initInstance($(this), overlay, overlayContent);
503        });
504
505
506    };
507
508    return api;
509
510}(jQuery);
511
512XA.register("overlay", XA.component.overlay);
513
514
515[].forEach.call(document.querySelectorAll('.search-results.overlay-source'), function (e) {
516    XA.dom.observeDOM(e, function () { XA.component.overlay.init(); });
517});

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.