Compare commits

...

5 Commits

Author SHA1 Message Date
Inga Kirschnick
d3cfd2cfaf Editing Meta Data and Tokens 2023-10-09 16:30:46 +02:00
Inga Kirschnick
14c10aeab1 Merge branch 'query-builder' of gitlab.ub.uni-bielefeld.de:sfb1288inf/nopaque into query-builder 2023-10-09 15:42:10 +02:00
Inga Kirschnick
2dec17b1b9 Editing Entity Type 2023-10-09 15:42:01 +02:00
Patrick Jentsch
9fe38fab52 Remove debug messages 2023-10-09 14:34:06 +02:00
Patrick Jentsch
e20dd01710 Better auto initialization method for forms and resource displays 2023-10-09 14:21:31 +02:00
16 changed files with 276 additions and 154 deletions

View File

@ -33,7 +33,19 @@ class ConcordanceQueryBuilder {
document.querySelector('#corpus-analysis-concordance-positional-attr-modal'), document.querySelector('#corpus-analysis-concordance-positional-attr-modal'),
{ {
onOpenStart: () => { onOpenStart: () => {
this.tokenAttributeBuilderFunctions.preparePositionalAttrModal();
this.tokenAttributeBuilderFunctions.optionToggleHandler(); this.tokenAttributeBuilderFunctions.optionToggleHandler();
},
onCloseStart: () => {
this.tokenAttributeBuilderFunctions.resetPositionalAttrModal();
}
}
);
this.elements.structuralAttrModal = M.Modal.init(
document.querySelector('#corpus-analysis-concordance-structural-attr-modal'),
{
onCloseStart: () => {
this.structuralAttributeBuilderFunctions.resetStructuralAttrModal();
} }
} }
); );

View File

@ -3,6 +3,8 @@ class ElementReferencesQueryBuilder {
// General Elements // General Elements
this.queryInputField = document.querySelector('#corpus-analysis-concordance-query-builder-input-field'); this.queryInputField = document.querySelector('#corpus-analysis-concordance-query-builder-input-field');
this.queryChipElements = []; this.queryChipElements = [];
this.editingModusOn = false;
this.editedQueryChipElementIndex = undefined;
// Structural Attribute Builder Elements // Structural Attribute Builder Elements
this.structuralAttrModal = M.Modal.getInstance(document.querySelector('#corpus-analysis-concordance-structural-attr-modal')); this.structuralAttrModal = M.Modal.getInstance(document.querySelector('#corpus-analysis-concordance-structural-attr-modal'));
@ -12,6 +14,7 @@ class ElementReferencesQueryBuilder {
this.englishEntTypeSelection = document.querySelector('#corpus-analysis-concordance-english-ent-type-selection'); this.englishEntTypeSelection = document.querySelector('#corpus-analysis-concordance-english-ent-type-selection');
this.germanEntTypeSelection = document.querySelector('#corpus-analysis-concordance-german-ent-type-selection'); this.germanEntTypeSelection = document.querySelector('#corpus-analysis-concordance-german-ent-type-selection');
this.textAnnotationSelection = document.querySelector('#corpus-analysis-concordance-text-annotation-options'); this.textAnnotationSelection = document.querySelector('#corpus-analysis-concordance-text-annotation-options');
this.textAnnotationInput = document.querySelector('#corpus-analysis-concordance-text-annotation-input');
// Token Attribute Builder Elements // Token Attribute Builder Elements
this.positionalAttrModal = M.Modal.getInstance(document.querySelector('#corpus-analysis-concordance-positional-attr-modal')); this.positionalAttrModal = M.Modal.getInstance(document.querySelector('#corpus-analysis-concordance-positional-attr-modal'));

View File

@ -5,7 +5,7 @@ class GeneralFunctionsQueryBuilder {
toggleClass(elements, className, action){ toggleClass(elements, className, action){
elements.forEach(element => { elements.forEach(element => {
document.querySelector('[data-toggle-area="' + element + '"]').classList[action](className); document.querySelector(`[data-toggle-area="${element}"]`).classList[action](className);
}); });
} }
@ -22,7 +22,7 @@ class GeneralFunctionsQueryBuilder {
removePlaceholder() { removePlaceholder() {
let placeholder = this.elements.queryInputField.querySelector('#corpus-analysis-concordance-query-builder-input-field-placeholder'); let placeholder = this.elements.queryInputField.querySelector('#corpus-analysis-concordance-query-builder-input-field-placeholder');
if (placeholder) { if (placeholder && this.elements.queryInputField !== undefined) {
this.elements.queryInputField.innerHTML = ''; this.elements.queryInputField.innerHTML = '';
} }
} }
@ -41,21 +41,33 @@ class GeneralFunctionsQueryBuilder {
}) })
} }
submitQueryChipElement(dataType = undefined, prettyQueryText = undefined, queryText = undefined, index = null, isClosingTag = false, isEditable = false) {
if (this.elements.editingModusOn) {
let editedQueryChipElement = this.elements.queryChipElements[this.elements.editedQueryChipElementIndex];
editedQueryChipElement.dataset.type = dataType;
editedQueryChipElement.dataset.query = queryText;
editedQueryChipElement.firstChild.textContent = prettyQueryText;
this.updateChipList();
this.queryPreviewBuilder();
} else {
this.queryChipFactory(dataType, prettyQueryText, queryText, index, isClosingTag, isEditable);
}
}
queryChipFactory(dataType, prettyQueryText, queryText, index = null, isClosingTag = false) {
queryChipFactory(dataType, prettyQueryText, queryText, index = null, isClosingTag = false, isEditable = false) {
// Creates a new query chip element, adds Eventlisteners for selection, deletion and drag and drop and appends it to the query input field. // Creates a new query chip element, adds Eventlisteners for selection, deletion and drag and drop and appends it to the query input field.
queryText = Utils.escape(queryText); queryText = Utils.escape(queryText);
prettyQueryText = Utils.escape(prettyQueryText); prettyQueryText = Utils.escape(prettyQueryText);
let queryChipElement = Utils.HTMLToElement( let queryChipElement = Utils.HTMLToElement(
` `
<span class="chip query-component" data-type="${dataType}" data-query="${queryText}" draggable="true" data-closing-tag="${isClosingTag}"> <span class="chip query-component" data-type="${dataType}" data-query="${queryText}" draggable="true" data-closing-tag="${isClosingTag}">
${prettyQueryText} ${prettyQueryText}${isEditable ? '<i class="material-icons chip-action-button" data-chip-action="edit" style="padding-left:5px; font-size:18px; cursor:pointer;">edit</i>': ''}
${isClosingTag ? '<i class="material-icons" style="padding-top:5px; font-size:20px; cursor:pointer;">lock_open</i>' : '<i class="material-icons close">close</i>'} ${isClosingTag ? '<i class="material-icons chip-action-button" data-chip-action="lock" style="padding-top:5px; font-size:20px; cursor:pointer;">lock_open</i>' : '<i class="material-icons close chip-action-button" data-chip-action="delete">close</i>'}
</span> </span>
` `
); );
this.actionListeners(queryChipElement, isClosingTag); this.actionListeners(queryChipElement);
queryChipElement.addEventListener('dragstart', this.handleDragStart.bind(this, queryChipElement)); queryChipElement.addEventListener('dragstart', this.handleDragStart.bind(this, queryChipElement));
queryChipElement.addEventListener('dragend', this.handleDragEnd); queryChipElement.addEventListener('dragend', this.handleDragEnd);
@ -80,7 +92,7 @@ class GeneralFunctionsQueryBuilder {
this.queryPreviewBuilder(); this.queryPreviewBuilder();
} }
actionListeners(queryChipElement, isClosingTag) { actionListeners(queryChipElement) {
let notQuantifiableDataTypes = ['start-sentence', 'end-sentence', 'start-entity', 'start-empty-entity', 'end-entity', 'token-incidence-modifier']; let notQuantifiableDataTypes = ['start-sentence', 'end-sentence', 'start-entity', 'start-empty-entity', 'end-entity', 'token-incidence-modifier'];
queryChipElement.addEventListener('click', (event) => { queryChipElement.addEventListener('click', (event) => {
if (event.target.classList.contains('chip')) { if (event.target.classList.contains('chip')) {
@ -89,22 +101,101 @@ class GeneralFunctionsQueryBuilder {
} }
} }
}); });
queryChipElement.querySelector('i').addEventListener('click', () => { let chipActionButtons = queryChipElement.querySelectorAll('.chip-action-button');
if (isClosingTag) { chipActionButtons.forEach(button => {
this.lockClosingChipElement(queryChipElement); button.addEventListener('click', (event) => {
} else { if (event.target.dataset.chipAction === 'delete') {
this.deleteChipElement(queryChipElement); this.deleteChipElement(queryChipElement);
} else if (event.target.dataset.chipAction === 'edit') {
this.editChipElement(queryChipElement);
} else if (event.target.dataset.chipAction === 'lock') {
this.lockClosingChipElement(queryChipElement);
} }
}); });
});
}
editChipElement(queryChipElement) {
this.elements.editingModusOn = true;
this.elements.editedQueryChipElementIndex = Array.from(this.elements.queryInputField.children).indexOf(queryChipElement);
switch (queryChipElement.dataset.type) {
case 'start-entity':
this.elements.structuralAttrModal.open();
this.toggleClass(['entity-builder'], 'hide', 'remove');
this.toggleEditingAreaStructureAttrModal('add');
let entType = queryChipElement.dataset.query.replace(/<ent_type="|">/g, '');
let isEnglishEntType = this.elements.englishEntTypeSelection.querySelector(`option[value=${entType}]`) !== null;
let selection = isEnglishEntType ? this.elements.englishEntTypeSelection : this.elements.germanEntTypeSelection;
this.resetMaterializeSelection([selection], entType);
break;
case 'text-annotation':
this.elements.structuralAttrModal.open();
this.toggleClass(['text-annotation-builder'], 'hide', 'remove');
this.toggleEditingAreaStructureAttrModal('add');
let [textAnnotationSelection, textAnnotationContent] = queryChipElement.dataset.query
.replace(/:: ?match\.text_|"|"/g, '')
.split('=');
this.resetMaterializeSelection([this.elements.textAnnotationSelection], textAnnotationSelection);
this.elements.textAnnotationInput.value = textAnnotationContent;
break;
case 'token':
let [tokenAttr, tokenValue] = queryChipElement.dataset.query.replace(/\[|\]|"/g, '').split('=');
if (tokenAttr === 'pos') {
tokenAttr = this.elements.englishPosSelection.querySelector(`option[value=${tokenValue}]`) ? 'english-pos' : 'german-pos';
}
this.editTokenChipElement(tokenAttr, tokenValue);
break;
default:
break;
}
}
editTokenChipElement(tokenAttr, tokenValue) {
this.resetMaterializeSelection([this.elements.positionalAttrSelection], tokenAttr);
this.elements.positionalAttrModal.open();
switch (tokenAttr) {
case 'word':
this.elements.wordInput.value = tokenValue;
break;
case 'lemma':
this.elements.lemmaInput.value = tokenValue;
break;
case 'english-pos':
this.resetMaterializeSelection([this.elements.englishPosSelection], tokenValue);
break;
case 'german-pos':
this.resetMaterializeSelection([this.elements.germanPosSelection], tokenValue);
break;
case 'simple-pos':
this.resetMaterializeSelection([this.elements.simplePosSelection], tokenValue);
break;
default:
break;
}
} }
lockClosingChipElement(queryChipElement) { lockClosingChipElement(queryChipElement) {
let chipIndex = Array.from(this.elements.queryInputField.children).indexOf(queryChipElement); let chipIndex = Array.from(this.elements.queryInputField.children).indexOf(queryChipElement);
this.queryChipFactory(queryChipElement.dataset.type, queryChipElement.firstChild.textContent, queryChipElement.dataset.query, chipIndex+1); this.submitQueryChipElement(queryChipElement.dataset.type, queryChipElement.firstChild.textContent, queryChipElement.dataset.query, chipIndex+1);
this.deleteChipElement(queryChipElement); this.deleteChipElement(queryChipElement);
this.updateChipList(); this.updateChipList();
} }
deleteChipElement(attr) {
if (attr.dataset.type === "start-sentence") {
this.elements.sentenceElement.innerHTML = 'Sentence';
} else if (attr.dataset.type === "start-entity" || attr.dataset.type === "start-empty-entity") {
this.elements.entityElement.innerHTML = 'Entity';
}
this.elements.queryInputField.removeChild(attr);
if (this.elements.queryInputField.children.length === 0) {
this.addPlaceholder();
}
this.updateChipList();
this.queryPreviewBuilder();
}
handleDragStart(queryChipElement, event) { handleDragStart(queryChipElement, event) {
// is called when a query chip is dragged. It creates a dropzone (in form of a chip) for the dragged chip and adds it to the query input field. // is called when a query chip is dragged. It creates a dropzone (in form of a chip) for the dragged chip and adds it to the query input field.
let queryChips = this.elements.queryInputField.querySelectorAll('.query-component'); let queryChips = this.elements.queryInputField.querySelectorAll('.query-component');
@ -176,20 +267,6 @@ class GeneralFunctionsQueryBuilder {
queryPreview.parentNode.classList.toggle('hide', queryString === ';'); queryPreview.parentNode.classList.toggle('hide', queryString === ';');
} }
deleteChipElement(attr) {
if (attr.dataset.type === "start-sentence") {
this.elements.sentenceElement.innerHTML = 'Sentence';
} else if (attr.dataset.type === "start-entity" || attr.dataset.type === "start-empty-entity") {
this.elements.entityElement.innerHTML = 'Entity';
}
this.elements.queryInputField.removeChild(attr);
if (this.elements.queryInputField.children.length === 0) {
this.addPlaceholder();
}
this.updateChipList();
this.queryPreviewBuilder();
}
selectChipElement(attr) { selectChipElement(attr) {
document.querySelectorAll('.chip.teal').forEach(element => { document.querySelectorAll('.chip.teal').forEach(element => {
if (element !== attr) { if (element !== attr) {
@ -207,7 +284,7 @@ class GeneralFunctionsQueryBuilder {
// Adds a token incidence modifier to the query input field. // Adds a token incidence modifier to the query input field.
let selectedChip = this.elements.queryInputField.querySelector('.chip.teal'); let selectedChip = this.elements.queryInputField.querySelector('.chip.teal');
let selectedChipIndex = Array.from(this.elements.queryInputField.children).indexOf(selectedChip); let selectedChipIndex = Array.from(this.elements.queryInputField.children).indexOf(selectedChip);
this.queryChipFactory('token-incidence-modifier', incidenceModifierPretty, incidenceModifier, selectedChipIndex+1); this.submitQueryChipElement('token-incidence-modifier', incidenceModifierPretty, incidenceModifier, selectedChipIndex+1);
this.selectChipElement(selectedChip); this.selectChipElement(selectedChip);
} }
@ -243,7 +320,7 @@ class GeneralFunctionsQueryBuilder {
let expertModeInputFieldValue = document.querySelector('#corpus-analysis-concordance-form-query').value; let expertModeInputFieldValue = document.querySelector('#corpus-analysis-concordance-form-query').value;
let chipElements = this.parseTextToChip(expertModeInputFieldValue); let chipElements = this.parseTextToChip(expertModeInputFieldValue);
for (let chipElement of chipElements) { for (let chipElement of chipElements) {
this.queryChipFactory(chipElement['type'], chipElement['pretty'], chipElement['query']); this.submitQueryChipElement(chipElement['type'], chipElement['pretty'], chipElement['query']);
} }
} }

View File

@ -9,23 +9,48 @@ class StructuralAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQu
}); });
}); });
document.querySelector('.ent-type-selection-action[data-ent-type="any"]').addEventListener('click', () => { document.querySelector('.ent-type-selection-action[data-ent-type="any"]').addEventListener('click', () => {
this.queryChipFactory('start-empty-entity', 'Entity Start', '<ent>'); this.submitQueryChipElement('start-empty-entity', 'Entity Start', '<ent>');
this.queryChipFactory('end-entity', 'Entity End', '</ent>', null, true); this.submitQueryChipElement('end-entity', 'Entity End', '</ent>', null, true);
this.resetAndCloseStructuralAttrModal(); this.elements.structuralAttrModal.close();
}); });
document.querySelector('.ent-type-selection-action[data-ent-type="english"]').addEventListener('change', (event) => { document.querySelector('.ent-type-selection-action[data-ent-type="english"]').addEventListener('change', (event) => {
this.queryChipFactory('start-entity', `Entity Type=${event.target.value}`, `<ent_type="${event.target.value}">`); this.submitQueryChipElement('start-entity', `Entity Type=${event.target.value}`, `<ent_type="${event.target.value}">`, null, false, true);
this.queryChipFactory('end-entity', 'Entity End', '</ent_type>', null, true); if (!this.elements.editingModusOn) {
this.resetAndCloseStructuralAttrModal(); this.submitQueryChipElement('end-entity', 'Entity End', '</ent_type>', null, true);
}
this.elements.structuralAttrModal.close();
}); });
document.querySelector('.ent-type-selection-action[data-ent-type="german"]').addEventListener('change', (event) => {
this.submitQueryChipElement('start-entity', `Entity Type=${event.target.value}`, `<ent_type="${event.target.value}">`, null, false, true);
if (!this.elements.editingModusOn) {
this.submitQueryChipElement('end-entity', 'Entity End', '</ent_type>', null, true);
}
this.elements.structuralAttrModal.close();
});
}
resetStructuralAttrModal() {
this.resetMaterializeSelection([this.elements.englishEntTypeSelection, this.elements.germanEntTypeSelection]);
this.resetMaterializeSelection([this.elements.textAnnotationSelection], 'address');
this.elements.textAnnotationInput.value = '';
this.toggleClass(['entity-builder', 'text-annotation-builder'], 'hide', 'add');
this.toggleEditingAreaStructureAttrModal('remove');
this.elements.editingModusOn = false;
this.elements.editedQueryChipElementIndex = undefined;
}
toggleEditingAreaStructureAttrModal(action) {
// If the user edits a query chip element, the corresponding editing area is displayed and the other areas are hidden or disabled.
this.toggleClass(['sentence-button', 'entity-button', 'text-annotation-button', 'any-type-entity-button'], 'disabled', action);
} }
actionButtonInStrucAttrModalHandler(action) { actionButtonInStrucAttrModalHandler(action) {
switch (action) { switch (action) {
case 'sentence': case 'sentence':
this.queryChipFactory('start-sentence', 'Sentence Start', '<s>'); this.submitQueryChipElement('start-sentence', 'Sentence Start', '<s>');
this.queryChipFactory('end-sentence', 'Sentence End', '</s>', null, true); this.submitQueryChipElement('end-sentence', 'Sentence End', '</s>', null, true);
this.resetAndCloseStructuralAttrModal(); this.elements.structuralAttrModal.close();
break; break;
case 'entity': case 'entity':
this.toggleClass(['entity-builder'], 'hide', 'toggle'); this.toggleClass(['entity-builder'], 'hide', 'toggle');
@ -57,19 +82,8 @@ class StructuralAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQu
}, 3000); }, 3000);
} else { } else {
let queryText = `:: match.text_${textAnnotationOptions.value}="${textAnnotationInput.value}"`; let queryText = `:: match.text_${textAnnotationOptions.value}="${textAnnotationInput.value}"`;
this.queryChipFactory('text-annotation', `${textAnnotationOptions.value}=${textAnnotationInput.value}`, queryText); this.submitQueryChipElement('text-annotation', `${textAnnotationOptions.value}=${textAnnotationInput.value}`, queryText, null, false, true);
this.resetAndCloseStructuralAttrModal();
}
}
resetAndCloseStructuralAttrModal() {
let textAnnotatinInput = document.querySelector('#corpus-analysis-concordance-text-annotation-input');
textAnnotatinInput.value = '';
this.resetMaterializeSelection([this.elements.englishEntTypeSelection, this.elements.germanEntTypeSelection]);
this.resetMaterializeSelection([this.elements.textAnnotationSelection], 'address');
this.toggleClass(['entity-builder', 'text-annotation-builder'], 'hide', 'add');
this.elements.structuralAttrModal.close(); this.elements.structuralAttrModal.close();
} }
}
} }

View File

@ -3,20 +3,8 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
super(elements); super(elements);
this.elements = elements; this.elements = elements;
this.elements.positionalAttrSelection.addEventListener('change', (event) => { this.elements.positionalAttrSelection.addEventListener('change', () => {
this.toggleClass(['word', 'lemma', 'english-pos', 'german-pos', 'simple-pos'], 'hide', 'add'); this.preparePositionalAttrModal();
if (event.target.value !== 'empty-token') {
this.toggleClass([event.target.value], 'hide', 'remove');
this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'add');
this.resetMaterializeSelection([this.elements.englishPosSelection, this.elements.germanPosSelection, this.elements.simplePosSelection]);
}
if (event.target.value === 'word' || event.target.value === 'lemma') {
this.toggleClass(['input-field-options'], 'hide', 'remove');
} else if (event.target.value === 'empty-token'){
this.addTokenToQuery();
} else {
this.toggleClass(['input-field-options'], 'hide', 'add');
}
}); });
// Options for positional attribute selection // Options for positional attribute selection
@ -33,6 +21,48 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
this.elements.simplePosSelection.addEventListener('change', () => {this.optionToggleHandler();}); this.elements.simplePosSelection.addEventListener('change', () => {this.optionToggleHandler();});
} }
resetPositionalAttrModal() {
let originalSelectionList =
`
<option value="word" selected>word</option>
<option value="lemma" >lemma</option>
<option value="english-pos">english pos</option>
<option value="german-pos">german pos</option>
<option value="simple-pos">simple_pos</option>
<option value="empty-token">empty token</option>
`;
this.elements.positionalAttrSelection.innerHTML = originalSelectionList;
this.elements.tokenQuery.innerHTML = '';
this.toggleClass(['word', 'lemma', 'english-pos', 'german-pos', 'simple-pos'], 'hide', 'add');
this.toggleClass(['word', 'input-field-options'], 'hide', 'remove');
this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'add');
document.querySelector('#corpus-analysis-concordance-positional-attr-selection option[value="word"]').selected = true;
this.elements.wordInput.value = '';
this.elements.lemmaInput.value = '';
this.resetMaterializeSelection([this.elements.englishPosSelection, this.elements.germanPosSelection, this.elements.simplePosSelection]);
this.resetMaterializeSelection([this.elements.positionalAttrSelection], "word");
this.elements.editingModusOn = false;
this.elements.editedQueryChipElementIndex = undefined;
}
preparePositionalAttrModal() {
let selection = this.elements.positionalAttrSelection.value;
this.toggleClass(['word', 'lemma', 'english-pos', 'german-pos', 'simple-pos'], 'hide', 'add');
if (selection !== 'empty-token') {
this.toggleClass([selection], 'hide', 'remove');
this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'add');
this.resetMaterializeSelection([this.elements.englishPosSelection, this.elements.germanPosSelection, this.elements.simplePosSelection]);
}
if (selection === 'word' || selection === 'lemma') {
this.toggleClass(['input-field-options'], 'hide', 'remove');
} else if (selection === 'empty-token'){
this.addTokenToQuery();
} else {
this.toggleClass(['input-field-options'], 'hide', 'add');
}
}
tokenInputCheck() { tokenInputCheck() {
let input; let input;
@ -52,10 +82,8 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
} }
optionToggleHandler() { optionToggleHandler() {
let input; let input = this.tokenInputCheck();
input = this.tokenInputCheck(); if ((input.value === '' || input.value === 'default') && this.elements.editingModusOn === false) {
if (input.value === '' || input.value === 'default') {
this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'add'); this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'add');
} else { } else {
this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'remove'); this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'remove');
@ -154,8 +182,7 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
// isTokenQueryInvalid looks if a valid value is passed. If the input fields/dropdowns are empty (isTokenQueryInvalid === true), no token is added. // isTokenQueryInvalid looks if a valid value is passed. If the input fields/dropdowns are empty (isTokenQueryInvalid === true), no token is added.
if (this.elements.isTokenQueryInvalid === false) { if (this.elements.isTokenQueryInvalid === false) {
tokenQueryCQLText = '[' + tokenQueryCQLText + ']'; tokenQueryCQLText = '[' + tokenQueryCQLText + ']';
this.queryChipFactory('token', tokenQueryPrettyText, tokenQueryCQLText); this.submitQueryChipElement('token', tokenQueryPrettyText, tokenQueryCQLText, null, false, true);
this.resetPositionalAttrModal();
this.elements.positionalAttrModal.close(); this.elements.positionalAttrModal.close();
} }
} }
@ -308,27 +335,4 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
this.toggleClass(['input-field-options'], 'hide', 'add'); this.toggleClass(['input-field-options'], 'hide', 'add');
} }
} }
resetPositionalAttrModal() {
let originalSelectionList =
`
<option value="word" selected>word</option>
<option value="lemma" >lemma</option>
<option value="english-pos">english pos</option>
<option value="german-pos">german pos</option>
<option value="simple-pos">simple_pos</option>
<option value="empty-token">empty token</option>
`;
this.elements.positionalAttrSelection.innerHTML = originalSelectionList;
this.elements.tokenQuery.innerHTML = '';
this.toggleClass(['word', 'lemma', 'english-pos', 'german-pos', 'simple-pos'], 'hide', 'add');
this.toggleClass(['word', 'input-field-options'], 'hide', 'remove');
this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'add');
document.querySelector('#corpus-analysis-concordance-positional-attr-selection option[value="word"]').selected = true;
this.resetMaterializeSelection([this.elements.englishPosSelection, this.elements.germanPosSelection, this.elements.simplePosSelection]);
this.resetMaterializeSelection([this.elements.positionalAttrSelection], "word");
}
} }

View File

@ -1,10 +1,5 @@
Forms.CreateContributionForm = class CreateContributionForm extends Forms.BaseForm { Forms.CreateContributionForm = class CreateContributionForm extends Forms.BaseForm {
static autoInit() { static htmlClass = 'create-contribution-form';
let createContributionFormElements = document.querySelectorAll('.create-contribution-form');
for (let createContributionFormElement of createContributionFormElements) {
new Forms.CreateContributionForm(createContributionFormElement);
}
}
constructor(formElement) { constructor(formElement) {
super(formElement); super(formElement);

View File

@ -1,10 +1,5 @@
Forms.CreateCorpusFileForm = class CreateCorpusFileForm extends Forms.BaseForm { Forms.CreateCorpusFileForm = class CreateCorpusFileForm extends Forms.BaseForm {
static autoInit() { static htmlClass = 'create-corpus-file-form';
let createCorpusFileFormElements = document.querySelectorAll('.create-corpus-file-form');
for (let createCorpusFileFormElement of createCorpusFileFormElements) {
new Forms.CreateCorpusFileForm(createCorpusFileFormElement);
}
}
constructor(formElement) { constructor(formElement) {
super(formElement); super(formElement);

View File

@ -1,10 +1,5 @@
Forms.CreateJobForm = class CreateJobForm extends Forms.BaseForm { Forms.CreateJobForm = class CreateJobForm extends Forms.BaseForm {
static autoInit() { static htmlClass = 'create-job-form';
let createJobFormElements = document.querySelectorAll('.create-job-form');
for (let createJobFormElement of createJobFormElements) {
new Forms.CreateJobForm(createJobFormElement);
}
}
constructor(formElement) { constructor(formElement) {
super(formElement); super(formElement);

View File

@ -3,15 +3,22 @@ var Forms = {};
Forms.autoInit = () => { Forms.autoInit = () => {
for (let propertyName in Forms) { for (let propertyName in Forms) {
let property = Forms[propertyName]; let property = Forms[propertyName];
// Call the autoInit method of all properties that are subclasses of Forms.BaseForm // Call autoInit of all properties that are subclasses of Forms.BaseForm.
// This does not include Forms.BaseForm itself.
if (property.prototype instanceof Forms.BaseForm) { if (property.prototype instanceof Forms.BaseForm) {
property.autoInit(); // Check if the static htmlClass property is defined.
if (property.htmlClass === undefined) {return;}
// Gather all HTML elements that have the `this.htmlClass` class
// and do not have the no-autoinit class.
let formElements = document.querySelectorAll(`.${property.htmlClass}:not(.no-autoinit)`);
// Create an instance of this class for each form element.
for (let formElement of formElements) {new property(formElement);}
} }
} }
}; };
Forms.BaseForm = class BaseForm { Forms.BaseForm = class BaseForm {
static autoInit() {throw 'Not implemented';} static htmlClass;
constructor(formElement) { constructor(formElement) {
this.formElement = formElement; this.formElement = formElement;

View File

@ -1,4 +1,6 @@
ResourceDisplays.CorpusDisplay = class CorpusDisplay extends ResourceDisplays.BaseDisplay { ResourceDisplays.CorpusDisplay = class CorpusDisplay extends ResourceDisplays.BaseDisplay {
static htmlClass = 'corpus-display';
constructor(displayElement) { constructor(displayElement) {
super(displayElement); super(displayElement);
this.corpusId = displayElement.dataset.corpusId; this.corpusId = displayElement.dataset.corpusId;

View File

@ -1,6 +1,25 @@
var ResourceDisplays = {}; var ResourceDisplays = {};
ResourceDisplays.autoInit = () => {
for (let propertyName in ResourceDisplays) {
let property = ResourceDisplays[propertyName];
// Call autoInit of all properties that are subclasses of `ResourceDisplays.BaseDisplay`.
// This does not include `ResourceDisplays.BaseDisplay` itself.
if (property.prototype instanceof ResourceDisplays.BaseDisplay) {
// Check if the static `htmlClass` property is defined.
if (property.htmlClass === undefined) {return;}
// Gather all HTML elements that have the `this.htmlClass` class
// and do not have the `no-autoinit` class.
let displayElements = document.querySelectorAll(`.${property.htmlClass}:not(.no-autoinit)`);
// Create an instance of this class for each display element.
for (let displayElement of displayElements) {new property(displayElement);}
}
}
}
ResourceDisplays.BaseDisplay = class BaseDisplay { ResourceDisplays.BaseDisplay = class BaseDisplay {
static htmlClass;
constructor(displayElement) { constructor(displayElement) {
this.displayElement = displayElement; this.displayElement = displayElement;
this.userId = this.displayElement.dataset.userId; this.userId = this.displayElement.dataset.userId;

View File

@ -1,4 +1,6 @@
ResourceDisplays.JobDisplay = class JobDisplay extends ResourceDisplays.BaseDisplay { ResourceDisplays.JobDisplay = class JobDisplay extends ResourceDisplays.BaseDisplay {
static htmlClass = 'job-display';
constructor(displayElement) { constructor(displayElement) {
super(displayElement); super(displayElement);
this.jobId = this.displayElement.dataset.jobId; this.jobId = this.displayElement.dataset.jobId;

View File

@ -140,6 +140,7 @@
document.querySelectorAll('#nav-more-dropdown-trigger'), document.querySelectorAll('#nav-more-dropdown-trigger'),
{alignment: 'right', constrainWidth: false, coverTrigger: false} {alignment: 'right', constrainWidth: false, coverTrigger: false}
); );
ResourceDisplays.autoInit();
ResourceList.autoInit(); ResourceList.autoInit();
Forms.autoInit(); Forms.autoInit();

View File

@ -65,16 +65,16 @@
<br> <br>
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<a class="btn-small waves-effect waves-light" data-structural-attr-modal-action-button="sentence">sentence</a> <a class="btn-small waves-effect waves-light" data-structural-attr-modal-action-button="sentence" data-toggle-area="sentence-button">sentence</a>
<a class="btn-small waves-effect waves-light" data-structural-attr-modal-action-button="entity">entity</a> <a class="btn-small waves-effect waves-light" data-structural-attr-modal-action-button="entity" data-toggle-area="entity-button">entity</a>
<a class="btn-small waves-effect waves-light" data-structural-attr-modal-action-button="meta-data">Meta Data</a> <a class="btn-small waves-effect waves-light" data-structural-attr-modal-action-button="meta-data" data-toggle-area="text-annotation-button">Meta Data</a>
</div> </div>
</div> </div>
<div id="corpus-analysis-concordance-entity-builder" data-toggle-area="entity-builder" class="hide"> <div id="corpus-analysis-concordance-entity-builder" data-toggle-area="entity-builder" class="hide">
<p></p> <p></p>
<br> <br>
<div class="row"> <div class="row">
<a class="btn waves-effect waves-light col ent-type-selection-action" data-ent-type="any">Add Entity of any type</a> <a class="btn waves-effect waves-light col ent-type-selection-action" data-ent-type="any" data-toggle-area="any-type-entity-button">Add Entity of any type</a>
<p class="col s1 l1"></p> <p class="col s1 l1"></p>
<div class= "input-field col s3"> <div class= "input-field col s3">
<select id="corpus-analysis-concordance-english-ent-type-selection" name="englishenttype" class="ent-type-selection-action" data-ent-type="english"> <select id="corpus-analysis-concordance-english-ent-type-selection" name="englishenttype" class="ent-type-selection-action" data-ent-type="english">
@ -386,7 +386,6 @@
{{ exactly_nm_modal_content("character") }} {{ exactly_nm_modal_content("character") }}
</div> </div>
</div>
</div> </div>
{% endmacro %} {% endmacro %}

View File

@ -5,7 +5,7 @@
{% block page_content %} {% block page_content %}
<div class="container"> <div class="container">
<div class="row" data-corpus-id="{{ corpus.hashid }}" data-user-id="{{ corpus.user.hashid }}" id="corpus-display"> <div class="row corpus-display" data-corpus-id="{{ corpus.hashid }}" data-user-id="{{ corpus.user.hashid }}">
<div class="col s12"> <div class="col s12">
<h1>{{ corpus.title }}</h1> <h1>{{ corpus.title }}</h1>
</div> </div>
@ -237,8 +237,6 @@
{% block scripts %} {% block scripts %}
{{ super() }} {{ super() }}
<script> <script>
let corpusDisplay = new ResourceDisplays.CorpusDisplay(document.querySelector('#corpus-display'));
{# {% if current_user.is_following_corpus(corpus) %} {# {% if current_user.is_following_corpus(corpus) %}
let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]'); let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]');
unfollowRequestElement.addEventListener('click', () => { unfollowRequestElement.addEventListener('click', () => {

View File

@ -5,7 +5,7 @@
{% block page_content %} {% block page_content %}
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col s12" data-job-id="{{ job.hashid }}" data-user-id="{{ job.user.hashid }}" id="job-display"> <div class="col s12 job-display" data-job-id="{{ job.hashid }}" data-user-id="{{ job.user.hashid }}">
<div class="row"> <div class="row">
<div class="col s8 m9 l10"> <div class="col s8 m9 l10">
<h1 id="title"><i style="font-size: inherit;" class="nopaque-icons service-icons" data-service="{{ job.service }}"></i> <span class="job-title"></span></h1> <h1 id="title"><i style="font-size: inherit;" class="nopaque-icons service-icons" data-service="{{ job.service }}"></i> <span class="job-title"></span></h1>
@ -150,7 +150,6 @@
{% block scripts %} {% block scripts %}
{{ super() }} {{ super() }}
<script> <script>
let jobDisplay = new ResourceDisplays.JobDisplay(document.querySelector('#job-display'));
let deleteJobRequestElement = document.querySelector('#delete-job-request'); let deleteJobRequestElement = document.querySelector('#delete-job-request');
let restartJobRequestElement = document.querySelector('#restart-job-request'); let restartJobRequestElement = document.querySelector('#restart-job-request');
deleteJobRequestElement.addEventListener('click', (event) => { deleteJobRequestElement.addEventListener('click', (event) => {