CKEditor 4 表格选择与 image2 组件:深入解析 1027 组件取消选中问题及测试用例

📅 发布时间:2026/10/16 1:39:57
CKEditor 4 表格选择与 image2 组件:深入解析 1027 组件取消选中问题及测试用例
前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载导读本篇文章围绕 CKEditor 4 仓库中一张与表格选择Table Selection及 image2 组件Widget相关的集成测试用例文档展开重点剖析在表格中点击图片组件后如何正确地取消选中组件、恢复单元格光标从而保证用户能够在表格内自由输入文字与插入新图片。文中将完整还原该手动测试Manual Test的复现步骤、预期行为与判定标准并结合 tableselection 插件源码 与 image2 插件源码 中的关键逻辑说明其底层实现原理帮助开发者理解这一类组件与表格选择互斥场景的成因与处理方式。一、测试文档背景tableselection 与 image2 的集成场景1.1 关联文档位置与文件构成本次讨论的关联文档位于仓库的集成测试目录下测试说明手动测试步骤deselectwidget.md测试页面HTML 夹具deselectwidget.html该目录位于tests/plugins/tableselection/integrations/image2/从路径可以看出它是表格选择tableselection插件与增强图片image2插件之间的集成测试。同目录下还包含一个自动化的单元测试 paste.js用于验证表格内粘贴图片组件的行为与本手动测试共同覆盖了两者在表格场景下的协作。1.2 涉及的核心插件插件作用仓库位置table基础表格内容支持plugins/table/plugin.jstableselection提供表格内的伪选择fake selection能力支持跨单元格框选plugins/tableselection/plugin.jsimage2将图片增强为可编辑组件Widget支持拖拽缩放、对齐、加注等plugins/image2/plugin.jswidget组件框架为 image2 提供底座plugins/widget/plugin.jswysiwygarea经典 iframe 编辑区域plugins/wysiwygarea/plugin.jsundo/clipboard/basicstyles/toolbar/resize撤销、剪贴板、基础样式、工具栏与窗口缩放对应 plugins 目录其中tableselection插件的依赖声明为requires: clipboard,tabletools见 plugins/tableselection/plugin.js#L1195并声明了isSupportedEnvironment()不支持 IE 11 以下版本L1197-L1199这也是测试页面中会调用bender.tools.ignoreUnsupportedEnvironment( tableselection )的原因。二、测试用例全解析手动复现步骤与判定标准2.1 Bender 测试元数据文档首部的 Bender 标签声明了该用例的属性bender-tags: 1027, 4.8.0, widget, bug bender-ui: collapsed bender-ckeditor-plugins: undo,clipboard,basicstyles,toolbar,wysiwygarea,widget,table,tableselection,resize,image2字段含义1027关联的缺陷Bug编号即后文提到的 #10274.8.0该缺陷在 4.8.0 版本引入或修复结合源码注释该修复随 4.8.0 一并发布widget/bug用例类型标签表示这是组件相关的缺陷回归测试bender-ui: collapsed手动测试以折叠 UI 方式呈现便于聚焦编辑器内容bender-ckeditor-plugins测试页面加载的插件列表完整复刻了缺陷场景所需的运行环境。2.2 测试页面夹具Fixture配套的 HTML 文件 deselectwidget.html 定义了测试环境labelLenas path: input styleborder:2px solid black typetext value%BASE_PATH%_assets/lena.jpg readonly/label textarea ideditor table border1 cellpadding1 cellspacing1 stylewidth:500px tbody tr tdText/td tdTest/td /tr tr tdimg altLena src%BASE_PATH%_assets/lena.jpg styleheight:150px; width:150px //td tdnbsp;/td /tr tr tdnbsp;/td tdnbsp;/td /tr /tbody /table pnbsp;/p /textarea script if ( bender.tools.env.mobile ) { bender.ignore(); } bender.tools.ignoreUnsupportedEnvironment( tableselection ); CKEDITOR.replace( editor, { extraPlugins: image2 } ); /script要点说明表格结构一个 3 行 × 2 列的表格第二行第一列放置了一张 150px × 150px 的 Lena 图片lena.jpg为测试资产位于 tests/_assets/lena.jpg。图片路径提示页面上方提供只读输入框展示 Lena 图片的路径%BASE_PATH%_assets/lena.jpg供测试者在插入新图片步骤中使用。运行环境过滤移动端直接bender.ignore()跳过通过bender.tools.ignoreUnsupportedEnvironment( tableselection )在不支持 tableselection 的浏览器IE 11上自动忽略。编辑器初始化CKEDITOR.replace( editor, { extraPlugins: image2 } )在默认插件集基础上额外启用image2从而让lena.jpg在进入编辑器后被 upcast 为图片组件Widget。2.3 复现步骤文档原文完整继承按文档所述操作步骤为点击图片Lena 的图片使图片组件获得焦点并处于选中状态点击表格中的另一个单元格然后开始操作注意不要点击表格外部输入一些文字插入一张新图片Lena 图片的路径显示在编辑器上方。2.4 预期行为Expected可以自由地输入文字并编辑文本可以添加新的图片图片不再保持残留选中状态。2.5 非预期行为Unexpected无法执行上述预期中的任何操作选择Selection始终停留在图片上。简而言之点击单元格后光标应当从组件移入单元格用户可以正常编辑如果选择一直粘在图片上则说明出现了 #1027 所描述的回归缺陷。三、缺陷根因为什么选择会粘在图片组件上3.1 两套选择机制的冲突在启用tableselection后表格内存在两套并行的选择机制Widget 的假选择fake selection点击image2图片组件时widget 插件会用一个不可见的假选择fake selection包裹组件表现为图片外围出现高亮/控制手柄参见 plugins/widget/plugin.js 中Widget.focus()相关逻辑。表格的伪选择fake table selectiontableselection通过给单元格添加cke_table-faked-selection类来模拟跨单元格框选见 plugins/tableselection/plugin.js#L9其视觉样式定义于 plugins/tableselection/styles/tableselection.css。当用户先选中图片组件、再点击表格单元格时tableselection的鼠标处理逻辑fakeSelectionMouseHandlerL288会尝试判断是否清除当前选择。如果判断失误就会把组件的选中状态残留下来导致后续输入、插入图片全部失效——这正是文档中Unexpected描述的现象。3.2 关键修复点识别组件作为事件目标#1027在 plugins/tableselection/plugin.js#L218 附近fakeSelectByMouse函数中有一段针对 #1027 的注释与逻辑// The selection is inside one cell, so we should allow native selection, // but only in case if no other cell between mousedown and mouseup // was selected. // We dont want to clear selection if widget is event target (#1027). if ( !fakeSelection.dirty cells.length 1 !( isWidget( evt.data.getTarget() ) ) ) { return clearFakeCellSelection( editor, evt.name mouseup ); }其含义是当鼠标按下到抬起之间只经过一个单元格、且事件目标不是组件时才允许清除表格伪选择、恢复原生选择。若事件目标是组件例如图片 Widget则不要清除选择以免破坏组件自身的假选择状态。配套的isWidget工具函数定义在 plugins/tableselection/plugin.js#L20-L22function isWidget( element ) { return CKEDITOR.plugins.widget CKEDITOR.plugins.widget.isDomWidget( element ); }而CKEDITOR.plugins.widget.isDomWidget的定义位于 plugins/widget/plugin.js#L1723-L1725Widget.isDomWidget function( node ) { return node ? this.isDomWidgetWrapper( node ) || this.isDomWidgetElement( node ) : false; };即只要 DOM 节点带有data-cke-widget-wrapper组件包装层或data-widget组件元素属性就被判定为组件。这两个属性分别由 Widget.isDomWidgetWrapper 与 Widget.isDomWidgetElement 判断。3.3 另一处组件感知处理鼠标事件过滤在fakeSelectionMouseHandler入口plugins/tableselection/plugin.js#L288-L297还有一层组件防护// Prevent applying table selection when widget is selected. // Mouseup remains a possibility to finish table selection when user release mouse button above widget in table. if ( evt.name ! mouseup isWidget( evt.data.getTarget() ) ) { return; }意思是除 mouseup 之外的鼠标事件如 mousedown、mousemove若命中组件则直接忽略不触发表格伪选择mouseup 仍保留作为在表格内释放鼠标、结束框选的兜底路径。这就确保了用户对组件的常规操作点击、拖动不会被表格选择逻辑干扰。3.4 组件本身对 image 类型选择的避让除了 tableselection 一侧的防护fakeSelectionChangeHandler中还针对图片被选中的情况做了处理plugins/tableselection/plugin.js#L230-L254var enclosedNode ranges ranges[ 0 ].getEnclosedNode(), isEnclosedNodeAnImage enclosedNode ( enclosedNode.type CKEDITOR.NODE_ELEMENT ) enclosedNode.is( img ), ... // Dont perform fake selection when image is selected (#2235). if ( isEnclosedNodeAnImage ) { editor.getSelection().reset(); return; }当选区封闭节点是img元素时直接重置选择并返回不做表格伪选择。这从另一条路径保证了图片被选中时表格选择不介入。四、从源码结构理解整个点击单元格 → 取消选中组件的链路综合上文一次完整的交互链路可以概括为用户点击图片组件 └─ widget 插件接管组件获得焦点fake selection on widget 用户点击表格内另一单元格事件目标为单元格或单元格内文本 ├─ fakeSelectionMouseHandler 收到 mousedown/mouseup │ ├─ 目标非组件 → 允许进入表格伪选择流程 │ ├─ cells.length 1 且 fakeSelection.dirty false │ │ └─ 清除表格伪选择 clearFakeCellSelection( editor, true ) │ │ └─ 移除 cke_table-faked-selection 类并重置原生选择 │ └─ 目标为组件 → 跳过/不干预#1027 防护 └─ 光标落入单元格可自由输入文字 / 插入新图片其中clearFakeCellSelectionplugins/tableselection/plugin.js#L120-L149承担清除工作移除编辑区域上的cke_table-faked-selection-editor类遍历并移除所有单元格上的cke_table-faked-selection类清除表格上的cke-table-faked-selection-table数据属性在reset为true时重置fakeSelection状态并仅在当前选择确实在表格内时调用editor.getSelection().reset()——源码注释明确指出这一步是为了避免破坏组件选择L143-L147。此外tableselection的初始化L1223-L1243将fakeSelectionMouseHandler绑定在文档级的mousedown/mousemove/mouseup事件上并将fakeSelectionChangeHandler绑定在编辑器的selectionCheck事件上构成鼠标拖拽 选区变化双重驱动的伪选择体系。五、测试资产与配套验证5.1 手动测试所需的图片资产测试步骤中插入新图片所引用的 Lena 图片路径为%BASE_PATH%_assets/lena.jpg对应仓库中的 tests/_assets/lena.jpg。手动测试时可直接将页面上方输入框中的路径复制到图片对话框中使用。5.2 同目录下的自动化集成测试与手动测试互补的自动化用例是 paste.js它验证了在tableselection image2组合下粘贴图片的关键行为function pasteImage( editor, callback ) { editor.once( afterPaste, function() { resume( function() { var images editor.editable().find( .cke_widget_image ); ...从源码结构看其断言方向包括粘贴后图片以cke_widget_image类标识的组件形式存在即被 upcast 为 image2 组件撤销undo只产生一个撤销步骤且撤销/重做行为正确paste.js#L25-L26粘贴后正确的单元格被选中。该用例同时覆盖 classic 与 inline 两种编辑器paste.js#L7-L12与手动测试共同组成对表格-组件集成行为的回归保障。5.3 image2 的组件化机制对测试前提的意义测试页面之所以能复现缺陷前提是lena.jpg在加载后被image2的 upcast 逻辑转换为组件。image2 插件的 upcast 定义位于 plugins/image2/plugin.js#L899-L971它会将独立的img或aimg、带 caption 类的figure识别为组件元素并交给 widget 框架处理同时排除带有data-cke-realelement的粘贴伪对象L910-L912。这正是点击图片后它会表现为一个可聚焦组件的机制来源。六、如何运行与回归验证6.1 运行 Bender 手动测试本仓库使用 Bender 作为测试框架见 bender.js 与 package.json 中的benderjs依赖。运行手动测试的一般方式# 安装依赖如尚未安装 npm install # 启动 bender 服务器并进入手动测试交互界面 ./node_modules/.bin/bender server run在打开的 Bender 测试列表中定位到tests/plugins/tableselection/integrations/image2/manual/deselectwidget.html随后按照本文2.3 复现步骤操作并对照2.4 预期行为与2.5 非预期行为判断结果。6.2 验证要点速查操作预期结果点击 Lena 图片图片组件被选中出现组件焦点样式点击表格另一单元格输入文字光标进入单元格文字可正常输入图片不再保持选中点击表格另一单元格插入新图片新图片可正常插入并成为组件原图片不再保持选中全程不点击表格外部上述行为在表格内部即可完成6.3 适用版本与运行前提该缺陷与修复与4.8.0版本相关见bender-tags当前仓库源码中的修复逻辑以注释(#1027)标注tableselection仅在 IE 11 及以上浏览器生效plugins/tableselection/plugin.js#L1197-L1199旧版 IE 中该测试会被自动忽略手动测试在移动端会被跳过bender.ignore()。七、总结本文以 deselectwidget.md 这份手动测试文档为核心完整还原了表格内点击图片组件后如何取消选中、恢复单元格编辑这一场景的复现步骤与预期标准并从源码层面解释了其背后组件假选择与表格伪选择两套机制的协调逻辑tableselection通过isWidget()识别事件目标是否为组件避免误清组件选择#1027 修复点plugin.js#L218-L220除 mouseup 外的鼠标事件命中组件时直接忽略防止表格选择干扰组件操作plugin.js#L293-L297选区封闭节点为img时重置选择、跳过表格伪选择plugin.js#L250-L254。对于需要深度定制表格 图片组件行为的开发者本文可作为理解两者交互边界、排查选择残留类问题的切入点同时 paste.js 与手动用例互为补充共同保障了这一集成场景的长期稳定。赞分享前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载相关推荐深入 CKEditor 4 Link 插件getSelectedLink 链接选中机制与手动测试用例解析深入 CKEditor 4 Link 插件getSelectedLink 链接选中机制与手动测试用例解析 导读 在 CKEditor 4 中编辑一个既有超链接前端UI组件CKEditor 4 Easy Image 插件与表格单元格选择Table Selection的交互ticket 1542 手动测试全解析CKEditor 4 Easy Image 插件与表格单元格选择Table Selection的交互ticket 1542 手动测试全解析 导读 本文围绕前端UI组件上一篇douyin-downloader 快速上手3 个场景把创作者主页无水印批量下载存进本地下一篇SQLFlow 实战用 SQL 训练 DNN 分类器对 Iris 鸢尾花数据集进行分类创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考