1import Tagify from "@yaireo/tagify" 2 3const normalizeTagValue = value => value.toString().trim().replace(/,+/g, ''); 4 5const serializeTags = tags => tags.map(tag => normalizeTagValue(tag.value)) 6 .filter(value => value.length > 0) 7 .join(' '); 8 9const fetchTagSuggestions = (input, tagify, query) => { 10 query = normalizeTagValue(query); 11 12 if (query.length === 0) { 13 tagify.whitelist = []; 14 tagify.dropdown.hide(); 15 return; 16 } 17 18 const requestId = (input.tagifyRequestId || 0) + 1; 19 input.tagifyRequestId = requestId; 20 tagify.loading(true); 21 22 fetch(`/tags.json?term=${encodeURIComponent(query)}`) 23 .then(res => res.json()) 24 .then(data => { 25 if (input.tagifyRequestId !== requestId) return; 26 tagify.whitelist = data.map(tag => ({ value: tag.name })); 27 tagify.loading(false); 28 tagify.dropdown.show(query); 29 }) 30 .catch(() => { 31 if (input.tagifyRequestId !== requestId) return; 32 tagify.loading(false); 33 }); 34}; 35 36const buildTagify = (input) => { 37 if (!window.Tagify || input.tagify) return; 38 39 const initialTags = input.value.split(/\s+/).filter(v => v.length > 0); 40 input.value = ''; 41 42 const tagify = new Tagify(input, { 43 delimiters: ',| ', 44 duplicates: false, 45 addTagOnBlur: true, 46 dropdown: { 47 enabled: 1, 48 maxItems: 10, 49 fuzzySearch: false, 50 highlightFirst: true, 51 closeOnSelect: true 52 }, 53 originalInputValueFormat: serializeTags, 54 transformTag: (tagData) => { 55 tagData.value = normalizeTagValue(tagData.value); 56 } 57 }); 58 59 if (initialTags.length > 0) tagify.addTags(initialTags); 60 tagify.on('input', (event) => fetchTagSuggestions(input, tagify, event.detail.value)); 61 input.tagify = tagify; 62}; 63 64const destroyTagify = (input) => { 65 if (!input.tagify) return; 66 input.tagify.destroy(); 67 delete input.tagify; 68 delete input.tagifyRequestId; 69}; 70 71document.addEventListener('turbo:load', () => { 72 document.querySelectorAll('.js-tagify').forEach(buildTagify); 73}); 74 75document.addEventListener('click', (event) => { 76 const label = event.target.closest('label'); 77 if (!label) return; 78 79 const input = document.getElementById(label.htmlFor); 80 if (!input?.classList?.contains('js-tagify') || !input.tagify) return; 81 82 event.preventDefault(); 83 input.tagify.DOM.input.focus(); 84}); 85 86document.addEventListener('turbo:before-cache', () => { 87 document.querySelectorAll('.js-tagify').forEach(destroyTagify); 88});
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.