码迷,mamicode.com
首页 > 其他好文 > 详细

实现一个简易的富文本编辑器(二):给富文本添加自定义事件

时间:2016-04-30 22:23:10      阅读:403      评论:0      收藏:0      [点我收藏+]

标签:

  为富文本添加一个提交按钮,点击按钮可以获取富文本内容。但是在提交前或者提交后我想做一些操作,比如内容校验内容清空等等。

  我们直接在该按钮上绑定点击事件同样可以达到目的,但是为了组件化,所以本例打算为提交按钮自定义beforeSubmit、afterSubmit两个事件。

1.创建发布订阅者对象

  前文说到,事件系统是发布-订阅模式的一个实现,模式给事件发布函数与事件处理函数进行解耦,使得两者无直接调用关系。

  简易发布订阅者对象实现如下:

var Event = {
//    _cachePool : {}, 处理函数缓存池不要写在该对象内,因为原型链继承会让子类共享引用类型数据。
    fire : function(type, msg) {
        var fns;
        if(!(fns = this._cachePool[type])) {
            return;
        }
        var len = fns.length;
        for(var i = 0, fn; i < len; i++) {
            fn = fns[i];
            fn.call(this, msg);
        }
    },
    on : function(type, callback) {
        if(!this._cachePool[type]) {
            this._cachePool[type] = [];
        }
        this._cachePool[type].push(callback);
    },
    un : function(type, callback) {
        var fns = this._cachePool[type];
        if(fns) {
            this._cachePool[type] = fns.filter(function(item){//注意兼容,一些低版本Array没有过滤函数
                return item !== callback;
            });
        }
    }
};

  这里要去掉缓存池,因为这个对象将是编辑器原型中的一份子,我们希望每个编辑器都有自己一个私有的缓存池,以避免不同编辑器实例监听到相同的事件。

2.编辑器样式

  本例编辑器给命令按钮设置图片样式,并且仅实现字体加粗功能:

.editorOut {
    border:1px solid #ccc;
    width:200px;
    height:200px;
    position:relative;
}
.editorTool {
    margin:2px;
    width:100%;
}
.editorFoot {
    margin:2px;
    width:100%;
    position:absolute;
    bottom:0;
}

.editorOut button {
    height:20px;
    width:20px;
    margin:1px;
    border:0px solid #fff;
    cursor:pointer;
    overflow:hidden;
}
.editorOut button.bold{
    background:url(./imgs.svg) 0px 0px;
    background-size:140px 40px;
}
.editorOut button.bold:hover {
    background:url(./imgs.svg) 0px -20px;
    background-size:140px 40px;
}

  注:SVG是绘制矢量图的标签(XML)语言,它的特点是不受像素影响。

3.实现简易编辑器

  利用js脚本,动态创建编辑器。

  _create函数创建编辑器,它封装了创建编辑器命令块、底部块、输入域等创建的过程。

  _createEditor为创建编辑器输入域函数。

  _createTool为创建命令块函数。

  _createCommandBtn为创建调用编辑器命令的按钮的函数,本例只实现一个按钮。

  _createFoot创建底部块函数。

  _onbeforeSubmit为启动自定义事件beforesubmit的函数。

  _onaftersubmit为启动自定义事件aftersubmit的函数。

  _createPrintBtn为创建输出按钮的函数。本例两个自定义事件都在这里启动。

EditorProto = {
    _create : function(id) {
        var editor = this._createEditor(id);
        var tool = this._createTool();
        var button = this._createCommandBtn();
        var foot = this._createFoot();
        var printBtn = this._createPrintBtn();
        this.printBtn = printBtn;
        tool.appendChild(button);
        foot.appendChild(printBtn);
        editor.insertBefore(tool, editor.firstChild);
        editor.appendChild(foot);
        return editor;
    },
    _createEditor : function(id) {
        var editor = document.getElementById(id);
        editor.className = "editorOut";
        editor.contentEditable = true;
        return editor;
    },
    _createTool : function() {
        var tool = document.createElement("div");
        tool.contentEditable = false;
        tool.className = "editorTool";
        return tool;
    },
    _createCommandBtn : function() {
        var button = document.createElement("button");
        button.className = "bold";
        button.title = "加粗";
        button.onclick = function(e) {
            document.execCommand("bold", false, null);
        };
        return button;
    },
    _createFoot : function() {
        var tool = document.createElement("div");
        tool.contentEditable = false;
        tool.className = "editorFoot";
        return tool;
    },
    _onbeforeSubmit : function(e, scope, callback) {
        scope.fire(‘beforesubmit‘, e);
    },
    _onaftersubmit : function(e, scope, callback) {
        scope.fire(‘aftersubmit‘, e);
    },
    _createPrintBtn : function() {
        var button = document.createElement("input"),
            that = this;
        button.type="button"
        button.value = "点击写出";
        button.onmousedown = function(e) {
            that._onbeforeSubmit(e, that);
        };
        button.onmouseup = function(e) {
            that._onaftersubmit(e, that);
        };
        return button;
    }
};

4.实现简易拷贝函数

  拷贝函数的作用是将Event对象与EditorProto对象糅合到一起。

var copyIf = function(sub, sup, config) {
    for(var p in sup) {
        if(!sub[p]) {
            sub[p] = sup[p];//拷贝
        }
    }
}

5.编辑器组件化

  为了达到最终new一次创建一个实例的目的,我们需要将编辑器对象加工成构造函数。像ExtJS、JQuery、Mini UI等都有实现自己的extend函数,本例就不单独实现继承函数了。

copyIf(EditorProto, Event);//将Event对象拷贝给EditorProto

function Editor(id) {
    this._cachePool = {};//事件处理函数的缓存池不能放到原型里
    this._create(id);//new 操作构造器的时候,创建编辑器实例
};
Editor.prototype = EditorProto;//原型链继承

6.验证beforesubmit与aftersubmit事件效果

  HTML里定义两个div,做为两个编辑器的容器。

<div id="editor">print...</div>
<div id="s"></div>

  JS里分别在HTML两个div内创建编辑器,并且第一个编辑器绑定两个自定义事件,第二个只绑定一个,测试效果。

var editor = new Editor("editor");
editor.on("beforesubmit", function() {console.log("beforesubmit");});
editor.on("aftersubmit", function() {console.log("aftersubmit");});

var s = new Editor("s");
s.on("beforesubmit", function() {console.log("s的提交前事件");});

  点击第一个编辑器会打印出“beforesubmit”与“aftersubmit”;点击第二个编辑器打印出“s的提交前事件”。

技术分享

  为编辑器创建自定义事件目的达成!

实现一个简易的富文本编辑器(二):给富文本添加自定义事件

标签:

原文地址:http://www.cnblogs.com/longhx/p/5445816.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!