implements basic menu functionalities

this includes standard block elements (headers, paragraphs, lists, rulers)
but not marks (bold, italic)
and for sure not special elements like the stat block
This commit is contained in:
koehr 2020-04-01 16:54:04 +02:00 committed by Norman
parent c64b9a95fb
commit 5fc559abac
4 changed files with 55 additions and 16 deletions

View file

@ -17,7 +17,7 @@
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import { blocks, State } from '@/editor.ts'
import { blocks, State } from '@/editor'
@Component
export default class DeckCardEditorMenu extends Vue {
@ -50,7 +50,7 @@ export default class DeckCardEditorMenu extends Vue {
padding: .2rem 1rem;
visibility: hidden;
opacity: 0;
transition: opacity 0.2s, visibility 0.2s;
transition: opacity .3s .2s, visibility .3s .2s;
background-color: var(--highlight-color);
z-index: 2;
}

View file

@ -7,7 +7,7 @@
/>
<div
:ref="content"
ref="content"
class="card-content"
:contenteditable="active"
@focus="start"
@ -30,13 +30,14 @@ import { Component, Prop, Vue } from 'vue-property-decorator'
import DeckCardEditorMenu from '@/components/deck-card-editor-menu.vue'
import {
elementNameToMenuState,
menuActionToCommand,
getElementAndParentName,
marks,
blocks,
State,
movementKeys,
controlSequenceKeys
} from '@/editor.ts'
} from '@/editor'
@Component({
components: { DeckCardEditorMenu }
@ -91,7 +92,13 @@ export default class DeckCardEditor extends Vue {
private editorAction (action: string) {
console.log('action', action)
// const content = this.$refs.content
const content = this.$refs.content as HTMLElement
content.focus()
const cmd = menuActionToCommand[action]
cmd()
this.$nextTick(() => this.syncMenuState())
}
private syncMenuState () {
@ -121,6 +128,8 @@ export default class DeckCardEditor extends Vue {
private start () {
this.contentInFocus = true
this.syncMenuState()
// insert paragraphs instead of DIVs on enter
document.execCommand('defaultParagraphSeparator', false, 'p')
}
private stop () {
@ -129,7 +138,7 @@ export default class DeckCardEditor extends Vue {
}
</script>
<style scoped>
<style>
.card-content p {
margin: 0;
line-height: 1.2;

View file

@ -1,5 +1,3 @@
export type State = KV<boolean>
export const movementKeys = [
'ArrowLeft',
'ArrowRight',
@ -37,11 +35,3 @@ export const blocks = [
'separator',
'statBlock'
]
export function getElementAndParentName (el: Node) {
const element = el.nodeName === '#text' ? el.parentElement : el
return [
element?.nodeName,
element?.parentElement?.nodeName
]
}

40
src/editor/index.ts Normal file
View file

@ -0,0 +1,40 @@
export type State = KV<boolean>
export {
movementKeys,
controlSequenceKeys,
elementNameToMenuState,
marks,
blocks
} from './constants'
function simpleAction (cmd: string, arg?: string): () => boolean {
return () => {
return document.execCommand(cmd, false, arg)
}
}
function insertHorizontalRule (): () => boolean {
return () => {
const hr = document.execCommand('insertHorizontalRule')
const p = document.execCommand('formatblock', false, 'P')
return hr && p
}
}
export const menuActionToCommand: KV<() => boolean> = {
paragraph: simpleAction('formatblock', 'P'),
heading1: simpleAction('formatblock', 'H1'),
heading2: simpleAction('formatblock', 'H2'),
heading3: simpleAction('formatblock', 'H3'),
bulletList: simpleAction('insertUnorderedList'),
numberedList: simpleAction('insertOrderedList'),
separator: insertHorizontalRule()
}
export function getElementAndParentName (el: Node) {
const element = el.nodeName === '#text' ? el.parentElement : el
return [
element?.nodeName,
element?.parentElement?.nodeName
]
}