Skip to content
Snippets Groups Projects
Commit 985e9b40 authored by Inga Kirschnick's avatar Inga Kirschnick
Browse files

Editing nested token queries and bug fixes

parent f4d3415c
No related branches found
No related tags found
No related merge requests found
...@@ -8,9 +8,6 @@ class ElementReferencesQueryBuilder { ...@@ -8,9 +8,6 @@ class ElementReferencesQueryBuilder {
// 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'));
this.sentenceElement = document.querySelector('[data-structural-attr-modal-action-button="sentence"]');
this.entityElement = document.querySelector('[data-structural-attr-modal-action-button="entity"]');
this.textAnnotationElement = document.querySelector('[data-structural-attr-modal-action-button="text-annotation"]');
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');
......
...@@ -56,7 +56,6 @@ class GeneralFunctionsQueryBuilder { ...@@ -56,7 +56,6 @@ class GeneralFunctionsQueryBuilder {
} }
} }
queryChipFactory(dataType, prettyQueryText, queryText, index = null, isClosingTag = false, isEditable = 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);
...@@ -118,6 +117,7 @@ class GeneralFunctionsQueryBuilder { ...@@ -118,6 +117,7 @@ class GeneralFunctionsQueryBuilder {
} }
editChipElement(queryChipElement) { editChipElement(queryChipElement) {
//TODO: Split this function into smaller functionss
this.elements.editingModusOn = true; this.elements.editingModusOn = true;
this.elements.editedQueryChipElementIndex = Array.from(this.elements.queryInputField.children).indexOf(queryChipElement); this.elements.editedQueryChipElementIndex = Array.from(this.elements.queryInputField.children).indexOf(queryChipElement);
switch (queryChipElement.dataset.type) { switch (queryChipElement.dataset.type) {
...@@ -141,54 +141,105 @@ class GeneralFunctionsQueryBuilder { ...@@ -141,54 +141,105 @@ class GeneralFunctionsQueryBuilder {
this.elements.textAnnotationInput.value = textAnnotationContent; this.elements.textAnnotationInput.value = textAnnotationContent;
break; break;
case 'token': case 'token':
let [tokenAttr, tokenValue] = queryChipElement.dataset.query.replace(/\[|\]|"/g, '').split('='); //This regex searches for word or lemma or pos or simple_pos="any string within single or double quotes" followed by one or no ignore case markers, followed by one or no condition characters.
if (tokenAttr === 'pos') { let regex = new RegExp('(word|lemma|pos|simple_pos)=(("[^"]+")|(\\\\u0027[^\\\\u0027]+\\\\u0027)) ?(%c)? ?(\\&|\\|)?', 'gm');
tokenAttr = this.elements.englishPosSelection.querySelector(`option[value=${tokenValue}]`) ? 'english-pos' : 'german-pos'; let m;
let queryElementsContent = [];
while ((m = regex.exec(queryChipElement.dataset.query)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
let tokenAttr = m[1];
// Passes english-pos by default so that the template is added. In editTokenChipElement it is then checked whether it is english-pos or german-pos.
if (tokenAttr === 'pos') {
tokenAttr = 'english-pos';
}
let tokenValue = m[2].replace(/"|'/g, '');
let ignoreCase = false;
let condition = undefined;
m.forEach((match) => {
if (match === "%c") {
ignoreCase = true;
} else if (match === "&") {
condition = "and";
} else if (match === "|") {
condition = "or";
}
});
queryElementsContent.push({tokenAttr: tokenAttr, tokenValue: tokenValue, ignoreCase: ignoreCase, condition: condition});
} }
this.editTokenChipElement(tokenAttr, tokenValue); this.editTokenChipElement(queryElementsContent);
break; break;
default: default:
break; break;
} }
} }
editTokenChipElement(tokenAttr, tokenValue) { editTokenChipElement(queryElementsContent) {
this.resetMaterializeSelection([this.elements.positionalAttrSelection], tokenAttr);
this.elements.positionalAttrModal.open(); this.elements.positionalAttrModal.open();
switch (tokenAttr) { queryElementsContent.forEach((queryElement) => {
case 'word': this.resetMaterializeSelection([this.elements.positionalAttrSelection], queryElement.tokenAttr);
this.elements.wordInput.value = tokenValue; this.preparePositionalAttrModal();
break; switch (queryElement.tokenAttr) {
case 'lemma': case 'word':
this.elements.lemmaInput.value = tokenValue; case 'lemma':
break; this.elements.tokenBuilderContent.querySelector('input').value = queryElement.tokenValue;
case 'english-pos': break;
this.resetMaterializeSelection([this.elements.englishPosSelection], tokenValue); case 'english-pos':
break; // English-pos is selected by default. Then it is checked whether the passed token value occurs in the english-pos selection. If not, the selection is reseted and changed to german-pos.
case 'german-pos': let selection = this.elements.tokenBuilderContent.querySelector('select');
this.resetMaterializeSelection([this.elements.germanPosSelection], tokenValue); queryElement.tokenAttr = selection.querySelector(`option[value=${queryElement.tokenValue}]`) ? 'english-pos' : 'german-pos';
break; this.resetMaterializeSelection([this.elements.positionalAttrSelection], queryElement.tokenAttr);
case 'simple-pos': this.preparePositionalAttrModal();
this.resetMaterializeSelection([this.elements.simplePosSelection], tokenValue); this.resetMaterializeSelection([this.elements.tokenBuilderContent.querySelector('select')], queryElement.tokenValue);
break; break;
default: case 'simple_pos':
break; this.resetMaterializeSelection([this.elements.tokenBuilderContent.querySelector('select')], queryElement.tokenValue);
} default:
break;
}
if (queryElement.ignoreCase) {
this.elements.ignoreCaseCheckbox.checked = true;
}
if (queryElement.condition !== undefined) {
this.conditionHandler(queryElement.condition, true);
}
});
} }
lockClosingChipElement(queryChipElement) { lockClosingChipElement(queryChipElement) {
let chipIndex = Array.from(this.elements.queryInputField.children).indexOf(queryChipElement); queryChipElement.dataset.closingTag = 'false';
this.submitQueryChipElement(queryChipElement.dataset.type, queryChipElement.firstChild.textContent, queryChipElement.dataset.query, chipIndex+1); let lockIcon = queryChipElement.querySelector('[data-chip-action="lock"]');
this.deleteChipElement(queryChipElement); lockIcon.textContent = 'lock';
this.updateChipList(); //TODO: Write unlock-Function?
} lockIcon.dataset.chipAction = 'unlock';
// let chipIndex = Array.from(this.elements.queryInputField.children).indexOf(queryChipElement);
// this.submitQueryChipElement(queryChipElement.dataset.type, queryChipElement.firstChild.textContent, queryChipElement.dataset.query, chipIndex+1);
// this.deleteChipElement(queryChipElement);
// this.updateChipList();
}
deleteChipElement(attr) { deleteChipElement(attr) {
if (attr.dataset.type === "start-sentence") { let elementIndex = Array.from(this.elements.queryInputField.children).indexOf(attr);
this.elements.sentenceElement.innerHTML = 'Sentence'; switch (attr.dataset.type) {
} else if (attr.dataset.type === "start-entity" || attr.dataset.type === "start-empty-entity") { case 'start-sentence':
this.elements.entityElement.innerHTML = 'Entity'; this.deletingClosingTagHandler(elementIndex, 'end-sentence');
break;
case 'start-entity':
this.deletingClosingTagHandler(elementIndex, 'end-entity');
break;
case 'token':
console.log(Array.from(this.elements.queryInputField.children)[elementIndex+1]);
let nextElement = Array.from(this.elements.queryInputField.children)[elementIndex+1];
if (nextElement.dataset.type === 'token-incidence-modifier') {
this.deleteChipElement(nextElement);
}
default:
break;
} }
this.elements.queryInputField.removeChild(attr); this.elements.queryInputField.removeChild(attr);
if (this.elements.queryInputField.children.length === 0) { if (this.elements.queryInputField.children.length === 0) {
...@@ -198,6 +249,18 @@ class GeneralFunctionsQueryBuilder { ...@@ -198,6 +249,18 @@ class GeneralFunctionsQueryBuilder {
this.queryPreviewBuilder(); this.queryPreviewBuilder();
} }
deletingClosingTagHandler(elementIndex, closingTagType) {
let closingTags = this.elements.queryInputField.querySelectorAll(`[data-type="${closingTagType}"]`);
for (let i = 0; i < closingTags.length; i++) {
let closingTag = closingTags[i];
if (Array.from(this.elements.queryInputField.children).indexOf(closingTag) > elementIndex) {
this.deleteChipElement(closingTag);
break;
}
}
}
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');
...@@ -325,7 +388,6 @@ class GeneralFunctionsQueryBuilder { ...@@ -325,7 +388,6 @@ class GeneralFunctionsQueryBuilder {
this.submitQueryChipElement(chipElement['type'], chipElement['pretty'], chipElement['query']); this.submitQueryChipElement(chipElement['type'], chipElement['pretty'], chipElement['query']);
} }
} }
parseTextToChip(query) { parseTextToChip(query) {
const parsingElementDict = { const parsingElementDict = {
......
...@@ -69,7 +69,7 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu ...@@ -69,7 +69,7 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
optionToggleHandler() { optionToggleHandler() {
let input = this.tokenInputCheck(this.elements.tokenBuilderContent); let input = this.tokenInputCheck(this.elements.tokenBuilderContent);
if ((input.value === '' || input.value === 'default') && this.elements.editingModusOn === false) { if (input.value === '' && this.elements.editingModusOn === false) {
this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'add'); this.toggleClass(['incidence-modifiers', 'or', 'and'], 'disabled', 'add');
} else if (this.elements.positionalAttrSelection.querySelectorAll('option').length === 1) { } else if (this.elements.positionalAttrSelection.querySelectorAll('option').length === 1) {
this.toggleClass(['and'], 'disabled', 'add'); this.toggleClass(['and'], 'disabled', 'add');
...@@ -95,7 +95,7 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu ...@@ -95,7 +95,7 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
let input; let input;
let kindOfToken = this.kindOfTokenCheck(this.elements.positionalAttrSelection.value); let kindOfToken = this.kindOfTokenCheck(this.elements.positionalAttrSelection.value);
// Takes all rows of the token query (if there is a query concatenation). // Takes all rows of the token query (if there is a query concatenation).
// Adds their contents to tokenQueryPrettyText and tokenQueryCQLText, which will later be expanded with the current input field. // Adds their contents to tokenQueryPrettyText and tokenQueryCQLText, which will later be expanded with the current input field.
let tokenQueryRows = this.elements.tokenQuery.querySelectorAll('.row'); let tokenQueryRows = this.elements.tokenQuery.querySelectorAll('.row');
tokenQueryRows.forEach(row => { tokenQueryRows.forEach(row => {
...@@ -108,7 +108,6 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu ...@@ -108,7 +108,6 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
tokenQueryPrettyText += `${tokenQueryKindOfToken}=${tokenQueryRowInput.value}${c} ${tokenConditionPrettyText} `; tokenQueryPrettyText += `${tokenQueryKindOfToken}=${tokenQueryRowInput.value}${c} ${tokenConditionPrettyText} `;
tokenQueryCQLText += `${tokenQueryKindOfToken}="${tokenQueryRowInput.value}"${c} ${tokenConditionCQLText}`; tokenQueryCQLText += `${tokenQueryKindOfToken}="${tokenQueryRowInput.value}"${c} ${tokenConditionCQLText}`;
}); });
if (kindOfToken === 'empty-token') { if (kindOfToken === 'empty-token') {
tokenQueryPrettyText += 'empty token'; tokenQueryPrettyText += 'empty token';
} else { } else {
...@@ -117,21 +116,19 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu ...@@ -117,21 +116,19 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
tokenQueryPrettyText += `${kindOfToken}=${input.value}${c}`; tokenQueryPrettyText += `${kindOfToken}=${input.value}${c}`;
tokenQueryCQLText += `${kindOfToken}="${input.value}"${c}`; tokenQueryCQLText += `${kindOfToken}="${input.value}"${c}`;
} }
// 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 ((input.value === '' || input.value === 'default') && this.elements.positionalAttrSelection.value !== 'empty-token') { if (this.elements.positionalAttrSelection.value !== 'empty-token' && input.value === '') {
this.disableTokenSubmit(); this.disableTokenSubmit();
} else { } else {
tokenQueryCQLText = `[${tokenQueryCQLText}]`; tokenQueryCQLText = `[${tokenQueryCQLText}]`;
this.submitQueryChipElement('token', tokenQueryPrettyText, tokenQueryCQLText, null, false, true); this.submitQueryChipElement('token', tokenQueryPrettyText, tokenQueryCQLText, null, false, kindOfToken === 'empty-token' ? false : true);
this.elements.positionalAttrModal.close(); this.elements.positionalAttrModal.close();
} }
} }
kindOfTokenCheck(kindOfToken) { kindOfTokenCheck(kindOfToken) {
return kindOfToken === 'english-pos' || kindOfToken === 'german-pos' ? 'pos' : kindOfToken; return kindOfToken === 'english-pos' || kindOfToken === 'german-pos' ? 'pos' : kindOfToken;
} }
actionButtonInOptionSectionHandler(elem) { actionButtonInOptionSectionHandler(elem) {
let input = this.tokenInputCheck(this.elements.tokenBuilderContent); let input = this.tokenInputCheck(this.elements.tokenBuilderContent);
...@@ -176,7 +173,7 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu ...@@ -176,7 +173,7 @@ class TokenAttributeBuilderFunctionsQueryBuilder extends GeneralFunctionsQueryBu
tokenInput.value += '{' + input + '}'; tokenInput.value += '{' + input + '}';
} }
conditionHandler(conditionText) { conditionHandler(conditionText, editMode = false) {
let tokenQueryTemplateClone = this.elements.tokenQueryTemplate.content.cloneNode(true); let tokenQueryTemplateClone = this.elements.tokenQueryTemplate.content.cloneNode(true);
tokenQueryTemplateClone.querySelector('.token-query-template-content').appendChild(this.elements.tokenBuilderContent.firstElementChild); tokenQueryTemplateClone.querySelector('.token-query-template-content').appendChild(this.elements.tokenBuilderContent.firstElementChild);
let notSelectedButton = tokenQueryTemplateClone.querySelector(`[data-condition-pretty-text]:not([data-condition-pretty-text="${conditionText}"])`); let notSelectedButton = tokenQueryTemplateClone.querySelector(`[data-condition-pretty-text]:not([data-condition-pretty-text="${conditionText}"])`);
......
...@@ -173,8 +173,8 @@ ...@@ -173,8 +173,8 @@
<div class="row"> <div class="row">
<div class="token-query-template-content"></div> <div class="token-query-template-content"></div>
<div class="col s4" style="margin-top:15px;"> <div class="col s4" style="margin-top:15px;">
<a class="btn-small waves-effect waves-light disabled" data-condition-pretty-text="or" data-condition-cql-text=" | ">or</a> <a class="btn-small waves-effect waves-light disabled" data-condition-pretty-text="or" data-condition-cql-text="| ">or</a>
<a class="btn-small waves-effect waves-light disabled" data-condition-pretty-text="and" data-condition-cql-text=" & ">and</a> <a class="btn-small waves-effect waves-light disabled" data-condition-pretty-text="and" data-condition-cql-text="& ">and</a>
<a class="btn-floating waves-effect waves-light red" data-token-query-content-action="delete" style="margin-left:8px;"><i class="material-icons right">delete</i></a> <a class="btn-floating waves-effect waves-light red" data-token-query-content-action="delete" style="margin-left:8px;"><i class="material-icons right">delete</i></a>
</div> </div>
</div> </div>
...@@ -208,7 +208,7 @@ ...@@ -208,7 +208,7 @@
<template class="token-builder-section" data-token-builder-section="english-pos"> <template class="token-builder-section" data-token-builder-section="english-pos">
<div class= "input-field col s4" data-kind-of-token="english-pos"> <div class= "input-field col s4" data-kind-of-token="english-pos">
<select name="englishpos"> <select name="englishpos">
<option value="default" disabled selected>English pos tagset</option> <option value="" disabled selected>English pos tagset</option>
<option value="ADD">email</option> <option value="ADD">email</option>
<option value="AFX">affix</option> <option value="AFX">affix</option>
<option value="CC">conjunction, coordinating</option> <option value="CC">conjunction, coordinating</option>
...@@ -264,7 +264,7 @@ ...@@ -264,7 +264,7 @@
<template class="token-builder-section" data-token-builder-section="german-pos"> <template class="token-builder-section" data-token-builder-section="german-pos">
<div class= "input-field col s4" data-kind-of-token="german-pos"> <div class= "input-field col s4" data-kind-of-token="german-pos">
<select name="germanpos"> <select name="germanpos">
<option value="default" disabled selected>German pos tagset</option> <option value="" disabled selected>German pos tagset</option>
<option value="ADJA">adjective, attributive</option> <option value="ADJA">adjective, attributive</option>
<option value="ADJD">adjective, adverbial or predicative</option> <option value="ADJD">adjective, adverbial or predicative</option>
<option value="ADV">adverb</option> <option value="ADV">adverb</option>
...@@ -327,7 +327,7 @@ ...@@ -327,7 +327,7 @@
<template class="token-builder-section" data-token-builder-section="simple_pos"> <template class="token-builder-section" data-token-builder-section="simple_pos">
<div class= "input-field col s4" data-kind-of-token="simple_pos"> <div class= "input-field col s4" data-kind-of-token="simple_pos">
<select name="simplepos"> <select name="simplepos">
<option value="default" disabled selected>simple_pos tagset</option> <option value="" disabled selected>simple_pos tagset</option>
<option value="ADJ">adjective</option> <option value="ADJ">adjective</option>
<option value="ADP">adposition</option> <option value="ADP">adposition</option>
<option value="ADV">adverb</option> <option value="ADV">adverb</option>
...@@ -367,7 +367,7 @@ ...@@ -367,7 +367,7 @@
</div> </div>
<p></p> <p></p>
<div class="row"> <div class="row">
<div class="col s8" > <div class="col s12" >
<a class="btn-small waves-effect waves-light tooltipped positional-attr-options-action-button" data-options-action="wildcard-char" data-position="top" data-tooltip="Look for a variable character (also called wildcard character)">Wildcard character</a> <a class="btn-small waves-effect waves-light tooltipped positional-attr-options-action-button" data-options-action="wildcard-char" data-position="top" data-tooltip="Look for a variable character (also called wildcard character)">Wildcard character</a>
<a class="btn-small waves-effect waves-light tooltipped positional-attr-options-action-button" data-options-action="option-group" data-position="top" data-tooltip="Find character sequences from a list of options">Option Group</a> <a class="btn-small waves-effect waves-light tooltipped positional-attr-options-action-button" data-options-action="option-group" data-position="top" data-tooltip="Find character sequences from a list of options">Option Group</a>
<a class="dropdown-trigger btn-small waves-effect waves-light disabled" href="#" data-target="corpus-analysis-concordance-character-incidence-modifiers-dropdown" data-toggle-area="incidence-modifiers" data-position="top" data-tooltip="Incidence Modifiers are special characters or patterns, <br>which determine how often a character represented previously should occur.">incidence modifiers</a> <a class="dropdown-trigger btn-small waves-effect waves-light disabled" href="#" data-target="corpus-analysis-concordance-character-incidence-modifiers-dropdown" data-toggle-area="incidence-modifiers" data-position="top" data-tooltip="Incidence Modifiers are special characters or patterns, <br>which determine how often a character represented previously should occur.">incidence modifiers</a>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment