<!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>