CKEditor 4 Table Resize 插件滚动后光标错位问题(4889)复现手册与修复原理解析
前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载本手册针对 CKEditor 4 的 Table Resize表格列宽拖拽调整插件在窄容器编辑器横向滚动后列边框上的缩放光标发生错位这一已知缺陷issue #4889随 4.20.0 版本修复给出基于 Bender 手动测试Manual Test的完整复现步骤、预期/非预期行为判定标准并结合插件源码与自动化测试从pillar柱线缓存失效的角度剖析缺陷根因与修复机制。读完本文你将掌握如何定位 Table Resize 的坐标计算核心、理解其滚动场景下的缓存失效问题并学会用仓库内置的 manual test 与 bender 自动化用例双重验证此类交互缺陷。一、手册定位一份bug 型手动测试文档本文所依据的文档是 scrollupdate.md它是 CKEditor 4 测试体系中典型的manual test手动测试说明文档与同目录下的 scrollupdate.html 页面配套使用。其文档头部的 Bender 指令完整描述了该用例的属性bender-ui: collapsed bender-tags: bug, 4.20.0, 4889 bender-ckeditor-plugins: wysiwygarea, toolbar, table, tableresize, tabletools, floatingspacebender-ui: collapsed手动测试页面以折叠collapsed方式嵌入 Bender 手动测试运行器 UI 中避免页面干扰操作bender-tags: bug, 4.20.0, 4889明确这是一个bug 回归用例对应 GitHub issue #4889修复随4.20.0版本发布见 CHANGES.md 中 Fixed: Incorrect position of the Table Resize cursor after scrolling the editor horizontallybender-ckeditor-plugins声明该用例需要加载wysiwygarea、toolbar、table、tableresize、tabletools、floatingspace等插件——注意tableresize插件本身在 plugin.js 中声明了requires: tabletools因此tabletools是其依赖项。这样的文档结构意味着它不讲解功能如何使用而是规定了一套可执行的缺陷复现流程。这是 CKEditor 4 质量保障体系中回归测试必须可复现、可判定原则的直接体现。二、缺陷背景Table Resize 的光标与 pillar 机制要理解这个 bug需要先了解 Table Resize 插件的工作方式。在 plugin.js 中插件通过buildTableColumnPillars()为表格的每一列边框计算一个pillar柱线即列边框的可拖拽命中区域其核心字段如下plugin.jspillar { table: table, index: pillarIndex, x: pillarLeft, // 柱线左边界基于 getDocumentPosition() 计算 y: pillarPosition.y, width: pillarWidth, // 最小为 3pxMath.max(pillarRight - pillarLeft, 3) height: pillarHeight, rtl: rtl };pillar 的x/y坐标全部来自CKEDITOR.dom.element.getDocumentPosition()——这是一个相对于文档的绝对坐标而不是相对于视口的坐标。当鼠标移动时mousemove处理器通过evt.getPageOffset()取得页面级坐标再调用getPillarAtPosition()判断鼠标是否落在某个 pillar 范围内plugin.js。为了提高性能插件把每次计算出的 pillars 缓存到表格的自定义数据_cke_table_pillars上plugin.js并只在mouseout/mousedown时通过clearPillarsCache()清除缓存plugin.js。滚动为何导致错位缺陷的根源在于pillar 坐标是相对文档的绝对坐标而getPageOffset()取到的鼠标位置会随着编辑区域滚动而变化。当编辑区域inline/divarea 容器或 iframe 文档发生横向滚动后页面级鼠标坐标已经变化但缓存的 pillars 中记录的是滚动前计算的文档坐标未随滚动失效于是getPillarAtPosition()命中了一个坐标过期的 pillarcolumnResizer.attachTo()据此把缩放条resizer定位到错误位置plugin.js表现为缩放光标从列边框上偏移。值得注意的是手动测试文档特别注明了一个细节The bug does not occur when dragging the scrollbar.用鼠标滚轮或触控板手势滚动时出现拖动滚动条时不出现。这与浏览器事件模型一致——拖动滚动条不会触发容器/文档的scroll事件流或鼠标位置计算路径不同而滚轮/手势滚动才会让编辑器内表格的文档坐标与页面鼠标坐标产生错位。三、复现步骤原文档核心操作流程以下步骤完整继承自 scrollupdate.md并结合 scrollupdate.html 的测试页面结构给出补充说明。测试页面包含三种编辑器形态共 3 个待测实例编辑器创建方式容器特征Inline editorCKEDITOR.inline( inline )250px 宽、overflow: auto的可编辑 divdiv-based editorCKEDITOR.replace( div, { extraPlugins: divarea, width: 250 } )250px 宽、overflow: auto的 div 编辑区iframe-based editorCKEDITOR.replace( iframe, { width: 250 } )250px 宽的标准 iframe 编辑区每个实例内部都是一张stylewidth:500px、border1的 5 行 4 列表格——即表格宽度500px远超容器宽度250px必然产生横向滚动条这是触发本 bug 的前提条件。此外 scrollupdate.html 中还有if ( bender.tools.env.mobile ) { bender.ignore(); }表示移动端环境自动跳过该用例。操作步骤将编辑器滚动到最右端再稍微向左回滚一点。⚠️注意必须使用鼠标滚轮或触控板手势滚动拖动滚动条无法复现该 bug原因见上文第二节。尝试拖拽调整最后一列将鼠标悬停到最右侧列边框上出现col-resize光标后按下拖拽。对页面上的全部 3 个编辑器inline、div-based、iframe-based重复上述过程。预期结果Expected缩放光标位于正确的位置即恰好贴合最后一列的边框线拖拽后列宽调整正常生效。非预期结果Unexpected缩放光标从列的边框上偏移——由于 pillar 缓存未随滚动失效resizer 被定位到了滚动前的位置鼠标指针看起来悬空在边框之外无法准确拖拽最后一列。四、修复原理scroll 事件触发 pillar 缓存重置针对 #4889plugin.js 中新增了如下修复逻辑// Reset pillars position on scroll (#4889). editable.attachListener( listenerTarget, scroll, function() { var tables editable.find( table ).toArray(); CKEDITOR.tools.array.forEach( tables, CKEDITOR.tools.debounce( function( table ) { table.removeCustomData( _cke_table_pillars ); }, 200 ) ); } );关键设计有三点监听目标的选择listenerTarget在 init 时被确定为——inline 编辑器用editable本身经典编辑器用editor.documentplugin.js。这样无论滚动发生在可编辑容器还是 iframe 文档上都能捕获到scroll事件。批量失效滚动发生时遍历 editable 内的所有表格逐一移除_cke_table_pillars缓存数据。下次鼠标移动时buildTableColumnPillars()会重新按最新文档坐标计算 pillars光标位置随即恢复正确。防抖debounce用CKEDITOR.tools.debounce( ..., 200 )将清除动作延迟 200ms 合并执行避免连续滚动造成频繁重算兼顾正确性与性能。与此同时自动化测试 tableresize.js 中也新增了两个断言用例test pillars are resetted on scroll (inline)对 inline 编辑器触发editable.fire( scroll, {} )等待 210ms超过 200ms 防抖窗口后断言table.getCustomData( _cke_table_pillars )为nulltest pillars are resetted on scroll (classic)对经典编辑器触发editor.document.fire( scroll, {} )同样断言缓存被清空。这两个用例与手动测试文档形成了自动化 人工双重验证的闭环自动化用例用 mock 事件验证缓存失效行为手动用例验证真实浏览器滚动交互下的最终用户体验。测试还定义了inlineOverflow/classicOverflow两个带横向溢出场景的编辑器实例tableresize.js与 manual test 页面的窄容器设置相互印证。五、如何运行该手动测试本仓库使用 Bender.js 作为测试运行框架其tests配置中Plugins分组以tests/为 basePath 覆盖plugins/**见 bender.js依赖由 package.json 中的benderjs系列包提供。运行全部手动测试bender run manual手动测试文档通过bender-ui等标记被 Bender 识别为 manual test 分组定位本用例运行后选择Plugins分组下的tableresize即可在页面列表中找到scrollupdate用例按第三节的步骤逐条验证。由于仓库只读本文仅介绍查看与运行方式实际验证时请在你的开发副本中安装依赖并启动 Bender 服务器然后按上述流程在真实浏览器中操作。六、小结从一份 manual test 学到什么通过这份 scrollupdate.md可以提炼出三条可复用的工程经验坐标缓存类交互缺陷的复现要点凡是基于文档绝对坐标 缓存的交互pillar、tooltip、浮动面板等都必须验证滚动、缩放等位移场景且复现方式滚轮 vs 拖滚动条可能影响 bug 是否出现测试文档必须写清楚修复的标准姿势监听scroll事件 → 失效相关缓存 → 用 debounce 控制频率是 CKEditor 4 中处理滚动导致缓存坐标过期类问题的通用模式见 plugin.js回归测试的双轨验证manual test真实交互体验 自动化断言缓存状态变化组合既保证用户视角正确又保证实现细节正确这在 tableresize.js 中体现得尤为清晰。如果需要继续深入 Table Resize 插件可阅读同目录下的其他手动测试如 pillar.mdpillar 高度与整表等高、mergedcells.md合并单元格边界命中、maximizeddivarea.md最大化后缩放等它们共同覆盖了该插件的坐标计算与交互边界场景。赞分享前端UI组件【免费下载链接】ckeditor4The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.项目地址https://gitcode.com/gh_mirrors/ck/ckeditor4点击查看免费下载相关推荐CKEditor 4 Copy Formatting 与 Table Resize 光标冲突修复从手动测试到源码原理CKEditor 4 Copy Formatting 与 Table Resize 光标冲突修复从手动测试到源码原理 Copy Formatting复制格式前端UI组件CKEditor 4 Table Resize 插件合并单元格Rowspan缩放修复解析与手动回归测试指南CKEditor 4 Table Resize 插件合并单元格Rowspan缩放修复解析与手动回归测试指南 本篇技术指南以 CKEditor 4 仓库中的手前端UI组件CKEditor 4 Table Resize 插件IE 下 border-collapse 表格右边界无法调整2823的修复原理与手动验证CKEditor 4 Table Resize 插件IE 下 border collapse 表格右边界无法调整 2823的修复原理与手动验证 本文以 C前端UI组件上一篇PyQt-SiliconUI基于PyQt5的终极UI框架让你的桌面应用瞬间灵动优雅下一篇Django-Treebeard 完全指南打造高效树形结构的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

大模型成长史:从鹦鹉学舌到独当一面

大模型成长史:从鹦鹉学舌到独当一面

最近老有人问我一个问题:大模型到底是不是“背了很多资料”才变得这么聪明?每次听到这种说法,我都觉得又对又不对。对的地方在于,模型的起步确实很像死记硬背;不对的地方在于,光靠“背”根本解释不了它为什…

2026/10/16 6:58:59 阅读更多 →
PDF4NET v16.1实战:.NET环境下的PDF生成、表单签名与PPT转换

PDF4NET v16.1实战:.NET环境下的PDF生成、表单签名与PPT转换

1. 项目到底解决什么问题1.1 我是在什么场景下盯上这个库的做 .NET 的同行应该都有过这种经历:业务侧丢过来一句话,说今天就要上线“电子合同预览生成”,打开浏览器一看,需求里面除了常规的文本落款,还带签字区、印章位…

2026/10/16 6:57:59 阅读更多 →
STM32驱动VL53L1X激光测距模块的硬件适配与I²C时序调试指南

STM32驱动VL53L1X激光测距模块的硬件适配与I²C时序调试指南

简介:本资源是面向嵌入式初学者与STM32开发者的VL53L1X激光测距传感器实战工程包,聚焦非接触式高精度距离测量场景,适用于智能小车避障、室内导航、自动对焦等物联网应用。项目基于STM32F103VET6(Cortex-M3内核)主控&a…

2026/10/16 6:57:59 阅读更多 →

最新新闻

PointMamba:用状态空间模型实现点云线性复杂度全局建模

PointMamba:用状态空间模型实现点云线性复杂度全局建模

如果你做过点云分类或者三维分割,大概率体会过那种尴尬:点数一多,显存告急,训练时间翻倍,推理延迟也压不下来。Transformer 用自注意力把点云建模往前带了一大步,但同时也把 N 的计算复杂度带进了三维世界。…

2026/10/16 7:39:11 阅读更多 →
智能小车设计方案:从硬件选型到PID控制与避障循迹的完整实战

智能小车设计方案:从硬件选型到PID控制与避障循迹的完整实战

/* 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 7:39:11 阅读更多 →
指纹模块UART指令帧格式与注册比对流程详解

指纹模块UART指令帧格式与注册比对流程详解

/* 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 7:39:11 阅读更多 →
大模型Agent核心模块拆解:从ReAct循环到最小实现路径

大模型Agent核心模块拆解:从ReAct循环到最小实现路径

这两年AI Agent几乎成了大模型落地绕不开的话题,社区里天天有人聊,团队里也陆续有人开始把花在“聊天”上的精力往Agent上转移。但说句实在话,现在很多讨论都用力过猛,一上来就是多智能体框架、复杂工作流编排、记忆系统设计&…

2026/10/16 7:39:11 阅读更多 →
电路等效变换详解:从电阻串并联到电源互换的化简方法

电路等效变换详解:从电阻串并联到电源互换的化简方法

/* 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 7:39:11 阅读更多 →
Android校园论坛App开发实战:从架构设计到毕设答辩全攻略

Android校园论坛App开发实战:从架构设计到毕设答辩全攻略

1. 项目概述:为什么说这是最适合做毕设的Android选题之一校园信息论坛这个题目,几乎是每年计算机毕业设计里“常青树”级别的存在。我见过太多人选电商系统、选点餐App、选运动打卡,最后做到中期答辩才发现业务逻辑复杂到失控——订单状态机、…

2026/10/16 7:38:11 阅读更多 →

日新闻

个人 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/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 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/15 9:49:14 阅读更多 →