Skip to content
Snippets Groups Projects
ContainerEditor.js 2.84 KiB
Newer Older
import { each, keys, includes } from 'lodash'
john's avatar
john committed
import {
  ContainerEditor as SubstanceContainerEditor,
  Surface,
  uuid
} from 'substance'

class ContainerEditor extends SubstanceContainerEditor {
  render ($$) {
    // TODO -- better ways to write this in es6
    var el = Surface.prototype.render.call(this, $$)

    var doc = this.getDocument()
    var containerId = this.getContainerId()
    var containerNode = doc.get(containerId)

    if (!containerNode) {
      console.warn('No container node found for ', containerId)
    }

    el.addClass('sc-container-editor container-node ' + containerId)
      .attr({
        spellCheck: false,
        'data-id': containerId
      })

    // if it IS empty, handle in didMount
    if (!this.isEmpty()) {
      containerNode.getNodes().forEach(function (node) {
        el.append(this._renderNode($$, node).ref(node.id))
      }.bind(this))
    }

    // TODO -- should maybe change to isEditable ?
    if (!this.props.disabled) {
      el.addClass('sm-enabled')
      el.setAttribute('contenteditable', true)
    }

    // editing locked, selection open (for comments)
    if (this.isReadOnlyMode()) {
      const documentSession = this.getDocumentSession()
      documentSession.on('didUpdate', this.disableToolbar, this)
    }

john's avatar
john committed
  didMount () {
    Surface.prototype.didMount.apply(this, arguments)
    this.container.on('nodes:changed', this.onContainerChange, this)
    if (this.isEmpty()) this.createText()

    if (this.isReadOnlyMode()) this.links()
  }

  // create an empty paragraph with an empty node
  // then select it for cursor focus
john's avatar
john committed
  createText () {
    var newSel

    this.transaction(function (tx) {
      var container = tx.get(this.props.containerId)
      var textType = tx.getSchema().getDefaultTextType()

      var node = tx.create({
        id: uuid(textType),
        type: textType,
        content: ''
      })

      container.show(node.id)

      newSel = tx.createSelection({
        type: 'property',
        path: [ node.id, 'content' ],
        startOffset: 0,
        endOffset: 0
      })
    }.bind(this))

    this.rerender()
    this.setSelection(newSel)
  }

  // only runs if editor is in read-only mode
  // disables all tools, apart from comments
  disableToolbar () {
    const commandStates = this.getCommandStates()

    each(keys(commandStates), key => {
      const allowed = ['comment', 'save', 'undo', 'redo']
      if (!includes(allowed, key)) commandStates[key].disabled = true
    })
  }

  getCommandStates () {
    const commandManager = this.context.commandManager
    return commandManager.getCommandStates()
  }

  isReadOnlyMode () {
    return !this.isEditable() && this.isSelectable()
  }

  links () {
    const allLinks = this.el.findAll('a')
    each(allLinks, link =>
      link.attr('target', '_blank')
    )
  }
john's avatar
john committed
export default ContainerEditor