mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 12:22:47 +00:00 
			
		
		
		
	Query Builder implementation
This commit is contained in:
		@@ -12,6 +12,7 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
      concordanceQueryBuilderButton: document.querySelector('#concordance-query-builder-button'),
 | 
			
		||||
      closeQueryBuilder: document.querySelector('#close-query-builder'),
 | 
			
		||||
      queryBuilderTutorialModal: document.querySelector('#query-builder-tutorial-modal'),
 | 
			
		||||
      valueValidator: true,
 | 
			
		||||
 | 
			
		||||
      //#region QueryBuilder Elements
 | 
			
		||||
      
 | 
			
		||||
@@ -206,7 +207,6 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  buttonfactory(dataType, prettyText, queryText) {
 | 
			
		||||
 | 
			
		||||
    window.location.href = '#query-container';
 | 
			
		||||
    this.elements.counter += 1;
 | 
			
		||||
    queryText = encodeURI(queryText);
 | 
			
		||||
@@ -226,7 +226,6 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
    } else if (this.elements.yourQuery.lastChild.dataset.type === 'text-annotation') {
 | 
			
		||||
      this.elements.yourQuery.insertBefore(buttonElement, this.elements.yourQuery.lastChild);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.elements.queryContainer.classList.remove('hide');
 | 
			
		||||
    this.queryPreviewBuilder();
 | 
			
		||||
 | 
			
		||||
@@ -252,25 +251,30 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
 | 
			
		||||
    //#region	 Drag&Drop Events
 | 
			
		||||
  dragStartHandler(event) {
 | 
			
		||||
    // Creates element with the class 'target' and all necessary drop functions, in which drop content can be released
 | 
			
		||||
    this.elements.dropButton = event.target;
 | 
			
		||||
    let targetChip = `
 | 
			
		||||
      <div class='chip target' ondragover='concordanceQueryBuilder.dragOverHandler(event)' ondragenter='concordanceQueryBuilder.dragEnterHandler(event)' ondragleave='concordanceQueryBuilder.dragLeaveHandler(event)' ondrop='concordanceQueryBuilder.dropHandler(event)'>
 | 
			
		||||
        Drop here
 | 
			
		||||
      </div>
 | 
			
		||||
    `.trim();
 | 
			
		||||
    // selects all nodes without target class
 | 
			
		||||
    let childNodes = this.elements.yourQuery.querySelectorAll('div:not(.target)');
 | 
			
		||||
 | 
			
		||||
    // Adds a target chip in front of all draggable childnodes
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      for (let element of childNodes) {
 | 
			
		||||
        if (element === event.target) {
 | 
			
		||||
          continue;
 | 
			
		||||
        } else if (element === event.target.nextSibling) {
 | 
			
		||||
        if (element === this.elements.dropButton) {
 | 
			
		||||
          // If the dragged element is not at the very end, a target chip is also inserted at the end
 | 
			
		||||
          if (childNodes[childNodes.length - 1] !== element) {
 | 
			
		||||
            childNodes[childNodes.length - 1].insertAdjacentHTML('afterend', targetChip);
 | 
			
		||||
          }
 | 
			
		||||
        } else if (element === this.elements.dropButton.nextSibling) {
 | 
			
		||||
          continue;
 | 
			
		||||
        } else {
 | 
			
		||||
          element.insertAdjacentHTML('beforebegin', targetChip)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      childNodes[childNodes.length-1].insertAdjacentHTML('afterend', targetChip);
 | 
			
		||||
    },0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -297,18 +301,6 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
 | 
			
		||||
  dropHandler(event) {
 | 
			
		||||
    let dropzone = event.target;
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < dropzone.parentElement.childNodes.length; i++) {
 | 
			
		||||
      if (dropzone === dropzone.parentElement.childNodes[i]) {
 | 
			
		||||
        nodeIndex = i;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    for (let i = 0; i < dropzone.parentElement.childNodes.length; i++) {
 | 
			
		||||
      if (this.elements.dropButton === dropzone.parentElement.childNodes[i]) {
 | 
			
		||||
        draggedElementIndex = i;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dropzone.parentElement.replaceChild(this.elements.dropButton, dropzone);
 | 
			
		||||
    this.queryPreviewBuilder();
 | 
			
		||||
  }
 | 
			
		||||
@@ -316,7 +308,6 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
 | 
			
		||||
  queryPreviewBuilder() {
 | 
			
		||||
    this.elements.yourQueryContent = [];
 | 
			
		||||
 | 
			
		||||
    for (let element of this.elements.yourQuery.childNodes) {
 | 
			
		||||
      let queryElement = decodeURI(element.dataset.query);
 | 
			
		||||
      if (queryElement.includes('<')) {
 | 
			
		||||
@@ -349,19 +340,48 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
 | 
			
		||||
  insertQuery() {
 | 
			
		||||
    this.elements.yourQueryContent = [];
 | 
			
		||||
    this.validateValue();
 | 
			
		||||
    if (this.elements.valueValidator === true) {
 | 
			
		||||
      for (let element of this.elements.yourQuery.childNodes) {
 | 
			
		||||
        let queryElement = decodeURI(element.dataset.query);
 | 
			
		||||
        if (queryElement !== 'undefined') {
 | 
			
		||||
          this.elements.yourQueryContent.push(queryElement);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      let queryString = this.elements.yourQueryContent.join(' ');
 | 
			
		||||
      queryString += ';';
 | 
			
		||||
 | 
			
		||||
      this.elements.concordanceQueryBuilder.classList.add('modal-close');
 | 
			
		||||
      this.elements.extFormQuery.value = queryString;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  validateValue() {
 | 
			
		||||
    this.elements.valueValidator = true;
 | 
			
		||||
    let sentenceCounter = 0;
 | 
			
		||||
    let sentenceEndCounter = 0;
 | 
			
		||||
    let entityCounter = 0;
 | 
			
		||||
    let entityEndCounter = 0;
 | 
			
		||||
    for (let element of this.elements.yourQuery.childNodes) {
 | 
			
		||||
      let queryElement = decodeURI(element.dataset.query);
 | 
			
		||||
      if (queryElement !== 'undefined') {
 | 
			
		||||
        this.elements.yourQueryContent.push(queryElement);
 | 
			
		||||
      if (element.dataset.type === 'start-sentence') {
 | 
			
		||||
        sentenceCounter += 1;
 | 
			
		||||
      }else if (element.dataset.type === 'end-sentence') {
 | 
			
		||||
        sentenceEndCounter += 1;
 | 
			
		||||
      }else if (element.dataset.type === 'start-entity' || element.dataset.type === 'start-empty-entity') {
 | 
			
		||||
        entityCounter += 1;
 | 
			
		||||
      }else if (element.dataset.type === 'end-entity') {
 | 
			
		||||
        entityEndCounter += 1;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let queryString = this.elements.yourQueryContent.join(' ');
 | 
			
		||||
    queryString += ';';
 | 
			
		||||
 | 
			
		||||
    this.elements.concordanceQueryBuilder.classList.add('modal-close');
 | 
			
		||||
    this.elements.extFormQuery.value = queryString;
 | 
			
		||||
    if (sentenceCounter !== sentenceEndCounter) {
 | 
			
		||||
      app.flash('Please add a closing sentence tag', 'error');
 | 
			
		||||
      this.elements.valueValidator = false;
 | 
			
		||||
    }
 | 
			
		||||
    if (entityCounter !== entityEndCounter) {
 | 
			
		||||
      app.flash('Please add a closing entity tag', 'error');
 | 
			
		||||
      this.elements.valueValidator = false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  clearAll() {
 | 
			
		||||
@@ -506,7 +526,7 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
            this.disableTokenSubmit();
 | 
			
		||||
          } else {
 | 
			
		||||
            tokenQueryContent += `word=${this.elements.wordInput.value}${c}`;
 | 
			
		||||
            tokenQueryText += `word='${this.elements.wordInput.value}'${c}`;
 | 
			
		||||
            tokenQueryText += `word="${this.elements.wordInput.value}"${c}`;
 | 
			
		||||
            this.elements.wordInput.value = '';
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
@@ -515,7 +535,7 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
            this.disableTokenSubmit();
 | 
			
		||||
          } else {
 | 
			
		||||
            tokenQueryContent += `lemma=${this.elements.lemmaInput.value}${c}`;
 | 
			
		||||
            tokenQueryText += `lemma='${this.elements.lemmaInput.value}'${c}`;
 | 
			
		||||
            tokenQueryText += `lemma="${this.elements.lemmaInput.value}"${c}`;
 | 
			
		||||
            this.elements.lemmaInput.value = '';
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
@@ -524,7 +544,7 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
            this.disableTokenSubmit();
 | 
			
		||||
          } else {
 | 
			
		||||
            tokenQueryContent += `pos=${this.elements.englishPos.value}`;
 | 
			
		||||
            tokenQueryText += `pos='${this.elements.englishPos.value}'`;
 | 
			
		||||
            tokenQueryText += `pos="${this.elements.englishPos.value}"`;
 | 
			
		||||
            this.elements.englishPos.value = '';
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
@@ -533,7 +553,7 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
            this.disableTokenSubmit();
 | 
			
		||||
          } else {
 | 
			
		||||
            tokenQueryContent += `pos=${this.elements.germanPos.value}`;
 | 
			
		||||
            tokenQueryText += `pos='${this.elements.germanPos.value}'`;
 | 
			
		||||
            tokenQueryText += `pos="${this.elements.germanPos.value}"`;
 | 
			
		||||
            this.elements.germanPos.value = '';
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
@@ -542,7 +562,7 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
            this.disableTokenSubmit();
 | 
			
		||||
          } else {
 | 
			
		||||
            tokenQueryContent += `simple_pos=${this.elements.simplePos.value}`;
 | 
			
		||||
            tokenQueryText += `simple_pos='${this.elements.simplePos.value}'`;
 | 
			
		||||
            tokenQueryText += `simple_pos="${this.elements.simplePos.value}"`;
 | 
			
		||||
            this.elements.simplePos.value = '';
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
@@ -557,7 +577,7 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
      // Square brackets are added only if it is not an empty token (where they are already present).
 | 
			
		||||
      if (emptyTokenCheck === false) {
 | 
			
		||||
        tokenQueryText = '[' + tokenQueryText + ']';
 | 
			
		||||
      }
 | 
			
		||||
        }
 | 
			
		||||
      this.buttonfactory('token', tokenQueryContent, tokenQueryText);
 | 
			
		||||
      this.hideEverything();
 | 
			
		||||
      this.elements.positionalAttrArea.classList.add('hide');
 | 
			
		||||
@@ -686,21 +706,21 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
        break;
 | 
			
		||||
      case 'english-pos':
 | 
			
		||||
        this.elements.tokenQueryFilled = true;
 | 
			
		||||
        this.tokenButtonfactory(`pos=${this.elements.englishPos.value}`, `pos='${this.elements.englishPos.value}'`);
 | 
			
		||||
        this.tokenButtonfactory(`pos=${this.elements.englishPos.value}`, `pos="${this.elements.englishPos.value}"`);
 | 
			
		||||
        this.tokenButtonfactory('{' + this.elements.nInput.value + '}', '{' + this.elements.nInput.value + '}');
 | 
			
		||||
        this.elements.englishPosBuilder.classList.add('hide');
 | 
			
		||||
        this.elements.incidenceModifiersButton.classList.add('hide');
 | 
			
		||||
        break;
 | 
			
		||||
      case 'german-pos':
 | 
			
		||||
        this.elements.tokenQueryFilled = true;
 | 
			
		||||
        this.tokenButtonfactory(`pos=${this.elements.germanPos.value}`, `pos='${this.elements.germanPos.value}'`);
 | 
			
		||||
        this.tokenButtonfactory(`pos=${this.elements.germanPos.value}`, `pos="${this.elements.germanPos.value}"`);
 | 
			
		||||
        this.tokenButtonfactory('{' + this.elements.nInput.value + '}', '{' + this.elements.nInput.value + '}');
 | 
			
		||||
        this.elements.germanPosBuilder.classList.add('hide');
 | 
			
		||||
        this.elements.incidenceModifiersButton.classList.add('hide');
 | 
			
		||||
        break;
 | 
			
		||||
      case 'simple-pos-button':
 | 
			
		||||
        this.elements.tokenQueryFilled = true;
 | 
			
		||||
        this.tokenButtonfactory(`simple_pos=${this.elements.simplePos.value}`, `simple_pos='${this.elements.simplePos.value}'`);
 | 
			
		||||
        this.tokenButtonfactory(`simple_pos=${this.elements.simplePos.value}`, `simple_pos="${this.elements.simplePos.value}"`);
 | 
			
		||||
        this.tokenButtonfactory('{' + this.elements.nInput.value + '}', '{' + this.elements.nInput.value + '}');
 | 
			
		||||
        this.elements.simplePosBuilder.classList.add('hide');
 | 
			
		||||
        this.elements.incidenceModifiersButton.classList.add('hide');
 | 
			
		||||
@@ -727,21 +747,21 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
        break;
 | 
			
		||||
      case 'english-pos':
 | 
			
		||||
        this.elements.tokenQueryFilled = true;
 | 
			
		||||
        this.tokenButtonfactory(`pos=${this.elements.englishPos.value}`, `pos='${this.elements.englishPos.value}'`);
 | 
			
		||||
        this.tokenButtonfactory(`pos=${this.elements.englishPos.value}`, `pos="${this.elements.englishPos.value}"`);
 | 
			
		||||
        this.tokenButtonfactory(`{${this.elements.nmInput.value}, ${this.elements.mInput.value}}`, `{${this.elements.nmInput.value}, ${this.elements.mInput.value}}`);
 | 
			
		||||
        this.elements.englishPosBuilder.classList.add('hide');
 | 
			
		||||
        this.elements.incidenceModifiersButton.classList.add('hide');
 | 
			
		||||
        break;
 | 
			
		||||
      case 'german-pos':
 | 
			
		||||
        this.elements.tokenQueryFilled = true;
 | 
			
		||||
        this.tokenButtonfactory(`pos=${this.elements.germanPos.value}`, `pos='${this.elements.germanPos.value}'`);
 | 
			
		||||
        this.tokenButtonfactory(`pos=${this.elements.germanPos.value}`, `pos="${this.elements.germanPos.value}"`);
 | 
			
		||||
        this.tokenButtonfactory(`{${this.elements.nmInput.value}, ${this.elements.mInput.value}}`, `{${this.elements.nmInput.value}, ${this.elements.mInput.value}}`);
 | 
			
		||||
        this.elements.germanPosBuilder.classList.add('hide');
 | 
			
		||||
        this.elements.incidenceModifiersButton.classList.add('hide');
 | 
			
		||||
        break;
 | 
			
		||||
      case 'simple-pos-button':
 | 
			
		||||
        this.elements.tokenQueryFilled = true;
 | 
			
		||||
        this.tokenButtonfactory(`simple_pos=${this.elements.simplePos.value}`, `simple_pos='${this.elements.simplePos.value}'`);
 | 
			
		||||
        this.tokenButtonfactory(`simple_pos=${this.elements.simplePos.value}`, `simple_pos="${this.elements.simplePos.value}"`);
 | 
			
		||||
        this.tokenButtonfactory(`{${this.elements.nmInput.value}, ${this.elements.mInput.value}}`, `{${this.elements.nmInput.value}, ${this.elements.mInput.value}}`);
 | 
			
		||||
        this.elements.simplePosBuilder.classList.add('hide');
 | 
			
		||||
        this.elements.incidenceModifiersButton.classList.add('hide');
 | 
			
		||||
@@ -759,19 +779,19 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
    if (this.elements.positionalAttr.value === 'empty-token') {
 | 
			
		||||
      this.tokenButtonfactory(elem.innerText, elem.dataset.token);
 | 
			
		||||
    } else if (this.elements.positionalAttr.value === 'english-pos') {
 | 
			
		||||
      this.tokenButtonfactory(`pos=${this.elements.englishPos.value}`, `pos='${this.elements.englishPos.value}'`);
 | 
			
		||||
      this.tokenButtonfactory(`pos=${this.elements.englishPos.value}`, `pos="${this.elements.englishPos.value}"`);
 | 
			
		||||
      this.tokenButtonfactory(elem.innerText, elem.dataset.token);
 | 
			
		||||
      this.elements.englishPosBuilder.classList.add('hide');
 | 
			
		||||
      this.elements.incidenceModifiersButton.classList.add('hide');
 | 
			
		||||
      this.elements.tokenQueryFilled = true;
 | 
			
		||||
    } else if (this.elements.positionalAttr.value === 'german-pos') {
 | 
			
		||||
      this.tokenButtonfactory(`pos=${this.elements.germanPos.value}`, `pos='${this.elements.germanPos.value}'`);
 | 
			
		||||
      this.tokenButtonfactory(`pos=${this.elements.germanPos.value}`, `pos="${this.elements.germanPos.value}"`);
 | 
			
		||||
      this.tokenButtonfactory(elem.innerText, elem.dataset.token);
 | 
			
		||||
      this.elements.germanPosBuilder.classList.add('hide');
 | 
			
		||||
      this.elements.incidenceModifiersButton.classList.add('hide');
 | 
			
		||||
      this.elements.tokenQueryFilled = true;
 | 
			
		||||
    } else if (this.elements.positionalAttr.value === 'simple-pos-button') {
 | 
			
		||||
      this.tokenButtonfactory(`simple_pos=${this.elements.simplePos.value}`, `simple_pos='${this.elements.simplePos.value}'`);
 | 
			
		||||
      this.tokenButtonfactory(`simple_pos=${this.elements.simplePos.value}`, `simple_pos="${this.elements.simplePos.value}"`);
 | 
			
		||||
      this.tokenButtonfactory(elem.innerText, elem.dataset.token);
 | 
			
		||||
      this.elements.simplePosBuilder.classList.add('hide');
 | 
			
		||||
      this.elements.incidenceModifiersButton.classList.add('hide');
 | 
			
		||||
@@ -813,27 +833,27 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
    switch (this.elements.positionalAttr.value) {
 | 
			
		||||
      case 'word':
 | 
			
		||||
        tokenQueryContent = `word=${this.elements.wordInput.value}${c}`;
 | 
			
		||||
        tokenQueryText = `word='${this.elements.wordInput.value}'${c}`;
 | 
			
		||||
        tokenQueryText = `word="${this.elements.wordInput.value}"${c}`;
 | 
			
		||||
        this.elements.wordInput.value = '';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'lemma':
 | 
			
		||||
        tokenQueryContent = `lemma=${this.elements.lemmaInput.value}${c}`;
 | 
			
		||||
        tokenQueryText = `word='${this.elements.lemmaInput.value}'${c}`;
 | 
			
		||||
        tokenQueryText = `lemma="${this.elements.lemmaInput.value}"${c}`;
 | 
			
		||||
        this.elements.lemmaInput.value = '';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'english-pos':
 | 
			
		||||
        tokenQueryContent = `pos=${this.elements.englishPos.value}`;
 | 
			
		||||
        tokenQueryText = `pos='${this.elements.englishPos.value}'`;
 | 
			
		||||
        tokenQueryText = `pos="${this.elements.englishPos.value}"`;
 | 
			
		||||
        this.elements.englishPos.value = '';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'german-pos':
 | 
			
		||||
        tokenQueryContent = `pos=${this.elements.germanPos.value}`;
 | 
			
		||||
        tokenQueryText = `pos='${this.elements.germanPos.value}'`;
 | 
			
		||||
        tokenQueryText = `pos="${this.elements.germanPos.value}"`;
 | 
			
		||||
        this.elements.germanPos.value = '';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'simple-pos-button':
 | 
			
		||||
        tokenQueryContent = `simple_pos=${this.elements.simplePos.value}`;
 | 
			
		||||
        tokenQueryText = `simple_pos='${this.elements.simplePos.value}'`;
 | 
			
		||||
        tokenQueryText = `simple_pos="${this.elements.simplePos.value}"`;
 | 
			
		||||
        this.elements.simplePos.value = '';
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
@@ -888,7 +908,7 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  englishEntTypeHandler() {
 | 
			
		||||
    this.buttonfactory('start-entity', 'Entity Type=' + this.elements.englishEntType.value, '<ent_type="" + this.elements.englishEntType.value + "">');
 | 
			
		||||
    this.buttonfactory('start-entity', 'Entity Type=' + this.elements.englishEntType.value, '<ent_type="' + this.elements.englishEntType.value + '">');
 | 
			
		||||
    this.elements.entity.innerHTML = 'End Entity';
 | 
			
		||||
    this.hideEverything();
 | 
			
		||||
    this.elements.entityAnyType = false;
 | 
			
		||||
@@ -900,7 +920,7 @@ class ConcordanceQueryBuilder {
 | 
			
		||||
  }   
 | 
			
		||||
 | 
			
		||||
  germanEntTypeHandler() {
 | 
			
		||||
    this.buttonfactory('start-entity', 'Entity Type=' + this.elements.germanEntType.value, '<ent_type="" + this.elements.germanEntType.value + "">');
 | 
			
		||||
    this.buttonfactory('start-entity', 'Entity Type=' + this.elements.germanEntType.value, '<ent_type="' + this.elements.germanEntType.value + '">');
 | 
			
		||||
    this.elements.entity.innerHTML = 'End Entity';
 | 
			
		||||
    this.hideEverything();
 | 
			
		||||
    this.elements.entityAnyType = false;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user