| <!DOCTYPE html> |
| <html lang="en"> |
| |
|
|
| <head> |
| |
|
|
| <script |
| src="https://code.jquery.com/jquery-3.4.1.slim.min.js" |
| integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" |
| crossorigin="anonymous" |
| ></script> |
| <script |
| src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" |
| integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" |
| crossorigin="anonymous" |
| ></script> |
| <script |
| src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" |
| integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" |
| crossorigin="anonymous" |
| ></script> |
| <link |
| rel="stylesheet" |
| href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" |
| integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" |
| crossorigin="anonymous" |
| /> |
| <link rel="stylesheet" href="/static/styles/emphasis.css" /> |
| <script |
| src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" |
| integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" |
| crossorigin="anonymous" |
| ></script> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> |
| <style> |
| * { |
| box-sizing: border-box; |
| } |
| |
| .row { |
| display: flex; |
| flex-direction: column; |
| } |
| |
| |
| |
| |
| |
| .column { |
| flex: 50%; |
| padding: 15px; |
| } |
| |
| .instance { |
| border: 1px solid #070707; |
| background-color: cccccc; |
| border-radius: 5px; |
| padding: 15px; |
| display: block; |
| justify-content: center; |
| width: fit-content; |
| max-width: 80%; |
| text-align: left; |
| margin: 0 auto; |
| font-size: 15pt; |
| } |
| |
| .instance p { |
| font-weight: bold; |
| display: block; |
| } |
| |
| .annotation_schema { |
| padding: 5px; |
| display: flex; |
| justify-content: center; |
| width: 80%; |
| text-align: left; |
| margin: 0 auto; |
| } |
| |
| fieldset { |
| border: 1px solid #160085; |
| background-color: cccccc; |
| padding: 10px 15px 10px 15px; |
| } |
| |
| legend { |
| color: black; |
| } |
| |
| input[type="text"] { |
| -webkit-box-sizing: border-box; |
| -moz-box-sizing: border-box; |
| box-sizing: border-box; |
| width: 100%; |
| } |
| |
| input { |
| margin: 5px; |
| } |
| |
| .likert li { |
| float: left; |
| list-style-type: none; |
| } |
| |
| |
| .sidepanel { |
| min-height: 250px; |
| width: 0; |
| position: fixed; |
| z-index: 1; |
| top: 95px; |
| left: 1px; |
| background-color: #111; |
| overflow-x: hidden; |
| padding-top: 10px; |
| padding-bottom: 20px; |
| transition: 0.5s; |
| } |
| |
| |
| .sidepanel a { |
| padding: 8px 8px 8px 32px; |
| text-decoration: none; |
| font-size: 55px; |
| color: #ffffff; |
| display: block; |
| transition: 0.3s; |
| } |
| |
| |
| .sidepanel a:hover { |
| color: #f1f1f1; |
| } |
| |
| |
| .sidepanel table { |
| color: #ffffff; |
| font-size: 20px; |
| |
| margin-left: 20px; |
| margin-top: 10px; |
| border-spacing: 10px; |
| } |
| |
| .sidepanel td, |
| th { |
| color: #ffffff; |
| padding: 5px; |
| } |
| |
| .sidepanel tr:nth-child(even) { |
| background-color: #333333; |
| } |
| |
| |
| .sidepanel .closebtn { |
| position: absolute; |
| top: 0; |
| right: 25px; |
| font-size: 36px; |
| margin-left: 50px; |
| } |
| |
| |
| .openbtn { |
| cursor: pointer; |
| |
| |
| |
| |
| |
| |
| } |
| |
| .openbtn:hover { |
| background-color: #444; |
| } |
| |
| |
| .instructions { |
| |
| transition: 0.5s; |
| overflow-y: hidden; |
| border: 1px solid #070707; |
| background-color: cccccc; |
| border-radius: 5px; |
| padding: 15px; |
| display: block; |
| justify-content: center; |
| width: fit-content; |
| max-width: 80%; |
| text-align: left; |
| margin: 0 auto; |
| font-size: 14pt; |
| } |
| |
| |
| .instructions .closebtn { |
| position: absolute; |
| top: 0; |
| right: 25px; |
| font-size: 36px; |
| margin-left: 50px; |
| } |
| |
| |
| .instructions .openbtn { |
| cursor: pointer; |
| |
| |
| |
| |
| |
| |
| } |
| |
| .span_container { |
| border-width: 3px; |
| border-style: solid; |
| border: 2px solid black; |
| position: relative; |
| border-radius: 5px; |
| padding: 2px 5px; |
| background-color: pink; |
| } |
| |
| .span_label { |
| position: absolute; |
| top: -12px; |
| left: 5px; |
| font-size: 7px; |
| padding: 1px 1px; |
| border-radius: 3px; |
| background-color: pink; |
| border: 2px solid red; |
| text-align: center; |
| } |
| |
| .span_close { |
| position: absolute; |
| top: -7px; |
| right: -7px; |
| width: 14px; |
| height: 14px; |
| font-size: 7px; |
| padding: 2px 2px; |
| border-radius: 50%; |
| background-color: gray; |
| border: 2px solid black; |
| text-align: center; |
| font: 7pt Arial, sans-serif; |
| } |
| </style> |
| </head> |
|
|
|
|
| |
|
|
| <style> |
| :root { |
| --background: #ffffff; |
| --foreground: #09090b; |
| --card: #ffffff; |
| --card-foreground: #09090b; |
| --popover: #ffffff; |
| --popover-foreground: #09090b; |
| --primary: #6e56cf; |
| --primary-foreground: #ffffff; |
| --secondary: #f4f4f5; |
| --secondary-foreground: #18181b; |
| --muted: #f4f4f5; |
| --muted-foreground: #71717a; |
| --accent: #f4f4f5; |
| --accent-foreground: #18181b; |
| --destructive: #ef4444; |
| --destructive-foreground: #fafafa; |
| --border: #e4e4e7; |
| --input: #e4e4e7; |
| --ring: #6e56cf; |
| --radius: 0.5rem; |
| --primary-color: #6e56cf; |
| --secondary-color: #7c66ce; |
| --accent-color: #a18fff; |
| --dark-color: #09090b; |
| --light-color: #fafafa; |
| --gray-color: #71717a; |
| --light-gray: #f4f4f5; |
| --light-bg: #f5f7fb; |
| --heading-color: white; |
| --text-color: #555555; |
| --success-color: #10b981; |
| --border-radius: 0.5rem; |
| --box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), |
| 0 1px 2px -1px rgb(0 0 0 / 0.1); |
| --transition: all 0.2s ease; |
| --section-padding-top: 100px; |
| } |
| |
| |
| .shadcn-button { |
| display: inline-flex; |
| align-items: center; |
| justify-content: center; |
| border-radius: var(--radius); |
| font-weight: 500; |
| font-size: 0.875rem; |
| height: 2.5rem; |
| padding-left: 1rem; |
| padding-right: 1rem; |
| transition: var(--transition); |
| cursor: pointer; |
| text-decoration: none; |
| } |
| |
| .shadcn-button-primary { |
| background-color: var(--primary); |
| color: var(--primary-foreground); |
| border: 1px solid var(--primary); |
| } |
| |
| .shadcn-button-primary:hover { |
| background-color: var(--secondary-color); |
| color: var(--primary-foreground); |
| } |
| |
| .shadcn-button-outline { |
| background-color: transparent; |
| color: var(--primary); |
| border: 1px solid var(--border); |
| } |
| |
| .shadcn-button-outline:hover { |
| background-color: var(--secondary); |
| color: var(--primary); |
| } |
| |
| |
| .sidepanel { |
| height: 100%; |
| width: 0; |
| position: fixed; |
| z-index: 1000; |
| top: 0; |
| right: 0; |
| background-color: var(--card); |
| overflow-x: hidden; |
| transition: 0.3s; |
| padding-top: 60px; |
| box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1); |
| } |
| |
| .sidepanel a { |
| padding: 8px 8px 8px 32px; |
| text-decoration: none; |
| font-size: 16px; |
| color: var(--foreground); |
| display: block; |
| transition: 0.3s; |
| } |
| |
| .sidepanel .closebtn { |
| position: absolute; |
| top: 0; |
| right: 25px; |
| font-size: 36px; |
| margin-left: 50px; |
| color: var(--muted-foreground); |
| } |
| |
| |
| .span_container { |
| position: relative; |
| display: inline-block; |
| border-radius: var(--radius); |
| } |
| |
| .span_label { |
| position: absolute; |
| top: -18px; |
| left: 0; |
| font-size: 10px; |
| border-radius: 3px; |
| padding: 0 3px; |
| color: var(--primary); |
| } |
| |
| .span_close { |
| position: absolute; |
| top: -18px; |
| right: 0; |
| font-size: 12px; |
| border-radius: 3px; |
| padding: 0 3px; |
| cursor: pointer; |
| color: var(--destructive); |
| } |
| |
| |
| .shadcn-card { |
| height: 65vh; |
| background-color: var(--card); |
| border-radius: var(--radius); |
| border: 1px solid var(--border); |
| box-shadow: var(--box-shadow); |
| overflow: hidden; |
| } |
| |
| .shadcn-card-header { |
| padding: 1.5rem; |
| border-bottom: 1px solid var(--border); |
| } |
| |
| .shadcn-card-content { |
| padding: 1.5rem; |
| } |
| |
| fieldset { |
| border: 1px solid var(--border); |
| border-radius: var(--radius); |
| padding: 1rem; |
| margin-bottom: 1rem; |
| } |
| |
| legend { |
| font-weight: 500; |
| color: var(--heading-color); |
| padding: 0 0.5rem; |
| } |
| |
| |
| input[type="text"], |
| input[type="number"], |
| textarea, |
| select { |
| border: 1px solid var(--border); |
| border-radius: var(--radius); |
| padding: 0.5rem; |
| background-color: var(--background); |
| color: var(--foreground); |
| transition: var(--transition); |
| } |
| |
| input[type="text"]:focus, |
| input[type="number"]:focus, |
| textarea:focus, |
| select:focus { |
| outline: none; |
| border-color: var(--ring); |
| box-shadow: 0 0 0 2px var(--ring-opacity); |
| } |
| </style> |
|
|
| {{ custom_js | safe }} |
|
|
| <body style="background-color: var(--background); color: var(--foreground)"> |
| <input type="hidden" name="username" id="username" value="{{username}}" /> |
| <input |
| type="hidden" |
| name="instance_id" |
| id="instance_id" |
| value="{{instance_id}}" |
| /> |
| <input |
| type="hidden" |
| name="alert_time_each_instance" |
| id="alert_time_each_instance" |
| value="{{alert_time_each_instance}}" |
| /> |
| <p id="timecounter" hidden>Time spent:</p> |
|
|
| <div id="mySidepanel" class="sidepanel"> |
| <a |
| href="javascript:void(0)" |
| class="closebtn" |
| target_id="mySidepanel" |
| onclick="closeNav(this.getAttribute('target_id'))" |
| >×</a |
| > |
| <table><tr><th>Key</th><th>Description</th></tr><tr><td style="text-align: center;">←</td><td>Move backward</td></tr><tr><td style="text-align: center;">→</td><td>Move forward</td></tr><tr><td style="text-align: center;">1</td><td>relevance: 1</td></tr><tr><td style="text-align: center;">2</td><td>relevance: 2</td></tr><tr><td style="text-align: center;">3</td><td>relevance: 3</td></tr><tr><td style="text-align: center;">4</td><td>relevance: 4</td></tr><tr><td style="text-align: center;">5</td><td>relevance: 5</td></tr><tr><td style="text-align: center;">1</td><td>coherence: 1</td></tr><tr><td style="text-align: center;">2</td><td>coherence: 2</td></tr><tr><td style="text-align: center;">3</td><td>coherence: 3</td></tr><tr><td style="text-align: center;">4</td><td>coherence: 4</td></tr><tr><td style="text-align: center;">5</td><td>coherence: 5</td></tr></table> |
| </div> |
|
|
| <div id="Statpanel" class="sidepanel"> |
| <a |
| href="javascript:void(0)" |
| class="closebtn" |
| target_id="Statpanel" |
| onclick="closeNav(this.getAttribute('target_id'))" |
| >×</a |
| > |
| [[statistics_nav]] |
| </div> |
|
|
| <script> |
| |
| document.addEventListener("click", function (event) { |
| const hintEl = event.target.closest(".hint"); |
| if (!hintEl) return; |
| |
| const aiHelp = hintEl.closest(".ai-help"); |
| const tooltip = aiHelp.querySelector(".tooltip"); |
| const tooltipText = tooltip.querySelector(".tooltip-text"); |
| const annotationId = aiHelp.closest("[data-annotation-id]")?.dataset |
| .annotationId; |
| const text = document.getElementById("instance-text").innerText; |
| |
| fetch("get_ai_hint", { |
| method: "POST", |
| credentials: "same-origin", |
| body: JSON.stringify({ annotation_id: annotationId, text: text }), |
| headers: { "Content-Type": "application/json" }, |
| }) |
| .then((response) => response.json()) |
| .then((data) => { |
| tooltipText.innerHTML = `<span class="reasoning">Reasoning:</span> ${data.reasoning}`; |
| tooltip.classList.toggle("active"); |
| }) |
| .catch((error) => { |
| tooltipText.innerHTML = `<span class="reasoning">Error:</span> Could not load hint`; |
| tooltip.classList.toggle("active"); |
| console.error("Error fetching AI hint:", error); |
| }); |
| }); |
| document.addEventListener("click", function (event) { |
| if (!event.target.closest(".ai-help")) { |
| document.querySelectorAll(".tooltip.active").forEach((tooltip) => { |
| tooltip.classList.remove("active"); |
| }); |
| } |
| }); |
| </script> |
|
|
| <script> |
| document.addEventListener("keyup", function (event) { |
| var active_id = document.activeElement.id; |
| var active_type = document.activeElement.getAttribute("type"); |
| if ((active_id == "go_to") | (active_type == "text")) return; |
| |
| |
| var checkboxes = document.querySelectorAll("input[type=checkbox]"); |
| var radios = document.querySelectorAll("input[type=radio]"); |
| var x = event.key.toLowerCase(); |
| |
| for (var i = 0; i < checkboxes.length; i++) { |
| |
| if (x === checkboxes[i].value) { |
| checkboxes[i].checked = !checkboxes[i].checked; |
| if (checkboxes[i].onclick != null) |
| checkboxes[i].onclick.apply(checkboxes[i]); |
| return; |
| } |
| } |
| for (var i = 0; i < radios.length; i++) { |
| |
| if (x === radios[i].value) { |
| radios[i].checked = !radios[i].checked; |
| if (radios[i].onclick != null) radios[i].onclick.apply(radios[i]); |
| return; |
| } |
| } |
| |
| |
| |
| get_new_instance(event); |
| }); |
| |
| function getFieldSetState(element) { |
| |
| |
| |
| |
| |
| var fieldSet = element.closest("fieldset"); |
| |
| |
| var inputs = fieldSet.querySelectorAll("input"); |
| |
| |
| var state = Array.from(inputs).map((input) => { |
| return { |
| name: input.getAttribute("label_name"), |
| value: input.checked, |
| |
| }; |
| }); |
| return state; |
| } |
| |
| function registerAnnotation(element) { |
| |
| |
| sc = element.getAttribute("selection_constraint"); |
| if (sc && sc == "single") { |
| state = getFieldSetState(element); |
| } else if (element.getAttribute("type") == "range") { |
| state = [ |
| { |
| name: element.getAttribute("label_name"), |
| value: element.value, |
| }, |
| ]; |
| } |
| |
| else { |
| state = [ |
| { |
| name: element.getAttribute("label_name"), |
| value: element.checked, |
| |
| }, |
| ]; |
| } |
| |
| |
| var schema = element.getAttribute("schema"); |
| |
| |
| var instance_id = document.getElementById("instance_id").value; |
| |
| |
| var post_req = { |
| type: "label", |
| schema: schema, |
| state: state, |
| instance_id: instance_id, |
| }; |
| |
| |
| fetch("/updateinstance", { |
| method: "POST", |
| body: JSON.stringify(post_req), |
| credentials: "same-origin", |
| headers: { |
| "Content-type": "application/json; charset=UTF-8", |
| }, |
| }); |
| } |
| |
| function registerTextAnnotation(element) { |
| |
| var schema = element.getAttribute("schema"); |
| |
| |
| var instance_id = document.getElementById("instance_id").value; |
| |
| state = [ |
| { |
| name: element.getAttribute("label_name"), |
| value: element.value, |
| }, |
| ]; |
| |
| |
| var post_req = { |
| type: "label", |
| schema: schema, |
| state: state, |
| instance_id: instance_id, |
| }; |
| |
| |
| fetch("/updateinstance", { |
| method: "POST", |
| body: JSON.stringify(post_req), |
| credentials: "same-origin", |
| headers: { |
| "Content-type": "application/json; charset=UTF-8", |
| }, |
| }); |
| } |
| |
| function getSelectedText() { |
| var text = ""; |
| if (typeof window.getSelection != "undefined") { |
| text = window.getSelection().toString(); |
| } else if ( |
| typeof document.selection != "undefined" && |
| document.selection.type == "Text" |
| ) { |
| text = document.selection.createRange().text; |
| } |
| return text; |
| } |
| |
| function deleteSpanAnnotation( |
| spanElem, |
| schema, |
| labelName, |
| title, |
| start, |
| end |
| ) { |
| |
| var instance_id = document.getElementById("instance_id").value; |
| |
| |
| var spanText = spanElem.innerText; |
| |
| |
| var post_req = { |
| type: "span", |
| schema: schema, |
| state: [ |
| { |
| name: labelName, |
| start: start, |
| end: end, |
| title: title, |
| value: null, |
| }, |
| ], |
| instance_id: instance_id, |
| }; |
| |
| |
| fetch("/updateinstance", { |
| method: "POST", |
| body: JSON.stringify(post_req), |
| credentials: "same-origin", |
| headers: { |
| "Content-type": "application/json; charset=UTF-8", |
| }, |
| }); |
| |
| |
| $(spanElem).find("div").first().remove(); |
| |
| $(spanElem).find("div").last().remove(); |
| |
| $(spanElem.firstChild).unwrap(); |
| } |
| |
| function getEarlierChildren(n, skipMe) { |
| var r = []; |
| for (; n; n = n.nextSibling) |
| if (n.nodeType == 1 && n != skipMe) r.push(n); |
| else if (n == skipMe) break; |
| return r; |
| } |
| |
| function getEarlierSiblings(n) { |
| return getEarlierChildren(n.parentNode.firstChild, n); |
| } |
| |
| function getTextOfSpans(elems) { |
| text = ""; |
| for (i = 0; i < elems.length; i++) { |
| |
| |
| e = elems[i].cloneNode(true); |
| console.log("e", e); |
| |
| $(e).find("div").remove(); |
| console.log("sib text", e.textContent); |
| text += " " + e.textContent; |
| } |
| |
| return text.trim(); |
| } |
| |
| function getSelectionIndices() { |
| |
| var selection = window.getSelection(); |
| |
| if (selection.rangeCount === 0) { |
| return { start: -1, end: -1 }; |
| } |
| |
| |
| var range = selection.getRangeAt(0); |
| |
| |
| var leftMost = range.startContainer; |
| var leftSibs = getEarlierSiblings(leftMost); |
| console.log("leftSibs", leftSibs); |
| |
| var leftText = getTextOfSpans(leftSibs); |
| |
| |
| var parentDiv = $(range.commonAncestorContainer).closest( |
| 'div[name="instance_text"]' |
| )[0]; |
| |
| |
| if (!parentDiv) { |
| return { start: -2, end: -2 }; |
| } |
| |
| |
| |
| |
| |
| parentDiv = parentDiv.cloneNode(true); |
| |
| |
| console.log( |
| "before delete", |
| range.startContainer, |
| range.startOffset, |
| range.endOffset |
| ); |
| var tempRange = document.createRange(); |
| tempRange.setStart(parentDiv, 0); |
| tempRange.setEnd(range.startContainer, range.startOffset); |
| |
| |
| $(parentDiv).find("div").remove(); |
| |
| console.log("after delete"); |
| console.dir(parentDiv.innerHTML); |
| console.log("text"); |
| console.dir(parentDiv.textContent); |
| |
| console.log( |
| "after delete", |
| range.startContainer, |
| range.startOffset, |
| range.endOffset |
| ); |
| |
| |
| var div = document.createElement("div"); |
| div.appendChild(tempRange.cloneContents()); |
| |
| var s = range.startContainer.textContent.toString(); |
| |
| var whitespaceOffset = s.length - s.trimStart().length; |
| |
| var startOffset = range.startOffset - whitespaceOffset; |
| |
| if (leftText.length > 0) { |
| |
| startOffset += leftText.length + 1; |
| } |
| |
| |
| var selectedTextLength = range.toString().length; |
| |
| |
| var endOffset = startOffset + selectedTextLength; |
| |
| return { start: startOffset, end: endOffset }; |
| } |
| |
| function surroundSelection(schema, labelName, title, selectionColor) { |
| |
| |
| |
| |
| |
| |
| if (window.getSelection().rangeCount == 0) { |
| return; |
| } |
| var range = window.getSelection().getRangeAt(0); |
| |
| |
| |
| |
| if (range.startOffset == range.endOffset) { |
| return; |
| } |
| |
| |
| var instance_id = document.getElementById("instance_id").value; |
| |
| if (window.getSelection) { |
| var sel = window.getSelection(); |
| |
| |
| |
| |
| |
| if (!sel.anchorNode.parentElement) { |
| return; |
| } |
| |
| |
| |
| |
| |
| if (sel.rangeCount && sel.toString().trim().length > 0) { |
| |
| var selText = window.getSelection().toString().trim(); |
| console.log("selText1", selText); |
| |
| |
| var range = sel.getRangeAt(0); |
| var start = range.startOffset; |
| var end = range.endOffset; |
| |
| var text = range.startContainer.textContent.substring(start, end); |
| var s = range.startContainer.textContent.toString(); |
| |
| var whitespaceOffset = s.length - s.trimStart().length; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var sel = window.getSelection(); |
| var range = sel.getRangeAt(0); |
| var div = document.createElement("div"); |
| div.appendChild(range.cloneContents()); |
| var selText = div.innerHTML; |
| |
| |
| tsc = selectionColor.replace(")", ", 0.25)"); |
| |
| var span = document.createElement("span"); |
| span.className = "span_container"; |
| span.setAttribute("selection_label", labelName); |
| span.setAttribute("style", "background-color:rgb" + tsc + ";"); |
| |
| var label = document.createElement("div"); |
| label.className = "span_label"; |
| label.textContent = title; |
| label.setAttribute( |
| "style", |
| "background-color:white;" + |
| "border:2px solid rgb" + |
| selectionColor + |
| ";" |
| ); |
| |
| var delLabel = document.createElement("div"); |
| delLabel.className = "span_close"; |
| delLabel.textContent = "×"; |
| delLabel.setAttribute("style", "background-color:white;"); |
| |
| delLabel.onclick = function () { |
| deleteSpanAnnotation( |
| span, |
| schema, |
| labelName, |
| title, |
| range.startOffset, |
| range.endOffset |
| ); |
| }; |
| |
| |
| startEnd = getSelectionIndices(); |
| console.log("startEnd", startEnd); |
| state = [ |
| { |
| name: labelName, |
| start: startEnd["start"], |
| end: startEnd["end"], |
| title: title, |
| value: sel.toString(), |
| }, |
| ]; |
| |
| |
| |
| |
| var post_req = { |
| type: "span", |
| schema: schema, |
| state: state, |
| instance_id: instance_id, |
| }; |
| |
| |
| fetch("/updateinstance", { |
| method: "POST", |
| body: JSON.stringify(post_req), |
| credentials: "same-origin", |
| headers: { |
| "Content-type": "application/json; charset=UTF-8", |
| }, |
| }); |
| |
| var range = sel.getRangeAt(0).cloneRange(); |
| range.surroundContents(span); |
| sel.removeAllRanges(); |
| sel.addRange(range); |
| span.appendChild(label); |
| span.appendChild(delLabel); |
| |
| |
| sel.empty(); |
| } |
| } |
| } |
| |
| function changeSpanLabel( |
| checkbox, |
| schema, |
| spanLabel, |
| spanTitle, |
| spanColor |
| ) { |
| |
| document.onmouseup = function (e) { |
| var senderElement = e.target; |
| |
| if (senderElement.getAttribute("class") == "span_close") { |
| e.stopPropagation(); |
| return true; |
| } |
| if (checkbox.checked) { |
| surroundSelection(schema, spanLabel, spanTitle, spanColor); |
| } |
| }; |
| } |
| |
| |
| |
| </script> |
| <script> |
| function barValue(range, sibling) { |
| |
| sibling.value = range.value; |
| |
| |
| |
| |
| |
| } |
| </script> |
|
|
| <script> |
| function onlyOne(checkbox) { |
| |
| |
| var x = document.getElementsByClassName(checkbox.className); |
| var i; |
| for (i = 0; i < x.length; i++) { |
| if (x[i].value != checkbox.value) x[i].checked = false; |
| } |
| } |
| </script> |
|
|
| <script> |
| function whetherNone(checkbox) { |
| |
| |
| var x = document.getElementsByClassName(checkbox.className); |
| var i; |
| for (i = 0; i < x.length; i++) { |
| if (checkbox.value == "None" && x[i].value != "None") |
| x[i].checked = false; |
| if (checkbox.value != "None" && x[i].value == "None") |
| x[i].checked = false; |
| } |
| } |
| </script> |
|
|
| <script> |
| function click_to_next() { |
| |
| |
| |
| var e = $.Event("keyup"); |
| e.key = "ArrowRight"; |
| |
| get_new_instance(e); |
| } |
| |
| function click_to_prev() { |
| |
| |
| |
| var e = $.Event("keyup"); |
| e.key = "ArrowLeft"; |
| |
| get_new_instance(e); |
| } |
| </script> |
|
|
| {{annotation}} |
|
|
| <script> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| </script> |
|
|
| <script> |
| |
| var countDownDate = new Date().getTime(); |
| |
| |
| var x = setInterval(function () { |
| |
| var now = new Date().getTime(); |
| |
| |
| var distance = now - countDownDate; |
| |
| |
| var days = Math.floor(distance / (1000 * 60 * 60 * 24)); |
| var hours = Math.floor( |
| (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) |
| ); |
| var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); |
| var seconds = Math.floor((distance % (1000 * 60)) / 1000); |
| var total_seconds = Math.floor(distance / 1000); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var alert_time_each_instance = document.getElementById( |
| "alert_time_each_instance" |
| ).value; |
| if (total_seconds % alert_time_each_instance == 0) { |
| |
| |
| alert( |
| "You have spent " + total_seconds + " seconds on this instance" |
| ); |
| } |
| }, 1000); |
| </script> |
|
|
| <script> |
| |
| function post(params) { |
| |
| var post_req = { |
| instance_id: instance_id, |
| }; |
| for (var key in params) { |
| if (params.hasOwnProperty(key)) { |
| post_req[key] = params[key]; |
| } |
| } |
| |
| |
| $("form input, form select").each(function () { |
| var input = $(this); |
| var type = input.attr("type"); |
| var name = input.attr("name"); |
| |
| if (!name) return; |
| |
| if (type === "checkbox" || type === "radio") { |
| if (input.is(":checked")) { |
| post_req[name] = true; |
| } |
| } else if (type === "text" || input.is("select")) { |
| post_req[name] = input.val(); |
| } else { |
| console.log("unknown input type:", type); |
| } |
| }); |
| |
| |
| |
| |
| |
| fetch("/annotate", { |
| method: "POST", |
| body: JSON.stringify(post_req), |
| credentials: "same-origin", |
| headers: { |
| "Content-type": "application/json; charset=UTF-8", |
| }, |
| }) |
| .then((response) => { |
| if (!response.ok) { |
| throw new Error("Network response was not ok"); |
| } |
| return response.text(); |
| }) |
| .then((html) => { |
| |
| document.body.innerHTML = html; |
| |
| watch_text_boxes(); |
| }) |
| .catch((error) => { |
| console.error("Error:", error); |
| |
| }); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| |
| |
| |
| function validateForm() { |
| var rows = document.querySelectorAll("tr[schema='multirate']"); |
| for (var i = 0; i < rows.length; i++) { |
| var inputs = rows[i].querySelectorAll( |
| "input[type='radio'][validation='required']" |
| ); |
| if (inputs.length > 0) { |
| var checked = Array.from(inputs).some((input) => input.checked); |
| } else { |
| var checked = true; |
| } |
| |
| if (!checked) { |
| alert("Please complete all the require fields"); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| |
| |
| |
| |
| |
| function validate_answers() { |
| |
| var inputs = document.querySelectorAll( |
| "input[validation=required_label]" |
| ); |
| for (var i = 0; i < inputs.length; ++i) { |
| if ( |
| inputs[i].getAttribute("validation") == "required_label" && |
| inputs[i].checked == false |
| ) { |
| |
| var legend = inputs[i].closest("fieldset").querySelector("legend"); |
| var question = legend.textContent; |
| |
| |
| var neededAnswer = inputs[i].getAttribute("label_name"); |
| |
| |
| |
| alert( |
| 'The question "' + |
| question + |
| '" requires the label "' + |
| neededAnswer + |
| '" to be selected to proceed' |
| ); |
| return false; |
| } |
| } |
| |
| |
| var fields = document.getElementsByTagName("fieldset"); |
| for (var i = 0; i < fields.length; ++i) { |
| var inputs = fields[i].querySelectorAll( |
| "input[validation=required], select[validation=required], textarea[validation=required]" |
| ); |
| |
| |
| if (inputs.length == 0) { |
| continue; |
| } |
| |
| |
| |
| |
| |
| |
| checked_flag = false; |
| for (var j = 0; j < inputs.length; ++j) { |
| |
| |
| |
| |
| |
| |
| |
| if (inputs[j].getAttribute("for_span") == "True") { |
| |
| if ($(".span_container").length > 0) { |
| checked_flag = true; |
| break; |
| } else if ( |
| inputs[j].name.slice(-8) == "bad_text" && |
| inputs[j].checked == true |
| ) { |
| checked_flag = true; |
| break; |
| } |
| } |
| |
| |
| if ( |
| inputs[j].getAttribute("for_span") != "True" && |
| inputs[j].checked == true |
| ) { |
| checked_flag = true; |
| break; |
| } |
| |
| |
| |
| if ( |
| inputs[j].type == "text" || |
| inputs[j].tagName == "TEXTAREA" || |
| inputs[j].type == "number" || |
| inputs[j].type == "select-one" |
| ) { |
| if (inputs[j].value.length == 0) { |
| alert(inputs[j].name + " must be completed to proceed"); |
| return false; |
| } else { |
| checked_flag = true; |
| } |
| } |
| } |
| |
| |
| |
| |
| var legend = inputs[i].closest("fieldset").querySelector("legend"); |
| var question = legend.textContent; |
| |
| |
| if (checked_flag == false) { |
| alert("You must answer the following item to proceed: " + question); |
| return false; |
| } |
| |
| } |
| return true; |
| } |
| |
| |
| |
| |
| |
| |
| function get_new_instance(event) { |
| var x = event.key; |
| var action = ""; |
| var ism = ""; |
| |
| |
| |
| |
| if (x == "ArrowLeft") { |
| |
| action = "prev_instance"; |
| } else if (x == "ArrowRight") { |
| |
| |
| if (validateForm() == true && validate_answers() == true) { |
| action = "next_instance"; |
| } else { |
| return; |
| } |
| } else { |
| |
| return; |
| } |
| |
| var instance_id = document.getElementById("instance_id").value; |
| var time_string = document.getElementById("timecounter").innerHTML; |
| |
| var post_req = { |
| label: ism, |
| action: action, |
| instance_id: instance_id, |
| behavior_time_string: time_string, |
| }; |
| |
| console.log("post_req: ", post_req); |
| |
| |
| post(post_req); |
| } |
| </script> |
|
|
| <script> |
| $(document).ready(function () { |
| $('[data-toggle="tooltip"]').tooltip(); |
| }); |
| </script> |
|
|
| {{var_elems | safe}} |
|
|
| |
| <nav |
| class="navbar sticky-top shadow-sm" |
| style=" |
| background-color: var(--primary-color); |
| padding: 0.75rem 1rem; |
| margin-bottom: 1.5rem; |
| " |
| > |
| <div class="container-fluid d-flex align-items-center"> |
| |
| <div class="navbar-brand"> |
| <span |
| class="fw-bold" |
| style="color: var(--light-color); font-size: 1.25rem" |
| >Simple Likert Scale Example</span |
| > |
| </div> |
|
|
| |
| <div |
| class="d-flex align-items-center justify-content-center flex-grow-1 gap-4" |
| > |
| |
| <div></div> |
|
|
| |
| <div |
| class="d-flex align-items-center" |
| style="color: var(--light-color); margin-right: 40px" |
| > |
| <span |
| >Progress: |
| <span class="fw-medium">{{finished}}/{{total_count}}</span></span |
| > |
| </div> |
|
|
| |
| <div style="margin-left: 40px"> |
| <form |
| action="/go_to" |
| method="post" |
| class="d-flex align-items-center" |
| > |
| <input |
| type="hidden" |
| name="firstname" |
| id="a" |
| value="{{firstname}}" |
| /> |
| <input |
| type="hidden" |
| name="lastname" |
| id="b" |
| value="{{lastname}}" |
| /> |
| <input type="hidden" name="email" id="c" value="{{username}}" /> |
| <input type="hidden" name="src" id="src" value="go_to" /> |
| <label |
| for="go_to" |
| class="me-2" |
| style="color: var(--light-color); margin-bottom: 0" |
| >Go to:</label |
| > |
| <input |
| type="number" |
| name="go_to" |
| id="go_to" |
| class="form-control form-control-sm me-2" |
| style=" |
| width: 70px; |
| height: 31px; |
| border: none; |
| border-radius: var(--radius); |
| " |
| value="" |
| onfocusin="user_input()" |
| onfocusout="user_input_leave()" |
| max="{{total_count}}" |
| min="0" |
| required |
| /> |
| <button |
| type="submit" |
| class="shadcn-button" |
| style=" |
| height: 31px; |
| line-height: 1; |
| padding: 0 0.75rem; |
| background-color: var(--light-color); |
| color: var(--primary-color); |
| border: none; |
| " |
| > |
| Go |
| </button> |
| </form> |
| </div> |
| </div> |
|
|
| |
| <div |
| class="d-flex align-items-center" |
| style=" |
| background-color: rgba(255, 255, 255, 0.15); |
| padding: 0.5rem 1rem; |
| border-radius: var(--radius); |
| " |
| > |
| <div class="me-3" style="color: var(--light-color)"> |
| <span |
| >Logged in as <span class="fw-medium">{{username}}</span></span |
| > |
| </div> |
| <div |
| class="border-start" |
| style=" |
| padding-left: 20px; |
| height: 24px; |
| display: flex; |
| align-items: center; |
| " |
| > |
| <a |
| href="/logout" |
| class="shadcn-button" |
| style=" |
| background-color: var(--light-color); |
| color: var(--primary-color); |
| height: auto; |
| padding: 0.25rem 0.75rem !important; |
| font-size: 0.875rem; |
| min-width: 60px; |
| text-align: center; |
| border: none; |
| text-decoration: none; |
| " |
| >Logout</a |
| > |
| </div> |
| </div> |
| </div> |
| </nav> |
|
|
| <div class="container-fluid"> |
| <div id="task_layout" class="shadcn-card mb-4"> |
| <div class="shadcn-card-content"> |
| |
|
|
| <div class="row"> |
| <div class="col-md-12"> |
|
|
| <div class="row"> |
| <div class="col-md-12"> |
| <div name="context_text" class="instance"> |
| <div id="instance-text" name="instance_text"> |
| {{instance | safe}} |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div style="height: 15px;" /> |
| |
| </div> |
| <div class="col-md-12"> |
| <div class="annotation_schema"> |
| |
| <style> |
| |
| .shadcn-likert-container { |
| border: 1px solid #E5E5EA; |
| border-radius: 18px 0 18px 18px; |
| padding: 1rem; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| width: fit-content; |
| max-width: 100%; |
| margin: 1.5rem auto; |
| font-family: ui-sans-serif, system-ui, sans-serif; |
| position: relative; |
| } |
| |
| .shadcn-likert-title { |
| font-size: 1rem; |
| font-weight: 500; |
| color: black; |
| text-align: left; |
| width: 100%; |
| } |
| |
| .shadcn-likert-scale { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| width: 100%; |
| } |
| |
| .shadcn-likert-endpoint { |
| display: flex; |
| align-items: center; |
| height: 2.5rem; |
| flex: 0 0 auto; |
| font-size: 0.875rem; |
| color: var(--muted-foreground); |
| padding: 0 0.5rem; |
| max-width: 30%; |
| text-align: center; |
| word-wrap: break-word; |
| overflow-wrap: break-word; |
| hyphens: auto; |
| } |
| |
| .shadcn-likert-options { |
| display: flex; |
| flex: 1; |
| justify-content: space-between; |
| position: relative; |
| padding: 0 0.5rem; |
| gap: 0.5rem; |
| } |
| |
| .shadcn-likert-track { |
| position: absolute; |
| height: 2px; |
| background-color: var(--border); |
| left: 0.5rem; |
| right: 0.5rem; |
| top: 0.625rem; |
| transform: none; |
| z-index: 0; |
| } |
| |
| .shadcn-likert-option { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| position: relative; |
| z-index: 1; |
| } |
| |
| .shadcn-likert-input { |
| opacity: 0; |
| position: absolute; |
| width: 0; |
| height: 0; |
| } |
| |
| .shadcn-likert-button { |
| width: 1.25rem; |
| height: 1.25rem; |
| border-radius: 50%; |
| background-color: var(--secondary); |
| border: 2px solid var(--border); |
| margin-bottom: 0.5rem; |
| cursor: pointer; |
| transition: var(--transition); |
| } |
| |
| .shadcn-likert-input:checked + .shadcn-likert-button { |
| background-color: var(--primary); |
| border-color: var(--primary); |
| transform: scale(1.1); |
| box-shadow: 0 0 0 3px rgba(110, 86, 207, 0.2); |
| } |
| |
| .shadcn-likert-input:focus + .shadcn-likert-button { |
| box-shadow: 0 0 0 3px rgba(110, 86, 207, 0.2); |
| } |
| |
| .shadcn-likert-input:hover + .shadcn-likert-button { |
| border-color: var(--primary); |
| } |
| |
| .shadcn-likert-label { |
| font-size: 0.75rem; |
| color: var(--muted-foreground); |
| margin-top: 0.25rem; |
| text-align: center; |
| } |
| |
| .shadcn-likert-input:checked ~ .shadcn-likert-label { |
| color: var(--primary); |
| font-weight: 500; |
| } |
| |
| .shadcn-likert-bad-text { |
| display: flex; |
| align-items: center; |
| margin-top: 0.75rem; |
| padding: 0.5rem 0; |
| } |
| |
| .shadcn-likert-bad-text-label { |
| margin-left: 0.5rem; |
| font-size: 0.875rem; |
| color: var(--text-color); |
| word-wrap: break-word; |
| overflow-wrap: break-word; |
| flex: 1; |
| } |
| |
| fieldset[schema] { |
| width: fit-content; |
| max-width: 100%; |
| overflow: visible; |
| } |
| |
| .ai-help { |
| width: 9.375rem; |
| height: 2.063rem; |
| border: 1px solid #E5E5EA; |
| border-radius: 18px; |
| position: absolute; |
| top: -0.75rem; |
| right: -0.05rem; |
| background-color: white; |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| } |
| |
| .ai-help-word { |
| font-size: 1rem; |
| margin: 0; |
| } |
| |
| .hint { |
| cursor: pointer; |
| } |
| |
| .hint:hover { |
| color: #6E56CF; |
| } |
| |
| .tooltip { |
| position: absolute; |
| top: 120%; |
| left: 50%; |
| transform: translateX(-50%); |
| background-color: white; |
| padding: 1rem; |
| border-radius: .5rem; |
| white-space: nowrap; |
| box-shadow: 0 2px 8px rgba(0,0,0,0.2); |
| z-index: 1000; |
| opacity: 0; |
| visibility: hidden; |
| transition: opacity 0.3s, visibility 0.3s; |
| min-width: 20rem; |
| max-width: 24rem; |
| overflow-wrap: break-word; |
| word-wrap: break-word; |
| white-space: normal; |
| max-height: 15rem; |
| overflow: auto; |
| } |
| |
| .tooltip.active { |
| opacity: 1; |
| visibility: visible; |
| } |
| |
| .reasoning { |
| font-weight: bold; |
| } |
| |
| .tooltip-text{ |
| margin: 0; |
| } |
| |
| </style> |
|
|
| <form id="relevance" class="annotation-form likert shadcn-likert-container" action="javascript:void(0)" data-annotation-id="0"> |
| <div class="ai-help"> |
| <h3 class="ai-help-word"><span class="hint">Hint</span> | <span>Keyword</span></h3> |
| <div class="tooltip"> |
| <p class="tooltip-text"> |
| <span class="reasoning">Reasoning:</span> {ai} |
| </p> |
| </div> |
| </div> |
|
|
|
|
| <fieldset schema="relevance" style="border: none; padding: 0; margin: 0; width: auto; min-width: fit-content;"> |
| <legend class="shadcn-likert-title">Relevance</legend> |
| <div class="shadcn-likert-scale" style="max-width: min(100%, calc(300px + 5 * 40px + 250px));"> |
| <div class="shadcn-likert-endpoint">Not Relevant</div> |
| <div class="shadcn-likert-options"> |
| <div class="shadcn-likert-track"></div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="relevance shadcn-likert-input" |
| type="radio" |
| id="relevance:::1" |
| name="relevance:::1" |
| value="1" |
| schema="relevance" |
| label_name="1" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="relevance:::1"></label> |
| <span class="shadcn-likert-label">1</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="relevance shadcn-likert-input" |
| type="radio" |
| id="relevance:::2" |
| name="relevance:::2" |
| value="2" |
| schema="relevance" |
| label_name="2" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="relevance:::2"></label> |
| <span class="shadcn-likert-label">2</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="relevance shadcn-likert-input" |
| type="radio" |
| id="relevance:::3" |
| name="relevance:::3" |
| value="3" |
| schema="relevance" |
| label_name="3" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="relevance:::3"></label> |
| <span class="shadcn-likert-label">3</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="relevance shadcn-likert-input" |
| type="radio" |
| id="relevance:::4" |
| name="relevance:::4" |
| value="4" |
| schema="relevance" |
| label_name="4" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="relevance:::4"></label> |
| <span class="shadcn-likert-label">4</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="relevance shadcn-likert-input" |
| type="radio" |
| id="relevance:::5" |
| name="relevance:::5" |
| value="5" |
| schema="relevance" |
| label_name="5" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="relevance:::5"></label> |
| <span class="shadcn-likert-label">5</span> |
| </div> |
| |
| </div> |
| <div class="shadcn-likert-endpoint">Super Relevant</div> |
| </div> |
| |
| </fieldset></form> |
| |
|
|
| <style> |
| |
| .shadcn-likert-container { |
| border: 1px solid #E5E5EA; |
| border-radius: 18px 0 18px 18px; |
| padding: 1rem; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| width: fit-content; |
| max-width: 100%; |
| margin: 1.5rem auto; |
| font-family: ui-sans-serif, system-ui, sans-serif; |
| position: relative; |
| } |
| |
| .shadcn-likert-title { |
| font-size: 1rem; |
| font-weight: 500; |
| color: black; |
| text-align: left; |
| width: 100%; |
| } |
| |
| .shadcn-likert-scale { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| width: 100%; |
| } |
| |
| .shadcn-likert-endpoint { |
| display: flex; |
| align-items: center; |
| height: 2.5rem; |
| flex: 0 0 auto; |
| font-size: 0.875rem; |
| color: var(--muted-foreground); |
| padding: 0 0.5rem; |
| max-width: 30%; |
| text-align: center; |
| word-wrap: break-word; |
| overflow-wrap: break-word; |
| hyphens: auto; |
| } |
| |
| .shadcn-likert-options { |
| display: flex; |
| flex: 1; |
| justify-content: space-between; |
| position: relative; |
| padding: 0 0.5rem; |
| gap: 0.5rem; |
| } |
| |
| .shadcn-likert-track { |
| position: absolute; |
| height: 2px; |
| background-color: var(--border); |
| left: 0.5rem; |
| right: 0.5rem; |
| top: 0.625rem; |
| transform: none; |
| z-index: 0; |
| } |
| |
| .shadcn-likert-option { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| position: relative; |
| z-index: 1; |
| } |
| |
| .shadcn-likert-input { |
| opacity: 0; |
| position: absolute; |
| width: 0; |
| height: 0; |
| } |
| |
| .shadcn-likert-button { |
| width: 1.25rem; |
| height: 1.25rem; |
| border-radius: 50%; |
| background-color: var(--secondary); |
| border: 2px solid var(--border); |
| margin-bottom: 0.5rem; |
| cursor: pointer; |
| transition: var(--transition); |
| } |
| |
| .shadcn-likert-input:checked + .shadcn-likert-button { |
| background-color: var(--primary); |
| border-color: var(--primary); |
| transform: scale(1.1); |
| box-shadow: 0 0 0 3px rgba(110, 86, 207, 0.2); |
| } |
| |
| .shadcn-likert-input:focus + .shadcn-likert-button { |
| box-shadow: 0 0 0 3px rgba(110, 86, 207, 0.2); |
| } |
| |
| .shadcn-likert-input:hover + .shadcn-likert-button { |
| border-color: var(--primary); |
| } |
| |
| .shadcn-likert-label { |
| font-size: 0.75rem; |
| color: var(--muted-foreground); |
| margin-top: 0.25rem; |
| text-align: center; |
| } |
| |
| .shadcn-likert-input:checked ~ .shadcn-likert-label { |
| color: var(--primary); |
| font-weight: 500; |
| } |
| |
| .shadcn-likert-bad-text { |
| display: flex; |
| align-items: center; |
| margin-top: 0.75rem; |
| padding: 0.5rem 0; |
| } |
| |
| .shadcn-likert-bad-text-label { |
| margin-left: 0.5rem; |
| font-size: 0.875rem; |
| color: var(--text-color); |
| word-wrap: break-word; |
| overflow-wrap: break-word; |
| flex: 1; |
| } |
| |
| fieldset[schema] { |
| width: fit-content; |
| max-width: 100%; |
| overflow: visible; |
| } |
| |
| .ai-help { |
| width: 9.375rem; |
| height: 2.063rem; |
| border: 1px solid #E5E5EA; |
| border-radius: 18px; |
| position: absolute; |
| top: -0.75rem; |
| right: -0.05rem; |
| background-color: white; |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| } |
| |
| .ai-help-word { |
| font-size: 1rem; |
| margin: 0; |
| } |
| |
| .hint { |
| cursor: pointer; |
| } |
| |
| .hint:hover { |
| color: #6E56CF; |
| } |
| |
| .tooltip { |
| position: absolute; |
| top: 120%; |
| left: 50%; |
| transform: translateX(-50%); |
| background-color: white; |
| padding: 1rem; |
| border-radius: .5rem; |
| white-space: nowrap; |
| box-shadow: 0 2px 8px rgba(0,0,0,0.2); |
| z-index: 1000; |
| opacity: 0; |
| visibility: hidden; |
| transition: opacity 0.3s, visibility 0.3s; |
| min-width: 20rem; |
| max-width: 24rem; |
| overflow-wrap: break-word; |
| word-wrap: break-word; |
| white-space: normal; |
| max-height: 15rem; |
| overflow: auto; |
| } |
| |
| .tooltip.active { |
| opacity: 1; |
| visibility: visible; |
| } |
| |
| .reasoning { |
| font-weight: bold; |
| } |
| |
| .tooltip-text{ |
| margin: 0; |
| } |
| |
| </style> |
|
|
| <form id="fluency" class="annotation-form likert shadcn-likert-container" action="javascript:void(0)" data-annotation-id="1"> |
| <div class="ai-help"> |
| <h3 class="ai-help-word"><span class="hint">Hint</span> | <span>Keyword</span></h3> |
| <div class="tooltip"> |
| <p class="tooltip-text"> |
| <span class="reasoning">Reasoning:</span> {ai} |
| </p> |
| </div> |
| </div> |
|
|
|
|
| <fieldset schema="fluency" style="border: none; padding: 0; margin: 0; width: auto; min-width: fit-content;"> |
| <legend class="shadcn-likert-title">Fluency</legend> |
| <div class="shadcn-likert-scale" style="max-width: min(100%, calc(300px + 10 * 40px + 250px));"> |
| <div class="shadcn-likert-endpoint">Not fluent</div> |
| <div class="shadcn-likert-options"> |
| <div class="shadcn-likert-track"></div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::1" |
| name="fluency:::1" |
| value="1" |
| schema="fluency" |
| label_name="1" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::1"></label> |
| <span class="shadcn-likert-label">1</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::2" |
| name="fluency:::2" |
| value="2" |
| schema="fluency" |
| label_name="2" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::2"></label> |
| <span class="shadcn-likert-label">2</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::3" |
| name="fluency:::3" |
| value="3" |
| schema="fluency" |
| label_name="3" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::3"></label> |
| <span class="shadcn-likert-label">3</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::4" |
| name="fluency:::4" |
| value="4" |
| schema="fluency" |
| label_name="4" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::4"></label> |
| <span class="shadcn-likert-label">4</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::5" |
| name="fluency:::5" |
| value="5" |
| schema="fluency" |
| label_name="5" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::5"></label> |
| <span class="shadcn-likert-label">5</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::6" |
| name="fluency:::6" |
| value="6" |
| schema="fluency" |
| label_name="6" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::6"></label> |
| <span class="shadcn-likert-label">6</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::7" |
| name="fluency:::7" |
| value="7" |
| schema="fluency" |
| label_name="7" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::7"></label> |
| <span class="shadcn-likert-label">7</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::8" |
| name="fluency:::8" |
| value="8" |
| schema="fluency" |
| label_name="8" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::8"></label> |
| <span class="shadcn-likert-label">8</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::9" |
| name="fluency:::9" |
| value="9" |
| schema="fluency" |
| label_name="9" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::9"></label> |
| <span class="shadcn-likert-label">9</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="fluency shadcn-likert-input" |
| type="radio" |
| id="fluency:::10" |
| name="fluency:::10" |
| value="0" |
| schema="fluency" |
| label_name="0" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="fluency:::10"></label> |
| <span class="shadcn-likert-label">10</span> |
| </div> |
| |
| </div> |
| <div class="shadcn-likert-endpoint">Super fluent</div> |
| </div> |
| |
| </fieldset></form> |
| |
|
|
| <style> |
| |
| .shadcn-likert-container { |
| border: 1px solid #E5E5EA; |
| border-radius: 18px 0 18px 18px; |
| padding: 1rem; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| width: fit-content; |
| max-width: 100%; |
| margin: 1.5rem auto; |
| font-family: ui-sans-serif, system-ui, sans-serif; |
| position: relative; |
| } |
| |
| .shadcn-likert-title { |
| font-size: 1rem; |
| font-weight: 500; |
| color: black; |
| text-align: left; |
| width: 100%; |
| } |
| |
| .shadcn-likert-scale { |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| width: 100%; |
| } |
| |
| .shadcn-likert-endpoint { |
| display: flex; |
| align-items: center; |
| height: 2.5rem; |
| flex: 0 0 auto; |
| font-size: 0.875rem; |
| color: var(--muted-foreground); |
| padding: 0 0.5rem; |
| max-width: 30%; |
| text-align: center; |
| word-wrap: break-word; |
| overflow-wrap: break-word; |
| hyphens: auto; |
| } |
| |
| .shadcn-likert-options { |
| display: flex; |
| flex: 1; |
| justify-content: space-between; |
| position: relative; |
| padding: 0 0.5rem; |
| gap: 0.5rem; |
| } |
| |
| .shadcn-likert-track { |
| position: absolute; |
| height: 2px; |
| background-color: var(--border); |
| left: 0.5rem; |
| right: 0.5rem; |
| top: 0.625rem; |
| transform: none; |
| z-index: 0; |
| } |
| |
| .shadcn-likert-option { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| position: relative; |
| z-index: 1; |
| } |
| |
| .shadcn-likert-input { |
| opacity: 0; |
| position: absolute; |
| width: 0; |
| height: 0; |
| } |
| |
| .shadcn-likert-button { |
| width: 1.25rem; |
| height: 1.25rem; |
| border-radius: 50%; |
| background-color: var(--secondary); |
| border: 2px solid var(--border); |
| margin-bottom: 0.5rem; |
| cursor: pointer; |
| transition: var(--transition); |
| } |
| |
| .shadcn-likert-input:checked + .shadcn-likert-button { |
| background-color: var(--primary); |
| border-color: var(--primary); |
| transform: scale(1.1); |
| box-shadow: 0 0 0 3px rgba(110, 86, 207, 0.2); |
| } |
| |
| .shadcn-likert-input:focus + .shadcn-likert-button { |
| box-shadow: 0 0 0 3px rgba(110, 86, 207, 0.2); |
| } |
| |
| .shadcn-likert-input:hover + .shadcn-likert-button { |
| border-color: var(--primary); |
| } |
| |
| .shadcn-likert-label { |
| font-size: 0.75rem; |
| color: var(--muted-foreground); |
| margin-top: 0.25rem; |
| text-align: center; |
| } |
| |
| .shadcn-likert-input:checked ~ .shadcn-likert-label { |
| color: var(--primary); |
| font-weight: 500; |
| } |
| |
| .shadcn-likert-bad-text { |
| display: flex; |
| align-items: center; |
| margin-top: 0.75rem; |
| padding: 0.5rem 0; |
| } |
| |
| .shadcn-likert-bad-text-label { |
| margin-left: 0.5rem; |
| font-size: 0.875rem; |
| color: var(--text-color); |
| word-wrap: break-word; |
| overflow-wrap: break-word; |
| flex: 1; |
| } |
| |
| fieldset[schema] { |
| width: fit-content; |
| max-width: 100%; |
| overflow: visible; |
| } |
| |
| .ai-help { |
| width: 9.375rem; |
| height: 2.063rem; |
| border: 1px solid #E5E5EA; |
| border-radius: 18px; |
| position: absolute; |
| top: -0.75rem; |
| right: -0.05rem; |
| background-color: white; |
| display: flex; |
| justify-content: center; |
| align-items: center; |
| } |
| |
| .ai-help-word { |
| font-size: 1rem; |
| margin: 0; |
| } |
| |
| .hint { |
| cursor: pointer; |
| } |
| |
| .hint:hover { |
| color: #6E56CF; |
| } |
| |
| .tooltip { |
| position: absolute; |
| top: 120%; |
| left: 50%; |
| transform: translateX(-50%); |
| background-color: white; |
| padding: 1rem; |
| border-radius: .5rem; |
| white-space: nowrap; |
| box-shadow: 0 2px 8px rgba(0,0,0,0.2); |
| z-index: 1000; |
| opacity: 0; |
| visibility: hidden; |
| transition: opacity 0.3s, visibility 0.3s; |
| min-width: 20rem; |
| max-width: 24rem; |
| overflow-wrap: break-word; |
| word-wrap: break-word; |
| white-space: normal; |
| max-height: 15rem; |
| overflow: auto; |
| } |
| |
| .tooltip.active { |
| opacity: 1; |
| visibility: visible; |
| } |
| |
| .reasoning { |
| font-weight: bold; |
| } |
| |
| .tooltip-text{ |
| margin: 0; |
| } |
| |
| </style> |
|
|
| <form id="coherence" class="annotation-form likert shadcn-likert-container" action="javascript:void(0)" data-annotation-id="2"> |
| <div class="ai-help"> |
| <h3 class="ai-help-word"><span class="hint">Hint</span> | <span>Keyword</span></h3> |
| <div class="tooltip"> |
| <p class="tooltip-text"> |
| <span class="reasoning">Reasoning:</span> {ai} |
| </p> |
| </div> |
| </div> |
|
|
|
|
| <fieldset schema="coherence" style="border: none; padding: 0; margin: 0; width: auto; min-width: fit-content;"> |
| <legend class="shadcn-likert-title">Coherence</legend> |
| <div class="shadcn-likert-scale" style="max-width: min(100%, calc(300px + 5 * 40px + 250px));"> |
| <div class="shadcn-likert-endpoint">Not Coherent</div> |
| <div class="shadcn-likert-options"> |
| <div class="shadcn-likert-track"></div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="coherence shadcn-likert-input" |
| type="radio" |
| id="coherence:::1" |
| name="coherence:::1" |
| value="1" |
| schema="coherence" |
| label_name="1" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="coherence:::1"></label> |
| <span class="shadcn-likert-label">1</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="coherence shadcn-likert-input" |
| type="radio" |
| id="coherence:::2" |
| name="coherence:::2" |
| value="2" |
| schema="coherence" |
| label_name="2" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="coherence:::2"></label> |
| <span class="shadcn-likert-label">2</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="coherence shadcn-likert-input" |
| type="radio" |
| id="coherence:::3" |
| name="coherence:::3" |
| value="3" |
| schema="coherence" |
| label_name="3" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="coherence:::3"></label> |
| <span class="shadcn-likert-label">3</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="coherence shadcn-likert-input" |
| type="radio" |
| id="coherence:::4" |
| name="coherence:::4" |
| value="4" |
| schema="coherence" |
| label_name="4" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="coherence:::4"></label> |
| <span class="shadcn-likert-label">4</span> |
| </div> |
| |
| <div class="shadcn-likert-option"> |
| <input class="coherence shadcn-likert-input" |
| type="radio" |
| id="coherence:::5" |
| name="coherence:::5" |
| value="5" |
| schema="coherence" |
| label_name="5" |
| selection_constraint="single" |
| validation="required" |
| onclick="onlyOne(this);registerAnnotation(this);"> |
| <label class="shadcn-likert-button" for="coherence:::5"></label> |
| <span class="shadcn-likert-label">5</span> |
| </div> |
| |
| </div> |
| <div class="shadcn-likert-endpoint">Super Coherent</div> |
| </div> |
| |
| </fieldset></form> |
| |
|
|
| </div> |
| </div> |
| </div> |
|
|
|
|
| |
| </div> |
| </div> |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| <div class="my-4"> |
| |
| <div class="d-flex justify-content-between align-items-center"> |
| |
| <div> |
| <a |
| role="button" |
| href="#" |
| class="shadcn-button shadcn-button-outline openbtn" |
| target_id="Statpanel" |
| width="475px" |
| onclick="openNav(this.getAttribute('target_id'),this.getAttribute('width'))" |
| > |
| <svg |
| xmlns="http://www.w3.org/2000/svg" |
| width="16" |
| height="16" |
| fill="currentColor" |
| class="bi bi-bar-chart-line me-1" |
| viewBox="0 0 16 16" |
| > |
| <path |
| d="M11 2a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v12h.5a.5.5 0 0 1 0 1H.5a.5.5 0 0 1 0-1H1v-3a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3h1V7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7h1V2zm1 12h2V2h-2v12zm-3 0V7H7v7h2zm-5 0v-3H2v3h2z" |
| /> |
| </svg> |
| Statistics |
| </a> |
| </div> |
|
|
| |
| <div> |
| <a |
| class="shadcn-button shadcn-button-outline me-2" |
| href="#" |
| role="button" |
| onclick="click_to_prev()" |
| style="vertical-align: middle" |
| > |
| <svg |
| xmlns="http://www.w3.org/2000/svg" |
| width="16" |
| height="16" |
| fill="currentColor" |
| class="bi bi-arrow-left" |
| viewBox="0 0 16 16" |
| style=" |
| display: inline-block; |
| vertical-align: middle; |
| margin-right: 0.25rem; |
| " |
| > |
| <path |
| fill-rule="evenodd" |
| d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z" |
| /> |
| </svg> |
| <span style="display: inline-block; vertical-align: middle" |
| >Previous</span |
| > |
| </a> |
| <a |
| class="shadcn-button shadcn-button-primary" |
| href="#" |
| role="button" |
| onclick="click_to_next()" |
| style="vertical-align: middle" |
| > |
| <span style="display: inline-block; vertical-align: middle" |
| >Next</span |
| > |
| <svg |
| xmlns="http://www.w3.org/2000/svg" |
| width="16" |
| height="16" |
| fill="currentColor" |
| class="bi bi-arrow-right" |
| viewBox="0 0 16 16" |
| style=" |
| display: inline-block; |
| vertical-align: middle; |
| margin-left: 0.25rem; |
| " |
| > |
| <path |
| fill-rule="evenodd" |
| d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z" |
| /> |
| </svg> |
| </a> |
| </div> |
|
|
| |
| <div> |
| <a |
| role="button" |
| href="#" |
| class="shadcn-button shadcn-button-outline openbtn" |
| target_id="mySidepanel" |
| onclick="openNav(this.getAttribute('target_id'))" |
| > |
| <svg |
| xmlns="http://www.w3.org/2000/svg" |
| width="16" |
| height="16" |
| fill="currentColor" |
| class="bi bi-question-circle me-1" |
| viewBox="0 0 16 16" |
| > |
| <path |
| d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z" |
| /> |
| <path |
| d="M5.255 5.786a.237.237 0 0 0 .241.247h.825c.138 0 .248-.113.266-.25.09-.656.54-1.134 1.342-1.134.686 0 1.314.343 1.314 1.168 0 .635-.374.927-.965 1.371-.673.489-1.206 1.06-1.168 1.987l.003.217a.25.25 0 0 0 .25.246h.811a.25.25 0 0 0 .25-.25v-.105c0-.718.273-.927 1.01-1.486.609-.463 1.244-.977 1.244-2.056 0-1.511-1.276-2.241-2.673-2.241-1.267 0-2.655.59-2.75 2.286zm1.557 5.763c0 .533.425.927 1.01.927.609 0 1.028-.394 1.028-.927 0-.552-.42-.94-1.029-.94-.584 0-1.009.388-1.009.94z" |
| /> |
| </svg> |
| Help |
| </a> |
| </div> |
| </div> |
| </div> |
|
|
| <hr style="color: var(--border)" /> |
| <footer |
| class="py-2 text-center" |
| style="font-size: 0.75rem; color: var(--muted-foreground)" |
| > |
| Copyright © 2025 |
| <a |
| href="https://blablablab.si.umich.edu/" |
| style="color: var(--primary); text-decoration: none" |
| >Blablablab</a |
| > |
| <span class="mx-2">|</span> |
| <a |
| href="https://github.com/davidjurgens/potato" |
| style="color: var(--primary); text-decoration: none" |
| >Chat with us on GitHub</a |
| > |
| <span class="mx-2">|</span> |
| <a |
| href="https://github.com/davidjurgens/potato#cite-us" |
| style="color: var(--primary); text-decoration: none" |
| >Cite Us</a |
| > |
| </footer> |
| </div> |
|
|
| <script> |
| |
| function openNav(target_id, width = "350px") { |
| document.getElementById(target_id).style.width = width; |
| } |
| |
| |
| function closeNav(target_id) { |
| document.getElementById(target_id).style.width = "0"; |
| } |
| |
| function closeNav2(target_id) { |
| |
| console.error(document.getElementById(target_id).style.display); |
| if ( |
| document.getElementById(target_id).style.display == "block" || |
| document.getElementById(target_id).style.display == "" |
| ) { |
| document.getElementById(target_id).style.display = "none"; |
| localStorage.setItem("show_instructions", "false"); |
| } else { |
| document.getElementById(target_id).style.display = "block"; |
| localStorage.setItem("show_instructions", "true"); |
| } |
| } |
| |
| |
| |
| window.addEventListener("load", function () { |
| var show = localStorage.getItem("show_instructions"); |
| if (document.getElementById("instructions")) { |
| if (show === "true") { |
| document.getElementById("instructions").style.display = "block"; |
| } else { |
| document.getElementById("instructions").style.display = "none"; |
| } |
| } |
| }); |
| |
| function watch_text_boxes() { |
| let timer; |
| const waitTime = 1000; |
| |
| var text_boxes = document.querySelectorAll("input[type=text]"); |
| for (var i = 0; i < text_boxes.length; i++) { |
| |
| |
| text_boxes[i].addEventListener("input", function (event) { |
| console.log("text box input event"); |
| clearTimeout(timer); |
| timer = setTimeout(() => { |
| registerTextAnnotation(event.target); |
| }, waitTime); |
| }); |
| } |
| |
| var text_areas = document.querySelectorAll("textarea"); |
| |
| for (var i = 0; i < text_areas.length; i++) { |
| |
| |
| text_areas[i].addEventListener("input", function (event) { |
| |
| clearTimeout(timer); |
| timer = setTimeout(() => { |
| registerTextAnnotation(event.target); |
| }, waitTime); |
| }); |
| } |
| } |
| watch_text_boxes(); |
| </script> |
| </body> |
| </html> |
|
|