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.