summernote 是一个功能非常强大的 web 编辑器,可以应用到各种场景下。最近在 Meteor 中做了一个小功能,就是实现 summernote 的 toolbar 跟随页面滚动的效果。这样即使文章内容很长,要插入一个图片或者使用其他特殊标签的时候,不必滚动页面到最上方去找 toolbar 了。效果如下:

toolbar3 toolbar4

实现代码

summernote 有一个插件功能,很惭愧,因为个人时间问题,没有去研究如何使用,可以将以下代码封装成 summernote 的插件,这样在任何页面调用 summernote ,toolbar 滚动功能都可以生效了。本文只介绍一下如何在 meteor 应用中使用该函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Template.articleNewModal.repositionToolbar = function () {
// 根据 summernote className 找到他的 toolbar
const $editor = $('.editor').siblings('.note-editor');
const $toolbar = $editor.find('.note-toolbar');
// 得到 toolbar 的高度
const toolbarHeight = $toolbar.height();
// 得到浏览器当前滚动条 top 位置
const windowTop = $(window).scrollTop();
// 编辑器的 top 位置
const editorTop = $editor.offset().top;
// 编辑器的 bottom 位置
const editorBottom = editorTop + $editor.height();

// 判断如果滚动条 top 位置大于编辑器 top 位置,且编辑器 bottom 没有超出滚动条 top
// 且编辑器的 bottom 大于 toolbar 的高度(让 toolbar 不超出编辑器范围)
if (windowTop > editorTop && windowTop < editorBottom && editorBottom > toolbarHeight) {
// 设置 toolbar position 为 fixed,并根据滚动条设置固定坐标
const pos = $('#mmodal').scrollTop() - toolbarHeight + (toolbarHeight < 100 ? 15 : 50);
$toolbar.css('position', 'fixed');
$toolbar.css('top', `${pos}px`);
$toolbar.css('width', `${$editor.width()}px`);
$toolbar.css('z-index', '99999');
$editor.css('padding-top', '42px');
} else {
// 如果不符合以上条件,则让 toolbar 的宽度等于编辑器的宽度
// 如果自适应页面拖动时可以保证 toolbar 不超出编辑器
$toolbar.css('width', `${$editor.width()}px`);
}

// 如果编辑器的顶部在视野范围内,则让 toolbar 恢复原位。
if (editorTop > 0) {
$toolbar.css('position', 'static');
$editor.css('padding-top', '0px');
}
};

Meteor 如何调用

  在 meteor 中,只需要响应滚动条宿主的 scroll 消息即可。我这里因为弹出的是一个 bootstrap 风格的 modal。所以响应了 modal 的 scroll 消息。将如下代码放到你模版中的 onRendered 函数中即可。这样这个模版下 className 为 modal 的

1
2
3
4
5
// scroll event
$('.modal').scroll(function () {
$('.note-image-popover').hide();
Template.articleNewModal.repositionToolbar();
});

还有,当页面发生大小改变的时候,也需要触发这个函数,已保证 toolbar 的位置和宽度是适应编辑器的。

1
2
3
4
// window resize
$(window).resize(function () {
Template.articleNewModal.repositionToolbar();
});