news 2026/10/16 5:40:08

CKEditor 4 floatpanel 浮层面板:窗口缩放与移动端软键盘场景下的定位行为验证指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CKEditor 4 floatpanel 浮层面板:窗口缩放与移动端软键盘场景下的定位行为验证指南
  • 前端
  • UI组件

【免费下载链接】ckeditor4

The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.

项目地址:https://gitcode.com/gh_mirrors/ck/ckeditor4
点击查看免费下载

导读

本文围绕 CKEditor 4 中 floatpanel(浮层面板)组件在窗口尺寸变化与移动端软键盘弹出/收起两种场景下的定位与显示行为展开。floatpanel 是 CKEditor 4 工具栏下拉框(Paragraph Format、Font、Color 等)与右键菜单的底层承载组件,其定位正确性直接影响编辑器的日常可用性。阅读本文后,你将理解 floatpanel 的定位原理与reposition()机制,掌握如何通过 Bender 手动测试用例验证面板在移动设备软键盘、浏览器窗口缩放下的表现,并能对照自动化测试与源码定位同类回归问题。

本文的验证要点以仓库中的手动测试说明 tests/plugins/floatpanel/manual/resize.md 为骨架,结合 floatpanel 插件源码、Bender 自动化测试与格式下拉框(format 插件)实现展开。


一、floatpanel:几乎所有下拉 UI 的底层载体

1.1 什么是 floatpanel

floatpanel 是 CKEditor 4 中的一个 UI 基础组件,用于承载那些"悬浮在文档上方、不占据正常文档流"的面板内容。插件声明极其精简:

// plugins/floatpanel/plugin.js CKEDITOR.plugins.add( 'floatpanel', { requires: 'panel' } );

它本身不渲染任何 UI,而是依赖panel插件提供的面板渲染能力,对外暴露CKEDITOR.ui.floatPanel类,并在构造时强制将面板内容放入 iframe(definition.forceIFrame = 1,见 plugins/floatpanel/plugin.js),从而隔离宿主页面样式对面板内容的干扰。

从源码注释可以确认它的使用范围:

"It is reused by rich combos, color combos, menus, etc. and it renders its content using CKEDITOR.ui.panel."

也就是说,富下拉框(rich combo)、颜色下拉框、菜单等 UI 全部复用 floatpanel。

1.2 谁在用它:以 Paragraph Format 为例

本文手动测试的主角是工具栏上的Paragraph Format(段落格式)下拉框。它由format插件通过richcombo注册:

// plugins/format/plugin.js init: function( editor ) { ... editor.ui.addRichCombo( 'Format', { label: lang.label, title: lang.panelTitle, toolbar: 'styles,20', ... panel: { css: [ CKEDITOR.skin.getPath( 'editor' ) ].concat( config.contentsCss ), multiSelect: false, attributes: { 'aria-label': lang.panelTitle } }, ... } ); }

而richcombo插件在声明依赖时直接指定了floatpanel:

// plugins/richcombo/plugin.js CKEDITOR.plugins.add( 'richcombo', { requires: 'floatpanel,listblock,button', ... });

在createPanel()中,richcombo 会实例化一个CKEDITOR.ui.floatPanel并注册列表块(plugins/richcombo/plugin.js):

var panel = new CKEDITOR.ui.floatPanel( editor, panelParentElement, panelDefinition ), list = panel.addListBlock( this.id, panelBlockDefinition );

因此,Paragraph Format 下拉框展开后,其视觉呈现与定位逻辑完全由 floatpanel 负责——这正是本测试用例要验证的对象。


二、手动测试用例全解:resize 场景

2.1 测试文件与其元数据

本用例位于tests/plugins/floatpanel/manual/目录,由一对文件组成:

  • 操作说明:tests/plugins/floatpanel/manual/resize.md
  • 测试页面:tests/plugins/floatpanel/manual/resize.html

resize.md头部是 Bender 手动测试的元数据声明:

@bender-tags: bug, 4.5.4, trac11724 @bender-ui: collapsed @bender-include: ../../embedbase/_helpers/tools.js @bender-ckeditor-plugins: wysiwygarea,sourcearea,htmlwriter,entities,toolbar,elementspath,undo,clipboard,format,basicstyles,font,autolink,autoembed,link

逐条解读:

指令含义
@bender-tags: bug, 4.5.4, trac11724标注该用例属于 bug 回归测试,关联 4.5.4 版本中修复的 ticket #11724
@bender-ui: collapsed以折叠 UI 模式加载测试页面(仅显示编辑器本体)
@bender-include: ../../embedbase/_helpers/tools.js引入 embedbase 插件的测试辅助工具 tests/plugins/embedbase/_helpers/tools.js
@bender-ckeditor-plugins: ...声明测试页启用的插件集合,其中format提供 Paragraph Format 下拉框、richcombo(经 format 间接依赖)提供下拉框 UI 载体

测试页面本体极其简单——一个 80% 宽度的居中容器内放置经典编辑器实例:

<!-- tests/plugins/floatpanel/manual/resize.html --> <div style="width: 80%; margin: 0 auto"> <textarea cols="80" id="classic" name="classic" rows="10"> <p>Test</p> </textarea> </div> <script> CKEDITOR.replace( 'classic' ); </script>

2.2 移动设备验证步骤

原文档针对移动端给出如下操作序列:

  1. 点击编辑区,让系统软键盘弹出(软件键盘可见);
  2. 点击工具栏上的 Paragraph Format 下拉框,展开样式列表;
  3. 预期结果:软键盘应自动收起,且下拉框保持可见、位置正确。

这条路径背后对应着一个真实的移动端 bug(ticket #11724)。软键盘的弹出会改变浏览器视口高度,触发window.resize事件;而旧实现中 floatpanel 监听窗口 resize 后直接执行hide(),导致在 Android / iOS 上"下拉框一打开就消失"。修复后,窗口 resize 不再无条件隐藏面板,而是触发重定位(见下文第三节源码分析)。

2.3 其他设备(桌面)验证步骤

原文档针对桌面浏览器给出另一组操作序列:

  1. 打开 Paragraph Format 下拉框;
  2. 检查其初始定位是否正确(应紧贴下拉按钮、完整显示在视口内);
  3. 缩放浏览器窗口(改变窗口尺寸);
  4. 预期结果:下拉框应要么被隐藏,要么被正确重定位,不允许出现"面板悬在半空、与触发按钮错位"或"面板被裁切"的情况。

注意"要么隐藏、要么重定位"是 4.5.4 修复后明确的两种合法结果——这与源码中hide()与reposition()两条路径并存的设计完全一致(详见下文)。

2.4 判定标准小结

设备类型触发操作期望结果
移动设备点编辑区 → 软键盘弹出 → 点 Paragraph Format软键盘收起,下拉框可见且定位正确
桌面浏览器打开 Paragraph Format → 缩放窗口面板隐藏或正确重定位,不错位、不裁切

三、源码级原理:4.5.4 的修复如何生效

3.1 定位计算:showBlock 的四个角

floatpanel 的定位在showBlock()中完成(plugins/floatpanel/plugin.js)。它根据corner参数决定面板与触发元素的对齐方式:

  • LTR(从左到右)编辑器下:1=左上、2=右上、3=右下、4=左下;
  • RTL(从右到左)编辑器下:1=右上、2=左上、3=左下、4=右下。

同时支持offsetX、offsetY微调偏移。定位完成后,还有一段"智能适配视口"的逻辑(plugins/floatpanel/plugin.js):通过getBoundingClientRect()与getViewPaneSize()比较面板矩形与视口尺寸,当右侧空间不足时向左翻转、下方空间不足时向上翻转,确保面板完整落在视口内——这正是桌面步骤 2"初始定位正确、不被裁切"的实现保障。

3.2 两类事件监听:hide 与 reposition

floatPanel 构造函数中注册了如下事件(plugins/floatpanel/plugin.js):

editor.on( 'mode', hide ); editor.on( 'resize', hide ); // When resize of the window is triggered floatpanel should be repositioned according to new dimensions. // https://dev.ckeditor.com/ticket/11724. Fixes issue with undesired panel hiding on Android and iOS. doc.getWindow().on( 'resize', function() { this.reposition(); }, this );
  • 编辑器resize事件 → hide:编辑器本体尺寸变化(如用户拖动编辑器边框)时直接隐藏面板,避免面板与编辑器错位;
  • 窗口resize事件 → reposition:浏览器窗口尺寸变化(包括移动端软键盘弹出导致的视口变化)时,调用reposition()重新摆放面板,而不是隐藏。

源码注释明确写到:"When resize of the window is triggered floatpanel should be repositioned according to new dimensions. Fixes issue with undesired panel hiding on Android and iOS."——这正是 ticket #11724 的修复内容,与本文手动测试用例的trac11724标签一一对应。

3.3 reposition 的实现:完整重放 showBlock

reposition()(plugins/floatpanel/plugin.js)是 4.5.4 新增的 API:

/** * Repositions the panel with the same parameters that were used in the last {@link #showBlock} call. * * @since 4.5.4 */ reposition: function() { var blockParams = this._.showBlockParams; if ( this.visible && this._.showBlockParams ) { this.hide(); this.showBlock.apply( this, blockParams ); } }

其设计要点:

  1. showBlock()在每次展示时会把入参快照保存到this._.showBlockParams(见 plugins/floatpanel/plugin.js);
  2. reposition()仅在面板可见(this.visible)且存在快照时生效,先隐藏再以完全相同的一组参数重新执行showBlock();
  3. 由于窗口尺寸已经变化,showBlock()内部的视口适配逻辑会依据新尺寸重新计算翻转方向与坐标,从而把面板"搬"到正确位置。

因此,桌面场景下缩放窗口时,如果面板仍可见,它会带着一致的触发参数被重新摆放——而不是停留在旧坐标上。

3.4 为什么移动端"软键盘收起"能保住面板

移动端软键盘弹出时,浏览器会收缩视口高度,触发窗口 resize;此时面板通过reposition()被重新计算位置,不会被直接隐藏。同时,showBlock()中还针对 iOS 做了 blur 时序保护(plugins/floatpanel/plugin.js):iframe blur 后不立即隐藏,而是用CKEDITOR.tools.setTimeout( doHide, 0, this )延迟执行,并监听touchstart/touchend取消误触发——这样"点编辑区弹出键盘 → 再点下拉框"的连续操作不会因为焦点抖动把面板关掉。

注意:@bender-tags: ... 4.5.4, trac11724表明该用例是为验证 4.5.4 的修复而设计的手动回归用例,预期行为以 4.5.4 及以后版本的实现为准。


四、如何运行本手动测试

Bender 是 CKEditor 4 的测试运行器,其配置见 bender.js。手动测试需要指定接受手动测试的浏览器(manualBrowsers配置项,bender.js),并且测试服务器需要以 HTTPS 提供服务(privateKey/certificate配置指向 tests/_benderjs/ssl/key.pem 与 tests/_benderjs/ssl/cert.pem)。

典型运行方式:

  1. 在仓库根目录安装并启动 Bender 测试服务器,将浏览器加入manualBrowsers列表(本用例需要真机或模拟器上的移动浏览器,以及一台桌面浏览器);
  2. 打开 Bender 手动测试面板,定位到plugins/floatpanel→resize用例;
  3. 分别按上文第二节"移动设备"与"其他设备"两组步骤操作并核对预期结果;
  4. 若面板在软键盘弹出后消失、或在窗口缩放后错位/被裁切,即为回归,应关联 ticket #11724 排查。

@bender-ui: collapsed意味着测试页会以折叠 UI 呈现,便于聚焦编辑器本体;@bender-include引入的 tests/plugins/embedbase/_helpers/tools.js 为该页面提供辅助工具函数(同时它也是 autoembed 相关测试的共用助手)。


五、配套自动化测试:把行为固化为断言

除了手动用例,floatpanel 还配有 Bender 自动化测试 tests/plugins/floatpanel/floatpanel.js,其中'test panel reposition on window resize'与手动用例直接呼应:

// 模拟 window resize 事件 var e = document.createEvent( 'HTMLEvents' ); e.initEvent( 'resize', true, false ); document.body.dispatchEvent( e ); assert.isTrue( showBlockSpy.calledTwice, 'panel.showBlock should be called twice' ); assert.isTrue( repositionSpy.calledOnce, 'panel.reposition should be called once' ); // 检查第二次 showBlock 使用了与第一次完全相同的参数 args = showBlockSpy.firstCall.args; assert.isTrue( showBlockSpy.secondCall.calledWith( args[0], args[1], args[2] ), 'Second showBlock() call should use same arguments as first call.' );

这段测试用sinon.spy分别监听showBlock与reposition,断言窗口 resize 触发后:

  • reposition()恰好被调用一次;
  • showBlock()被调用两次(首次打开 + reposition 内部重放);
  • 第二次showBlock()的参数与第一次完全一致——验证了reposition()"用相同参数重放"的实现约定。

同文件还覆盖了面板的打开/隐藏、mode切换时隐藏、编辑器resize时隐藏、第二个面板在编辑器 resize 时被关闭(ticket #9800)等行为,共同构成 floatpanel 生命周期与定位行为的回归防线。手动用例与自动化用例互补:自动化用例锁定"事件→调用"的契约,手动用例则验证真实设备上的视觉结果(软键盘交互、视口适配)。


六、版本与历史背景

  • 4.5.4:修复 ticket #11724——"触屏设备上下拉框经常在打开后立即消失"。核心改动即在窗口 resize 时调用reposition()而非隐藏,并在插件源码中保留了明确的注释说明(plugins/floatpanel/plugin.js)。
  • 4.5.8:同目录下另一手动用例 tests/plugins/floatpanel/manual/rendering.md(标签4.5.8, trac13756)验证列表项内右键菜单的渲染布局不被裁切,与本文用例同属 floatpanel 布局正确性的回归矩阵。
  • 更早的 4.x 版本中,ticket #9800("Hide float panel when resizing the window")确立了"窗口 resize 时面板应隐藏或重定位"的行为边界(见 CHANGES.md),#11724 则进一步区分了移动端软键盘这一特殊 resize 来源。

这些历史 ticket 号(trac11724、trac9800、trac13756)均出现在测试元数据与 CHANGES.md 的 Fixed Issues 列表中,可作为回归排查时的检索关键词。


七、结论与实践要点

  1. floatpanel 是 CKEditor 4 下拉 UI 的公共底座:Paragraph Format、Font、颜色等 richcombo 下拉框及菜单都由它渲染与定位(依赖链:format → richcombo → floatpanel → panel)。
  2. 窗口 resize 与编辑器 resize 是两条不同的处理路径:前者触发reposition()重定位(4.5.4 起),后者触发hide()隐藏,二者不可混淆。
  3. 移动端软键盘场景的关键:软键盘弹出引起的视口变化不应导致下拉框消失;验证时重点观察"软键盘收起 + 面板保持可见且定位正确"。
  4. 桌面缩放场景的验收标准:缩放窗口后,面板要么被隐藏,要么被正确重定位,不得出现错位或裁切。
  5. 回归防线完整:手动用例(tests/plugins/floatpanel/manual/resize.md)验证真实设备表现,自动化用例(tests/plugins/floatpanel/floatpanel.js)锁定reposition()的行为契约,配合 CHANGES.md 中的 ticket 记录,可快速定位同类问题。
  • 前端
  • UI组件

【免费下载链接】ckeditor4

The best enterprise-grade WYSIWYG editor. Fully customizable with countless features and plugins.

项目地址:https://gitcode.com/gh_mirrors/ck/ckeditor4
点击查看免费下载
上一篇:5分钟掌握跨平台资源下载神器:从视频号到小红书的一站式解决方案
下一篇:突破标注精度瓶颈:Xtreme1测量工具深度解析与效能优化指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 5:39:32

利用Capture CIS 17.4 ORCAD Capture CIS 进行RC低通滤波仿真

一、时域仿真1、打开ORCAD软件&#xff0c;进入新建工程&#xff0c;填写工程文件名称&#xff0c;添加工程地址&#xff0c;同时勾选 Enable PSpice Simu..2、弹出的框里&#xff0c;选择最简单的一个模板simple.opj,然后点击OK。3、弹出的框选择PSpice A/D5、界面如下就建立…

作者头像 李华
网站建设 2026/10/16 5:39:29

PCB Editor 17.4 Allegro PCB Designer 出现KS错误

问题:DRC error "Shape to Route Keepin Spacing" TopConstraint value :0mmActual value :0mm解决办法:铺好铜以后&#xff0c;扩大电气限制框 把原来的电气限制框删除&#xff0c;重新画一个大一点的电气限制框&#xff0c;记着这回不要再铺铜了&#xff0c;这个办…

作者头像 李华
网站建设 2026/10/16 5:38:54

面对真实的自己

记录一下看到的一个有趣的文章&#xff1a;在制定计划的时候&#xff0c;人经常会陷入某种幻想。随便说几个例子&#xff1a;想读书的时候会想&#xff0c;应该读好书好&#xff0c;还是多读书好&#xff1f;想跑步的时候会想&#xff0c;应该早上跑好&#xff0c;还是晚上跑好…

作者头像 李华
网站建设 2026/10/16 5:35:30

易语言文件操作四件套:取尺寸、取时间、更名与存在判断详解

/* 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 5:33:16

顶层设计先行:企业如何建设数据系统的战略规划全解析

IDC数据显示&#xff0c;2026年中国数据治理平台市场规模突破860亿元&#xff0c;年复合增长率达29.7%&#xff0c;其中大型企业贡献超过65%的采购份额。然而&#xff0c;Gartner在2026年的研究中指出&#xff0c;80%的数据与分析治理举措可能因缺乏业务驱动力而失效&#xff0…

作者头像 李华