summernote toolbar 跟随页面自动滚动

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

toolbar3

toolbar4

实现代码

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

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 的

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

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

// window resize
$(window).resize(function () {
  Template.articleNewModal.repositionToolbar();
});

说说你的想法