CKEditor 4 对话框输入框文本方向(RTL/LTR)的切换与保存机制:dialogui 插件 bidi 方向标记(Direction Marker)源码解析
前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载CKEditor 4 的对话框Dialog中文本输入框textInput / textarea支持通过快捷键快速切换文本方向Right-to-Left 或 Left-to-Right并且这一方向会随输入值一起保存、在下一次打开对话框时自动恢复。本文以tests/plugins/dialogui/manual/inputdirsave.md手动测试为线索完整讲解该功能的操作方式、bidi属性配置、\u202A/\u202B方向标记的实现原理以及setDirectionMarker()/getDirectionMarker()等 API 的底层行为并给出在自定义插件对话框中启用该能力的实战方法。功能来源与定位该能力由 dialogui 插件Dialog User Interface提供在 CKEditor 4.5.0 中随工单 #10986 引入“支持通过 ShiftAltHome/End 快捷键改变对话框输入框与 textarea 的文本方向”。方向信息不会丢失而是以 Unicode 隐式定向字符Implicit Directional Characters前置到输入值中随字段值一起存取从而保证“下一次打开对话框时恢复相同的文本方向”。在仓库中这一功能同时被三处文件覆盖形成完整的“文档 → 实现 → 测试”闭环手动测试用例inputdirsave.md保存方向与 inputdirtoggle.md切换方向自动化单元测试dirmarker.js核心实现dialogui/plugin.js。实测操作以表格对话框的 Summary 输入框为例手动测试用例 inputdirsave.md 使用表格Table对话框中的“Summary”摘要输入框来验证方向保存行为。运行前提是编辑器加载了wysiwygarea, toolbar, table, contextmenu这些插件对应 Bender 元数据bender-ckeditor-plugins测试页面本身只是一个替换了#editor的普通编辑器实例见 inputdirsave.html。完整操作流程如下打开表格对话框点击工具栏上的 Table 按钮。聚焦 “Summary” 输入框。按ALT SHIFT END切换方向键盘没有 END 键时使用FN ALT SHIFT RIGHT ARROW。预期结果Summary 输入框的方向变为 RTL。可通过两种方式验证检查输入框元素应带有dirrtl属性直接输入文本或使用方向键会发现字符/光标行为发生反向具体表现取决于浏览器。输入一些文本。提交对话框插入一张表格。再次点击工具栏的表格按钮新建表格的对话框。预期结果Summary 输入框的方向为 LTR新建表格没有初始值方向回到默认。关闭该对话框不提交。打开第一张表格的属性对话框。预期结果Summary 输入框的方向恢复为 RTL。这套步骤的精髓在于验证了三个关键行为切换快捷键能实时改变输入框方向步骤 3–4保存方向随值存入summary属性提交后再打开同一表格时方向被恢复步骤 6、10–11隔离无初始值的新对话框使用默认方向 LTR不会被上一次的方向“污染”步骤 7–8。方向切换的快捷键与事件绑定快捷键处理逻辑位于 dialogui/plugin.js 的toggleBidiKeyUpHandler函数// context {CKEDITOR.dialog.uiElement} UI element (textarea or textInput) // param {CKEDITOR.dom.event} evt toggleBidiKeyUpHandler function( evt ) { var keystroke evt.data.getKeystroke(); // ALT SHIFT Home for LTR direction. if ( keystroke CKEDITOR.SHIFT CKEDITOR.ALT 36 ) this.setDirectionMarker( ltr ); // ALT SHIFT End for RTL direction. else if ( keystroke CKEDITOR.SHIFT CKEDITOR.ALT 35 ) this.setDirectionMarker( rtl ); };两个快捷键对应的键码分别是36Home和35End叠加SHIFT ALT修饰键。可见ALT SHIFT Home→ 切换为LTRALT SHIFT End→ 切换为RTL。该处理器只对声明了bidi: true的控件生效。对单行文本输入框textInput事件绑定发生在 plugin.js对话框load时给输入元素挂上keydown/keyup监听其中keyup中通过if ( me.bidi )判断后才调用toggleBidiKeyUpHandler。对多行文本域textarea同理见 plugin.jsif ( me.bidi ) { dialog.on( load, function() { me.getInputElement().on( keyup, toggleBidiKeyUpHandler ); }, me ); }注意keyup监听在 textInput 上注册时使用了较低的优先级null, null, 1000这是为了避免与对话框 OK 按钮的 Enter 键提交逻辑冲突对应工单 #3749见 plugin.js 的注释。bidi 属性如何在对话框定义中启用方向切换方向切换并非默认开启开发者需要在对话框字段定义中显式声明bidi: true。API 文档定义于 dialogDefinition.js要点如下ShiftAltEnd—— 切换为 RTLShiftAltHome—— 切换为 LTR默认情况下输入框不设置任何文本方向即继承编辑器自身的文本方向editor 的lang.dir一旦设置了方向会在该字段每个非空值前前置一个方向标记\u202ARTL或\u202BLTR该标记的作用正是“在下次打开对话框时恢复相同的文本方向”。仓库中的典型用例是表格对话框的 Summary 字段定义于 table/dialogs/table.js{ type: text, id: txtSummary, bidi: true, requiredContent: table[summary], label: editor.lang.table.summary, setup: function( selectedTable ) { this.setValue( selectedTable.getAttribute( summary ) || ); }, commit: function( data, selectedTable ) { if ( this.getValue() ) selectedTable.setAttribute( summary, this.getValue() ); else selectedTable.removeAttribute( summary ); } }这里的bidi: true让 Summary 输入框获得方向切换能力setup在对话框打开时把表格已有的summary属性值可能带方向标记灌入输入框commit在提交时把值含方向标记写回table元素。同时 table/plugin.js 的allowedContent声明了table{width,height,border-collapse}[align,border,cellpadding,cellspacing,summary]保证summary属性在内容过滤时不被剥离。方向标记的存储与恢复setValue / getValue 的魔法方向之所以能在对话框重开时“自动恢复”关键在于 dialogui 对setValue()与getValue()的重写——它们负责把方向标记从值中“剥离/注入”。setValue()plugin.js当字段bidi: true时检查值的首字符是否为标记setValue: function( value ) { if ( this.bidi ) { var marker value value.charAt( 0 ), dir ( marker \u202A ? ltr : marker \u202B ? rtl : null ); if ( dir ) { value value.slice( 1 ); } // Set the marker or reset it (if dirnull). this.setDirectionMarker( dir ); } if ( !value ) { value ; } return CKEDITOR.ui.dialog.uiElement.prototype.setValue.apply( this, arguments ); },首字符为\u202A→ 方向判定为ltr首字符为\u202B→ 方向判定为rtl其余情况方向为null无标记。随后标记字符被slice(1)剥离只把“纯文本”写入真实的inputDOM同时调用setDirectionMarker()把方向同步到dir属性上。这正是手动测试中“检查输入框应带有dir属性”的依据。getValue()plugin.js反向操作取值时若存在方向标记则把标记重新前置到值上getValue: function() { var value CKEDITOR.ui.dialog.uiElement.prototype.getValue.call( this ); if ( this.bidi value ) { var dir this.getDirectionMarker(); if ( dir ) { value ( dir ltr ? \u202A : \u202B ) value; } } return value; },这一来一回形成了方向保存的完整闭环用户在对话框里按ALTSHIFTEND把方向切为 RTL输入文本内容提交时commit调用getValue()得到\u202B 内容存入表格的summary属性下次打开该表格对话框setup调用setValue(\u202B内容)setValue识别出\u202B标记 → 恢复 RTL 方向 → 输入框显示纯文本内容。这解释了手动测试第 10–11 步“打开第一张表格对话框时方向应为 RTL”的原因而第 7–8 步新建表格因为没有summary初始值setValue()得到dir null方向回落为默认的 LTR。setDirectionMarker 与 getDirectionMarkerdir 与>/** * Sets the text direction marker and the dir attribute of the input element. * since 4.5.0 * param {String} dir The text direction. Pass null to reset. */ setDirectionMarker: function( dir ) { var inputElement this.getInputElement(); if ( dir ) { inputElement.setAttributes( { dir: dir, data-cke-dir-marker: dir } ); // Dont remove the dir attribute if this field hasnt got the marker, // because the dir attribute could be set independently. } else if ( this.getDirectionMarker() ) { inputElement.removeAttributes( [ dir, data-cke-dir-marker ] ); } }, /** * Gets the value of the text direction marker. * since 4.5.0 * returns {String} ltr, rtl or null if the marker is not set. */ getDirectionMarker: function() { return this.getInputElement().data( cke-dir-marker ); },需要特别说明的细节写入方向时同时设置两个属性dir用于浏览器的实际渲染/光标行为和data-cke-dir-markerCKEditor 内部用于识别“该方向是用户显式设置的”getDirectionMarker()读取的正是data-cke-dir-marker清除方向时只有当字段已有方向标记即getDirectionMarker()非空才移除dir和data-cke-dir-marker。注释明确说明原因dir属性可能被独立设置例如在字段定义中直接写dir: rtl见 plugin.js 对 textarea 的处理不能因为“本次没有标记”就误删用户显式配置的dir。自动化测试佐证dirmarker.js功能的行为边界在 dirmarker.js 中被完整固化其主要断言覆盖了真实输入值不含标记setValue(\u202Bhello!)后底层input的原始值通过CKEDITOR.ui.dialog.uiElement.prototype.getValue.call( field )读取不应包含\u202BgetValue 注入标记对 RTL 字段调用getValue()后结果首字符应为\u202B对 LTR 应为\u202AgetDirectionMarker 返回值分别验证rtl、ltr、null三种状态无标记字段原样传递未声明bidi的字段无论setValue传入什么值getValue()都原样返回标记不会被剥离或注入且getDirectionMarker()始终为null空值与纯标记空字符串不会产生标记只含标记的值\u202B会被剥成空字符串getValue()同样返回空串setDirectionMarker 的 DOM 效果传入rtl/ltr时data-cke-dir-marker与dir两个属性同步存在且值一致传入空值时两个属性都被移除。这些断言与手动测试inputdirsave.md的验证方式检查dir属性、观察光标/字符反向互为印证一个验证 DOM 表现一个验证数据流逻辑。在自己插件中启用该能力若要在自定义对话框字段中支持 RTL/LTR 切换与保存只需两步在字段定义中声明bidi: true适用于type: text、password、tel、textarea它们都由 dialogui 的textBuilder/commonBuilder构建见 plugin.js 与末尾的addUIElement注册 plugin.js在commit回调中使用this.getValue()自动携带标记写入数据源在setup回调中使用this.setValue(已有值)自动剥离标记并恢复方向回填输入框。一个最小示例CKEDITOR.dialog.add( myDialog, function( editor ) { return { title: My Dialog, contents: [ { id: info, elements: [ { type: text, id: myField, label: My Field, bidi: true, setup: function( widget ) { this.setValue( widget.data.myField || ); }, commit: function( widget ) { widget.setData( myField, this.getValue() ); } } ] } ] }; } );这样最终写入数据的字符串中会自然携带\u202A/\u202B前缀下次打开对话框时方向即可无损恢复——与表格对话框 Summary 字段的行为完全一致。小结CKEditor 4 对话框输入框的双向文本方向功能本质上是一套“DOM 属性 值内标记”的双通道机制dir/data-cke-dir-marker属性负责即时渲染与方向识别\u202A/\u202B标记负责跨会话持久化。理解setValue/getValue的剥标记、注标记逻辑以及setDirectionMarker/getDirectionMarker的属性读写规则是掌握并复用它无论是排查表格 Summary 字段类问题还是为自定义对话框接入 RTL 支持的关键。赞分享前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载相关推荐Angular Material 双向文本方向Bidirectionality指南用 CDK Bidi 让你的组件自动适配 LTR/RTLAngular Material 双向文本方向Bidirectionality指南用 CDK Bidi 让你的组件自动适配 LTR/RTL 本文基于 An前端UI组件设计系统Notepads 文本方向切换完全指南LTR 与 RTL 支持的终极教程Notepads 文本方向切换完全指南LTR 与 RTL 支持的终极教程 Notepads 作为一款现代化的轻量级文本编辑器提供了全面的 文本方向切换功能桌面应用uni-app x 中的 CSS direction 属性从 LTR 到 RTL 的文本方向控制与跨端兼容实践uni app x 中的 CSS direction 属性从 LTR 到 RTL 的文本方向控制与跨端兼容实践 导读 direction 是控制文本水平溢出方示例工程前端移动开发跨平台上一篇knowledge-work-plugins 小企业插件 content-strategy 技能避坑指南从销售数据分析到 30 天内容简报的八大 Gotchas 实战手册下一篇基于 Rube MCP 自动化 Idea Scale 任务awesome-codex-skills 中的 Composio 集成实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Airi 与 Home Assistant 集成:从 ADR 到 Electron 主进程服务的落地实现

Airi 与 Home Assistant 集成:从 ADR 到 Electron 主进程服务的落地实现

人工智能AI AgentMCP 服务工具调用GUI 自动化语音数字人交互助手 【免费下载链接】airi 💖🧸 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器,目标是接近 Neuro-sama 的高度;支持实时语音聊天、Minecraft 和 F…

2026/10/16 9:14:29 阅读更多 →
Compose 自定义 Indication 完全指南:从 InteractionSource 到可复用点击反馈

Compose 自定义 Indication 完全指南:从 InteractionSource 到可复用点击反馈

做了几年 Compose 的界面开发,你会发现一个迟早会碰上的问题:默认的ripple(水波纹)虽然够用,但它永远长成一个样。Material 官方把波纹设计成了统一的颜色、统一的按压缩放逻辑,一旦视觉设计师给了你一张“…

2026/10/16 9:13:28 阅读更多 →
Java 8 Stream API 入门与实战:从流水线到并行流

Java 8 Stream API 入门与实战:从流水线到并行流

“Java8之Steam API”——先别急着笑,我第一次接触这个API的时候,也在关键词里把 Stream 打成了 Steam,当时还纳闷为什么怎么搜都是游戏平台。这个标题字是错的,但很多人确实是从“Steam”这个错误拼写开始认识 Java 8 的 Stream …

2026/10/16 9:13:28 阅读更多 →

最新新闻

DeepSeek API调用避坑指南:Python环境、SDK版本与模型参数三重校准

DeepSeek API调用避坑指南:Python环境、SDK版本与模型参数三重校准

简介:本资源是一份面向Python开发者与AI应用工程师的DeepSeek API实战入门指南,聚焦从零开始调用大模型接口的核心流程,解决API注册、环境配置、代码集成、流式响应与多轮对话等关键问题。适用于需快速将DeepSeek语言能力嵌入聊天机器人、智能…

2026/10/16 18:13:56 阅读更多 →
小样本玻璃分类实战:Bagging集成KNN与决策树

小样本玻璃分类实战:Bagging集成KNN与决策树

1. 这不是“套模型”,而是理解分类问题本质的一次实操你拿到一份玻璃成分数据,想判断它属于哪一类工业用途的玻璃——是建筑用浮法玻璃、汽车挡风玻璃、还是实验室器皿用的硼硅酸盐玻璃?这类问题在材料科学、质检自动化、回收分拣场景里天天发…

2026/10/16 18:13:56 阅读更多 →
开源版WorkBuddy框架拆解:工具编排与上下文管理实战

开源版WorkBuddy框架拆解:工具编排与上下文管理实战

1. 这个"开源版 WorkBuddy"到底是个什么东西先把话说在前头:标题里那个"王炸"和"夯"是网络化的表达,剥掉情绪词,真正有价值的信息是——某头部大厂开源了一套面向团队协作场景的智能工作助手框架,圈…

2026/10/16 18:13:56 阅读更多 →
AI-native芯片设计:数据闭环与物理实现优化才是落地关键

AI-native芯片设计:数据闭环与物理实现优化才是落地关键

1. 从一条研究动态说起:AI-native 芯片设计到底在聊什么前阵子某头部科技团队放出了一份关于 AI-native 芯片设计的研究分享,圈子里讨论得挺热闹。我翻了一圈相关的技术帖和从业者的零散评论,发现大多数讨论都集中在“AI 能不能替代芯片设计工…

2026/10/16 18:13:56 阅读更多 →
OpenCV线性滤波实战:均值、高斯、方框滤波原理与选型指南

OpenCV线性滤波实战:均值、高斯、方框滤波原理与选型指南

1. 模糊图像这件事,到底在解决什么问题刚接触OpenCV那会儿,我对“模糊”这个操作是有点抗拒的。辛辛苦苦拍到的画面、跑出来的数据,为什么要主动把它弄糊?后来做缺陷检测项目,被噪声折腾得没脾气,才真正理解…

2026/10/16 18:13:56 阅读更多 →
COCO人体关键点数据集准备避坑指南

COCO人体关键点数据集准备避坑指南

1. 为什么“准备COCO Keypoints数据集”不是复制粘贴就能搞定的事很多人第一次接触人体姿态估计任务时,看到教程里轻描淡写一句“下载COCO数据集,用官方脚本转成Keypoints格式”,就以为万事大吉。我去年带一个跨专业转AI的团队做实时动作识别…

2026/10/16 18:12:55 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →