PHP前端开发

使用contentEditable属性创建一个所见即所得(WYSIWYG)编辑器

百变鹏仔 4周前 (09-21) #HTML
文章标签 编辑器

所见即所得编辑器非常受欢迎。您可能也曾在某个时候使用过其中之一。有很多库可以帮助您设置自己的编辑器。尽管它们设置起来很快,但使用这些库也有缺点。首先,它们很臃肿。其中大多数都有您可能不会使用的奇特功能。此外,自定义这些编辑器的外观可能会很令人头疼。

在本教程中,我们将构建我们自己的轻量级所见即所得编辑器。在本教程结束时,您将拥有一个具有基本格式化功能的编辑器,并且可以根据您的喜好设置样式。

我们首先介绍execCommand。我们将使用此命令来广泛地实现我们的编辑器。

Document.execCommand()

execCommand 是文档对象的一个​​方法。它允许我们操作可编辑区域的内容。当与 contentEditable 一起使用时,它可以帮助我们创建富文本编辑器。有很多命令可用,例如添加链接、将选择设置为粗体斜体以及更改字体大小或颜色。该方法遵循以下语法:

document.execCommand(CommandName, ShowDefaultUI, ValueArgument);

CommandName 是一个字符串,指定要执行的命令的名称。 ShowDefaultUI 是一个布尔值,指示是否应显示支持界面。该选项尚未完全实现,最好将其设置为 false。 ValueArgument 是一个字符串,用于提供图像 URL 或 foreColor 等信息。当命令不需要值才能生效时,此参数设置为 null。

我们需要使用此方法的不同版本来实现各种功能。在接下来的几段中,我将一一回顾它们。

没有值参数的命令

粗体、对齐、撤消和重做等命令不需要 ValueArgument。在这种情况下,我们使用以下语法:

document.execCommand(commandName, false, null);

CommandName 只是命令的名称,例如 justifyCenter、justifyRight、bold 等. 

带有值参数的命令

像 insertImage、createLink 和 foreColor 这样的命令需要第三个参数才能正常工作。对于这些命令,您需要以下语法:

document.execCommand(commandName, false, value);

对于 insertImage,该值是要插入的图像的 URL。对于 foreColor,它将是类似 #FF9966 的颜色值或类似 blue 的名称。

添加块样式标签的命令

添加 HTML 块样式标记需要使用 formatBlock 作为 commandName,并将标记名称用作 valueArgument。语法类似于:

document.execCommand('formatBlock', false, tagName);

此方法将在包含当前选择的行周围添加 HTML 块样式标记。它还会替换那里已经存在的任何标签。 tagName 可以是任何标题标记 (h1-h6)、p 或 blockquote。

我在这里讨论了最常用的命令。您可以访问 Mozilla 以获取所有可用命令的列表。

创建工具栏

基础知识完成后,是时候创建工具栏了。我将使用 Font Awesome 图标作为按钮。您可能已经注意到,除了一些差异外,所有 execCommand 都具有相似的结构。我们可以通过对工具栏按钮使用以下标记来利用这一点:

<a href="#" data-command='commandName'><i class='fa fa-icon'></i></a>

这样,每当用户单击按钮时,我们就能够根据 data-command 属性的值来判断要使用哪个版本的 execCommand 。以下是几个按钮供参考:

<a href="#" data-command='h2'>H2</a><a href="#" data-command='undo'><i class='fa fa-undo'></i></a><a href="#" data-command='createlink'><i class='fa fa-link'></i></a><a href="#" data-command='justifyLeft'><i class='fa fa-align-left'></i></a><a href="#" data-command='superscript'><i class='fa fa-superscript'></i></a>

第一个按钮的 data-command 属性值为 h2。在 JavaScript 中检查此值后,我们将使用 execCommand 方法的 formatBlock 版本。同样,对于最后一个按钮,superscript 建议我们使用 execCommand 的无 valueArgument 版本。

创建 foreColor 和 backColor 按钮是另一回事。它们带来了两个问题。根据我们提供给用户选择的颜色数量,编写这么多代码可能会很烦人并且容易出错。为了解决这个问题,我们可以使用以下 JavaScript 代码:

var colorPalette = ['000000', 'FF9966', '6699FF', '99FF66','CC0000', '00CC00', '0000CC', '333333', '0066FF', 'FFFFFF'];                    var forePalette = $('.fore-palette');for (var i = 0; i < colorPalette.length; i++) {  forePalette.append('<a href="#" data-command="forecolor" data-value="' + '#' + colorPalette[i] + '" style="background-color:' + '#' + colorPalette[i] + ';" class="palette-item"></a>');}

请注意,我还为每种颜色设置了一个 data-value 属性。稍后它将在 execCommand 方法中用作 valueArgument。

第二个问题是我们不能一直显示那么多颜色,因为这会占用大量空间并导致糟糕的用户体验。使用一点CSS,我们可以确保只有当用户将鼠标悬停在相应按钮上时才会出现调色板。这些按钮的标记也需要更改为以下内容:

<div class="fore-wrapper"><i class='fa fa-font'></i>  <div class="fore-palette">  </div></div>

要仅在 hover 上显示调色板,我们需要以下 CSS:

.fore-palette,.back-palette {  display: none;}.fore-wrapper:hover .fore-palette,.back-wrapper:hover .back-palette {  display: block;  float: left;  position: absolute;}

CodePen 演示中还有许多其他 CSS 规则可以使工具栏更漂亮,但这就是核心功能所需的全部。

向编辑器添加功能

现在,是时候让我们的编辑器发挥作用了。这样做所需的代码非常小。

$('.toolbar a').click(function(e) {      var command = $(this).data('command');    if (command == 'h1' || command == 'h2' || command == 'p') {    document.execCommand('formatBlock', false, command);  }    if (command == 'forecolor' || command == 'backcolor') {    document.execCommand($(this).data('command'), false, $(this).data('value'));  }    if (command == 'createlink' || command == 'insertimage') {    url = prompt('Enter the link here: ','http:\/\/');    document.execCommand($(this).data('command'), false, url);  }    else document.execCommand($(this).data('command'), false, null);  });

我们首先将单击事件附加到所有工具栏按钮。每当单击工具栏按钮时,我们都会将相应按钮的 data-command 属性的值存储在变量 command 中。稍后将用于调用 execCommand 方法的适当版本。它有助于编写简洁的代码并避免重复。

设置 foreColor 和 backColor 时,我使用 data-value 属性作为第三个参数。 createLink 和 insertImage 没有常量 url 值,因此我们使用提示从用户获取值。您可能还想执行其他检查以确保 url 有效。如果command变量不满足任何if块,我们运行第一个版本的execCommand。

这就是我们所见即所得编辑器的样子。

您还可以使用我在上次讨论的 localStorage 来实现自动保存功能教程。

跨浏览器差异

各种浏览器在实现上存在细微差异。例如,请记住,使用 formatBlock 时,Internet Explorer 仅支持标题标签 h1 - h6、address 和 pre。在指定 commandName 时,您还需要包含标记分隔符,例如

并非所有浏览器都支持所有命令。 Internet Explorer 不支持 insertHTML 和 hiliteColor 等命令。同样,只有 Firefox 支持 insertBrOnReturn。您可以在此 GitHub 页面上了解有关浏览器不一致的更多信息。

最终想法

创建您自己的所见即所得编辑器可以是一次很好的学习体验。在本教程中,我介绍了很多命令并使用了一些 CSS 来进行基本样式设置。作为练习,我建议您尝试实现一个工具栏按钮来设置文本选择的 font。该实现与 foreColor 按钮的实现类似。

我希望您喜欢本教程并学到一些新东西。如果您从头开始创建了自己的所见即所得编辑器,请随时在评论部分链接到它。