<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ner.edith</title> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.0.1/papaparse.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <style> body{font-family:Open Sans;font-size:16px} table{table-layout:fixed;width:70%;text-align:center} th{background-color:lightgray} td:hover{background-color:yellow} tr:hover{background-color:whitesmoke} .ner_per{background-color:skyblue} .ner_loc{background-color:goldenrod} .ner_org{background-color:plum} .ner_oth{background-color:lightgreen} .ner_todo{background-color:turquoise} </style> </head> <body> <h3>ner.edith: named entity recognition editor in html</h3> Please upload a TSV (tab-separated-values) file in the GermEval2014 data format<sup>[<a href="https://sites.google.com/site/germeval2014ner/data" target="_blank">i</a>]</sup>: <input type="file" id="tsv-file" name="files"/><br><br> <table id="table"> <thead> <tr> <th>OFFSET</th> <th>POSITION</th> <th>TOKEN</th> <th>NE-TAG</th> <th>NE-EMB</th> </tr> </thead> <tbody></tbody> </table> <script> var data; function handleFileSelect(evt) { var file = evt.target.files[0]; // TODO: adapt to streaming with 'chunk' callback for large file support, see https://www.papaparse.com/docs Papa.parse(file, { header: true, delimiter: '\t', comments: "#", skipEmptyLines: true, dynamicTyping: true, complete: function(results) { console.log(results); data = results; $.each(results.data, function(i, el) { var row = $("<tr/>"); row.append($("<td/>").text(i)); $.each(el, function(i, cell) { row.append($("<td/>").text(cell)); }); $("#table tbody").append(row); $("#table td:contains('B-PER')").addClass('ner_per'); $("#table td:contains('I-PER')").addClass('ner_per'); $("#table td:contains('B-LOC')").addClass('ner_loc'); $("#table td:contains('I-LOC')").addClass('ner_loc'); $("#table td:contains('B-ORG')").addClass('ner_org'); $("#table td:contains('I-ORG')").addClass('ner_org'); $("#table td:contains('B-OTH')").addClass('ner_oth'); $("#table td:contains('I-OTH')").addClass('ner_oth'); $("#table td:contains('B-TODO')").addClass('ner_oth'); $("#table td:contains('I-TODO')").addClass('ner_oth'); }); } }); } // https://javascript.info/task/edit-td-click let table = document.getElementById('table'); let editingTd; table.onclick = function(event) { let target = event.target.closest('.edit-cancel,.edit-ok,td'); if (!table.contains(target)) return; if (target.className == 'edit-cancel') { finishTdEdit(editingTd.elem, false); } else if (target.className == 'edit-ok') { finishTdEdit(editingTd.elem, true); } else if (target.nodeName == 'TD') { if (editingTd) return; makeTdEditable(target); } } function makeTdEditable(td) { editingTd = { elem: td, data: td.innerHTML }; td.classList.add('edit-td'); let textArea = document.createElement('textarea'); textArea.style.width = td.clientWidth + 'px'; textArea.style.height = td.clientHeight + 'px'; textArea.className = 'edit-area'; textArea.value = td.innerHTML; td.innerHTML = ''; td.appendChild(textArea); textArea.focus(); td.insertAdjacentHTML("beforeEnd", '<div class="edit-controls"><button class="edit-ok">OK</button><button class="edit-cancel">CANCEL</button></div>' ); } function finishTdEdit(td, isOk) { if (isOk) { td.innerHTML = td.firstChild.value; } else { td.innerHTML = editingTd.data; } td.classList.remove('edit-td'); editingTd = null; } $(document).ready(function() { $('#tsv-file').change(handleFileSelect); }); </script> </body> </html>