1/** 2 * @file 3 */ 4 5(function ($, Drupal, once) { 6 7 Drupal.behaviors.formtips = { 8 attach: function (context, settings) { 9 10 function hideOnClickOutside(element, $description) { 11 var outsideClickListener = function (event) { 12 var $target = $(event.target); 13 if (!$target.hasClass('formtip') && !$target.hasClass('formtips-processed')) { 14 $description.toggleClass('formtips-show', false); 15 } 16 } 17 18 $(document).on('click', outsideClickListener); 19 } 20 21 var formtip_settings = settings.formtips; 22 var selectors = formtip_settings.selectors; 23 if ($.isArray(selectors)) { 24 selectors = selectors.join(', '); 25 } 26 27 var $descriptions = $('.form-item .description,.form-item__description,.form-item .filter-guidelines,.fieldset__description') 28 .not(selectors) 29 .not('.formtips-processed'); 30 31 // Filter out empty descriptions. This helps avoid the password strength 32 // description getting caught in a help. 33 $descriptions = $descriptions.filter(function () { 34 return $.trim($(this).text()) !== ''; 35 }); 36 37 if (formtip_settings.max_width.length) { 38 $descriptions.css('max-width', formtip_settings.max_width); 39 } 40 41 // Hide descriptions when escaped is hit. 42 $(document).on('keyup', function (e) { 43 if (e.which === 27) { 44 $descriptions.removeClass('formtips-show'); 45 } 46 }); 47
48 // As in Drupal 10: Remove jQuery dependency from the once feature 49 // @see: https://www.drupal.org/node/3158256 50 $(once('formtips', $descriptions, context)).each(function () { 51 var $description = $(this); 52 var $item = $description.closest('.form-item'); 53 var descriptionId = $description.attr('id'); 54 var $formtip = $('<a class="formtip" aria-labelledby="' + descriptionId + '" href="javascript:void(0);" tabindex="0"></a>'); 55 56 // If there is no description id, skip. 57 if (!descriptionId) { 58 return; 59 } 60 61 if (descriptionId.endsWith('-format-guidelines')) { 62 // Grab the field id from guidelines 63 fieldId = descriptionId.slice(0, -18) + '-value'; 64 } 65 else { 66 // Otherwise grabs it from the field description 67 fieldId = descriptionId.substring(0, descriptionId.lastIndexOf("-") - 1); 68 } 69 70 // First try to find a label associated with that field 71 var $label = $item.find('[for="' + fieldId + '"]:not(.visually-hidden)'); 72 73 // Try to get the fieldset from the Field Group module. 74 if (!$label.length) { 75 $label = $('fieldset.field-group-fieldset[id="' + fieldId + '"] .fieldset__label:not(.visually-hidden)'); 76 } 77 78 // Try to get the fieldset of the checkboxes element. 79 if (!$label.length) { 80 $label = $('fieldset.fieldgroup[id="' + fieldId + '"] .fieldset__label:not(.visually-hidden)'); 81 } 82 83 // Try to get the label that was added as a placeholder. 84 if (!$label.length && $('#' + fieldId).attr('placeholder')) { 85 $label = $item.find('[for="' + fieldId + '"]'); 86 87 if ($label.length && $label.hasClass('visually-hidden')) { 88 $label.removeClass('visually-hidden'); 89 } 90 } 91 92 // Check if there is a field with the '-value' suffix. 93 if (!$label.length) { 94 fieldId = fieldId + '-value'; 95 $label = $item.find('[for="' + fieldId + '"]:not(.visually-hidden)'); 96 } 97 98 // Otherwise look for the first label, a fieldset legend or draggable 99 // table label. 100 if (!$label.length) { 101 $label = $item.find('.fieldset-legend,label,.label,.form-item__label').first(); 102 103 if ($label.length && $label.hasClass('visually-hidden')) { 104 $label.removeClass('visually-hidden'); 105 } 106 } 107 108 // Use the fieldset if the item is a radio or checkbox. 109 var $fieldset = $item.find('.fieldset-legend'); 110 if ($fieldset.length && $item.find('input[type="checkbox"], input[type="radio"]').length) { 111 $label = $fieldset; 112 } 113 114 // If there is no label, skip. 115 if (!$label.length) { 116 return; 117 } 118 119 $description.addClass('formtips-processed'); 120 121 $item.addClass('formtips-item'); 122 $description.toggleClass('formtips-show', false); 123 $description.attr('tabindex', '0'); 124 $description.attr('role', 'tooltip'); 125 $label.append($formtip); 126 127 if (formtip_settings.trigger_action === 'click') { 128 $formtip.on('click', function () { 129 // Filter guidelines use the 'display:none;' style by default. 130 if ($description.find('.filter-guidelines-item').length !== 0) { 131 $description.children().show(); 132 } 133 134 $description.toggleClass('formtips-show'); 135 return false; 136 }); 137 // Hide description when clicking elsewhere. 138 139 hideOnClickOutside($item[0], $description); 140 141 } 142 else { 143 $formtip.hoverIntent({ 144 sensitivity: formtip_settings.sensitivity, 145 interval: formtip_settings.interval, 146 over: function () { 147 // Filter guidelines use the 'display:none;' style by default. 148 if ($description.find('.filter-guidelines-item').length !== 0) { 149 $description.children().show(); 150 } 151 152 $description.toggleClass('formtips-show', true); 153 }, 154 timeout: formtip_settings.timeout, 155 out: function () { 156 $description.toggleClass('formtips-show', false); 157 } 158 }); 159 } 160 }); 161 } 162 }; 163 164})(jQuery, Drupal, 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.