PageSourceSearch

https://mediq.com/-/media/Base-Themes/Components-Theme/Scripts/component-overlay.js

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

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.