1/** 2 * @file 3 * Colorbox JS. 4 */ 5 6(function ($, Drupal, drupalSettings, once) { 7 8 'use strict'; 9 10 Drupal.behaviors.initColorbox = { 11 attach: function (context, settings) { 12 if (typeof $.colorbox !== 'function' || typeof settings.colorbox === 'undefined') { 13 return; 14 } 15 16 if (settings.colorbox.mobiledetect && window.matchMedia) { 17 // Disable Colorbox for small screens. 18 var mq = window.matchMedia('(max-device-width: ' + settings.colorbox.mobiledevicewidth + ')'); 19 if (mq.matches) { 20 $.colorbox.remove(); 21 return; 22 } 23 } 24 25 settings.colorbox.rel = function () { 26 return $(this).data('colorbox-gallery'); 27 }; 28 29 settings.colorbox.html = function () { 30 var $modalContent = $(this).find('> .modal-content'); 31 return $modalContent.length ? $(this).find('> .modal-content').children().clone() : false; 32 }; 33 34 $(once('init-colorbox', '.colorbox', context)) 35 .each(function() { 36 // Only images are supported for the "colorbox" class. 37 // The "photo" setting forces the href attribute to be treated as an image. 38 var extendParams = { 39 photo: true 40 }; 41 // If a title attribute is supplied, sanitize it. 42 var title = $(this).attr('title'); 43 if (typeof title === 'undefined') { 44 title = this.dataset.cboxTitle; 45 } 46 if (title) { 47 extendParams.title = Drupal.colorbox.sanitizeMarkup(title); 48 } 49 $(this).colorbox($.extend({}, settings.colorbox, extendParams)); 50 51 // Only allow http or https protocol in hrefs. 52 var href = $(this).attr('href'); 53 var protocolRegex = /^(https?)/; 54 if (href && href.substring(0, 1) !== '/') { 55 var protocol = href.split(':')[0]; 56 // Use a regex to match http or https protocol. 57 if (!protocolRegex.test(protocol)) { 58 $(this).removeAttr('href'); 59 } 60 } 61 var dataHref = this.dataset.cboxHref; 62 if (dataHref && dataHref.substring(0, 1) !== '/') { 63 var dataProtocol = dataHref.split(':')[0]; 64 if (!protocolRegex.test(dataProtocol)) { 65 delete this.dataset.cboxHref; 66 } 67 } 68 69 // Since the sanitized title has been passed to colorbox settings, 70 // delete the unsanitized data-cbox-title attribute. 71 delete this.dataset.cboxTitle; 72 73 // Disallow dangerous data attributes. 74 delete this.dataset.cboxIframeAttrs; 75 76 // Sanitize other data attributes. 77 var sanitizeDataList = ['cboxNext', 'cboxPrevious', 'cboxCurrent', 78 'cboxClose', 'cboxSlideshowstop', 'cboxSlideshowstart', 79 'cboxXhrError', 'cboxImgerror', 'cboxHtml' 80 ]; 81 for (var a of sanitizeDataList) { 82 if (this.dataset.hasOwnProperty(a)) { 83 this.dataset[a] = Drupal.colorbox.sanitizeMarkup(this.dataset[a]); 84 } 85 } 86 }); 87 88 $('.colorbox', context).colorbox({ 89 onComplete: function (e) { 90 var focus = $('#cboxContent').find('#cboxPrevious').css('display') !== 'none' ? $('#cboxContent').find('#cboxPrevious') : $('#cboxContent').find('#cboxClose'); 91 focus.focus(); 92 93 $('#cboxContent').on('keydown', function (e) { 94 var keyCode = e.keyCode || e.which; 95 var firstElement = $('#cboxContent').find('#cboxPrevious').last().is(':focus'); 96 var lastElement = $('#cboxContent').find('#cboxClose').first().is(':focus'); 97 if (keyCode === 9 && !e.shiftKey && lastElement) { 98 e.preventDefault(); 99 $('#cboxContent').find('#cboxPrevious').first().focus(); 100 } 101 else if (keyCode === 9 && e.shiftKey && firstElement) { 102 e.preventDefault(); 103 $('#cboxContent').find('#cboxClose').first().focus(); 104 } 105 }); 106 } 107 }); 108 } 109 }; 110 111 // Create colorbox namespace if it doesn't exist. 112 if (!Drupal.hasOwnProperty('colorbox')) { 113 Drupal.colorbox = {}; 114 } 115 116 /** 117 * Global function to allow sanitizing captions and control strings. 118 * 119 * @param markup 120 * String containing potential markup. 121 * @return @string 122 * Sanitized string with potentially dangerous markup removed. 123 */ 124 Drupal.colorbox.sanitizeMarkup = function(markup) { 125 // If DOMPurify installed, allow some HTML. Otherwise, treat as plain text. 126 if (typeof DOMPurify !== 'undefined') { 127 var purifyConfig = { 128 ALLOWED_TAGS: [ 129 'a', 130 'b', 131 'strong', 132 'i', 133 'em', 134 'u', 135 'cite', 136 'code', 137 'br' 138 ], 139 ALLOWED_ATTR: [ 140 'href', 141 'hreflang', 142 'title', 143 'target' 144 ] 145 } 146 if (drupalSettings.hasOwnProperty('dompurify_custom_config')) { 147 purifyConfig = drupalSettings.dompurify_custom_config; 148 } 149 return DOMPurify.sanitize(markup, purifyConfig); 150 } 151 else { 152 return Drupal.checkPlain(markup); 153 } 154 } 155 156})(jQuery, Drupal, drupalSettings, once);
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.