1/** 2 * WHAT: "Report error" form â morphs the toolbar into a compact feedback 3 * form, submits to /feedback, restores the toolbar when done. 4 * WHY: Small, self-contained â the form just needs the active selection 5 * (via toolbar.state.activeContext) and util helpers. 6 * DEPENDS ON: window.DwTextTools.util, window.DwTextTools.toolbar. 7 * EXPORTS on window.DwTextTools.feedback: show 8 */ 9 10(function () { 11 'use strict'; 12 13 var ns = (window.DwTextTools = window.DwTextTools || {}); 14 var util = ns.util; 15 var bar = ns.toolbar; 16 17 /** 18 * Morph the toolbar into the feedback form. Captures selection data up 19 * front so Cancel / Send still work if the DOM selection gets cleared. 20 */ 21 function show() { 22 var ctx = bar.state.activeContext; 23 var selectedText = ctx ? ctx.getSelectedText() : ''; 24 var context = ctx ? ctx.getContext() : {}; 25 if (!selectedText) return; 26 27 bar.beginForm(); 28 29 var preview = selectedText.length > 80 30 ? selectedText.substring(0, 80) + '\u2026' 31 : selectedText; 32 33 bar.state.element.innerHTML = 34 '<div class="dwtexttools-feedback-form">' + 35 '<div class="dwtexttools-feedback-preview">' + util.escapeHtml(preview) + '</div>' + 36 '<textarea class="dwtexttools-feedback-message" rows="3" placeholder="What is wrong?"></textarea>' + 37 // Honeypot â invisible to humans, bots fill it in 38 '<input type="text" class="dwtexttools-feedback-hp" tabindex="-1" autocomplete="off">' + 39 '<div class="dwtexttools-feedback-actions">' + 40 '<button class="dwtexttools-feedback-send" type="button">Send</button>' + 41 '<button class="dwtexttools-feedback-cancel" type="button">\u00D7</button>' + 42 '</div>' + 43 '</div>'; 44 45 bar.position(); 46 47 var root = bar.state.element; 48 var msgEl = root.querySelector('.dwtexttools-feedback-message'); 49 var hpEl = root.querySelector('.dwtexttools-feedback-hp'); 50 var sendBtn = root.querySelector('.dwtexttools-feedback-send'); 51 var cancelBtn = root.querySelector('.dwtexttools-feedback-cancel'); 52 53 if (msgEl) msgEl.focus(); 54 55 sendBtn.addEventListener('click', function () { 56 var message = msgEl ? msgEl.value.trim() : ''; 57 if (!message) { 58 msgEl.classList.add('dwtexttools-feedback-error'); 59 msgEl.placeholder = 'Please describe the error.'; 60 return; 61 } 62 63 sendBtn.disabled = true; 64 sendBtn.textContent = 'Sending\u2026'; 65 66 util.submitFeedback({ 67 selectedText: selectedText, 68 message: message, 69 pageUrl: window.location.href, 70 context: context, 71 hp: hpEl ? hpEl.value : '' 72 }, function (ok) { 73 if (ok) { 74 bar.restore('Thank you!'); 75 } else { 76 sendBtn.disabled = false; 77 sendBtn.textContent = 'Send'; 78 msgEl.classList.add('dwtexttools-feedback-error'); 79 msgEl.placeholder = 'Failed â try again?'; 80 } 81 }); 82 }); 83 84 cancelBtn.addEventListener('click', function () { bar.restore(); }); 85 86 if (msgEl) msgEl.addEventListener('keydown', function (e) { 87 if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) { 88 e.preventDefault(); 89 sendBtn.click(); 90 } 91 }); 92 } 93 94 ns.feedback = { show: show }; 95})();
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.