上下文工具栏只能包含为常规工具栏定义的按钮,或专门为启动 ContextForm 而注册的按钮。这些按钮以字符串列表形式呈现,每个字符串代表一个已注册的按钮名称。
注册上下文工具栏
通过调用注册表中的 addContextToolbar API 来注册上下文工具栏。规范如下:
| 名称 | 说明 |
|---|---|
| 此属性控制上下文工具栏何时显示 |
| 此属性控制上下文工具栏相对于当前光标的位置 |
| 此属性控制谓词(条件)是基于 |
| 一个字符串列表,表示已注册的工具栏按钮或已注册的上下文表单启动器。 |
上下文工具栏的定位
上下文工具栏有三种定位选项:selection、node 或 line。
selection定位会将上下文工具栏放置在当前选区的上方或下方(如果可能,则居中对齐)。node定位会将上下文工具栏放置在节点(例如表格或图片)边界的上方或下方。line定位会将上下文工具栏放置在当前选区的右侧(对于从右到左的语言,则为左侧)。
配置示例
此示例展示了 quickbars 插件如何添加标准的选区上下文工具栏以及一个自定义的图片对齐工具栏示例。当选中任何内容时,该上下文工具栏都会显示。
HTML
<textarea id="context-toolbar"> <p>点击下方的示例图片,将显示新配置的上下文工具栏。</p> <p><img style="display: block; margin-left: auto; margin-right: auto;" title="Tiny Logo" src="https://www.tiny.cloud/docs/tinymce/latest/_images/logos/android-chrome-256x256.png" alt="TinyMCE Logo" width="128" height="128"></p> <p>选择此句中的单词,查看另一个新配置的上下文工具栏。</p> <p>点击文本不应触发上下文工具栏</p> </textarea>
JS
tinymce.init({
selector: 'textarea#context-toolbar',
height: 350,
setup: (editor) => {
editor.ui.registry.addContextToolbar('imagealignment', {
predicate: (node) => node.nodeName.toLowerCase() === 'img',
items: 'alignleft aligncenter alignright',
position: 'node',
scope: 'node'
});
editor.ui.registry.addContextToolbar('textselection', {
predicate: (node) => !editor.selection.isCollapsed(),
items: 'bold italic | blockquote',
position: 'selection',
scope: 'node'
});
},
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
});为上下文工具栏按钮添加标签和分组
从 TinyMCE 7.6.0 版本开始,注册上下文工具栏时,支持将 items 指定为一个对象,该对象支持分组并可包含可选的名称和标签。这一改进通过将按钮组织为带标题或标签的分组,提升了工具栏的易用性。
该对象结构包含两个可选属性:name 和 label。
name:此属性用作包含按钮的分组标题。label:此属性用作每个按钮分组的标签。
如果name和label均未指定,则默认行为为不分组显示按钮。
items 的对象结构如下:
items: [
{
name: 'Formatting', // 可选,用作分组标题
items: [ 'bold', 'italic' ] // 已注册按钮名称的数组
},
{
label: 'History', // 可选,用作分组标签
items: [ 'undo', 'redo' ] // 已注册按钮名称的数组
},
{
items: [ 'undo', 'italic' ] // 未指定名称或标签,应用默认行为
}
]对于 7.8.0 及更高版本的编辑器,上下文工具栏还支持 navigateback 按钮,用于多级工具栏导航。使用嵌套工具栏时,此内置按钮可让用户返回上一级上下文工具栏。多级上下文工具栏配置示例:tinymce.init({
selector: 'textarea',
setup: (editor) => {
// 注册名为 'bar' 的主上下文工具栏
editor.ui.registry.addContextToolbar('bar', {
predicate: () => true, // 触发时始终显示工具栏
items: 'bold italic | undo redo | subbar1', // 工具栏按钮和嵌套工具栏触发器
position: 'line',
scope: 'editor'
});
// 注册名为 'subbar1' 的嵌套上下文工具栏
editor.ui.registry.addContextToolbar('subbar1', {
launch: { text: 'Subbar 1' }, // 显示在父工具栏中的按钮标签
items: 'navigateback bold italic | undo redo | subbar2'
// 'navigateback' 允许用户返回上一级工具栏
// 'subbar2' 是另一个嵌套工具栏(可类似定义)
});
}
});HTML
<textarea id="context-toolbar-labels"> <p>点击下方示例图片将显示新配置的上下文工具栏。</p> <p><img style="display: block; margin-left: auto; margin-right: auto;" title="Tiny Logo" src="https://www.tiny.cloud/docs/tinymce/latest/_images/logos/android-chrome-256x256.png" alt="TinyMCE Logo" width="128" height="128"></p> <p>选择此句中的单词,可查看另一个新配置的上下文工具栏。</p> <p>点击文本不应触发上下文工具栏</p> </textarea>
JS
tinymce.init({
selector: 'textarea#context-toolbar-labels',
height: 350,
setup: (editor) => {
editor.ui.registry.addContextToolbar('imagealignment', {
predicate: (node) => node.nodeName.toLowerCase() === 'img',
position: 'node',
scope: 'node',
items: [
{
name: 'Formatting',
items: ['alignleft', 'aligncenter', 'alignright']
},
{
label: 'Copy',
items: ['copy', 'paste']
}
],
});
editor.ui.registry.addContextToolbar('textselection', {
predicate: (node) => !editor.selection.isCollapsed(),
position: 'selection',
scope: 'node',
items: [
{
name: 'Format',
items: ['bold', 'italic', 'underline']
},
],
});
},
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
});以编程方式启动上下文工具栏
有一个名为 contexttoolbar-show 的 editor 事件,触发该事件可在当前选区显示上下文工具栏。该事件接收一个参数 toolbarKey,用于指定要显示的已注册上下文表单或上下文工具栏的名称。
排查上下文工具栏与上下文表单的冲突
在以下情况下,自定义上下文工具栏或自定义上下文表单可能会发生冲突:
编辑器提供的上下文工具栏或上下文表单,
快速工具栏(
quickbars)插件提供的上下文工具栏或上下文表单,其他自定义上下文工具栏或自定义上下文表单。
确定上下文工具栏和上下文表单的显示优先级
有三个设置决定上下文工具栏和上下文表单的优先级:scope、predicate 和 position。
scope- 将上下文工具栏或表单设置为:特定于某些类型的内容(node),或通用(全局)工具栏或表单(editor)。predicate- 谓词是应显示上下文工具栏或表单的条件。此设置是一个函数,用于确定上下文菜单或表单是否适用于当前选区或光标位置。该函数应返回一个布尔值。position- 设置上下文工具栏或表单相对于当前上下文(selection、node或line)的渲染位置。
通常:
上下文表单的优先级高于上下文工具栏。
具有
scope: 'node'的上下文表单的优先级高于scope: 'editor'。一个选区或光标位置只能显示一个上下文表单,它们不能与其他上下文表单或上下文工具栏拼接。
具有
position: 'selection'的上下文工具栏的优先级高于position: 'node',而position: 'line'的优先级最低。当需要显示多个上下文工具栏时,编辑器会拼接上下文工具栏,条件是:
匹配的谓词,
相同的
scope和position值。拼接的工具栏可能包含重复的工具栏项。
如果未找到匹配当前选区或光标位置的上下文工具栏或上下文表单,编辑器会递归地在当前节点的父节点中搜索匹配项,直至到达编辑器内容的根节点。
上下文工具栏和上下文表单的优先级说明
以下说明可用于排查上下文工具栏和上下文表单的行为。
编辑器将通过以下流程确定要显示的上下文工具栏或上下文表单:
查找所有同时满足以下条件的上下文表单:
scope: 'node'匹配当前选区或光标位置的谓词(条件)。
如果存在任何匹配的上下文表单,编辑器将显示第一个找到的表单,流程结束。
查找所有同时满足以下条件的上下文表单:
scope: 'editor'匹配当前选区或光标位置的谓词。
如果存在任何匹配的上下文表单,编辑器将显示第一个找到的表单,流程结束。
查找所有同时满足以下条件的上下文工具栏:
任意
scope匹配当前选区或光标位置的谓词。
如果存在任何匹配的上下文工具栏,编辑器将根据
position值确定上下文工具栏的优先级。所有具有
position: 'selection'或position: 'node'的上下文工具栏将被拼接,拼接后的工具栏将被显示,流程结束。否则,所有具有
position: line的上下文工具栏将被拼接,拼接后的工具栏将被显示,流程结束。
查找同时满足以下条件的上下文表单:
任意
scope谓词匹配当前节点、选区或光标位置的父节点。
如果找到任何上下文表单,则第一个找到的表单将被显示在编辑器中,流程结束。
查找同时满足以下条件的上下文工具栏:
任意
scope谓词匹配当前节点、选区或光标位置的父节点。
如果存在匹配的上下文工具栏,编辑器将根据
position值对上下文工具栏进行优先级排序。如果存在
position: 'selection'的上下文工具栏,它们将被拼接,拼接后的工具栏将被显示,流程结束。如果存在
position: 'node'的上下文工具栏,它们将被拼接,拼接后的工具栏将被显示,流程结束。否则,所有具有
position: line的上下文工具栏将被拼接,拼接后的工具栏将被显示,流程结束。
对 DOM 中每个连续的父节点重复步骤 4 和 5,针对具有
scope: node的上下文工具栏和上下文表单,直到满足以下条件之一:找到并显示匹配的上下文表单或上下文工具栏,
到达编辑器的根节点。