好久没写随笔了,因为最近比较忙,小公司基本都是一个前端干所有属于和部分不属于前端的事情,所以就没空弄了,即使想分享,也因为没有时间和精力就搁置了。

这周周六日休息,正好时间比较充裕(ps:目前处在单休中。。。),就分析了以下bootstrap-wysiwyg的源码,虽然只有200多行,但是本人js水平还是欠佳,所以大概用了一天的时间(ps:可怜我偶尔的双休还是变成了单休),对bootstrap-wysiwyg的源码进行了解读和部分的注释,在这里放出来,给需要的人,毕竟不是人人都喜欢百度的编辑器的(ps:我就是因为不喜欢百度编辑器的样式和一大堆文件的原因才会去看bootstrap-wysiwyg的源码的),这样,理解了内部构造也好扩展和修改,因为最近的项目图片不能转码提交,而是要上传到淘宝的oss上才返回地址显示在富文本编辑器中,这也是促使我对bootstrap-wysiwyg源码的解读,好了,废话太多了,简易注释的源码在下面:

  ps:里面我添加了对富文本编辑器中点击图片的监听事件(这个还是很有用的,比如修改图片大小),或者读到这篇文章的也可以去自己定义接口

    同时我也放在了github上,地址是:

    https://github.com/woleicom/bootstrap-wysiwyg-notes

    如果github被墙,国内可以访问oschina,地址是:

    https://git.oschina.net/woleicom/bootstrap-wysiwyg-notes

    喜欢的就给星吧,哈哈

 /* http://github.com/mindmup/bootstrap-wysiwyg */
/*global jQuery, $, FileReader*/
/*jslint browser:true*/
(function ($) {
'use strict';
/*转码图片*/
var readFileIntoDataUrl = function (fileInfo) {
var loader = $.Deferred(), //jq延迟对象
fReader = new FileReader();
fReader.onload = function (e) {
loader.resolve(e.target.result);
};
fReader.onerror = loader.reject; //拒绝
fReader.onprogress = loader.notify;
fReader.readAsDataURL(fileInfo); //转码图片
return loader.promise(); //返回promise
};
/*清空内容*/
$.fn.cleanHtml = function () {
var html = $(this).html();
return html && html.replace(/(<br>|\s|<div><br><\/div>|&nbsp;)*$/, '');
};
$.fn.wysiwyg = function (userOptions) {
var editor = this, //设置ui-jq='设置的插件别名的dom元素'(此句注释可忽略,是针对我的项目结构写的)
selectedRange,
options,
toolbarBtnSelector,
//更新工具栏
updateToolbar = function () {
if (options.activeToolbarClass) {
$(options.toolbarSelector).find(toolbarBtnSelector).each(function () {
var command = $(this).data(options.commandRole);
//判断光标所在位置以确定命令的状态,为真则显示为激活
if (document.queryCommandState(command)) {
$(this).addClass(options.activeToolbarClass);
} else {
$(this).removeClass(options.activeToolbarClass);
}
});
}
},
//插入内容
execCommand = function (commandWithArgs, valueArg) {
var commandArr = commandWithArgs.split(' '),
command = commandArr.shift(),
args = commandArr.join(' ') + (valueArg || '');
document.execCommand(command, 0, args);
updateToolbar();
},
//用jquery.hotkeys.js插件监听键盘
bindHotkeys = function (hotKeys) {
$.each(hotKeys, function (hotkey, command) {
editor.keydown(hotkey, function (e) {
if (editor.attr('contenteditable') && editor.is(':visible')) {
e.preventDefault();
e.stopPropagation();
execCommand(command);
}
}).keyup(hotkey, function (e) {
if (editor.attr('contenteditable') && editor.is(':visible')) {
e.preventDefault();
e.stopPropagation();
}
});
});
},
//获取当前range对象
getCurrentRange = function () {
var sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
return sel.getRangeAt(0); //从当前selection对象中获得一个range对象。
}
},
//保存
saveSelection = function () {
selectedRange = getCurrentRange();
},
//恢复
restoreSelection = function () {
var selection = window.getSelection(); //获取当前既获区,selection是对当前激活选中区(即高亮文本)进行操作
if (selectedRange) {
try {
//移除selection中所有的range对象,执行后anchorNode、focusNode被设置为null,不存在任何被选中的内容。
selection.removeAllRanges();
} catch (ex) {
document.body.createTextRange().select();
document.selection.empty();
}
//将range添加到selection当中,所以一个selection中可以有多个range。
//注意Chrome不允许同时存在多个range,它的处理方式和Firefox有些不同。
selection.addRange(selectedRange);
}
},
//插入文件(这里指图片)
insertFiles = function (files) {
editor.focus();
//遍历插入(应为可以多文件插入)
$.each(files, function (idx, fileInfo) {
//只可插入图片文件
if (/^image\//.test(fileInfo.type)) {
//转码图片
$.when(readFileIntoDataUrl(fileInfo))
.done(function (dataUrl) {
execCommand('insertimage', dataUrl); //插入图片dom及src属性值
})
.fail(function (e) {
options.fileUploadError("file-reader", e);
});
} else {
//非图片文件会调用config的错误函数
options.fileUploadError("unsupported-file-type", fileInfo.type);
}
});
},
//TODO 暂不了解用意
markSelection = function (input, color) {
restoreSelection();
//确定命令是否被支持,返回true或false
if (document.queryCommandSupported('hiliteColor')) {
document.execCommand('hiliteColor', 0, color || 'transparent');
}
saveSelection();
input.data(options.selectionMarker, color);
},
//绑定工具栏相应工具事件
bindToolbar = function (toolbar, options) {
//给所有工具栏上的控件绑定点击事件
toolbar.find(toolbarBtnSelector).click(function () {
restoreSelection();
editor.focus(); //获取焦点
//设置相应配置的工具execCommand
execCommand($(this).data(options.commandRole));
//保存
saveSelection();
});
//对[data-toggle=dropdown]进行单独绑定点击事件处理 字体大小
toolbar.find('[data-toggle=dropdown]').click(restoreSelection);
//对input控件进行单独处理,webkitspeechchange为语音事件
toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () {
var newValue = this.value; //获取input 的value
this.value = ''; //清空value防止冲突
restoreSelection();
if (newValue) {
editor.focus();//获取焦点
//设置相应配置的工具execCommand
execCommand($(this).data(options.commandRole), newValue);
}
saveSelection();
}).on('focus', function () { //获取焦点
var input = $(this);
if (!input.data(options.selectionMarker)) {
markSelection(input, options.selectionColor);
input.focus();
}
}).on('blur', function () { //失去焦点
var input = $(this);
if (input.data(options.selectionMarker)) {
markSelection(input, false);
}
});
toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () {
restoreSelection();
if (this.type === 'file' && this.files && this.files.length > 0) {
insertFiles(this.files);
}
saveSelection();
this.value = '';
});
},
//初始化拖放事件
initFileDrops = function () {
editor.on('dragenter dragover', false)
.on('drop', function (e) {
var dataTransfer = e.originalEvent.dataTransfer;
e.stopPropagation();
e.preventDefault();
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
insertFiles(dataTransfer.files);
}
});
};
//合并传入的配置对象userOptions和默认的配置对象config
options = $.extend({}, $.fn.wysiwyg.defaults, userOptions);
//设置查找字符串:a[data-edit] button[data-edit] input[type=button][data-edit]
toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']';
//设置热键 容器有[data-role=editor-toolbar]属性的dom元素
bindHotkeys(options.hotKeys);
//是否允许拖放 允许则配置拖放
if (options.dragAndDropImages) {initFileDrops();}
//配置工具栏
bindToolbar($(options.toolbarSelector), options);
//设置编辑区域为可编辑状态并绑定事件mouseup keyup mouseout
editor.attr('contenteditable', true)
.on('mouseup keyup mouseout', function () {
saveSelection();
updateToolbar();
});
//编辑区域绑定图片点击事件
//TODO 这是我自己添加的,因为有时要对图片进行一些操作
editor.on('mousedown','img', function (e) {
e.preventDefault();
}).on('click', 'img', function (e) {
var $img = $(e.currentTarget);
console.log($img);
e.preventDefault();
e.stopPropagation();
});
//window绑定touchend事件
$(window).bind('touchend', function (e) {
var isInside = (editor.is(e.target) || editor.has(e.target).length > 0),
currentRange = getCurrentRange(),
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
if (!clear || isInside) {
saveSelection();
updateToolbar();
}
});
return this;
};
//配置参数
$.fn.wysiwyg.defaults = {
hotKeys: { //热键 应用hotkeys.js jquery插件
'ctrl+b meta+b': 'bold',
'ctrl+i meta+i': 'italic',
'ctrl+u meta+u': 'underline',
'ctrl+z meta+z': 'undo',
'ctrl+y meta+y meta+shift+z': 'redo',
'ctrl+l meta+l': 'justifyleft',
'ctrl+r meta+r': 'justifyright',
'ctrl+e meta+e': 'justifycenter',
'ctrl+j meta+j': 'justifyfull',
'shift+tab': 'outdent',
'tab': 'indent'
},
toolbarSelector: '[data-role=editor-toolbar]',
commandRole: 'edit',
activeToolbarClass: 'btn-info',
selectionMarker: 'edit-focus-marker',
selectionColor: 'darkgrey',
dragAndDropImages: true, //是否支持拖放,默认为支持
fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); }
};
}(window.jQuery));

简易富文本编辑器bootstrap-wysiwyg源码注释的更多相关文章

  1. vue+element ui项目总结点(三)富文本编辑器 vue-wangeditor

    1.参考 https://www.npmjs.com/package/vue-wangeditor 使用该富文本编辑器 <template> <div class="egi ...

  2. 轻量级富文本编辑器wangEditor源码结构介绍

    1. 引言 wangEditor——一款轻量级html富文本编辑器(开源软件) 网站:http://www.wangeditor.com/ demo演示:http://www.wangeditor.c ...

  3. 使用百度UMeditor富文本编辑器,修改自定义图片上传,修改源码

    富文本编辑器,不多说了,这个大家应该都用到过,至于用到的什么版本,那就分很多种 CKEditor:很早以前叫FCK,那个时候也用过,现在改名了,比较流行的一个插件,国外很多公司在用 UEDITOR:百 ...

  4. easyUI整合富文本编辑器KindEditor详细教程(附源码)

    原因 在今年4月份的时候写过一篇关于easyui整合UEditor的文章Spring+SpringMVC+MyBatis+easyUI整合优化篇(六)easyUI与富文本编辑器UEditor整合,从那 ...

  5. quillJS 富文本编辑器源码分析系列1

    quillJS 富文本编辑器目前是一款很火富文本编辑器,使用广泛,github 上面的 star 有 22,492,虽然说不以 star 论英雄,不过这可以说明它还是比较受欢迎的: 它的特点是:轻量, ...

  6. 富文本编辑器Simditor的简易使用

    最近打算自己做一个博客系统,并不打算使用帝国cms或者wordpress之类的做后台管理!自己处于学习阶段也就想把从前台到后台一起谢了.好了,废话不多说了,先来看看富文本编辑器SimDitor,这里是 ...

  7. 【前端】wangEditor(富文本编辑器) 简易使用示例

    转载请说明作者或者注明出处,谢谢 说到前端常用的编辑器,自然也少不了富文本编辑器(RichText Editor) 笔者在此之前也看了一些相关的在线编辑器,其中包括了当百度搜索“富文本编辑器”字样时出 ...

  8. Bootstrap富文本编辑器-bootstrap-wysiwyg

    在进行英语试题的录入中,因为英语试题经常会有类似如下的试题: My friend watches dragon boat races at the Dragon Boat Festival.(对划线部 ...

  9. Quill – 可以灵活自定义的开源的富文本编辑器

    Quill 的建立是为了解决现有的所见即所得(WYSIWYG)的编辑器本身就是所见即所得(指不能再扩张)的问题.如果编辑器不正是你想要的方式,这是很难或不可能对其进行自定义以满足您的需求. Quill ...

随机推荐

  1. 《剑指Offer》面试题-从头到尾打印链表

    题目描述: 输入一个链表,从尾到头打印链表每个节点的值. 输入: 每个输入文件仅包含一组测试样例.每一组测试案例包含多行,每行一个大于0的整数,代表一个链表的节点.第一行是链表第一个节点的值,依次类推 ...

  2. RoleManager 进行角色管理

    ASP.NET Identity 使用 RoleManager 进行角色管理 (VS2013RC) 注:本文系作者原创,但可随意转载. 最近做一个Web平台系统,系统包含3个角色,“管理员, 企业用户 ...

  3. 修改Ubuntu Server的分辨率

    修改Ubuntu Server的分辨率,其实就是找到关键的文件,然后修改参数,重启一下,就可以看见效果了. 1.打开文件并修改参数 文件位置:/etc/default/grub 修改位置:GRUB_C ...

  4. 程序媛也话Android 之 自定义控件(垂直方向滑动条)

    Android里已经有足够多的控件供开发者使用,但有时候我们还是会想要一些不一样的东西,比如一些UI特效,比如一些3D动画,今天就讲讲比较basic的东西:自定义控件. 1.效果图 如果项目里需要一个 ...

  5. C语言中数据类型的长度

    面试中C里面int长度经常会被问到,下面总结一下作为资料: 首先看看一般规定: 标准c规定,int长度等于机器字长,short的表示范围不能大于int的表示范围,long的表示范围不能小于int的表示 ...

  6. 解决中文乱码( jsp表单提交中文时出现乱码)

    有三种方法: 1.建立一个filter中文解决乱码 2.Struts2在struts.xml中修改默认的编码设定 3.用Spring解决中文乱码 4.直接在jsp中修改解决 1.建立一个filter解 ...

  7. 关于socket通讯,如何才能高效?

    关于socket通讯,如何才能高效? 网络通讯,一个不朽的话题,今天和一个做游戏的朋友(以前的同事聊天),他向我诉说了他的痛苦 他之前是做客户端的,无奈人力资源紧张,也开始搞服务器,他说自己的服务器总 ...

  8. C# 对象池的实现

    C# 对象池的实现 对象池服务可以减少从头创建每个对象的系统开销.在激活对象时,它从池中提取.在停用对象时,它放回池中,等待下一个请求.我们来看下主线程中,如何与对象池打交道: static void ...

  9. Centos 64位 Install certificate on apache 即走https协议

    Centos 64位 Install certificate on apache 即走https协议 一: 先要apache 请求ssl证书的csr 一下是步骤: 重要注意事项 An Importan ...

  10. [置顶] SQL注入安全分析

    (一)       应用环境列表 网络互联设备操作系统 序号 操作系统名称 设备名称 脆弱性 1 IOS_路由器_内部_1 route1 2 IOS_路由器_VPN_1 路由器_VPN_1 3 IOS ...