You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CKEditor 5插件迁移:创建含输入框、文本域等的弹窗

CKEditor 5 自定义链接data属性插件实现示例

以下是适配TYPO3场景的CKEditor 5插件代码,包含你需要的输入框、文本域、复选框及说明文本控件,可直接参考修改:

核心对话框构建代码(view.js)

import { Dialog, DialogView } from '@ckeditor/ckeditor5-ui';
import { LabeledInputView, TextareaView, CheckboxView, View } from '@ckeditor/ckeditor5-ui';
import { Locale } from '@ckeditor/ckeditor5-utils';

export default class LinkDataAttributesView extends DialogView {
    constructor(locale) {
        super(locale);
        const t = locale.t;

        // 说明文本容器
        const infoView = new View(locale);
        infoView.setTemplate({
            tag: 'div',
            attributes: {
                class: 'ck-link-data-info'
            },
            children: [
                {
                    tag: 'p',
                    children: [t('为链接添加自定义data属性,仅支持合法的HTML data-前缀属性')]
                }
            ]
        });

        // 文本输入框(示例:data-tracking-id)
        this.trackingIdInput = new LabeledInputView(locale, 'text');
        this.trackingIdInput.label = t('跟踪ID');
        this.trackingIdInput.inputView.placeholder = t('输入跟踪ID');

        // 文本域(示例:data-description)
        this.descriptionTextarea = new TextareaView(locale);
        this.descriptionTextarea.label = t('描述文本');
        this.descriptionTextarea.placeholder = t('输入链接的描述信息');
        this.descriptionTextarea.rows = 3;

        // 复选框(示例:data-new-window)
        this.newWindowCheckbox = new CheckboxView(locale);
        this.newWindowCheckbox.label = t('在新窗口打开');
        this.newWindowCheckbox.set({
            value: '1'
        });

        // 组装对话框内容
        this.content.add(infoView);
        this.content.add(this.trackingIdInput);
        this.content.add(this.descriptionTextarea);
        this.content.add(this.newWindowCheckbox);

        // 设置对话框按钮
        this.buttons.set('save', {
            type: 'submit',
            label: t('保存'),
            class: 'ck-button-save'
        });
        this.buttons.set('cancel', {
            label: t('取消'),
            class: 'ck-button-cancel'
        });
    }
}

插件主逻辑(plugin.js)

import { Plugin } from '@ckeditor/ckeditor5-core';
import { ButtonView } from '@ckeditor/ckeditor5-ui';
import LinkDataAttributesView from './view';
import linkIcon from '@ckeditor/ckeditor5-link/theme/icons/link.svg';

export default class LinkDataAttributes extends Plugin {
    static get pluginName() {
        return 'LinkDataAttributes';
    }

    init() {
        const editor = this.editor;
        const t = editor.t;

        // 添加工具栏按钮
        editor.ui.componentFactory.add('linkDataAttributes', locale => {
            const button = new ButtonView(locale);
            button.set({
                label: t('链接属性'),
                icon: linkIcon,
                tooltip: true
            });

            // 点击按钮打开对话框
            button.on('execute', () => {
                this._openDialog();
            });

            return button;
        });
    }

    _openDialog() {
        const editor = this.editor;
        const locale = editor.locale;
        const dialog = new Dialog(locale);
        const view = new LinkDataAttributesView(locale);

        // 从选中的A标签读取现有属性
        const selection = editor.model.document.selection;
        const linkElement = selection.getSelectedElement() || selection.getFirstPosition().parent;
        if (linkElement && linkElement.is('element', 'a')) {
            view.trackingIdInput.inputView.value = linkElement.getAttribute('data-tracking-id') || '';
            view.descriptionTextarea.value = linkElement.getAttribute('data-description') || '';
            view.newWindowCheckbox.isChecked = linkElement.getAttribute('data-new-window') === '1';
        }

        // 绑定对话框提交事件
        dialog.on('submit', () => {
            editor.model.change(writer => {
                const linkElement = selection.getSelectedElement() || selection.getFirstPosition().parent;
                if (linkElement && linkElement.is('element', 'a')) {
                    // 写入/移除data属性
                    const trackingId = view.trackingIdInput.inputView.value.trim();
                    if (trackingId) {
                        writer.setAttribute('data-tracking-id', trackingId, linkElement);
                    } else {
                        writer.removeAttribute('data-tracking-id', linkElement);
                    }

                    const description = view.descriptionTextarea.value.trim();
                    if (description) {
                        writer.setAttribute('data-description', description, linkElement);
                    } else {
                        writer.removeAttribute('data-description', linkElement);
                    }

                    const newWindow = view.newWindowCheckbox.isChecked ? '1' : '';
                    if (newWindow) {
                        writer.setAttribute('data-new-window', newWindow, linkElement);
                    } else {
                        writer.removeAttribute('data-new-window', linkElement);
                    }
                }
            });

            dialog.destroy();
        });

        // 绑定取消事件
        dialog.on('cancel', () => dialog.destroy());

        dialog.show(view);
    }
}

TYPO3 整合要点

  1. 在你的扩展ext_localconf.php中注册插件:
$GLOBALS['TYPO3_CONF_VARS']['RTE']['Presets']['default']['editor']['config']['plugins'][] = 'linkdataattributes';
$GLOBALS['TYPO3_CONF_VARS']['RTE']['Presets']['default']['editor']['imports'][] = 'EXT:your_extension/Resources/Public/JavaScript/CKEditor5/';
  1. 将插件文件放入EXT:your_extension/Resources/Public/JavaScript/CKEditor5/目录,确保路径正确。
  2. 在TYPO3的RTE预设yaml文件中添加工具栏按钮:
editor:
  toolbar:
    items:
      - ...
      - linkDataAttributes

内容的提问来源于stack exchange,提问作者Alex Kellner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 07:15:35