mirror of
https://github.com/qurator-spk/neat.git
synced 2025-07-01 22:49:56 +02:00
implement keyboard support
This commit is contained in:
parent
06501c9340
commit
ede687065e
4 changed files with 1544 additions and 146 deletions
|
@ -82,7 +82,42 @@ No. TOKEN NE-TAG NE-EMB GND-ID url_id left,right,top,bottom
|
||||||
The processing pipeline applied is documented in [Provenance](https://github.com/qurator-spk/neath/blob/master/docs/Provenance.md).
|
The processing pipeline applied is documented in [Provenance](https://github.com/qurator-spk/neath/blob/master/docs/Provenance.md).
|
||||||
|
|
||||||
We also provide some [Python tools](https://github.com/qurator-spk/neath/tree/master/tools) that help with data wrangling.
|
We also provide some [Python tools](https://github.com/qurator-spk/neath/tree/master/tools) that help with data wrangling.
|
||||||
#### Navigation
|
#### Keyboard - Layout
|
||||||
|
|
||||||
|
| Key Combi| Action |
|
||||||
|
|:---------|:-------------------------------------------|
|
||||||
|
| Left | Move one cell left |
|
||||||
|
| Right | Move one cell right |
|
||||||
|
| Up | Move one row up |
|
||||||
|
| Down | Move one row down |
|
||||||
|
| PageDown | Move page down |
|
||||||
|
| PageUp | Move page up |
|
||||||
|
|----------|--------------------------------------------|
|
||||||
|
| s t | Start new sentence in current row |
|
||||||
|
| m e | Merge current row with row above |
|
||||||
|
| s p | Create copy of current row one row below |
|
||||||
|
| 0 | Set POSITION of current row to zero |
|
||||||
|
|----------|--------------------------------------------|
|
||||||
|
| backspace| Set NE-TAG / NE-EMB to "O" |
|
||||||
|
| b p | Set NE-TAG / NE-EMB to "B-PER" |
|
||||||
|
| b l | Set NE-TAG / NE-EMB to "B-LOC" |
|
||||||
|
| b o | Set NE-TAG / NE-EMB to "B-ORG" |
|
||||||
|
| b w | Set NE-TAG / NE-EMB to "B-WORK" |
|
||||||
|
| b c | Set NE-TAG / NE-EMB to "B-CONF" |
|
||||||
|
| b e | Set NE-TAG / NE-EMB to "B-EVT" |
|
||||||
|
| b t | Set NE-TAG / NE-EMB to "B-TODO" |
|
||||||
|
| i p | Set NE-TAG / NE-EMB to "I-PER" |
|
||||||
|
| i l | Set NE-TAG / NE-EMB to "I-LOC" |
|
||||||
|
| i o | Set NE-TAG / NE-EMB to "I-ORG" |
|
||||||
|
| i w | Set NE-TAG / NE-EMB to "I-WORK" |
|
||||||
|
| i c | Set NE-TAG / NE-EMB to "I-CONF" |
|
||||||
|
| i e | Set NE-TAG / NE-EMB to "I-EVT" |
|
||||||
|
| i t | Set NE-TAG / NE-EMB to "I-TODO" |
|
||||||
|
|----------|--------------------------------------------|
|
||||||
|
| enter | Edit TOKEN or GND-ID |
|
||||||
|
|----------|--------------------------------------------|
|
||||||
|
|
||||||
|
#### Mouse-Navigation
|
||||||
* use mouse wheel to scroll up and down
|
* use mouse wheel to scroll up and down
|
||||||
* use navigation `<<` and `>>` to move faster
|
* use navigation `<<` and `>>` to move faster
|
||||||
#### Image Support
|
#### Image Support
|
||||||
|
|
1155
keypress.js
Normal file
1155
keypress.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -14,8 +14,8 @@
|
||||||
body{font-family:Verdana;font-size:16px}
|
body{font-family:Verdana;font-size:16px}
|
||||||
table{table-layout:fixed;width:100%;text-align:center}
|
table{table-layout:fixed;width:100%;text-align:center}
|
||||||
th{background-color:lightgray}
|
th{background-color:lightgray}
|
||||||
.editable:hover{background-color:yellow}
|
.editable:focus{background-color:yellow}
|
||||||
tr:hover{background-color:whitesmoke}
|
tr:focus-within{background-color:whitesmoke}
|
||||||
|
|
||||||
.accordion:hover .accordion-item:hover .accordion-item-content,
|
.accordion:hover .accordion-item:hover .accordion-item-content,
|
||||||
.accordion .accordion-item--default .accordion-item-content{height:10.5em}
|
.accordion .accordion-item--default .accordion-item-content{height:10.5em}
|
||||||
|
@ -55,8 +55,8 @@
|
||||||
<div class="col-9">
|
<div class="col-9">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<h3><a href="https://github.com/qurator-spk/neath" target="_blank">neath</a>: named entity annotation tool in html</h3>
|
<h3><a href="https://github.com/qurator-spk/neath" target="_blank" tabindex="-1">neath</a>: named entity annotation tool in html</h3>
|
||||||
<a href="https://github.com/qurator-spk/neath/blob/master/docs/User_Guide.md" target="_blank">User Guide</a> | <a href="https://github.com/qurator-spk/neath/blob/master/docs/Annotation_Guidelines.md" target="_blank">Annotation Guidelines</a> | <a href="https://github.com/qurator-spk/neath/issues" target="_blank">Issues</a><hr>
|
<a href="https://github.com/qurator-spk/neath/blob/master/docs/User_Guide.md" target="_blank" tabindex="-1">User Guide</a> | <a href="https://github.com/qurator-spk/neath/blob/master/docs/Annotation_Guidelines.md" target="_blank" tabindex="-1">Annotation Guidelines</a> | <a href="https://github.com/qurator-spk/neath/issues" target="_blank" tabindex="-1">Issues</a><hr>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -88,6 +88,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="keypress.js"></script>
|
||||||
<script src="neath.js"></script>
|
<script src="neath.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
401
neath.js
401
neath.js
|
@ -1,11 +1,11 @@
|
||||||
|
|
||||||
function loadFile(evt, onComplete) {
|
function loadFile(evt, onComplete) {
|
||||||
|
|
||||||
var file = evt.target.files[0];
|
let file = evt.target.files[0];
|
||||||
|
|
||||||
var urls = null;
|
let urls = null;
|
||||||
|
|
||||||
var reader = new FileReader();
|
let reader = new FileReader();
|
||||||
|
|
||||||
reader.onload =
|
reader.onload =
|
||||||
function(event) {
|
function(event) {
|
||||||
|
@ -13,7 +13,7 @@ function loadFile(evt, onComplete) {
|
||||||
let link_detector = /(https?:\/\/[^\s]+)/g;
|
let link_detector = /(https?:\/\/[^\s]+)/g;
|
||||||
|
|
||||||
let lines = event.target.result.split(/\r\n|\n/);
|
let lines = event.target.result.split(/\r\n|\n/);
|
||||||
for(var i = 0; i < lines.length; i++){
|
for(let i = 0; i < lines.length; i++){
|
||||||
|
|
||||||
let line = lines[i];
|
let line = lines[i];
|
||||||
|
|
||||||
|
@ -52,8 +52,12 @@ function setupInterface(data, file, urls) {
|
||||||
let startIndex=0;
|
let startIndex=0;
|
||||||
let endIndex=displayRows;
|
let endIndex=displayRows;
|
||||||
|
|
||||||
|
let do_not_display = new Set(['url_id', 'left', 'right', 'top', 'bottom']);
|
||||||
|
let tagClasses = 'ner_per ner_loc ner_org ner_work ner_conf ner_evt ner_todo';
|
||||||
|
|
||||||
let has_changes = false;
|
let has_changes = false;
|
||||||
var save_timeout = null;
|
|
||||||
|
let save_timeout = null;
|
||||||
|
|
||||||
function notifyChange() {
|
function notifyChange() {
|
||||||
if (save_timeout != null) clearTimeout(save_timeout);
|
if (save_timeout != null) clearTimeout(save_timeout);
|
||||||
|
@ -104,12 +108,6 @@ function setupInterface(data, file, urls) {
|
||||||
save_timeout = setTimeout(checker, 3000);
|
save_timeout = setTimeout(checker, 3000);
|
||||||
};
|
};
|
||||||
|
|
||||||
// public interface
|
|
||||||
var that =
|
|
||||||
{
|
|
||||||
hasChanges: function () { return has_changes; }
|
|
||||||
};
|
|
||||||
|
|
||||||
function updatePreview(nRow) {
|
function updatePreview(nRow) {
|
||||||
|
|
||||||
if (urls == null) return;
|
if (urls == null) return;
|
||||||
|
@ -139,8 +137,6 @@ function setupInterface(data, file, urls) {
|
||||||
img_url = img_url.replace('width', width.toString());
|
img_url = img_url.replace('width', width.toString());
|
||||||
img_url = img_url.replace('height', height.toString());
|
img_url = img_url.replace('height', height.toString());
|
||||||
|
|
||||||
//console.log(img_url)
|
|
||||||
|
|
||||||
$("#preview").attr("src", img_url);
|
$("#preview").attr("src", img_url);
|
||||||
|
|
||||||
img_url = urls[data.data[nRow]['url_id']];
|
img_url = urls[data.data[nRow]['url_id']];
|
||||||
|
@ -165,6 +161,8 @@ function setupInterface(data, file, urls) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function colorCode() {
|
function colorCode() {
|
||||||
|
$(".editable").removeClass(tagClasses);
|
||||||
|
|
||||||
$("#table td:contains('B-PER')").addClass('ner_per');
|
$("#table td:contains('B-PER')").addClass('ner_per');
|
||||||
$("#table td:contains('I-PER')").addClass('ner_per');
|
$("#table td:contains('I-PER')").addClass('ner_per');
|
||||||
$("#table td:contains('B-LOC')").addClass('ner_loc');
|
$("#table td:contains('B-LOC')").addClass('ner_loc');
|
||||||
|
@ -183,18 +181,6 @@ function setupInterface(data, file, urls) {
|
||||||
|
|
||||||
let editingTd;
|
let editingTd;
|
||||||
|
|
||||||
function gotoLocation(evt) {
|
|
||||||
|
|
||||||
if (urls == null) return;
|
|
||||||
if (editingTd != null) return;
|
|
||||||
|
|
||||||
let tableInfo = $(evt.target).data('tableInfo');
|
|
||||||
|
|
||||||
let nRow = tableInfo.nRow;
|
|
||||||
|
|
||||||
updatePreview(nRow)
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeTdEditable(td) {
|
function makeTdEditable(td) {
|
||||||
|
|
||||||
editingTd = {
|
editingTd = {
|
||||||
|
@ -219,7 +205,12 @@ function setupInterface(data, file, urls) {
|
||||||
$(td).html(editingTd.data);
|
$(td).html(editingTd.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let listener = new window.keypress.Listener(td);
|
||||||
|
|
||||||
|
listener.simple_combo("enter", function() { td.click(); });
|
||||||
|
|
||||||
editingTd = null;
|
editingTd = null;
|
||||||
|
$(td).focus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -250,52 +241,41 @@ function setupInterface(data, file, urls) {
|
||||||
function(evt) {
|
function(evt) {
|
||||||
editingTd.finish(editingTd.elem, false);
|
editingTd.finish(editingTd.elem, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let listener = new window.keypress.Listener(td);
|
||||||
|
|
||||||
|
listener.simple_combo('enter', function() { $('#edit-ok').click(); } );
|
||||||
|
listener.simple_combo('esc', function() { $('#edit-cancel').click(); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeLineSplitMerge(td) {
|
function tableEditAction(nRow, action) {
|
||||||
|
|
||||||
editingTd = {
|
if (action == null) return;
|
||||||
elem: td,
|
|
||||||
data: td.innerHTML,
|
|
||||||
tokenizer_action: null,
|
|
||||||
finish: function(td, isOk) {
|
|
||||||
$(td).html(editingTd.data);
|
|
||||||
$(td).addClass('editable');
|
|
||||||
|
|
||||||
if (editingTd.tokenizer_action == null) {
|
if (action.includes('merge')) {
|
||||||
editingTd = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tableInfo = $(td).data('tableInfo');
|
if (nRow < 1) return;
|
||||||
|
|
||||||
if (editingTd.tokenizer_action.includes('merge')) {
|
let pos = nRow + 1;
|
||||||
|
word_pos = data.data[nRow - 1]['No.'] + 1
|
||||||
if (tableInfo.nRow < 1) {
|
|
||||||
editingTd = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let pos = tableInfo.nRow + 1;
|
|
||||||
word_pos = data.data[tableInfo.nRow - 1]['No.'] + 1
|
|
||||||
while((pos < data.data.length) && (data.data[pos]['No.'] > 1)) {
|
while((pos < data.data.length) && (data.data[pos]['No.'] > 1)) {
|
||||||
data.data[pos]['No.'] = word_pos;
|
data.data[pos]['No.'] = word_pos;
|
||||||
pos++;
|
pos++;
|
||||||
word_pos++;
|
word_pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.data[tableInfo.nRow - 1]['TOKEN'] += data.data[tableInfo.nRow]['TOKEN'];
|
data.data[nRow - 1]['TOKEN'] += data.data[nRow]['TOKEN'];
|
||||||
|
|
||||||
data.data.splice(tableInfo.nRow, 1);
|
data.data.splice(nRow, 1);
|
||||||
|
|
||||||
notifyChange();
|
notifyChange();
|
||||||
}
|
}
|
||||||
else if (editingTd.tokenizer_action.includes('split')) {
|
else if (action.includes('split')) {
|
||||||
|
|
||||||
data.data.splice(tableInfo.nRow, 0, JSON.parse(JSON.stringify(data.data[tableInfo.nRow])));
|
data.data.splice(nRow, 0, JSON.parse(JSON.stringify(data.data[nRow])));
|
||||||
data.data[tableInfo.nRow + 1]['No.'] += 1
|
data.data[nRow + 1]['No.'] += 1;
|
||||||
|
|
||||||
let pos = tableInfo.nRow + 2;
|
let pos = nRow + 2;
|
||||||
while ((pos < data.data.length) && (data.data[pos]['No.'] > 1)) {
|
while ((pos < data.data.length) && (data.data[pos]['No.'] > 1)) {
|
||||||
data.data[pos]['No.']++;
|
data.data[pos]['No.']++;
|
||||||
pos++;
|
pos++;
|
||||||
|
@ -303,9 +283,9 @@ function setupInterface(data, file, urls) {
|
||||||
|
|
||||||
notifyChange();
|
notifyChange();
|
||||||
}
|
}
|
||||||
else if (editingTd.tokenizer_action.includes('sentence')) {
|
else if (action.includes('sentence')) {
|
||||||
|
|
||||||
let pos = tableInfo.nRow;
|
let pos = nRow;
|
||||||
|
|
||||||
let new_row = JSON.parse(JSON.stringify(data.data[pos]))
|
let new_row = JSON.parse(JSON.stringify(data.data[pos]))
|
||||||
|
|
||||||
|
@ -326,10 +306,25 @@ function setupInterface(data, file, urls) {
|
||||||
notifyChange();
|
notifyChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
editingTd = null;
|
|
||||||
|
|
||||||
updateTable();
|
updateTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeLineSplitMerge(td) {
|
||||||
|
|
||||||
|
editingTd = {
|
||||||
|
elem: td,
|
||||||
|
data: td.innerHTML,
|
||||||
|
tokenizer_action: null,
|
||||||
|
finish: function(td, isOk) {
|
||||||
|
$(td).html(editingTd.data);
|
||||||
|
$(td).addClass('editable');
|
||||||
|
|
||||||
|
let tableInfo = $(td).data('tableInfo');
|
||||||
|
|
||||||
|
tableEditAction(tableInfo.nRow, editingTd.tokenizer_action)
|
||||||
|
|
||||||
|
editingTd = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let edit_html = `
|
let edit_html = `
|
||||||
|
@ -337,11 +332,11 @@ function setupInterface(data, file, urls) {
|
||||||
<section class="accordion-item tokenizer-action">↕ split</section>
|
<section class="accordion-item tokenizer-action">↕ split</section>
|
||||||
<section class="accordion-item tokenizer-action">⟳ merge</section>
|
<section class="accordion-item tokenizer-action">⟳ merge</section>
|
||||||
<section class="accordion-item tokenizer-action">☇ sentence</section>
|
<section class="accordion-item tokenizer-action">☇ sentence</section>
|
||||||
</div>
|
</div>`;
|
||||||
`;
|
|
||||||
|
|
||||||
$(td).removeClass();
|
$(td).removeClass('editable');
|
||||||
$(td).html(edit_html);
|
$(td).html(edit_html);
|
||||||
|
|
||||||
$('#tokenizer').mouseleave(
|
$('#tokenizer').mouseleave(
|
||||||
function(event) {
|
function(event) {
|
||||||
editingTd.finish(editingTd.elem, false);
|
editingTd.finish(editingTd.elem, false);
|
||||||
|
@ -404,7 +399,7 @@ function setupInterface(data, file, urls) {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
$(td).removeClass();
|
$(td).removeClass('editable');
|
||||||
$(td).html(edit_html);
|
$(td).html(edit_html);
|
||||||
$('#tagger').mouseleave(
|
$('#tagger').mouseleave(
|
||||||
function(event) {
|
function(event) {
|
||||||
|
@ -417,16 +412,11 @@ function setupInterface(data, file, urls) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTable() {
|
function createTable() {
|
||||||
|
|
||||||
let do_not_display = new Set(['url_id', 'left', 'right', 'top', 'bottom']);
|
|
||||||
|
|
||||||
editingTd = null;
|
editingTd = null;
|
||||||
|
|
||||||
let editable_html =
|
let editable_html =`<td class="editable hover">`;
|
||||||
`
|
|
||||||
<td class="editable hover">
|
|
||||||
`;
|
|
||||||
|
|
||||||
$('#table-body').empty();
|
$('#table-body').empty();
|
||||||
|
|
||||||
|
@ -436,34 +426,98 @@ function setupInterface(data, file, urls) {
|
||||||
if (nRow < startIndex) return;
|
if (nRow < startIndex) return;
|
||||||
if (nRow >= endIndex) return;
|
if (nRow >= endIndex) return;
|
||||||
|
|
||||||
var row = $("<tr/>");
|
let row = $("<tr/>").data('tableInfo', { 'nRow': nRow });
|
||||||
|
|
||||||
|
row.focusin(function() { updatePreview(row.data('tableInfo').nRow); });
|
||||||
|
|
||||||
row.append($('<td class="hover"/>').
|
row.append($('<td class="hover"/>').
|
||||||
text(nRow).
|
text(nRow).
|
||||||
data('tableInfo', { 'nRow': nRow })
|
data('tableInfo', { 'nRow': nRow })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let row_listener = new window.keypress.Listener(row);
|
||||||
|
|
||||||
|
row_listener.sequence_combo('0',
|
||||||
|
function() {
|
||||||
|
|
||||||
|
data.data[row.data('tableInfo').nRow]['No.'] = 0;
|
||||||
|
|
||||||
|
row.children('.editable').first().html('0');
|
||||||
|
|
||||||
|
notifyChange();
|
||||||
|
});
|
||||||
|
|
||||||
|
row_listener.sequence_combo('s t', function() {
|
||||||
|
tableEditAction(row.data('tableInfo').nRow, 'sentence');
|
||||||
|
});
|
||||||
|
|
||||||
|
row_listener.sequence_combo('s p', function() {
|
||||||
|
tableEditAction(row.data('tableInfo').nRow, 'split');
|
||||||
|
});
|
||||||
|
|
||||||
|
row_listener.sequence_combo('m e', function() {
|
||||||
|
tableEditAction(row.data('tableInfo').nRow, 'merge');
|
||||||
|
});
|
||||||
|
|
||||||
$.each(el,
|
$.each(el,
|
||||||
function(column, content) {
|
function(column, content) {
|
||||||
|
|
||||||
|
let td = $(editable_html)
|
||||||
|
|
||||||
|
let listener = new window.keypress.Listener(td);
|
||||||
|
|
||||||
if (do_not_display.has(column)) return
|
if (do_not_display.has(column)) return
|
||||||
|
|
||||||
var clickAction = function() { console.log('Do something different');}
|
let clickAction = function() { console.log('Do something different');}
|
||||||
|
|
||||||
|
if (column == 'No.') {
|
||||||
|
|
||||||
if (column == 'No.')
|
|
||||||
clickAction = makeLineSplitMerge
|
clickAction = makeLineSplitMerge
|
||||||
|
}
|
||||||
|
|
||||||
if ((column == 'TOKEN') || (column == 'GND-ID'))
|
if ((column == 'TOKEN') || (column == 'GND-ID')) {
|
||||||
clickAction = makeTdEditable
|
clickAction = makeTdEditable
|
||||||
|
|
||||||
if ((column == 'NE-TAG') || (column == 'NE-EMB'))
|
listener.simple_combo("enter", function() {
|
||||||
|
td.click();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((column == 'NE-TAG') || (column == 'NE-EMB')) {
|
||||||
clickAction = makeTagEdit
|
clickAction = makeTagEdit
|
||||||
|
|
||||||
row.append(
|
let tagAction = function(tag) {
|
||||||
$(editable_html).
|
data.data[nRow][column] = tag;
|
||||||
|
|
||||||
|
$(td).html(tag);
|
||||||
|
colorCode();
|
||||||
|
notifyChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
listener.sequence_combo('b p', function() { tagAction('B-PER'); });
|
||||||
|
listener.sequence_combo('b l', function() { tagAction('B-LOC'); });
|
||||||
|
listener.sequence_combo('b o', function() { tagAction('B-ORG'); });
|
||||||
|
listener.sequence_combo('b w', function() { tagAction('B-WORK'); });
|
||||||
|
listener.sequence_combo('b c', function() { tagAction('B-CONF'); });
|
||||||
|
listener.sequence_combo('b e', function() { tagAction('B-EVT'); });
|
||||||
|
listener.sequence_combo('b t', function() { tagAction('B-TODO'); });
|
||||||
|
|
||||||
|
listener.sequence_combo('i p', function() { tagAction('I-PER'); });
|
||||||
|
listener.sequence_combo('i l', function() { tagAction('I-LOC'); });
|
||||||
|
listener.sequence_combo('i o', function() { tagAction('I-ORG'); });
|
||||||
|
listener.sequence_combo('i w', function() { tagAction('I-WORK'); });
|
||||||
|
listener.sequence_combo('i c', function() { tagAction('I-CONF'); });
|
||||||
|
listener.sequence_combo('i e', function() { tagAction('I-EVT'); });
|
||||||
|
listener.sequence_combo('i t', function() { tagAction('I-TODO'); });
|
||||||
|
|
||||||
|
listener.sequence_combo('backspace', function() { tagAction('O'); });
|
||||||
|
}
|
||||||
|
|
||||||
|
td.attr('tabindex', 0).
|
||||||
text(content).
|
text(content).
|
||||||
data('tableInfo', { 'nRow': nRow, 'column': column , 'clickAction': clickAction })
|
data('tableInfo', { 'nRow': nRow, 'column': column , 'clickAction': clickAction })
|
||||||
);
|
|
||||||
|
row.append(td);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#table tbody").append(row);
|
$("#table tbody").append(row);
|
||||||
|
@ -471,7 +525,14 @@ function setupInterface(data, file, urls) {
|
||||||
|
|
||||||
colorCode();
|
colorCode();
|
||||||
|
|
||||||
$(".hover").on('mouseover', gotoLocation);
|
$(".hover").on('mouseover',
|
||||||
|
function (evt) {
|
||||||
|
|
||||||
|
if (editingTd != null) return;
|
||||||
|
|
||||||
|
$(evt.target).focus();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if ($("#docpos").val() != startIndex) {
|
if ($("#docpos").val() != startIndex) {
|
||||||
|
|
||||||
|
@ -479,6 +540,73 @@ function setupInterface(data, file, urls) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateTable() {
|
||||||
|
|
||||||
|
editingTd = null;
|
||||||
|
|
||||||
|
let rows = $('tbody').children('tr');
|
||||||
|
|
||||||
|
let pRow = 0;
|
||||||
|
|
||||||
|
$.each(data.data,
|
||||||
|
function(nRow, el) {
|
||||||
|
|
||||||
|
if (nRow < startIndex) return;
|
||||||
|
if (nRow >= endIndex) return;
|
||||||
|
|
||||||
|
|
||||||
|
let row = $(rows[pRow]);
|
||||||
|
let tableInfo = row.data('tableInfo');
|
||||||
|
|
||||||
|
tableInfo.nRow = nRow;
|
||||||
|
|
||||||
|
row.data('tableInfo', tableInfo);
|
||||||
|
|
||||||
|
let loc = $(row.children('td').first());
|
||||||
|
loc.data('tableInfo', tableInfo);
|
||||||
|
loc.text(nRow);
|
||||||
|
|
||||||
|
let columns = $(rows[pRow]).children('.editable');
|
||||||
|
let pColumn = 0;
|
||||||
|
|
||||||
|
$.each(el,
|
||||||
|
function(column_name, content) {
|
||||||
|
|
||||||
|
if (do_not_display.has(column_name)) return
|
||||||
|
|
||||||
|
let td = $(columns[pColumn]);
|
||||||
|
|
||||||
|
tableInfo = td.data('tableInfo');
|
||||||
|
|
||||||
|
tableInfo.nRow = nRow;
|
||||||
|
|
||||||
|
td.text(content).data('tableInfo', tableInfo);
|
||||||
|
|
||||||
|
pColumn++;
|
||||||
|
});
|
||||||
|
|
||||||
|
pRow++;
|
||||||
|
});
|
||||||
|
|
||||||
|
colorCode();
|
||||||
|
|
||||||
|
if ($("#docpos").val() != startIndex) {
|
||||||
|
|
||||||
|
$("#docpos").val(data.data.length - startIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePreview($(':focus').data('tableInfo').nRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
let wnd_listener = new window.keypress.Listener();
|
||||||
|
|
||||||
|
wnd_listener.simple_combo('tab',
|
||||||
|
function () {
|
||||||
|
if (editingTd != null)
|
||||||
|
return false; // If we are in editing mode, we do not want to propagate the TAB event.
|
||||||
|
else return true; // In non-editing mode, we want to get the "normal" tab behaviour.
|
||||||
|
});
|
||||||
|
|
||||||
let slider_pos = data.data.length - startIndex;
|
let slider_pos = data.data.length - startIndex;
|
||||||
let slider_min = displayRows;
|
let slider_min = displayRows;
|
||||||
let slider_max = data.data.length;
|
let slider_max = data.data.length;
|
||||||
|
@ -510,12 +638,12 @@ function setupInterface(data, file, urls) {
|
||||||
<table id="table">
|
<table id="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><button class="btn btn-link" id="back"><<</button>LOCATION</th>
|
<th><button class="btn btn-link" id="back" tabindex="-1"><<</button>LOCATION</th>
|
||||||
<th>POSITION</th>
|
<th>POSITION</th>
|
||||||
<th>TOKEN</th>
|
<th>TOKEN</th>
|
||||||
<th>NE-TAG</th>
|
<th>NE-TAG</th>
|
||||||
<th>NE-EMB</th>
|
<th>NE-EMB</th>
|
||||||
<th>GND-ID<button class="btn btn-link" id="next">>></button></th>
|
<th>GND-ID<button class="btn btn-link" id="next" tabindex="-1">>></button></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="table-body"></tbody>
|
<tbody id="table-body"></tbody>
|
||||||
|
@ -525,7 +653,7 @@ function setupInterface(data, file, urls) {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
let save_html =
|
let save_html =
|
||||||
`<button class="btn btn-primary saveButton" id="save" disabled>Save Changes</button>`
|
`<button class="btn btn-primary saveButton" id="save" disabled tabindex="-1">Save Changes</button>`
|
||||||
|
|
||||||
$("#tableregion").html(table_html)
|
$("#tableregion").html(table_html)
|
||||||
|
|
||||||
|
@ -552,11 +680,12 @@ function setupInterface(data, file, urls) {
|
||||||
csv = [ lines[0] ];
|
csv = [ lines[0] ];
|
||||||
let url_id = -1;
|
let url_id = -1;
|
||||||
|
|
||||||
for(var i = 0; i < data.data.length; i++){
|
for(let i = 0; i < data.data.length; i++){
|
||||||
if (data.data[i]['url_id'] > url_id) {
|
if (data.data[i]['url_id'] > url_id) {
|
||||||
|
|
||||||
url_id = data.data[i]['url_id'];
|
url_id = data.data[i]['url_id'];
|
||||||
|
|
||||||
|
if (urls != null)
|
||||||
csv.push("# " + urls[url_id]);
|
csv.push("# " + urls[url_id]);
|
||||||
}
|
}
|
||||||
csv.push(lines[i+1]);
|
csv.push(lines[i+1]);
|
||||||
|
@ -573,7 +702,7 @@ function setupInterface(data, file, urls) {
|
||||||
|
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
var blob = data.constructor !== Blob
|
let blob = data.constructor !== Blob
|
||||||
? new Blob([data], {type: mimetype || 'application/octet-stream'})
|
? new Blob([data], {type: mimetype || 'application/octet-stream'})
|
||||||
: data ;
|
: data ;
|
||||||
|
|
||||||
|
@ -582,7 +711,7 @@ function setupInterface(data, file, urls) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var lnk = document.createElement('a'),
|
let lnk = document.createElement('a'),
|
||||||
url = window.URL,
|
url = window.URL,
|
||||||
objectURL;
|
objectURL;
|
||||||
|
|
||||||
|
@ -615,7 +744,7 @@ function setupInterface(data, file, urls) {
|
||||||
$(target).data('tableInfo').clickAction(target);
|
$(target).data('tableInfo').clickAction(target);
|
||||||
});
|
});
|
||||||
|
|
||||||
updateTable();
|
createTable();
|
||||||
|
|
||||||
$('#tableregion')[0].addEventListener("wheel",
|
$('#tableregion')[0].addEventListener("wheel",
|
||||||
function(event) {
|
function(event) {
|
||||||
|
@ -638,12 +767,11 @@ function setupInterface(data, file, urls) {
|
||||||
updateTable();
|
updateTable();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#back').on('click',
|
function stepsBackward (nrows) {
|
||||||
function(evt) {
|
|
||||||
|
|
||||||
if (startIndex >= displayRows) {
|
if (startIndex >= nrows) {
|
||||||
startIndex -= displayRows;
|
startIndex -= nrows;
|
||||||
endIndex -= displayRows;
|
endIndex -= nrows;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
startIndex = 0;
|
startIndex = 0;
|
||||||
|
@ -652,13 +780,10 @@ function setupInterface(data, file, urls) {
|
||||||
|
|
||||||
updateTable();
|
updateTable();
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
$('#next').on('click',
|
function stepsForward(nrows) {
|
||||||
function(evt) {
|
if (endIndex + nrows < data.data.length) {
|
||||||
|
endIndex += nrows;
|
||||||
if (endIndex + displayRows < data.data.length) {
|
|
||||||
endIndex += displayRows;
|
|
||||||
startIndex = endIndex - displayRows;
|
startIndex = endIndex - displayRows;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -668,7 +793,89 @@ function setupInterface(data, file, urls) {
|
||||||
|
|
||||||
updateTable();
|
updateTable();
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
$('#back').on('click', function() { stepsBackward(displayRows); } );
|
||||||
|
|
||||||
|
$('#next').on('click', function() { stepsForward(displayRows); } );
|
||||||
|
|
||||||
|
wnd_listener.simple_combo('pageup',
|
||||||
|
function() {
|
||||||
|
if (editingTd != null) return;
|
||||||
|
|
||||||
|
$('#back').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
wnd_listener.simple_combo('pagedown',
|
||||||
|
function() {
|
||||||
|
if (editingTd != null) return;
|
||||||
|
|
||||||
|
$('#next').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
wnd_listener.simple_combo('left',
|
||||||
|
function() {
|
||||||
|
if (editingTd != null) return true;
|
||||||
|
|
||||||
|
let prev = $(':focus').prev('.editable')
|
||||||
|
|
||||||
|
if (prev.length==0) {
|
||||||
|
$(':focus').closest('tr').prev('tr').children('.editable').last().focus();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prev.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
wnd_listener.simple_combo('right',
|
||||||
|
function() {
|
||||||
|
if (editingTd != null) return true;
|
||||||
|
|
||||||
|
let next = $(':focus').next('.editable')
|
||||||
|
|
||||||
|
if (next.length==0) {
|
||||||
|
$(':focus').closest('tr').next('tr').children('.editable').first().focus();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
wnd_listener.simple_combo('up',
|
||||||
|
function() {
|
||||||
|
if (editingTd != null) return true;
|
||||||
|
|
||||||
|
let prev = $(':focus').closest('tr').prev('tr')
|
||||||
|
|
||||||
|
let pos = $(':focus').closest('tr').children('.editable').index($(':focus'))
|
||||||
|
|
||||||
|
if (prev.length==0) {
|
||||||
|
stepsBackward(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prev.children('.editable')[pos].focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
wnd_listener.simple_combo('down',
|
||||||
|
function() {
|
||||||
|
if (editingTd != null) return true;
|
||||||
|
|
||||||
|
let next = $(':focus').closest('tr').next('tr')
|
||||||
|
|
||||||
|
let pos = $(':focus').closest('tr').children('.editable').index($(':focus'))
|
||||||
|
|
||||||
|
if (next.length==0) {
|
||||||
|
stepsForward(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next.children('.editable')[pos].focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// public interface
|
||||||
|
let that =
|
||||||
|
{
|
||||||
|
hasChanges: function () { return has_changes; }
|
||||||
|
};
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
}
|
}
|
||||||
|
@ -683,7 +890,7 @@ $(document).ready(
|
||||||
loadFile ( evt,
|
loadFile ( evt,
|
||||||
function(results, file, urls) {
|
function(results, file, urls) {
|
||||||
|
|
||||||
var neath = setupInterface(results, file, urls);
|
let neath = setupInterface(results, file, urls);
|
||||||
|
|
||||||
$(window).bind("beforeunload",
|
$(window).bind("beforeunload",
|
||||||
function() {
|
function() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue