text: /**
   * RASH section plugin RAJE
   */
  
  const NON_EDITABLE_HEADER_SELECTOR = 'header.page-header.container.cgen'
  const BIBLIOENTRY_SUFFIX = 'biblioentry_'
  const ENDNOTE_SUFFIX = 'endnote_'
  
  const BIBLIOGRAPHY_SELECTOR = 'section[role=doc-bibliography]'
  const BIBLIOENTRY_SELECTOR = 'li[role=doc-biblioentry]'
  
  const ENDNOTES_SELECTOR = 'section[role=doc-endnotes]'
  const ENDNOTE_SELECTOR = 'section[role=doc-endnote]'
  
  const ABSTRACT_SELECTOR = 'section[role=doc-abstract]'
  const ACKNOWLEDGEMENTS_SELECTOR = 'section[role=doc-acknowledgements]'
  
  const MAIN_SECTION_SELECTOR = 'div#raje_root > section:not([role])'
  const SECTION_SELECTOR = 'section:not([role])'
  const SPECIAL_SECTION_SELECTOR = 'section[role]'
  
  const MENU_SELECTOR = 'div[id^=mceu_][id$=-body][role=menu]'
  
  const DATA_UPGRADE = 'data-upgrade'
  const DATA_DOWNGRADE = 'data-downgrade'
  
  const HEADING = 'Heading'
  
  const HEADING_TRASFORMATION_FORBIDDEN = 'Error, you cannot transform the current header in this way!'
  
  tinymce.PluginManager.add('raje_section', function (editor, url) {
  
    let raje_section_flag = false
    let raje_stored_selection
  
    editor.addButton('raje_section', {
      type: 'menubutton',
      text: 'Headings',
      title: 'heading',
      icons: false,
  
      // Sections sub menu
      menu: [{
        text: `${HEADING} 1.`,
        onclick: function (e) {
          section.addOrDownUpgrade(e, 1)
        }
      }, {
        text: `${HEADING} 1.1.`,
        onclick: function (e) {
          section.addOrDownUpgrade(e, 2)
        }
      }, {
        text: `${HEADING} 1.1.1.`,
        onclick: function (e) {
          section.addOrDownUpgrade(e, 3)
        }
      }, {
        text: `${HEADING} 1.1.1.1.`,
        onclick: function (e) {
          section.addOrDownUpgrade(e, 4)
        }
      }, {
        text: `${HEADING} 1.1.1.1.1.`,
        onclick: function (e) {
          section.addOrDownUpgrade(e, 5)
        }
      }, {
        text: `${HEADING} 1.1.1.1.1.1.`,
        onclick: function (e) {
          section.addOrDownUpgrade(e, 6)
        }
      }, {
        text: 'Special',
        menu: [{
            text: 'Abstract',
            onclick: function () {
  
              section.addAbstract()
            }
          },
          {
            text: 'Acknowledgements',
            onclick: function () {
              section.addAcknowledgements()
            }
          },
          {
            text: 'References',
            onclick: function () {
  
              tinymce.triggerSave()
  
              // Only if bibliography section doesn't exists
              if (!$(BIBLIOGRAPHY_SELECTOR).length) {
  
                // TODO change here
                tinymce.activeEditor.undoManager.transact(function () {
                  // Add new biblioentry
                  section.addBiblioentry()
  
                  // Update iframe
                  updateIframeFromSavedContent()
  
                  //move caret and set focus to active aditor #105
                  tinymce.activeEditor.selection.select(tinymce.activeEditor.dom.select(`${BIBLIOENTRY_SELECTOR}:last-child`)[0], true)
                })
              } else
                tinymce.activeEditor.selection.select(tinymce.activeEditor.dom.select(`${BIBLIOGRAPHY_SELECTOR}>h1`)[0])
  
              scrollTo(`${BIBLIOENTRY_SELECTOR}:last-child`)
  
              tinymce.activeEditor.focus()
            }
          }
        ]
      }]
    })
  
    editor.on('keyDown', function (e) {
  
      // instance of the selected element
      let selectedElement = $(tinymce.activeEditor.selection.getNode())
  
      try {
  
        let keycode = e.keyCode
  
        // Save bounds of current selection (start and end)
        let startNode = $(tinymce.activeEditor.selection.getRng().startContainer)
        let endNode = $(tinymce.activeEditor.selection.getRng().endContainer)
  
        const SPECIAL_CHARS =
          (keycode > 47 && keycode < 58) || // number keys
          (keycode > 95 && keycode < 112) || // numpad keys
          (keycode > 185 && keycode < 193) || // ;=,-./` (in order)
          (keycode > 218 && keycode < 223); // [\]' (in order)
  
        // Block special chars in special elements
        if (SPECIAL_CHARS &&
          (startNode.parents(SPECIAL_SECTION_SELECTOR).length || endNode.parents(SPECIAL_SECTION_SELECTOR).length) &&
          (startNode.parents('h1').length > 0 || endNode.parents('h1').length > 0))
          return false
  
        // #################################
        // ### BACKSPACE && CANC PRESSED ###
        // #################################
        if (e.keyCode == 8 || e.keyCode == 46) {
  
          //let toRemoveSections = section.getSectionsinSelection(tinymce.activeEditor.selection)
          raje_section_flag = true
  
          // Prevent remove from header
          if (selectedElement.is(NON_EDITABLE_HEADER_SELECTOR) ||
            (selectedElement.attr('data-mce-caret') == 'after' && selectedElement.parent().is(RAJE_SELECTOR)) ||
            (selectedElement.attr('data-mce-caret') && selectedElement.parent().is(RAJE_SELECTOR)) == 'before')
            return false
  
          // If selection isn't collapsed manage delete
          if (!tinymce.activeEditor.selection.isCollapsed()) {
            return section.manageDelete()
          }
  
          // If SELECTION STARTS or ENDS in special section
          else if (startNode.parents(SPECIAL_SECTION_SELECTOR).length || endNode.parents(SPECIAL_SECTION_SELECTOR).length) {
  
            let startOffset = tinymce.activeEditor.selection.getRng().startOffset
            let startOffsetNode = 0
            let endOffset = tinymce.activeEditor.selection.getRng().endOffset
            let endOffsetNode = tinymce.activeEditor.selection.getRng().endContainer.length
  
            // Completely remove the current special section if is entirely selected
            if (
              // Check if the selection contains the entire section
              startOffset == startOffsetNode && endOffset == endOffsetNode &&
  
              // Check if the selection starts from h1
              (startNode.parents('h1').length != endNode.parents('h1').length) && (startNode.parents('h1').length || endNode.parents('h1').length) &&
  
              // Check if the selection ends in the last child
              (startNode.parents(SPECIAL_SECTION_SELECTOR).children().length == $(tinymce.activeEditor.selection.getRng().endContainer).parentsUntil(SPECIAL_SECTION_SELECTOR).index() + 1)) {
  
            }
  
            // Remove the current special section if selection is at the start of h1 AND selection is collapsed 
            if (tinymce.activeEditor.selection.isCollapsed() && (startNode.parents('h1').length || startNode.is('h1')) && startOffset == 0) {
  
              tinymce.activeEditor.undoManager.transact(function () {
  
                // Remove the section and update 
                selectedElement.parent(SPECIAL_SECTION_SELECTOR).remove()
                tinymce.triggerSave()
  
                // Update references
                updateReferences()
                updateIframeFromSavedContent()
              })
  
              return false
            }
  
            // Chek if inside the selection to remove, there is bibliography
            let hasBibliography = false
            $(tinymce.activeEditor.selection.getContent()).each(function () {
              if ($(this).is(BIBLIOGRAPHY_SELECTOR))
                hasBibliography = true
            })
  
            if (hasBibliography) {
  
              tinymce.activeEditor.undoManager.transact(function () {
  
                // Execute normal delete
                tinymce.activeEditor.execCommand('delete')
  
                // Update saved content
                tinymce.triggerSave()
  
                // Remove selector without hader
                $(BIBLIOGRAPHY_SELECTOR).remove()
  
                // Update iframe and restore selection
                updateIframeFromSavedContent()
              })
  
              return false
            }
  
            // if selection starts or ends in a biblioentry
            if (startNode.parents(BIBLIOENTRY_SELECTOR).length || endNode.parents(BIBLIOENTRY_SELECTOR).length) {
  
              // Both delete event and update are stored in a single undo level
              tinymce.activeEditor.undoManager.transact(function () {
  
                tinymce.activeEditor.execCommand('delete')
                section.updateBibliographySection()
                updateReferences()
  
                // update iframe
                updateIframeFromSavedContent()
              })
  
              return false
            }
          }
  
  
        }
      } catch (exception) {}
  
      // #################################
      // ######### ENTER PRESSED #########
      // #################################
      if (e.keyCode == 13) {
  
        // When enter is pressed inside an header, not at the end of it
        if (selectedElement.is('h1,h2,h3,h4,h5,h6') && selectedElement.text().trim().length != tinymce.activeEditor.selection.getRng().startOffset) {
  
          section.addWithEnter()
          return false
        }
  
        // If selection is before/after header
        if (selectedElement.is('p')) {
  
          // Block enter before header
          if (selectedElement.attr('data-mce-caret') == 'before')
            return false
  
  
          // Add new section after header
          if (selectedElement.attr('data-mce-caret') == 'after') {
            section.add(1)
            return false
          }
        }
  
        // If enter is pressed inside bibliography selector
        if (selectedElement.parents(BIBLIOGRAPHY_SELECTOR).length) {
  
          tinymce.triggerSave()
  
          let id = getSuccessiveElementId(BIBLIOENTRY_SELECTOR, BIBLIOENTRY_SUFFIX)
  
          // Pressing enter in h1 will add a new biblioentry and caret reposition
          if (selectedElement.is('h1')) {
  
            section.addBiblioentry(id)
            updateIframeFromSavedContent()
          }
  
          // If selected element is inside text
          else if (selectedElement.is('p'))
            section.addBiblioentry(id, null, selectedElement.parent('li'))
  
  
          // If selected element is without text
          else if (selectedElement.is('li'))
            section.addBiblioentry(id, null, selectedElement)
  
          // Move caret #105
          tinymce.activeEditor.selection.setCursorLocation(tinymce.activeEditor.dom.select(`${BIBLIOENTRY_SELECTOR}#${id} > p`)[0], false)
          return false
        }
  
        // Adding sections with shortcuts #
        if (selectedElement.is('p') && selectedElement.text().trim().substring(0, 1) == '#') {
  
          let level = section.getLevelFromHash(selectedElement.text().trim())
          let deepness = $(selectedElement).parentsUntil(RAJE_SELECTOR).length - level + 1
  
          // Insert section only if caret is inside abstract section, and user is going to insert a sub section
          // OR the cursor isn't inside other special sections
          // AND selectedElement isn't inside a figure
          if (((selectedElement.parents(ABSTRACT_SELECTOR).length && deepness > 0) || !selectedElement.parents(SPECIAL_SECTION_SELECTOR).length) && !selectedElement.parents(FIGURE_SELECTOR).length) {
  
            section.add(level, selectedElement.text().substring(level).trim())
            return false
          }
        }
      }
    })
  
    editor.on('NodeChange', function (e) {
      section.updateSectionToolbar()
    })
  })
  
  section = {
  
    /**
     * Function called when a new section needs to be attached, with buttons
     */
    add: function (level, text) {
  
      // Select current node
      let selectedElement = $(tinymce.activeEditor.selection.getNode())
  
      // Create the section
      let newSection = this.create(text != null ? text : selectedElement.html().trim(), level)
  
      tinymce.activeEditor.undoManager.transact(function () {
  
        // Check what kind of section needs to be inserted
        if (section.manageSection(selectedElement, newSection, level ? level : selectedElement.parentsUntil(RAJE_SELECTOR).length)) {
  
          // Remove the selected section
          selectedElement.remove()
  
          // If the new heading has text nodes, the offset won't be 0 (as normal) but instead it'll be length of node text
          moveCaret(newSection.find(':header').first()[0])
  
          // Update editor content
          tinymce.triggerSave()
        }
      })
    },
  
    /**
     * 
     */
    addOrDownUpgrade: function (e, level) {
  
      let selectedMenuItem = $(e.target).parent('.mce-menu-item')
  
      if (selectedMenuItem.attr(DATA_UPGRADE))
        return this.upgrade()
  
      if (selectedMenuItem.attr(DATA_DOWNGRADE))
        return this.downgrade()
  
      return this.add(level)
    },
  
    /**
     * Function called when a new section needs to be attached, with buttons
     */
    addWithEnter: function () {
  
      // Select current node
      let selectedElement = $(tinymce.activeEditor.selection.getNode())
  
      // If the section isn't special
      if (!selectedElement.parent().attr('role')) {
  
        level = selectedElement.parentsUntil(RAJE_SELECTOR).length
  
        // Create the section
        let newSection = this.create(selectedElement.text().trim().substring(tinymce.activeEditor.selection.getRng().startOffset), level)
  
        tinymce.activeEditor.undoManager.transact(function () {
  
          // Check what kind of section needs to be inserted
          section.manageSection(selectedElement, newSection, level)
  
          // Remove the selected section
          selectedElement.html(selectedElement.text().trim().substring(0, tinymce.activeEditor.selection.getRng().startOffset))
  
          moveCaret(newSection.find(':header').first()[0], true)
  
          // Update editor
          tinymce.triggerSave()
        })
      } else
        notify('Error, headers of special sections (abstract, acknowledments) cannot be splitted', 'error', 4000)
    },
  
    /**
     * Get the last inserted id
     */
    getNextId: function () {
      let id = 0
      $('section[id]').each(function () {
        if ($(this).attr('id').indexOf('section') > -1) {
          let currId = parseInt($(this).attr('id').replace('section', ''))
          id = id > currId ? id : currId
        }
      })
      return `section${id+1}`
    },
  
    /**
     * Retrieve and then remove every successive elements 
     */
    getSuccessiveElements: function (element, deepness) {
  
      let successiveElements = $('<div></div>')
  
      while (deepness >= 0) {
  
        if (element.nextAll(':not(.footer)')) {
  
          // If the deepness is 0, only paragraph are saved (not sections)
          if (deepness == 0) {
            // Successive elements can be p or figures
            successiveElements.append(element.nextAll(`p,${FIGURE_SELECTOR}`))
            element.nextAll().remove(`p,${FIGURE_SELECTOR}`)
          } else {
            successiveElements.append(element.nextAll())
            element.nextAll().remove()
          }
        }
  
        element = element.parent('section')
        deepness--
      }
  
      return $(successiveElements.html())
    },
  
    /**
     * 
     */
    getLevelFromHash: function (text) {
  
      let level = 0
      text = text.substring(0, text.length >= 6 ? 6 : text.length)
  
      while (text.length > 0) {
  
        if (text.substring(text.length - 1) == '#')
          level++
  
          text = text.substring(0, text.length - 1)
      }
  
      return level
    },
  
    /**
     * Return JQeury object that represent the section
     */
    create: function (text, level) {
      // Create the section
  
      // Trim white spaces and add zero_space char if nothing is inside
  
      if (typeof text != "undefined") {
        text = text.trim()
        if (text.length == 0)
          text = "<br>"
      } else
        text = "<br>"
  
      return $(`<section id="${this.getNextId()}"><h${level} data-rash-original-wrapper="h1">${text}</h${level}></section>`)
    },
  
    /**
     * Check what kind of section needs to be added, and preceed
     */
    manageSection: function (selectedElement, newSection, level) {
  
      let deepness = $(selectedElement).parentsUntil(RAJE_SELECTOR).length - level + 1
  
      if (deepness >= 0) {
  
        // Block insert selection if caret is inside special section, and user is going to insert a sub section
        if ((selectedElement.parents(SPECIAL_SECTION_SELECTOR).length && deepness != 1) || (selectedElement.parents(ACKNOWLEDGEMENTS_SELECTOR).length &&
            selectedElement.parents(BIBLIOGRAPHY_SELECTOR) &&
            selectedElement.parents(ENDNOTES_SELECTOR)))
          return false
  
        // Get direct parent and ancestor reference
        let successiveElements = this.getSuccessiveElements(selectedElement, deepness)
  
        if (successiveElements.length)
          newSection.append(successiveElements)
  
        // CASE: sub section
        if (deepness == 0)
          selectedElement.after(newSection)
  
        // CASE: sibling section
        else if (deepness == 1)
          selectedElement.parent('section').after(newSection)
  
        // CASE: ancestor section at any uplevel
        else
          $(selectedElement.parents('section')[deepness - 1]).after(newSection)
  
        headingDimension()
  
        return true
      }
    },
  
    /**
     * 
     */
    upgrade: function () {
  
      let selectedElement = $(tinymce.activeEditor.selection.getNode())
  
      if (selectedElement.is(':header')) {
  
        // Get the references of selected and parent section
        let selectedSection = selectedElement.parent(SECTION_SELECTOR)
        let parentSection = selectedSection.parent(SECTION_SELECTOR)
  
        // If there is a parent section upgrade is allowed
        if (parentSection.length) {
  
          // Everything in here, is an atomic undo level
          tinymce.activeEditor.undoManager.transact(function () {
  
            // Save the section and detach
            let bodySection = $(selectedSection[0].outerHTML)
            selectedSection.detach()
  
            // Update dimension and move the section out
            parentSection.after(bodySection)
  
            tinymce.triggerSave()
            headingDimension()
            updateIframeFromSavedContent()
          })
        }
  
        // Notify error
        else
          notify(HEADING_TRASFORMATION_FORBIDDEN, 'error', 2000)
      }
    },
  
    /**
     * 
     */
    downgrade: function () {
  
      let selectedElement = $(tinymce.activeEditor.selection.getNode())
  
      if (selectedElement.is('h1,h2,h3,h4,h5,h6')) {
        // Get the references of selected and sibling section
        let selectedSection = selectedElement.parent(SECTION_SELECTOR)
        let siblingSection = selectedSection.prev(SECTION_SELECTOR)
  
        // If there is a previous sibling section downgrade is allowed
        if (siblingSection.length) {
  
          // Everything in here, is an atomic undo level
          tinymce.activeEditor.undoManager.transact(function () {
  
            // Save the section and detach
            let bodySection = $(selectedSection[0].outerHTML)
            selectedSection.detach()
  
            // Update dimension and move the section out
            siblingSection.append(bodySection)
  
            tinymce.triggerSave()
            // Refresh tinymce content and set the heading dimension
            headingDimension()
            updateIframeFromSavedContent()
          })
        }
      }
  
      // Notify error
      else
        notify(HEADING_TRASFORMATION_FORBIDDEN, 'error', 2000)
    },
  
    /**
     * 
     */
    addAbstract: function () {
  
      if (!$(ABSTRACT_SELECTOR).length) {
  
        tinymce.activeEditor.undoManager.transact(function () {
  
          // This section can only be placed after non editable header
          $(NON_EDITABLE_HEADER_SELECTOR).after(`<section id="doc-abstract" role="doc-abstract"><h1>Abstract</h1></section>`)
  
          updateIframeFromSavedContent()
        })
      }
  
      //move caret and set focus to active aditor #105
      moveCaret(tinymce.activeEditor.dom.select(`${ABSTRACT_SELECTOR} > h1`)[0])
      scrollTo(ABSTRACT_SELECTOR)
    },
  
    /**
     * 
     */
    addAcknowledgements: function () {
  
      if (!$(ACKNOWLEDGEMENTS_SELECTOR).length) {
  
        let ack = $(`<section id="doc-acknowledgements" role="doc-acknowledgements"><h1>Acknowledgements</h1></section>`)
  
        tinymce.activeEditor.undoManager.transact(function () {
  
          // Insert this section after last non special section 
          // OR after abstract section 
          // OR after non editable header
          if ($(MAIN_SECTION_SELECTOR).length)
            $(MAIN_SECTION_SELECTOR).last().after(ack)
  
          else if ($(ABSTRACT_SELECTOR).length)
            $(ABSTRACT_SELECTOR).after(ack)
  
          else
            $(NON_EDITABLE_HEADER_SELECTOR).after(ack)
  
          updateIframeFromSavedContent()
        })
      }
  
      //move caret and set focus to active aditor #105
      moveCaret(tinymce.activeEditor.dom.select(`${ACKNOWLEDGEMENTS_SELECTOR} > h1`)[0])
      scrollTo(ACKNOWLEDGEMENTS_SELECTOR)
    },
  
    /**
     * This method is the main one. It's called because all times the intent is to add a new biblioentry (single reference)
     * Then it checks if is necessary to add the entire <section> or only the missing <ul>
     */
    addBiblioentry: function (id, text, listItem) {
  
      // Add bibliography section if not exists
      if (!$(BIBLIOGRAPHY_SELECTOR).length) {
  
        let bibliography = $(`<section id="doc-bibliography" role="doc-bibliography"><h1>References</h1><ul></ul></section>`)
  
        // This section is added after acknowledgements section
        // OR after last non special section
        // OR after abstract section
        // OR after non editable header 
        if ($(ACKNOWLEDGEMENTS_SELECTOR).length)
          $(ACKNOWLEDGEMENTS_SELECTOR).after(bibliography)
  
        else if ($(MAIN_SECTION_SELECTOR).length)
          $(MAIN_SECTION_SELECTOR).last().after(bibliography)
  
        else if ($(ABSTRACT_SELECTOR).length)
          $(ABSTRACT_SELECTOR).after(bibliography)
  
        else
          $(NON_EDITABLE_HEADER_SELECTOR).after(bibliography)
  
      }
  
      // Add ul in bibliography section if not exists
      if (!$(BIBLIOGRAPHY_SELECTOR).find('ul').length)
        $(BIBLIOGRAPHY_SELECTOR).append('<ul></ul>')
  
      // IF id and text aren't passed as parameters, these can be retrieved or init from here
      id = (id) ? id : getSuccessiveElementId(BIBLIOENTRY_SELECTOR, BIBLIOENTRY_SUFFIX)
      text = text ? text : '<br/>'
  
      let newItem = $(`<li role="doc-biblioentry" id="${id}"><p>${text}</p></li>`)
  
      // Append new li to ul at last position
      // OR insert the new li right after the current one
      if (!listItem)
        $(`${BIBLIOGRAPHY_SELECTOR} ul`).append(newItem)
  
      else
        listItem.after(newItem)
    },
  
    /**
     * 
     */
    updateBibliographySection: function () {
  
      // Synchronize iframe and stored content
      tinymce.triggerSave()
  
      // Remove all sections without p child
      $(`${BIBLIOENTRY_SELECTOR}:not(:has(p))`).each(function () {
        $(this).remove()
      })
    },
  
    /**
     * 
     */
    addEndnote: function (id) {
  
      // Add the section if it not exists
      if (!$(ENDNOTE_SELECTOR).length) {
  
        let endnotes = $(`<section id="doc-endnotes" role="doc-endnotes"><h1 data-rash-original-content="">Footnotes</h1></section>`)
  
        // Insert this section after bibliography section
        // OR after acknowledgements section
        // OR after non special section selector
        // OR after abstract section
        // OR after non editable header 
        if ($(BIBLIOGRAPHY_SELECTOR).length)
          $(BIBLIOGRAPHY_SELECTOR).after(endnotes)
  
        else if ($(ACKNOWLEDGEMENTS_SELECTOR).length)
          $(ACKNOWLEDGEMENTS_SELECTOR).after(endnotes)
  
        else if ($(MAIN_SECTION_SELECTOR).length)
          $(MAIN_SECTION_SELECTOR).last().after(endnotes)
  
        else if ($(ABSTRACT_SELECTOR).length)
          $(ABSTRACT_SELECTOR).after(endnotes)
  
        else
          $(NON_EDITABLE_HEADER_SELECTOR).after(endnotes)
      }
  
      // Create and append the new endnote
      let endnote = $(`<section role="doc-endnote" id="${id}"><p><br/></p></section>`)
      $(ENDNOTES_SELECTOR).append(endnote)
    },
  
    /**
     * 
     */
    updateSectionToolbar: function () {
  
      // Dropdown menu reference
      let menu = $(MENU_SELECTOR)
  
      if (menu.length) {
        section.restoreSectionToolbar(menu)
  
        // Save current selected element
        let selectedElement = $(tinymce.activeEditor.selection.getRng().startContainer)
  
        if (selectedElement[0].nodeType == 3)
          selectedElement = selectedElement.parent()
  
        // If current element is p
        if (selectedElement.is('p') || selectedElement.parent().is('p')) {
  
          // Check if caret is inside special section
          // In this case enable only first menuitem if caret is in abstract
          if (selectedElement.parents(SPECIAL_SECTION_SELECTOR).length) {
  
            if (selectedElement.parents(ABSTRACT_SELECTOR).length)
              menu.children(`:lt(1)`).removeClass('mce-disabled')
  
            return false
          }
  
          // Get deepness of the section
          let deepness = selectedElement.parents(SECTION_SELECTOR).length + 1
  
          // Remove disabling class on first {deepness} menu items
          menu.children(`:lt(${deepness})`).removeClass('mce-disabled')
  
          // Get the section list and update the dropdown with the right texts
          let list = section.getAncestorSectionsList(selectedElement)
          for (let i = 0; i <= list.length; i++) {
            menu.children(`:eq(${i})`).find('span.mce-text').text(list[i])
          }
        }
  
        // Enable only for upgrade/downgrade
        else if (!selectedElement.parents(SPECIAL_SECTION_SELECTOR).length && selectedElement.is('h1,h2,h3')) {
  
          // Get the selected section
          let selectedSection = selectedElement.parents(SECTION_SELECTOR).first()
  
          // Get the number of the heading (eg. H1 => 1, H2 => 2)
          let index = parseInt(selectedElement.prop('tagName').toLowerCase().replace('h', ''))
  
          // Get the deepness of the section (eg. 1 if is a main section, 2 if is a subsection)
          let deepness = selectedElement.parents(SECTION_SELECTOR).length
  
          // Get the list of texts that are bee
          let list = section.getAncestorSectionsList(selectedElement)
  
          // The text index in list
          let i = deepness - index
  
          // Update text upgrade and downgrade
          menu.children(`:eq(${0})`).find('span.mce-text').text('Upgrade')
          menu.children(`:eq(${1})`).find('span.mce-text').text('Downgrade')
  
          // Check if the current section has a parent
          // In this case the upgrade is permitted
          if (selectedSection.parent(SECTION_SELECTOR).length) {
  
            // menu item inside the dropdown
            let menuItem = menu.children(`:eq(${0})`)
            menuItem.removeClass('mce-disabled')
            menuItem.attr(DATA_UPGRADE, true)
          }
  
          if (selectedSection.prev().is(SECTION_SELECTOR)) {
  
            // menu item inside the dropdown
            let menuItem = menu.children(`:eq(${1})`)
            menuItem.removeClass('mce-disabled')
            menuItem.attr(DATA_DOWNGRADE, true)
          }
        }
  
        // Disable in any other cases
        else
          menu.children(':gt(10)').addClass('mce-disabled')
      }
    },
  
    getAncestorSectionsList: function (selectedElement) {
  
      let preHeaders = []
      let list = []
      let parentSections = selectedElement.parents('section')
  
      // Save index of all parent sections
      for (let i = parentSections.length; i > 0; i--) {
        let elem = $(parentSections[i - 1])
        let index = elem.parent().children(SECTION_SELECTOR).index(elem) + 1
        preHeaders.push(index)
      }
  
      // Update text of all menu item
      for (let i = 0; i <= preHeaders.length; i++) {
  
        let text = `${HEADING} `
  
        // Update text based on section structure
        if (i != preHeaders.length) {
          for (let x = 0; x <= i; x++)
            text += `${preHeaders[x] + (x == i ? 1 : 0)}.`
        }
  
        // In this case raje changes text of next sub heading
        else {
          for (let x = 0; x < i; x++)
            text += `${preHeaders[x]}.`
  
          text += '1.'
        }
  
        list.push(text)
      }
  
      return list
    },
  
    /**
     * Restore normal text in section toolbar and disable all
     */
    restoreSectionToolbar: function (menu) {
  
      let cnt = 1
  
      menu.children(':lt(6)').each(function () {
        let text = `${HEADING} `
  
        for (let i = 0; i < cnt; i++)
          text += `1.`
  
        // Remove data elements
        $(this).removeAttr(DATA_UPGRADE)
        $(this).removeAttr(DATA_DOWNGRADE)
  
        $(this).find('span.mce-text').text(text)
        $(this).addClass('mce-disabled')
  
        cnt++
      })
  
      // Enable upgrade/downgrade last three menu items
      menu.children(':gt(10)').removeClass('mce-disabled')
    },
  
    manageDelete: function () {
  
      let range = tinymce.activeEditor.selection.getRng()
      let startNode = $(range.startContainer).parent()
      let endNode = $(range.endContainer).parent()
      let commonAncestorContainer = $(range.commonAncestorContainer)
  
      // Deepness is relative to the common ancestor container of the range startContainer and end
      let deepness = endNode.parent('section').parentsUntil(commonAncestorContainer).length + 1
      let currentElement = endNode
      let toMoveElements = []
  
      tinymce.activeEditor.undoManager.transact(function () {
  
        // Get and detach all next_end
        for (let i = 0; i <= deepness; i++) {
          currentElement.nextAll('section,p,figure,pre,ul,ol').each(function () {
            toMoveElements.push($(this))
  
            $(this).detach()
          })
          currentElement = currentElement.parent()
        }
  
        // Execute delete
        tinymce.activeEditor.execCommand('delete')
  
        // Detach all next_begin
        startNode.nextAll().each(function () {
          $(this).detach()
        })
  
        // Append all next_end to startnode parent
        toMoveElements.forEach(function (element) {
          startNode.parent('section').append(element)
        })
  
        tinymce.triggerSave()
  
        // Refresh headings
        headingDimension()
  
        // Update references if needed
        updateReferences()
  
        updateIframeFromSavedContent()
      })
      return false
    }
  }