Newer
Older
import { each, keys, includes } from 'lodash'
import {
ContainerEditor as SubstanceContainerEditor,
// deleteCharacter,
// deleteSelection,
} from 'substance'
class ContainerEditor extends SubstanceContainerEditor {
render ($$) {
// native spellcheck
el.attr('spellcheck', this.props.spellcheck === 'native')
// TODO -- should maybe change to isEditable ?
// or maybe delete it? we never pass a disabled prop explicitly
if (!this.props.disabled) {
el.addClass('sm-enabled')
el.setAttribute('contenteditable', true)
}
return el
}
if (this.isReadOnlyMode()) {
const documentSession = this.getDocumentSession()
documentSession.on('didUpdate', this.disableToolbar, this)
this.addTargetToLinks()
}
onTextInput (event) {
if (!this.props.trackChanges) return super.onTextInput(event)
onTextInputShim (event) {
if (!this.props.trackChanges) return super.onTextInputShim(event)
this.handleTracking({
event: event,
status: 'add',
surfaceEvent: 'input',
keypress: true
})
}
if (!this.props.trackChanges) return super._handleDeleteKey(event)
this.handleTracking({
event: event,
status: 'delete',
surfaceEvent: 'delete'
})
}
_handleSpaceKey (event) {
if (!this.props.trackChanges) return super._handleSpaceKey(event)
this.handleTracking({
event: event,
status: 'add',
surfaceEvent: 'space'
})
}
shouldIgnoreKeypress (event) {
// see Surface's onTextInputShim for comments
if (
event.which === 0 ||
event.charCode === 0 ||
event.keyCode === keys.TAB ||
event.keyCode === keys.ESCAPE ||
Boolean(event.metaKey) ||
(Boolean(event.ctrlKey) ^ Boolean(event.altKey))
) {
return true
}
return false
}
getTextFromKeypress (event) {
let character = String.fromCharCode(event.which)
if (!event.shiftKey) character = character.toLowerCase()
if (character.length === 0) return null
return character
}
handleTracking (options) {
const trackChangesProvider = this.context.trackChangesProvider
const { event, keypress, surfaceEvent } = options
if (!keypress) {
event.preventDefault()
event.stopPropagation()
}
if (keypress) {
if (this.shouldIgnoreKeypress(event)) return
const text = this.getTextFromKeypress(event)
event.data = text
event.preventDefault()
event.stopPropagation()
}
if (!keypress && !event.data) return
if (surfaceEvent === 'delete') {
const direction = (event.keyCode === keyboardKeys.BACKSPACE) ? 'left' : 'right'
options.move = direction
options.key = (direction === 'left') ? 'BACKSPACE' : 'DELETE'
}
// create an empty paragraph with an empty node
// then select it for cursor focus
this.editorSession.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',
containerId: 'body',
surfaceId: 'body',
path: [ node.id, 'content' ],
startOffset: 0,
endOffset: 0
})
}.bind(this))
this.rerender()
// 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', 'note', 'save', 'undo', 'redo', 'track-change-toggle-view']
if (!includes(allowed, key)) commandStates[key].disabled = true
})
}
getCommandStates () {
const commandManager = this.context.commandManager
return commandManager.getCommandStates()
}
isReadOnlyMode () {
return !this.isEditable() && this.isSelectable()
}
const allLinks = this.el.findAll('a')
each(allLinks, link =>
link.attr('target', '_blank')
)
}