如何在 Medium Editor 中使用链接?

How to use links in Medium Editor?

我一直在尝试优秀的Medium Editor。我一直遇到的问题是我似乎无法将 links 转换为 "work"。

最简单的,这里有一些HTML/JS用来演示问题:

HTML:

<html>
<head>
  <script src="//cdn.jsdelivr.net/medium-editor/latest/js/medium-editor.min.js"></script>
  <link rel="stylesheet" href="//cdn.jsdelivr.net/medium-editor/latest/css/medium-editor.min.css" type="text/css" media="screen" charset="utf-8">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/medium-editor/latest/css/themes/beagle.min.css" type="text/css">
</head>
<body>
  <div class='editable'>
    Hello world.  <a href="http://www.google.com">link</a>
  </div>
</body>
</html>

Javascript:

var editor = new MediumEditor('.editable');

这个 fiddle 演示了问题(使用上面的代码)。

在我看来,单击 link 应该会将我带到 link 的 href 所定位的任何位置。使用 link 的唯一方法是右键单击并在新选项卡或新选项卡中打开 window -- 我不想让我的用户这样做。

我觉得我一定是在配置中遗漏了一些简单的东西(Anchor Preview Options or the Anchor Form Options)。很遗憾,我没有看到它。

在我的实际应用中,我不是使用jQuery,而是使用angularjs。如果不存在严格的 Medium Editor 答案,我可以退回到使用基本 JS 或 angularjs 提供的任何东西。

根据评论中@Valijon 的一些想法,我能够使用以下代码让它工作:

var iElement = angular.element(mediumEditorElement);

iElement.on('click', function(event) {
  if (
      event.target && event.target.tagName == 'A' &&
      event.target.href && !event.defaultPrevented) {
    $window.open(event.target.href, '_blank');
  }
});

我认为关键是显然编辑器让事件传播到祖先元素,所以我能够只监听顶级编辑器元素上的点击。

此处,$window 是 angular 的 $window 服务 -- 如果您不使用 angularjswindow可以做到这一点,我使用 angular.element 来简化事件侦听器注册表,但您可以使用 old-fashioned 方式(或使用您选择的 JS 框架)。

我找到了如何绑定事件。

这是完整的事件列表https://github.com/yabwe/medium-editor/blob/master/CUSTOM-EVENTS.md

尝试将您的代码更改为

var editor = new MediumEditor('.editable')
    .subscribe("editableClick", function(e){if (e.target.href) {window.open(e.target.href)}})

https://jsfiddle.net/fhr18gm1/

因此 medium-editor 建立在 built-in 浏览器支持 contenteditable 元素之上。当您实例化 medium-editor 时,它会将 contenteditable=true 属性添加到您提供的任何元素中。

默认情况下,由于文本现在是可编辑的(contenteditable 属性使浏览器将其视为所见即所得文本),浏览器不再支持单击 link 进行导航。因此,medium-editor 并没有阻止这些 link 点击的发生,浏览器本身就是这样做的,作为使文本可编辑的一部分。

medium-editor 内置了与 link 交互的扩展:

  • 锚扩展
    • 允许 adding/removing links
  • anchor-preview 分机
    • 悬停 link
    • 时显示工具提示
    • 单击工具提示时,允许通过锚扩展编辑 link 的 href

我觉得小编的目的就是这里的误会。编辑器允许编辑文本,为了 add/remove/update link,您需要能够单击它而不会自动离开。这就是我认为的 'edit' 模式。

但是,由于编辑而产生的 html 是有效的 html,如果您将 html 放在一个没有 [= 的元素中11=] 属性,一切都会按预期工作。我认为这是 'publish mode'

我查看像 word 或 google 文档这样的编辑器,您会看到类似的行为,当您编辑文档时,links 不会在您单击时离开在它们上,您必须在单击 link 后实际选择通过单独的操作来导航它们。但是,在文档的 'published' 版本中,单击 link 实际上会打开浏览器 window 并导航到那里。

我认为这确实是一个很好的建议,作为对现有 anchor-preview 扩展的增强。悬停 link 时出现的工具提示可能有多个选项(即编辑 Link | 删除 Link | 导航至 URL)。

tldr;

当 'editing' 文本在浏览器中通过 built-in 所见即所得支持 (contenteditable) 时,

Link 无法在单击时导航。当不处于 'edit' 模式时,links 将按预期工作。 这可以很好地增强 medium-editor anchor-preview 扩展。

当我问这个问题时,我真正想要的是在 "edit" 模式下类似于 Google Docs 的行为(). I opened an issue on the Medium Editor tracker 他们决定不将其作为核心的一部分来实现中型编辑器,但他们指出,他们很乐意有人将该功能添加为扩展。

因此,我决定按照建议将该功能作为扩展来实现。它可以作为 MediumTools1 的一部分找到。该项目仍处于非常早期的阶段(例如,我没有做任何事情来使样式看起来更好,或者使用更好的缩小实践等。但我们很乐意为此接受 Pull Requests)。

代码的内容如下所示:

var ClassName = {
  INNER: 'medium-editor-toolbar-anchor-preview-inner',
  INNER_CHANGE: 'medium-editor-toolbar-anchor-preview-inner-change',
  INNER_REMOVE: 'medium-editor-toolbar-anchor-preview-inner-remove'
}

var AnchorPreview = MediumEditor.extensions.anchorPreview;
GdocMediumAnchorPreview = MediumEditor.Extension.extend.call(
  AnchorPreview, {

    /** @override */
    getTemplate: function () {
      return '<div class="medium-editor-toolbar-anchor-preview">' +
        '  <a class="' + ClassName.INNER + '"></a>' +
        '  -' +
        '  <a class="' + ClassName.INNER_CHANGE + '">Change</a>' +
        '  |' +
        '  <a class="' + ClassName.INNER_REMOVE + '">Remove</a>' +
        '</div>';
    },

    /** @override */
    createPreview: function () {
      var el = this.document.createElement('div');

      el.id = 'medium-editor-anchor-preview-' + this.getEditorId();
      el.className = 'medium-editor-anchor-preview';
      el.innerHTML = this.getTemplate();

      var targetBlank =
          this.getEditorOption('targetBlank') ||
          this.getEditorOption('gdocAnchorTargetBlank');
      if (targetBlank) {
        el.querySelector('.' + ClassName.INNER).target = '_blank';
      }

      var changeEl = el.querySelector('.' + ClassName.INNER_CHANGE);
      this.on(changeEl, 'click', this.handleClick.bind(this));

      var unlinkEl = el.querySelector('.' + ClassName.INNER_REMOVE);
      this.on(unlinkEl, 'click', this.handleUnlink.bind(this));

      return el;
    },

    /** Unlink the currently active anchor. */
    handleUnlink: function() {
      var activeAnchor = this.activeAnchor;
      if (activeAnchor) {
        this.activeAnchor.outerHTML = this.activeAnchor.innerHTML;
        this.hidePreview();
      }
    }
  });

作为解释,我只是使用 medium 的原型继承风格 "subclass" original/builtin AnchorPreview 扩展。我重写 getTemplate 方法以将额外的 link 添加到标记中。然后我从 getPreview 的基本实现中借鉴了很多,但我将新的操作绑定到每个 link 中。最后,我需要在单击 "Remove" 时对 "unlinking" 和 link 执行操作,因此我为此添加了一个方法。 unlink 方法可能可以使用 contenteditable magic 做得更好(以确保它是浏览器撤消堆栈的一部分),但我没有花时间去弄明白(尽管它会使对任何感兴趣的人来说都是一个很好的 Pull Request :-).

1目前,这只是 的一部分,但我希望这会在某个时候改变。 . .