vue富文本编辑器@人功能tinymce

获取光标的位置插件 caret-pos

import { position, offset } from 'caret-pos'
// 设置@人弹窗的位置
const setDialogPos = () => {
            nextTick(() => {
                const frame = document.getElementById('tinymces' + edittorIndex.value + '_ifr')
                // 编辑器dom ,has contenteditable atrribute
                const body = frame.contentWindow.document.body
                const html = frame.contentWindow.document.getElementsByTagName('html')[0]
                // markAtEl为当前光标在哪个元素,此值可设可不设
                const startElStyle = window.getComputedStyle ? window.getComputedStyle(markAtEl.value, '') : markAtEl.value.currentStyle
                const lineH = parseInt(startElStyle['line-height']) ? parseInt(startElStyle['line-height']) : parseInt(startElStyle['font-size']) + 10
                // dialogEl 为弹窗dom
                const childEle = dialogEl.value
                const parentW = body.offsetWidth
                const htmlH = html.clientHeight
                const childW = dialogEl.value.offsetWidth
                const childH = dialogEl.value.offsetHeight
                // 因为tinymce为iframe 中,所以要获取iframe 的位置
                const pos = position(body, { iframe: frame })
                const off = offset(body, { iframe: frame })
                // 弹框偏移超出父元素的宽高
                if (parentW - pos.left < childW) {
                    childEle.style.left = off.left - childW + 'px'
                } else {
                    childEle.style.left = off.left + 'px'
                }
                if (htmlH - pos.top < childH) {
                    childEle.style.bottom = htmlH - (off.top - html.scrollTop) + 10 + 'px'
                    childEle.style.top = ''
                } else {
                    childEle.style.top = off.top - html.scrollTop + 40 + lineH + 'px'
                    childEle.style.bottom = ''
                }
            })
        }

tinymce 富文本编辑器初始化设置

// init编辑器的配置参数
// 要想自己删除@人的时候是整个人名删除而不是一个文字文字的删除只需要引入 noneditable 插件即可
const settings = {
                selector: '#tinymces' + index.value,
                language_url: '/tinymce/zh_CN.js',
                skin_url: '/tinymce/skins/oxide',
                content_css: '/tinymce/skins/oxide/content.css',
                language: 'zh_CN',
                height: height.value,
                plugins: 'lists wordcount noneditable',
                toolbar: 'bold italic |  strikethrough underline | bullist numlist | mybutton',
                valid_elements: '*[*]',
                valid_children: '*[*]',
                menubar: false,
                branding: false,
                statusbar: false,
                SelectVal: '',
                fontsize_formats: '12px 14px 16px 18px 24px 36px 48px 56px 72px',
                setup: function(editor) {
                    // 功能按钮中添加自定义的button
                    editor.ui.registry.addButton('atPeople', {
                        icon: 'paste-text',
                        tooltip: '@人员',
                        text: '@',
                        onAction: function() {
                            atPeopleShowSet()
                        }
                    })
                }
            }
// ...
// show@弹框设置
        const atPeopleShowSet = () => {
            state.isShow = true
            // 获取当前光标在哪个dom 中
            state.selectionStart = state.activeEditor.selection.getStart()
        }
        // @人插入到富文本编辑器
        const selectPeople = (item) => {
            // 在编辑器中插入选择的要@的人
            state.activeEditor.execCommand('mceInsertContent', false, `@${item.name}`)
            state.isPeopleSelect = true
        }

注意:
在选择人后弹框隐藏,此时编辑器应该获取焦点,这时用 state.activeEditor.execCommand('mceInsertContent... 这个方法插入内容时编辑器会自动出发 focus事件然后blur 事件,所以要使编辑获取焦点需要在blur事件中再调用编辑获取焦点事件

// 编辑器中插入@人后,在编辑器 blur事件中调用编辑器获取焦点方法
const ifra = document.getElementById('tinymces' + index.value + '_ifr')
ifra.focus()

你可能感兴趣的:(vue富文本编辑器@人功能tinymce)