资讯动态

CKEditor 4 List Block 下拉面板防拖拽修复解析:从手动测试用例到源码实现

发布时间:2026/10/16 9:05:08 来源:尧图企业网站定制
前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载导读List Block 是 CKEditor 4 中驱动样式下拉框Styles Combo、字体/字号下拉框等富文本选择面板的核心 UI 组件。本文以仓库内针对问题 #2430 的手动测试用例 tests/plugins/listblock/manual/dragging.md 为主线完整还原打开样式下拉框后尝试拖拽列表项这一回归场景的测试步骤与预期结果并结合 plugins/listblock/plugin.js 的模板与类实现、tests/plugins/listblock/listblock.js 的自动化断言深入讲解下拉面板项为何可被拖拽、修复方案如何落地以及同一修复模式在 Color Button、Elements Path、Menu 等面板中的推广。读完本文你将掌握 CKEditor 4 面板类组件防拖拽的完整技术方案以及如何运行该功能的手动与自动化测试。一、场景背景为什么下拉面板里的条目能被拖拽是个 Bug1.1 List Block 在 CKEditor 4 中的定位List Block 是一个底层 UI 插件本身不直接暴露给用户而是作为richcombo富文本下拉组合框的依赖被引入// plugins/richcombo/plugin.js CKEDITOR.plugins.add( richcombo, { requires: floatpanel,listblock,button, ... } );而stylescombo样式下拉框又依赖richcomboplugins/stylescombo/plugin.js 第 10 行requires: richcombo。因此当你点击工具栏上的 Styles 下拉框、Font 下拉框、字号下拉框时实际看到的那一列可选择条目就是由 List Block 渲染的ul列表面板。1.2 Bug 的表现与危害在 CKEditor 4.11.2 之前这些下拉面板中的条目是可以被鼠标拖拽的。这带来一系列问题用户试图用鼠标框选或拖动面板项时浏览器会进入原生 HTML5 拖拽流程选中项会以半透明幽灵形态跟随鼠标干扰下拉框的交互条目被拖出面板后可能被误拖进编辑器正文区域触发编辑器的 drag drop 粘贴流程向正文插入意外内容视觉上给人这个控件是可以移动的的错误暗示破坏下拉选择框的可用性预期。该问题在官方变更日志中有明确记录CHANGES.md 第 766 行位于 CKEditor 4.11.2 一节#2430Fixed: Color Button and List Block items are draggable.即List Block 与 Color Button 的下拉项在 4.11.2 中被判定为可拖拽属于缺陷并在该版本中修复。二、手动测试用例逐行解析2.1 用例元数据手动测试文件 tests/plugins/listblock/manual/dragging.md 的头部声明了测试所需的全部上下文bender-tags: 2430, bug, 4.11.2 bender-ui: collapsed bender-ckeditor-plugins: wysiwygarea, toolbar, stylescombo, floatingspacebender-tags标记该用例关联的问题编号2430、类型为bug且与4.11.2版本相关bender-ui: collapsed在 Bender 手动测试运行器中测试页面默认折叠 UI便于聚焦操作bender-ckeditor-plugins手动用例页面只加载最小插件集——wysiwygarea经典编辑区、toolbar工具栏、stylescombo样式下拉框、floatingspace浮动面板空间保证测试环境干净、可复现。对应的测试页面 tests/plugins/listblock/manual/dragging.html 同时创建了一个经典编辑器CKEDITOR.replace( editor )和一个内联编辑器CKEDITOR.inline( inline )并且if ( bender.tools.env.mobile ) { bender.ignore(); }在移动端环境下直接跳过该用例——因为拖拽行为本质上是桌面端指针交互移动端无意义。2.2 完整操作步骤原文继承测试过程只有两个步骤打开 Styles样式下拉框。尝试拖拽下拉框中的条目。2.3 预期与意外结果预期Expected条目无法被拖拽。意外Unexpected条目可以被拖拽。这正是回归测试的标准写法修复 #2430 之后如果代码再次退化为可拖拽手动测试者应当立即在Unexpected一栏发现问题。该用例与 tests/plugins/listblock/manual/ariaselected.md、tests/plugins/listblock/manual/rightclick.md 共同组成了 List Block 手动测试矩阵分别覆盖选中态恢复#5437与右键行为#2857。三、源码层面的修复实现双保险防拖拽3.1 核心修复点draggablefalseondragstartreturn false;修复的核心代码位于 plugins/listblock/plugin.js 的onLoad阶段该阶段注册了三个 HTML 模板var list CKEDITOR.addTemplate( panel-list, ul rolepresentation classcke_panel_list{items}/ul ), listItem CKEDITOR.addTemplate( panel-list-item, li id{id} classcke_panel_listItem rolepresentation a id{id}_option _cke_focus1 hidefocustrue title{title} draggablefalse ondragstartreturn false; // Draggable attribute is buggy on Firefox. hrefjavascript:void(\{val}\) {language} onclick{onclick}CKEDITOR.tools.callFunction({clickFn},\{val}\); return false; roleoption {text} /a /li ), listGroup CKEDITOR.addTemplate( panel-list-group, h1 id{id} draggablefalse ondragstartreturn false; classcke_panel_grouptitle rolepresentation{label}/h1 );注意这里有两个层面HTML 属性draggablefalse标准化的 HTML5 防拖拽属性告诉浏览器该元素不可作为拖拽源内联事件ondragstartreturn false;在dragstart事件上直接返回false取消拖拽。源码注释明确说明——Draggable attribute is buggy on Firefox即Firefox 对draggable属性的支持存在缺陷仅靠属性不够可靠必须用事件处理器兜底。这两行同时出现在列表条目a和分组标题h1listGroup模板上说明修复覆盖了面板内的全部可点击元素而不只是选项条目本身。3.2 同一修复模式在相关插件中的推广#2430 的修复并非 List Block 独有同一属性 事件双保险模式被推广到了其他同类下拉/面板组件插件位置说明plugins/colorbutton/plugin.js第 410–411、431–432、540–541 行颜色面板的自动颜色、更多颜色以及每个色块a均带draggablefalse与ondragstartreturn false;注释同样提到 Firefox 的 bugplugins/elementspath/plugin.js第 50–51 行元素路径Elements Path条目注释为 Required by Firefox (#1191)关联早期问题 #1191plugins/menu/plugin.js第 96、109 行上下文菜单项同样应用了draggablefalse与ondragstartreturn false;这也解释了 CHANGES.md 中为何把修复表述为 Color Button and List Block items are draggable——两个组件在同一问题下一起修复而 Elements Path 与 Menu 则复用相同的技术方案。从源码结构看这已成为 CKEditor 4 面板类组件渲染可交互选项时的统一约定。3.3 防拖拽之外列表项的正常点击与键盘交互防拖拽修复不能影响条目原有的选择能力。listItem模板中的onclick会在点击时调用CKEDITOR.tools.callFunction( {clickFn}, {val} )并return false其中{clickFn}指向getClick()生成的注册函数getClick: function() { if ( !this._.click ) { this._.click CKEDITOR.tools.addFunction( function( value ) { var marked this.toggle( value ); if ( this.onClick ) this.onClick( value, marked ); }, this ); } return this._.click; }同时CKEDITOR.ui.listBlock的构造函数plugins/listblock/plugin.js 第 36–62 行为该面板块注册了完整的键盘导航40ARROW-DOWN→next9TAB→next38ARROW-UP→prevSHIFT 9SHIFTTAB→prev32SPACE→ IE 下mouseup其余浏览器clickIE 下13ENTER→mouseup因为 IE 会拦截onclick对应旧 ticket #8041可见List Block 在阻止鼠标拖拽的同时完整保留了鼠标点选、键盘上下导航、空格/回车确认等选择路径这也是防拖拽但不破坏功能这一修复原则的体现。四、自动化回归测试如何用断言锁死该修复4.1 针对 #2430 的自动化用例除手动测试外仓库还提供了自动化回归测试 tests/plugins/listblock/listblock.js其中名为test list block elements not draggable的用例直接对应 #2430// (#2430) test list block elements not draggable: function() { var bot this.editorBot; bot.combo( Styles, function( combo ) { var block combo._.panel.getBlock( combo.id ).element, items block.find( a ).toArray().concat( block.find( h1 ).toArray() ); combo._.panel.hide(); CKEDITOR.tools.array.forEach( items, function( element ) { assert.areEqual( false, element.getAttribute( draggable ), Draggable attribute value should be false. ); assert.areEqual( return false;, element.getAttribute( ondragstart ), ondragstart value should be return false;. ); } ); } ); }该用例的要点通过bot.combo( Styles, ... )打开样式下拉框拿到面板块 DOM 元素收集面板内所有a条目和h1分组标题与手动测试的操作对象完全一致对每个元素断言两个值draggable属性必须等于字符串falseondragstart属性必须等于return false;。也就是说自动化测试把手动测试的预期结果翻译成了可重复执行的属性断言——只要未来有人误删模板中的任一防护该用例就会立即失败。4.2 同文件中的相邻回归用例同文件还包含两个与面板交互密切相关的回归用例可用于理解 List Block 交互的完整边界test right clicking list block elements#2857仅 IE 下执行通过bender.tools.dispatchMouseEvent( item, mouseup, CKEDITOR.MOUSE_BUTTON_RIGHT )派发右键mouseup并用sinon.spy断言combo.onClick未被调用——右键不应触发选项应用。这对应模板中onclick的前缀逻辑IE 下会插入CKEDITOR.tools.getMouseButton(event)CKEDITOR.MOUSE_BUTTON_LEFT条件即只有左键才执行点击回调plugins/listblock/plugin.js 第 100–102 行。test list block correctly marks selected element upon reopening#5437打开 Font 下拉框选择 Comic Sans MS关闭后重新打开断言aria-selectedtrue与cke_selected类仍然保留对应 tests/plugins/listblock/manual/ariaselected.md 手动用例。其中右键判定依赖的CKEDITOR.tools.getMouseButton与normalizeMouseButton定义在 core/tools.js 第 1668 行与第 1725 行按钮常量CKEDITOR.MOUSE_BUTTON_LEFT 0、CKEDITOR.MOUSE_BUTTON_RIGHT 2定义在同文件第 3035 行与第 3055 行normalizeMouseButton专门处理 IE8 / IE9 Quirks 模式下与众不同的 button 值映射。五、如何运行这些测试CKEditor 4 的测试体系基于 Bender.js项目根目录的 bender.js 是测试配置入口framework 为yui应用ckeditor指向根目录的ckeditor.js。手动测试文件通过bender-tags/bender-ui等头部注释被 Bender 的手动测试运行器识别自动化用例则与普通 Bender 用例一样被收集执行。运行方式仅介绍查看与运行不涉及修改仓库安装依赖后在仓库根目录启动 Bender 服务器bender server run打开 Bender 提供的测试页面地址选择tests/plugins/listblock目录手动用例dragging会以步骤 → 预期/意外的清单形式呈现按 tests/plugins/listblock/manual/dragging.md 的步骤操作并人工核对结果自动化用例listblock.js由 Bender 在配置的浏览器中自动执行其中test list block elements not draggable会在毫秒级完成对全部a/h1节点的属性断言。六、总结与实战要点围绕 tests/plugins/listblock/manual/dragging.md 这一个看似简单的回归用例可以提炼出以下可复用的工程经验属性 事件双保险仅设置draggablefalse不足以覆盖所有浏览器Firefox 的draggable属性存在已知缺陷必须配合ondragstartreturn false;才能彻底阻断拖拽流程。覆盖面要完整修复不能只针对选项条目a面板中的分组标题h1、其他可交互元素都要一并处理List Block、Color Button、Elements Path、Menu 均遵循此模式。手动与自动化互补手动用例验证真实操作体验拖不动自动化用例以属性断言锁死实现细节draggable与ondragstart的精确值二者结合防止回归。修复不破坏既有交互防拖拽同时保留鼠标点选与键盘导航方向键、空格、回车并通过 #2857、#5437 等相邻用例守住交互边界。如果你正在为 CKEditor 4 的富文本面板类组件排查选项能被拖进编辑器之类的怪异现象或需要为自定义的CKEDITOR.ui.listBlock面板补充防拖拽逻辑直接参照 plugins/listblock/plugin.js 第 10–27 行的模板写法即可获得与官方一致的解决方案。赞分享前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载相关推荐CKEditor 4 色彩面板元素不可拖拽修复dragging 手动测试与 2430 源码级解析CKEditor 4 色彩面板元素不可拖拽修复dragging 手动测试与 2430 源码级解析 导读 本文围绕 CKEditor 4 中 colorbutt前端UI组件基于 Rube MCP 与 Composio 的 Coinranking 加密货币数据自动化实战指南基于 Rube MCP 与 Composio 的 Coinranking 加密货币数据自动化实战指南 导读 本指南围绕 composio skills/coin前端UI组件ODrive 端停止与归零Homing完整配置指南从限位开关接线到启动自动归零ODrive 端停止与归零Homing完整配置指南从限位开关接线到启动自动归零 本文以 ODrive 固件源码 Firmware/MotorContro前端UI组件上一篇通达信缠论插件5步解锁量化交易新境界的终极解决方案下一篇终极指南5分钟掌握Understat异步Python包获取专业足球数据创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑