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