recogito_integration-1.0.x-dev/js/admin.injector.js

js/admin.injector.js
let imageAnnotations = {};
let textAnnotations = {};
let $ = jQuery;

/**
 * Converts a hexadecimal color code into the corresponding RGBA string.
 * Credit:  https://stackoverflow.com/a/21648508
 *
 * @param {string} hex the hex color code
 * @returns the RGBA representation of hex
 */
function hexToRgbA(hex, transparency = 1) {
  let c;
  transparency === null ? 0 : transparency;
  if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)){
      c= hex.substring(1).split('');
      if(c.length== 3){
          c= [c[0], c[0], c[1], c[1], c[2], c[2]];
      }
      c= '0x'+c.join('');
      return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+`,${transparency})`;
  }
  throw new Error('Bad Hex');
}

$(document).ready(function() {
  let perms = drupalSettings.recogito_integration.permissions;
  let isAdmin = drupalSettings.recogito_integration.admin;
  if (!isAdmin) {
    return;
  }
  if (perms['view']) {
    initAnnotations(drupalSettings.recogito_integration);
  }
});

/**
 * Initialize the annotation for the entire page.
 *
 * @param {object} settings
 */
function initAnnotations(settings) {
  let customDOM = settings.custom_elements;
  let annotatables = settings.annotatable_fields;
  for (let field in annotatables) {
    settings.current_target = field;
    $(`[annotatable-field-id="${field}"]`).each(function() {
      switch ($(this).attr('annotatable-type')) {
        case 'field':
          attachAnnotations($(this), settings);
          break;

        case 'view_field':
          attachAnnotations($(this), settings);
          break;
      }
    });
  }
  for (let element of customDOM) {
    settings.current_target = element;
    $(`${element}`).each(function() {
      initComponents($(this), settings);
    });
  }
  getAnnotations(settings);
}

/**
 * Attaches annotations to jQuery Objects.
 *
 * @param {object} domObj
 * @param {object} settings
 */
function attachAnnotations(domObj, settings) {
  if (!domObj.is(':visible')) {
    return;
  }
  if (domObj.hasClass('field__item') || domObj.hasClass('field__items')) {
    initComponents(domObj, settings);
  }
  else if (domObj.find('.field__items').length > 0) {
    initComponents(domObj.find('.field__items').first(), settings);
  }
  else if (domObj.find('.field__item').length == 1) {
    initComponents(domObj.find('.field__item').first(), settings);
  }
  else {
    initComponents(domObj, settings);
  }
}

/**
 * Initialize a jQuery object with annotations based on content.
 * Image and Text annotations are handled separately.
 *
 * @param {object} domObj
 * @param {object} settings
 */
function initComponents(domObj, settings) {
  let img = $(domObj).find('img');
  if (img.length > 0) {
    img.each(function() {
      initAnnotorious($(this), settings);
    });
  }
  initRecogito(domObj, settings);
  attachTagsEvent(domObj, settings.tagOptions);
}

/**
 * Initialize Recogito for the particular jQuery object.
 *
 * @param {object} domObj
 * @param {object} settings
 */
function initRecogito(domObj, settings) {
  let userData = settings.userData;
  let tagList = settings.tagOptions.tagList;
  let tagStyleList = settings.tagOptions.tagStyleList;
  let tagSelector = settings.tagOptions.selector;
  let tagTextEntry = settings.tagOptions.textInput;
  let perms = settings.permissions;
  let target = settings.current_target;
  domObj.css({
    'background-color': '#dfeaff',
  });
  let txtAnnotation = Recogito.init({
    content: domObj[0],
    locale: 'auto',
    widgets: [
      'COMMENT',
      {widget: 'TAG',
      vocabulary: tagList,
      textPlaceHolder: 'Add tags by typing here and pressing Enter...'}
    ],
    readOnly: !perms['create'],
    allowEmpty: false,
  });
  txtAnnotation.setAuthInfo(userData);
  txtAnnotation.target = target;
  if (!textAnnotations[txtAnnotation.target]) {
    textAnnotations[txtAnnotation.target] = [];
  }
  textAnnotations[txtAnnotation.target].push(txtAnnotation);

  txtAnnotation.on('selectAnnotation', function(annotation) {
    clearSelected();
    let editable = perms['edit'] || (perms['edit-own'] && userData['id'] === annotation.body[0].creator.id);
    if (!editable) {
      setTimeout(() => readOnlyText(), 2);
      return;
    }
    setTimeout(() => {
      updateMenuByPermissions(settings, annotation);
      if (!tagTextEntry) {
        hideTagInput();
      }
      if (tagSelector) {
        attachTagSelector(tagStyleList);
      }
      attachTagList(settings.tagOptions);
      attachWrapperOk('Update');
    }, 2);
  });

  txtAnnotation.on('createAnnotation', function(annotation) {
    if (!perms['create']) {
      alert('You do not have permission to create annotations.');
      txtAnnotation.removeAnnotation(annotation);
      return;
    }
    annotation.target_element = target;
    annotation.node_id = settings.nodeId;
    annotation.type = 'Text';
    if (annotation.body.length <= 0) {
      txtAnnotation.removeAnnotation(annotation);
      return;
    }
    createAnnotation(annotation);
  });

  txtAnnotation.on('updateAnnotation', function(annotation, previous) {
    if (!perms['edit'] && !perms['edit-own']) {
      alert('You do not have permission to update annotations.');
      txtAnnotation.removeAnnotation(annotation);
      addAnnotation(txtAnnotation, previous);
      return;
    }
    if (!perms['edit'] && perms['edit-own'] && userData['id'] !== annotation.body[0].creator.id) {
      alert('You cannot edit as this annotation was created by another user.');
      txtAnnotation.removeAnnotation(annotation);
      addAnnotation(txtAnnotation, previous);
      return;
    }
    if (JSON.stringify(annotation) !== JSON.stringify(previous)) {
      annotation.type = 'Text';
      updateAnnotation(annotation);
      return;
    }
    applyStyle(annotation.id, annotation.style);
  });

  txtAnnotation.on('deleteAnnotation', function(annotation) {
    if (!perms['delete'] && !perms['delete-own']) {
      alert('You do not have permission to delete annotations.');
      location.reload();
      return;
    }
    if (!perms['delete'] && perms['delete-own'] && userData['id'] !== annotation.body[0].creator.id) {
      alert('You cannot delete as this annotation was created by another user.');
      location.reload();
      return;
    }
    if (!confirm('Are you sure you want to delete this annotation?')) {
      location.reload();
      return;
    }
    deleteAnnotation(annotation);
  });
}

/**
 * Attach a wrapper Annotate button in place of the OK button.
 *
 * @param {string} btnText
 */
function attachWrapperOk(btnText = 'Annotate') {
  let footer = $('#page').find('.r6o-footer');
  footer.find('.ok-annotation').first().hide();
  let wrapperOk = $(`<button class="r6o-btn ok-annotation">${btnText}</button>`);
  wrapperOk.on('click', function(event) {
    let tagEntry = $('#page').find('.r6o-autocomplete').find('input').first();
    return new Promise((resolve) => {
      tagEntry.val('');
      tagEntry.get(0).dispatchEvent(new InputEvent('input'));
      resolve();
    }).then(() => {
      setTimeout(() => {
        footer.find('.ok-annotation:hidden').first().click();
      }, 1);
    });
  });
  footer.append(wrapperOk);
}

/**
 * Update the tag functionality based on the changes in the DOM.
 *
 * @param {object} domObj
 * @param {object} defaultTags
 */
function attachTagsEvent(domObj, tagOptions) {
  let observer = new MutationObserver(function(mutations) {
    let attached = false;
    for (let mutation of mutations) {
      if (mutation.type === 'childList') {
        for (let node of mutation.addedNodes) {
          let isNode = node.nodeType === Node.ELEMENT_NODE && node.classList;
          if (!isNode) {
            continue;
          }
          if (attached) {
            return;
          }
          if ((node.tagName === 'SPAN' && node.classList.contains('r6o-selection')) ||
              (node.tagName === 'g' && node.querySelector('.a9s-annotation.editable.selected[data-id="undefined"]'))) {
            attached = true;
            clearSelected();
            setTimeout(() => {
              if (tagOptions.defaultTags.length > 0) {
                attachDefaultTags(tagOptions.defaultTags);
              }
              if (!tagOptions.textInput) {
                hideTagInput();
              }
              if (tagOptions.selector) {
                attachTagSelector(tagOptions.tagStyleList);
              }
              attachTagList(tagOptions);
              attachWrapperOk();
            }, 2);
          }
        }
      }
    }
  });
  observer.observe(domObj[0], { childList: true, subtree: true });
}

/**
 * Show/Hide the buttons in the tag list for a specific tag.
 *
 * @param {object} listOptions
 * @param {string} tag
 * @param {boolean} adding
 */
function selectorListToggle(listOptions, tag, adding) {
  let option = listOptions.find(`div[selector-tag='${tag}']`);
  if (option.length <= 0) {
    return;
  }
  let parent = option.first().parent();
  if (adding) {
    parent.find('.r6o-tag-add').hide();
    parent.find('.r6o-tag-remove').show();
    return;
  }
  parent.find('.r6o-tag-add').show();
  parent.find('.r6o-tag-remove').hide();
}

/**
 * Attach the tag list of the editor to remove duplicates or monitor list for tag selector.
 *
 * @param {object} tagOptions
 */
function attachTagList(tagOptions) {
  let tagObject = $('#page').find('.r6o-tag').first();
  let tagList = tagOptions.tagList;
  let createTag = tagOptions.createNewTag;
  let selector = tagOptions.selector;
  let listOptions = $('#page').find('.r6o-tag-lister').first().find('.r6o-tag-option');
  let observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      if (mutation.type === 'childList') {
        mutation.addedNodes.forEach(function(node) {
          if (node.nodeType !== Node.ELEMENT_NODE) {
            return;
          }
          let tagContent = null;
          if (node.tagName === 'LI') {
            tagContent = node.querySelector('span.r6o-label')?.textContent;
          }
          else if (node.tagName === 'UL') {
            tagContent = node.querySelector('li span.r6o-label')?.textContent;
          }
          if (!tagContent) {
            return;
          }
          if (!createTag && !tagList.includes(tagContent)) {
            removeTag(tagContent);
          }
          if (isInCurrentTags(tagContent, false)) {
            removeTag(tagContent);
          }
          if (selector) {
            selectorListToggle(listOptions, tagContent, true);
          }
        });
        if (selector) {
          mutation.removedNodes.forEach(function(node) {
            if (node.nodeType !== Node.ELEMENT_NODE) {
              return;
            }
            let tagContent = null;
            if (node.tagName === 'LI') {
              tagContent = node.querySelector('span.r6o-label')?.textContent;
            }
            else if (node.tagName === 'UL') {
              tagContent = node.querySelector('li span.r6o-label')?.textContent;
            }
            if (!tagContent || isInCurrentTags(tagContent, true)) {
              return;
            }
            selectorListToggle(listOptions, tagContent, false);
          });
        }
      }
    });
  });
  observer.observe(tagObject[0], { childList: true, subtree: true });
}

/**
 * Check if the tag is in the current list of tags from the tag list.
 *
 * @param {string} tag
 * @param {boolean} last
 *
 * @returns {boolean}
 */
function isInCurrentTags(tag, last) {
  let found = false;
  let queryString = 'li';
  if (!last) {
    queryString += ':not(:last)';
  }
  $('#page').find('.r6o-taglist').find(queryString).each(function() {
    if ($(this).find('.r6o-label').first().text() == tag) {
      found = true;
      return;
    }
  });
  return found;
}

/**
 * Fetch the current list of tags from the tag list
 *
 * @returns {array}
 */
function fetchCurrentTags() {
  let tags = [];
  $('#page').find('.r6o-taglist').find('li').each(function() {
    tags.push($(this).find('.r6o-label').first().text());
  });
  return tags;
}

/**
 * Make the text annotation read-only. (Makeshift)
 */
function readOnlyText() {
  let editor = $('#page').find('.r6o-editor');
  editor.find('.r6o-btn.delete-annotation').remove();
  editor.find('.r6o-autocomplete').remove();
  editor.find('.r6o-widget.comment.editable').remove();
  editor.find('.r6o-taglist li').each(function() {
    $(this).replaceWith($(this).clone());
  });
  editor.find('.r6o-icon.r6o-arrow-down').remove();
  editor.find('.r6o-btn.ok-annotation').remove();
  editor.find('.cancel-annotation').each(function() {
    $(this).attr('class', 'r6o-btn close-annotation');
  });
}

/**
 * Update the menu based on the permissions of the user.
 *
 * @param {object} settings
 * @param {object} annotation
 */
function updateMenuByPermissions(settings, annotation) {
  let perms = settings.permissions;
  let userData = settings.userData;
  let editor = $('#page').find('.r6o-editor');
  let deletable = perms['delete'] || (perms['delete-own'] && userData['id'] === annotation.body[0].creator.id);
  if (!deletable) {
    editor.find('.r6o-btn.delete-annotation').remove();
    editor.find('.r6o-icon.r6o-arrow-down').remove();
  }
}

/**
 * Submits tags to the tagging input box.
 *
 * @param {object} inputBox
 * @param {string} tag
 */
function submitTag(inputBox, tag) {
  let entryDom = inputBox.get(0);
  return new Promise((resolve) => {
    inputBox.val(tag);
    entryDom.dispatchEvent(new InputEvent('input'));
    resolve();
  }).then(() => {
    setTimeout(() => {
      entryDom.dispatchEvent(new KeyboardEvent('keydown', {which: 13}));
    }, 1);
  });
}

/**
 * Remove tag in the tagging list.
 *
 * @param {string} tag
 */
function removeTag(tag) {
  $('#page').find('.r6o-taglist').find('li').each(function() {
    if ($(this).find('.r6o-label').first().text() == tag) {
      $(this).find('.r6o-delete-wrapper').first().click();
    }
  });
}

/**
 * Attach default tags to the annotations.
 *
 * @param {object} defaultTags
 */
function attachDefaultTags(defaultTags) {
  let element = $('#page').find('.r6o-tag').first();
  if (element.length <= 0) {
    return;
  }
  if (element.hasClass('default-tags')) {
    return;
  }
  element.addClass('default-tags');
  let tagEntry = $('#page').find('.r6o-autocomplete').find('input').first();
  let promiseChain = Promise.resolve();
  for (let i in defaultTags) {
    promiseChain = promiseChain.then(() => {
      return submitTag(tagEntry, defaultTags[i]);
    });
  }
}

/**
 * Attach the tag selector to the annotations.
 *
 * @param {array} tags
 */
function attachTagSelector(tags) {
  let button = $('<button class="r6o-tag-button r6o-btn">Select Tag to Add</button>');
  let selector = $('<div class="r6o-tag-selector"></div>');
  let search = $('<input type="text" placeholder="Search tag..." class="r6o-tag-search">');
  search.on('input', function() {
    let value = $(this).val().toLowerCase();
    selector.find('.r6o-tag-option').each(function() {
      let text = $(this).find('div').text().toLowerCase();
      if (text.includes(value)) {
        $(this).show();
      }
      else {
        $(this).hide();
      }
    });
  });
  selector.append(search);
  let tagList = $('<div class="r6o-tag-lister"></div>');
  let currentTag = fetchCurrentTags();
  let tagEntry = $('#page').find('.r6o-autocomplete').find('input').first();
  if (tags.length <= 0) {
    tagList.text('No tags available.');
  }
  $.each(tags, function(index, value) {
    let option = $(`<label class="r6o-tag-option"></label>`);
    let label = $(`<div selector-tag="${value['name']}">${value['name']}</div>`);
    if (value['hasStyle']) {
      label.css({
        'background-color': hexToRgbA(value['style']['background_color'], value['style']['background_transparency']),
        'color': value['style']['text_color'],
        'border-bottom': `${value['style']['underline_stroke']}px ${value['style']['underline_style']} ${hexToRgbA(value['style']['underline_color'])}`
      });
    }
    option.append(label);
    let addOption = $('<button class="r6o-tag-add r6o-btn">Add</button>');
    let removeOption = $('<button class="r6o-tag-remove r6o-btn">Remove</button>');
    option.append(addOption);
    if (currentTag.includes(value['name'])) {
      addOption.hide();
    }
    option.append(removeOption);
    removeOption.hide();
    if (currentTag.includes(value['name'])) {
      removeOption.show();
    }
    tagList.append(option);

    addOption.on('click', function(event) {
      event.stopPropagation();
      if (addOption.is(':visible')) {
        addOption.hide();
        removeOption.show();
        submitTag(tagEntry, value['name']);
      }
    });

    removeOption.on('click', function(event) {
      event.stopPropagation();
      if (removeOption.is(':visible')) {
        removeOption.hide();
        addOption.show();
        removeTag(value['name']);
      }
    });

    option.on('click', function(event) {
      event.preventDefault();
      event.stopPropagation();
    });
  });

  selector.append(tagList);
  button.on('click', function(event) {
    event.stopPropagation();
    selector.animate({height: 'toggle'});
  });

  selector.on('click', function(event) {
    event.stopPropagation();
  });

  $(document).on('click', function(event) {
    if (!$(event.target).hasClass('r6o-delete-wrapper')) {
      selector.hide();
    }
  });

  $('#page').find('.r6o-autocomplete div').first().append(button).append(selector);
}

/**
 * Clear all selected annotations. Treat each as cancel button click.
 */
function clearSelected() {
  $('#page').find('.r6o-footer').find('.close-annotation, .cancel-annotation').each(function() {
    $(this).click();
  });
}

/**
 * Hide the text input for tags.
 */
function hideTagInput() {
  $('#page').find('.r6o-autocomplete div').find('input').hide();
}

/**
 * Initialize Annotorious for the particular jQuery object.
 *
 * @param {object} imgObj
 * @param {object} settings
 */
function initAnnotorious(imgObj, settings) {
  let tagList = settings.tagOptions.tagList;
  let tagStyleList = settings.tagOptions.tagStyleList;
  let perms = settings.permissions;
  let userData = settings.userData;
  let tagSelector = settings.tagOptions.selector;
  let tagTextEntry = settings.tagOptions.textInput;
  let target = settings.current_target;
  let imgAnnotation = Annotorious.init({
    image: imgObj[0],
    locale: 'auto',
    widgets: [
      'COMMENT',
      {widget: 'TAG',
      vocabulary: tagList,
      textPlaceHolder: 'Add tags by typing here and pressing Enter...'}
    ],
    readOnly: !perms['create'],
    allowEmpty: false,
  });
  imgAnnotation.setAuthInfo(userData);
  imgAnnotation.target = target;
  imgAnnotation.targetSrc = imgObj[0]['src'];
  if (!imageAnnotations[imgAnnotation.target]) {
    imageAnnotations[imgAnnotation.target] = [];
  }
  imageAnnotations[imgAnnotation.target].push(imgAnnotation);

  imgAnnotation.on('selectAnnotation', function(annotation) {
    clearSelectedForImage(annotation.id);
    let editable = perms['edit'] || (perms['edit-own'] && userData['id'] === annotation.body[0].creator.id);
    if (!editable) {
      return;
    }
    setTimeout(() => {
      updateMenuByPermissions(settings, annotation);
      if (!tagTextEntry) {
        hideTagInput();
      }
      if (tagSelector) {
        attachTagSelector(tagStyleList);
      }
      attachTagList(settings.tagOptions);
      attachWrapperOk('Update');
    }, 2);
  });

  imgAnnotation.on('createAnnotation', function(annotation) {
    if (!perms['create']) {
      alert('You do not have permission to create annotations.');
      imgAnnotation.removeAnnotation(annotation);
      return;
    }
    annotation.target_element = target;
    annotation.node_id = settings.nodeId;
    annotation.type = 'Image';
    if (annotation.body.length <= 0) {
      imgAnnotation.removeAnnotation(annotation);
      return;
    }
    createAnnotation(annotation);
  });

  imgAnnotation.on('updateAnnotation', function(annotation, previous) {
    if (!perms['edit'] && !perms['edit-own']) {
      alert('You do not have permission to update annotations.');
      imgAnnotation.removeAnnotation(annotation);
      addImageAnnotation(imgAnnotation, previous, true);
      return;
    }
    if (!perms['edit'] && perms['edit-own'] && userData['id'] !== annotation.body[0].creator.id) {
      alert('You cannot edit as this annotation was created by another user.');
      imgAnnotation.removeAnnotation(annotation);
      addImageAnnotation(imgAnnotation, previous, true);
      return;
    }
    if (JSON.stringify(annotation) !== JSON.stringify(previous)) {
      annotation.type = 'Image';
      updateAnnotation(annotation);
    }
  });

  imgAnnotation.on('deleteAnnotation', function(annotation) {
    if (!perms['delete'] && !perms['delete-own']) {
      alert('You do not have permission to delete annotations.');
      location.reload();
      return;
    }
    if (!perms['delete'] && perms['delete-own'] && userData['id'] !== annotation.body[0].creator.id) {
      alert('You cannot delete as this annotation was created by another user.');
      location.reload();
      return;
    }
    if (!confirm('Are you sure you want to delete this annotation?')) {
      location.reload();
      return;
    }
    deleteAnnotation(annotation);
  });
}

/**
 * Clear all selected annotations but for image annotation selects. Treat each as cancel button click.
 *
 * @param {string} annotationId
 */
function clearSelectedForImage(annotationId) {
  $('#page').find('.r6o-editor').each(function() {
    let annotationEle = $(this).parent().parent().find(`.a9s-annotation[data-id="${annotationId}"]`);
    if (annotationEle.length <= 0) {
      $(this).find('.r6o-footer').find('.close-annotation, .cancel-annotation').each(function() {
        $(this).click();
      });
    }
  });
}

/**
 * Adds text annotation to the desire Recogito instance.
 *
 * @param {Recogito} annotationInstance
 * @param {object} annotation
 */
function addAnnotation(annotationInstance, annotation) {
  let style = annotation.style;
  annotationInstance.addAnnotation(annotation);
  applyStyle(annotation.id, style);
}

/**
 * Apply the style to the annotation by ID.
 *
 * @param {string} annotationId
 * @param {object} style
 */
function applyStyle(annotationId, style) {
  $('#page').find(`[data-id='${annotationId}']`).css({
    'background-color': hexToRgbA(style.background_color, style.background_transparency),
    'color' : style.text_color,
    'border-bottom': `${style.underline_stroke}px ${style.underline_style} ${hexToRgbA(style.underline_color)}`
  });
}

/**
 * Adds image annotation to the desire Annotorious instance.
 *
 * @param {Annotorious} annotationInstance
 * @param {object} annotation
 * @param {boolean} readOnly
 */
function addImageAnnotation(annotationInstance, annotation, readOnly) {
  annotationInstance.addAnnotation(annotation, readOnly);
}

/**
 * Get all annotations of the current page.
 *
 * @param {object} settings
 */
function getAnnotations(settings) {
  let perms = settings.permissions;
  let userData = settings.userData;
  $.ajax({
    type: 'GET',
    url: '/recogito_integration/get',
    dataType: 'json',
    headers: {
      'nodeId': settings.nodeId
    },
    success: function(data) {
      data = JSON.parse(data);
      for (let content of data) {
        let annotation = AnnotationConverter.convertDataToW3C(content);
        switch (annotation.type) {
          case 'Text':
            annotation.type = 'Annotation';
            if (textAnnotations[annotation.target_element]) {
              for (let annotationInstance of textAnnotations[annotation.target_element]) {
                addAnnotation(annotationInstance, annotation);
              }
            }
            break;

          case 'Image':
            annotation.type = 'Annotation';
            if (imageAnnotations[annotation.target_element]) {
              for (let annotationInstance of imageAnnotations[annotation.target_element]) {
                if (annotationInstance.targetSrc === annotation.target.source) {
                  let editable = perms['edit'] || (perms['edit-own'] && userData['id'] === annotation.body[0].creator.id);
                  addImageAnnotation(annotationInstance, annotation, !editable);
                }
              }
            }
            break;
        }
      }
    },
    error: function(xhr, status, error) {
      alert('Unable to retrieve annotations: \n\n' + xhr.responseText);
    }
  })
}

/**
 * Remove the duplicate tags.
 *
 * @param {object} annotation
 */
function removeDuplicateTags(annotation) {
  let bodies = annotation.body;
  let newBody = [];
  let uniqueTags = [];
  for (let body of bodies) {
    if (body.purpose === 'tagging') {
      if (!uniqueTags.includes(body.value)) {
        uniqueTags.push(body.value);
        newBody.push(body);
      }
      else {
        newBody.push(body);
      }
    }
    else if (body.purpose === 'commenting') {
      newBody.push(body);
    }
  }
  annotation.body = newBody;
  return annotation;
}

/**
 * Create an annotation in by calling the database API.
 *
 * @param {object} annotation
 */
function createAnnotation(annotation) {
  annotation = removeDuplicateTags(annotation);
  let annotationData = AnnotationConverter.convertW3CToData(annotation);
  annotationData['nodeId'] = annotation.node_id;
  $.ajax({
    type: 'POST',
    url: '/recogito_integration/create',
    dataType: 'text',
    contentType: 'application/json',
    data: JSON.stringify(annotationData),
    success: function(data) {
      location.reload();
    },
    error: function(xhr, status, error) {
      alert('Unable to create the annotation: \n\n' + xhr.responseText);
      location.reload();
    }
  })
}

/**
 * Update an annotation in the database.
 *
 * @param {object} annotation
 */
function updateAnnotation(annotation) {
  let annotationData = AnnotationConverter.convertW3CToData(annotation);
  $.ajax({
    type: 'PUT',
    url: `/recogito_integration/update/${annotation.id.substring(1)}`,
    dataType: 'text',
    contentType: 'application/json',
    data: JSON.stringify(annotationData),
    success: function(data) {
      location.reload();
    },
    error: function(xhr, status, error) {
      alert('Unable to update the annotation: \n\n' + xhr.responseText);
      location.reload();
    }
  });
}
/**
 * Delete an annotation from the database.
 *
 * @param {object} annotation
 */
function deleteAnnotation(annotation) {
  $.ajax({
    type: 'DELETE',
    url: `/recogito_integration/delete/${annotation.id.substring(1)}`,
    dataType: 'text',
    success: function(data) {
      location.reload();
    },
    error: function(xhr, status, error) {
      alert('Unable to delete the annotation: \n\n' + xhr.responseText);
      location.reload();
    }
  });
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc