网站首页 » 前端开发 » JavaScript » 原生 JavaScript 做一个接地气的富文本编辑器
上一篇:
下一篇:

原生 JavaScript 做一个接地气的富文本编辑器

前言

这里不分享富文本编辑器都有哪些,哪些富文本编辑好用,而是简单地分享一下如何做一个比较接地气的而已很简单但很实用的富文本编辑器。当然这里也不是把这个富文本编辑器做很多强大,因为也没必要,并且也不是一天两天可以做得完的,为此是这里只是想通过一个简单的例子来说明如何做一个更加贴心的富文本编辑器。

在开始之前我们先来看一看效果图:

原生 javaScript 做一个接地气的富文本编辑器

富文本编辑器之旅

这里我先把代码贴出来,是好是坏并不重要,重要的是我这些不起眼的代码能够给你一点点启发,我就可以感动一整天了。

HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>原生 javaScript 做一个接地气的富文本编辑器</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
<div class="editor">
    <div class="editor-toolbar" id="editor-toolbar"></div>
    <div class="editor-body" id="editor-body" contenteditable="true"></div>
</div>
<script src="index.js"></script>
</body>
</html>
JavaScript
/*
* @Author: zhaoxixiong
* @Date:   2018-05-27 22:51:06
* @Last Modified by:   zhaoxixiong
* @Last Modified time: 2018-05-30 23:49:47
*/

const editor = document.getElementById("editor-body");
const toolbar = document.getElementById("editor-toolbar");
// 工具栏按钮
const toolbarButton = [
    {
        name:"H1",
        replaceBy: "<div class='para-title level-1'><h1 class='title-text'><br></h1></div><p><br></p>"
    },
    {
        name:"H2",
        replaceBy: "<div class='para-title level-2'><h2 class='title-text'><br></h2></div><p><br></p>"
    },
    {
        name:"H3",
        replaceBy: "<div class='para-title level-3'><h3 class='title-text'><br></h3></div><p><br></p>"
    },
    {
        name:"CODE",
        replaceBy: "<pre><code><br></pre></code><p><br></p>"
    },
    {
        name:"IMG",
        commandName:"insertImage",
        valueArgument:"H1",
    },
    {
        name:"LIST",
        replaceBy: "<ul class='post-item-list'><li><br></li></ul><p><br></p>"
    },
];

// 初始化标签
editor.innerHTML = "<p><br></p>";

toolbarRender();

// 渲染工具栏
function toolbarRender(){
    // 创建所需的编辑按钮
    const fragment = document.createDocumentFragment();
    const ul = document.createElement("ul");
    toolbarButton.forEach((value,index)=>{
        const a = document.createElement("a");
        const li = document.createElement("li");
        a.href = "javascript:;"
        a.id = "toolbar-btn-" + (index+1);
        const btnText = document.createTextNode(value.name);
        a.appendChild(btnText);
        li.appendChild(a);
        ul.appendChild(li);

    });
    fragment.appendChild(ul);
    toolbar.appendChild(fragment);

    // 绑定按钮点击事件
    bindToolbarBtn();
}

// 给按钮绑定事件
function bindToolbarBtn(){
    const btns = toolbar.getElementsByTagName("a");
    Array.prototype.forEach.call(btns,(item,index)=>{
        if(toolbarButton[index].name === "code"){
            item.onclick = ()=>{
                document.execCommand("insertHTML","",toolbarButton[index].replaceBy);
            }
        }
        if(toolbarButton[index].name.indexOf('H')>-1){ // 如果是 H 标签
           item.onclick = ()=>{
                   document.execCommand("insertHTML","",toolbarButton[index].replaceBy);
           }
        }

        if(toolbarButton[index].name === "IMG"){
            item.onclick = ()=>{
                document.execCommand("insertHTML","","<p><img class='img-responsive' src='http://yunkus.com/wp-content/themes/zxxPro/assets/images/default.jpg'></p>");
            }
        }

        if(toolbarButton[index].name === "LIST"){
            item.onclick = ()=>{
                document.execCommand("insertHTML","",toolbarButton[index].replaceBy);
            }
        }
    })
}

// 给富文本编辑器加按钮事件
editor.addEventListener("keyup",function(event){
    // 限制编辑器不能为空,至少要保留<p><br></p>
    if(!editor.innerHTML){
        editor.innerHTML = "<p><br></p>"
    }
});
CSS
/*
* @Author: zhaoxixiong
* @Date:   2018-05-27 22:52:12
* @Last Modified by:   zhaoxixiong
* @Last Modified time: 2018-05-31 00:00:26
*/
*{
    padding: 0;
    margin: 0;
    border:0;
}
ul{
    list-style: none;
}
a{
    text-decoration: none;
    color: #333;
}
p{
    margin-bottom: 12px;
}
.editor{
    margin: 28px auto;
    width: 760px;
    border:1px solid #c9d8db;
    box-shadow: 0 8px 40px rgba(0, 0, 0, 0.15);
}
.editor-body{
    height: 500px;
    outline: none;
    padding: 12px 10px;
    overflow-y: auto;
}
.editor-toolbar{
    height: 38px;
    line-height: 38px;
    border-bottom: 1px solid #c9d8db;
}
.editor-toolbar ul li a{
    padding: 0 10px;
    float: left;
    color: #666;
    transition: color 0.3s ease 0s
}
.editor-toolbar ul li a:hover{
    color: #333;
    cursor: pointer;
}
.para-title .title-text {
    position: relative;
}
.para-title .title-text::after {
    position: absolute;
    color: #373d41;
    margin-right: 5px;
    font-size: 12px;
    top: -3px;
    right: 0;
    font-style: italic;
    font-weight: normal;
}
.level-1 {
    margin: 0 0 1.3rem;
}
.level-1 .title-text::after {
    content: "super";
}
.level-2{
    display: block;
    margin: 1.5rem 0 1rem;
    padding: 0rem 0 0.5rem 0rem;
    border-bottom: 1px solid #dedede;
    font-weight: bolder;
    line-height: 1.5rem;
    clear: both;
}
.level-2 .title-text {
    margin-bottom: 0;
    font-size: 24px;
    font-weight: bolder;
    color: #373d41;
}
.level-2 .title-text::after {
    content: "main";
}
.level-3 {
    margin: 1.5rem 0 1.3rem;
}
.level-3 .title-text {
    color: #333;
    position: relative;
}
.level-3 .title-text::after {
    content: "sub";
}
.post-item-list {
    padding-left: 24px;
    list-style: circle;
}

富文本编辑器的实现方式多种多样,这里也只是冰山一角,如果你想做一个富文本编辑器,你也可以用其他的方法来实现,毕竟这里只是给你提供一种实现的可能。

对于上面的例子中的插入图片,你可以根据自己的实际情况来变通处理。虽然上面的例子有很多不足,但总得来说还是基本实现了一个简单的富文本编辑器。上面的编辑器不只是简单的标签组合,而是一些标签也自定义了一些默认的类名,这才是一些开发人员很可能想做的事情。

从本例子中发现:

  • 1、第一个注意点,工具栏需要需要使用 a 标签作为按钮,并且同时把 href 的值写成 javascript:;
  • 2、forEach 不能遍历 DOM 数组

在线示例:http://yunkus.com/demo/a-rich-text-editor-coding-by-javascript-only/

相关资料

https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand

 

 

  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/a-rich-text-editor-coding-by-javascript-only/

评论2
  1. 蛋蛋 2018年6月5日 at pm3:06 回复

    大熊你为何怎么这么叼

  2. 蛋蛋 2018年6月5日 at pm3:16 回复

    大熊你这么叼的吗

Leave a Reply

Your email address will not be published. Required fields are marked *

评论 END