- 前端
- UI组件
【免费下载链接】ckeditor4
The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.
本篇文章聚焦 CKEditor 4 的colordialog(颜色对话框)插件,围绕仓库中的手动测试文档 tests/plugins/colordialog/manual/addhash.md 展开:先给出可直接照做的 Bender 手动测试步骤,再深入plugin.js、dialogs/colordialog.js与自动化测试源码,解释「输入不带#的 3 位或 6 位十六进制色值时,确认后自动补上#」这一行为的实现原理、适用边界与内部调用链。读完你可以熟练复现该手动测试、理解editor.getColorFromDialog回调的返回值规则,并能在自己使用或二次开发颜色对话框时准确预判各种颜色格式的输入结果。
背景:为什么需要为十六进制色值自动补#
CSS 中合法的十六进制颜色既可以写作#ABC123(带前缀),也可以不带前缀。用户在使用颜色对话框时,往往会习惯性地只输入裸的十六进制数字(如ABC123或FFF),此时若直接把该值写入内联样式,得到的background-color: ABC123是无效的 CSS,颜色不会生效。
CKEditor 4 在colordialog关闭并取回颜色值的环节做了统一收口:凡是符合3 位或 6 位十六进制数字格式的输入,都会自动在开头补一个#,从而保证最终写入文档的颜色值始终是规范、可用的 CSS 颜色。这个行为对应仓库中的 issue 编号 565,并从 4.8.0 版本起以功能特性形式加入,因此手动测试文档addhash.md的 bender 标签写的是feature, colordialog, 565, 4.8.0。
手动测试文档逐条解读
原文档是一份 Bender 手动测试(manual test)脚本,运行前提是启用table、tabletools、colordialog、toolbar、wysiwygarea、sourcearea、contextmenu这组插件。完整步骤如下:
- 右键点击表格单元格(
Right click into table cell)。 - 选择
Cell -> Cell Properties,打开“单元格属性”对话框(由tabletools插件提供,见 plugins/tabletools/dialogs/tableCell.js)。 - 点击Background Color(背景色)旁边的
Choose按钮:- 期望结果:颜色对话框应弹出(
Color dialog should appear)。
- 期望结果:颜色对话框应弹出(
- 在输入框中输入 6 位十六进制色值,且不带前导
#(输入框位于Clear按钮正上方),例如ABC123。 - 确认(点击 OK):
- 期望结果:插入的颜色值开头自动补上了
#(Inserted color should contain additional '#' at the beginning),即得到#ABC123。
- 期望结果:插入的颜色值开头自动补上了
- 重复上述步骤,改用 3 位十六进制格式,例如
FFF,确认后应得到#FFF。
文档末尾有一条补充说明,划定了该行为的边界:
Note:You can also check the behaviour of color dialog by setting values in different formats (rgb, text) or invalid hex strings. For such colors
#should not be added.
即:对rgb(...)、rgba(...)、纯文本颜色名(如red)以及非法十六进制串,不会自动添加#。这正是下一节要讲的源码规则。
源码原理:#在哪里被加上
入口:editor.getColorFromDialog
colordialog插件在init中注册了名为colordialog的对话框命令,并通过editor.getColorFromDialog对外提供「打开颜色对话框并取回所选颜色」的 API,见 plugins/colordialog/plugin.js。签名如下:
editor.getColorFromDialog = function( callback, scope, options ) { ... };callback:对话框关闭后的回调,唯一参数为最终的颜色字符串(若未选择颜色或颜色无效则为null);scope:回调执行时的this上下文;options:可选项,会在show事件中以高优先级注入对话框数据(源码注释说明 priority 设为 5 是为了在对话框真正显示前把数据传进去)。
关键逻辑:onClose处理器
getColorFromDialog内部为对话框的ok与cancel事件绑定同一个onClose处理器(plugin.js),其中依次做了两件事:
第一步:格式合法性校验
var color = evt.name == 'ok' ? this.getValueOf( 'picker', 'selectedColor' ) : null; if ( color && !CKEDITOR.tools._isValidColorFormat( color ) ) { color = null; }只有点击OK才读取picker页签中selectedColor输入框的值;点击Cancel则直接得到null。随后调用 core/tools.js 中的私有工具方法CKEDITOR.tools._isValidColorFormat做字符级校验——它只检查字符串是否由a-z 0-9 ( ) # % , . /这些允许字符组成(去掉所有空白后匹配/^[a-z0-9()#%,./]+$/i),校验不通过则颜色置为null。
第二步:3 位 / 6 位十六进制自动补#
// Adding `#` character to hexadecimal 3 or 6 digit numbers to have proper color value (#565). if ( /^[0-9a-f]{3}([0-9a-f]{3})?$/i.test( color ) ) { color = '#' + color; }正则/^[0-9a-f]{3}([0-9a-f]{3})?$/i的含义是:恰好 3 位十六进制字符([0-9a-f]{3},即FFF这类格式),或者恰好 6 位十六进制字符(3 位加上可选的另外 3 位,即ABC123这类格式),大小写不敏感(i标志)。满足条件就在前面拼接#,最终通过callback.call( scope, color )把规范化后的颜色交还调用方。
为什么 rgb、颜色名、非法串不会被加#
结合上面两步可以精确解释文档末尾的 Note:
| 输入示例 | _isValidColorFormat校验 | 正则/^[0-9a-f]{3}([0-9a-f]{3})?$/i | 最终返回 |
|---|---|---|---|
ABC123 | 通过 | 匹配(6 位) | #ABC123 |
FFF/fde | 通过 | 匹配(3 位) | #FFF/#fde |
red | 通过(含字母) | 不匹配(3 个字符但r、e、d中r不是十六进制字符) | red(原样返回) |
rgb(10, 20, 30) | 通过(含括号与数字) | 不匹配 | rgb(10, 20, 30) |
1 | 通过 | 不匹配(位数不足 3) | 1(原样返回,属于非法 CSS 颜色,测试注释将其归类为 incorrect css color value) |
333333; | 不通过(含分号) | — | null |
| 空字符串 | 不通过(!colorCode直接返回 false) | — | null |
由此可见,补#是有意为之的白名单式规范化:只处理确定是十六进制色值的 3/6 位形式,其余格式一律原样放行,绝不擅自改写。
自动化测试佐证
仓库中对应行为的自动化测试位于 tests/plugins/colordialog/colordialog.js,其_should.ignore配置仅针对 IE8(该版本浏览器对非法颜色值的处理方式不同),其余用例完整覆盖了上表的行为:
'test colordialog add hash to color\'s values with 6 hexadecimal digits': function() { colorTools.assertColor( this.editor, '123456', '#123456' ); }, 'test colordialog add hash to color\'s values with 3 hexadecimal digits': function() { colorTools.assertColor( this.editor, 'FDE', '#FDE' ); }, 'test colordialog does not add hash to color value with 1 digit (incorrect css color value)': function() { colorTools.assertColor( this.editor, '1', '1' ); }, 'test colordialog does not add hash to color name': function() { colorTools.assertColor( this.editor, 'red', 'red' ); }, 'test colordialog does not add hash to rgb color value': function() { colorTools.assertColor( this.editor, 'rgb(10, 20, 30)', 'rgb(10, 20, 30)' ); }, 'test colordialog does not add hash to empty value ': function() { colorTools.assertColor( this.editor, '', '' ); }测试助手colorTools.assertColor定义在 tests/plugins/colordialog/_helpers/tools.js:先监听dialogShow事件,调用dialog.setValueOf( 'picker', 'selectedColor', inputColor )把输入写入对话框,再点击 OK 按钮,最后用editor.getColorFromDialog的回调断言返回值与期望值完全一致。这从测试层面证明:补#的行为发生在getColorFromDialog的返回环节,而不是在输入框或对话框内部——同一套输入在对话框里原样显示,只有在确认后才会被规范化。
从表格单元格属性到颜色对话框的调用链
手动测试第 1~3 步走的是真实业务路径:右键表格单元格 → 单元格属性 → 背景色 Choose 按钮。这条链路的实现依据是tabletools插件的 plugins/tabletools/dialogs/tableCell.js:
- 对话框定义开头读取
colorDialog = editor.plugins.colordialog(tableCell.js),以此判断是否渲染颜色选择按钮; - 当
colordialog插件存在时,bgColor输入框旁会追加一个type: 'button'、id: 'bgColorChoose'、label: langCell.chooseColor(对应 zh-cn 语言包中的 “选择颜色”)的按钮,onClick调用getColorForCell( this, 'bgColor' )(tableCell.js); getColorForCell(tableCell.js)正是通过editor.getColorFromDialog( function( color ) { ... }, button )打开颜色对话框,把回调中拿到的(可能已补过#的)颜色写回单元格属性对话框的bgColor输入框,并让按钮恢复焦点。
同样地,colorbutton插件在用户点击面板底部的 “更多颜色” 时也会走editor.getColorFromDialog(见 plugins/colorbutton/plugin.js),把选中的颜色通过setColor( color, colorName, history )应用到选区文本或背景。也就是说,补#的逻辑对所有经由getColorFromDialog打开颜色对话框的入口(表格单元格背景/边框色、文本色、背景色等)统一生效,无需每个调用方各自处理。
颜色对话框本身的构成
为了让手动测试更好上手,这里补充对话框内部布局,其实现全部位于 plugins/colordialog/dialogs/colordialog.js:
- 色板:
createColorTable()(colordialog.js)动态生成一个role="grid"的颜色表格,由基准色数组[ '00', '33', '66', '99', 'cc', 'ff' ]两两组合出 216 种网页安全色,最后一排额外追加从#000000到#ffffff的灰度色阶(每个单元格都带role="gridcell"、tabIndex=-1与无障碍标签)。 - 右侧面板:从上到下依次是“高亮(highlight)”预览色块、当前“选择颜色(selected)”预览色块、
selectedColor文本输入框以及Clear(清除)按钮。手动测试中提到的“输入框位于Clear按钮正上方”指的就是这里(colordialog.js)。 - 输入框联动:
selectedColor输入框的onChange会尝试把输入值设为右侧预览色块的背景色,失败(非法颜色)时调用clearSelected()清空预览(colordialog.js)。这正是用户可以自由输入ABC123、FFF、red或任意字符串进行测试的入口。 - 无障碍与键盘支持:色板单元格支持方向键移动焦点、空格/回车选择颜色,并根据 Rec. 709 luma 公式(
0.2126R + 0.7152G + 0.0722B,阈值 165)判断颜色明暗以切换聚焦高亮样式(colordialog.js)。
手动测试执行方式与常见问题
该文档是 CKEditor 4 仓库中 Bender 测试体系的一部分(手动测试的 UI 配置由@bender-ui: collapsed控制,即编辑器以折叠面板形式呈现)。运行相关手动/自动化测试需在仓库根目录通过 Bender 执行,例如:
# 启动 Bender 服务器后访问手动测试页面 npx bender server run # 或运行 colordialog 插件对应的自动化测试 npx bender run tests/plugins/colordialog(具体命令以仓库根目录的 bender.js 与 package.json 中配置的脚本为准。)
复现与排查建议:
- 确认补
#生效:输入 6 位(如ABC123)与 3 位(如FFF)裸十六进制值并确认,检查单元格背景色样式值是否为#ABC123/#FFF。也可在sourcearea下直接查看源码确认。 - 验证边界:按文档 Note 依次输入
red、rgb(10, 20, 30)、1、空值等,确认返回值原样或为null,绝不添加#。 - 多入口一致性:可通过表格单元格属性、
colorbutton的文本色/背景色“更多颜色”两个入口分别验证,结果应一致——因为两者最终都汇入同一个getColorFromDialog。
小结
addhash行为是 CKEditor 4 颜色选择流程中一处小而关键的用户体验设计:它把「用户输入裸十六进制色值」与「产出合法 CSS 颜色」之间的鸿沟,用一行白名单正则/^[0-9a-f]{3}([0-9a-f]{3})?$/i在getColorFromDialog的回调环节统一弥合。通过 addhash.md 手动测试、plugin.js 的onClose处理器、tools.js 的_isValidColorFormat校验以及 colordialog.js 的自动化用例,可以完整看到从需求、实现到测试验证的闭环。掌握这一规则后,无论是日常使用、编写自动化断言,还是基于getColorFromDialog做二次开发,都能对颜色值的最终形态有确定性的预期。
- 前端
- UI组件
【免费下载链接】ckeditor4
The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.
相关推荐
MAS v3.12 免费激活脚本:几分钟解决 Windows 和 Office 未激活的完整指南
MAS v3.12 免费激活脚本:几分钟解决 Windows 和 Office 未激活的完整指南 刚装好的系统右下角浮着一块"激活 Windows"提示,点开
前端UI组件Aperant PR Fix Agent 实战指南:将评审发现自动转化为精准代码修复
Aperant PR Fix Agent 实战指南:将评审发现自动转化为精准代码修复 Aperant(Autonomous multi session AI c
前端UI组件如何快速部署医疗AI:18个医学图像数据集的完整实战指南
如何快速部署医疗AI:18个医学图像数据集的完整实战指南 MedMNIST是一个专为医疗AI研究者和开发者设计的标准化医学图像数据集库,提供18个精心策划的2D
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考