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

这周周六日休息,正好时间比较充裕(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. Julia语言:让高性能科学计算人人可用

    Julia语言:让高性能科学计算人人可用要:一群科学家对现有计算工具感到不满:他们想要一套开源系统,有C的快速,Ruby的动态,Python的通用,R般在统计分析上得心应手,Perl的处理字符串处理, ...

  2. 正则表达式测试分析工具Expresso

    正则表达式测试分析工具Expresso 一个正则表达式的小工具--myRegexHelper   把以前做的一个功能抽取出来做成一个小的正则表达式测试工具.没什么特色,有两点功能: 一.方便的测试正则 ...

  3. APNs功能之Node.js和Mysql应用总结

    APNs功能之Node.js和Mysql应用总结 这篇文档主要是总结Node.js和Mysql的学习心得体会.当然也可以看作是此前所写的消息推送服务的续篇. 简单描述下应用背景,我们的应用需要实现苹果 ...

  4. Windows 7/8 64位下安装64位Apache 2.4.7

    准备软件: VC11 运行库 64位的apache版本 传送门:http://www.apachelounge.com/download/ 安装步骤: 修改httpd.conf配置文件 37行: Se ...

  5. Oracle常用操作

      比较时间 select * from up_date where update < to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss' ...

  6. jquery数据验证插件

    jquery数据验证插件(自制,简单,练手)   一:最近项目中js数据验证比较多,为了统一风格,移植复用,于是顺手封装了Jquery的插件. (function($) { var defaults ...

  7. [转]Hacking the iOS Spotlight

    原文:http://theiostream.tumblr.com/post/36905860826/hacking-the-ios-spotlight 原文:http://theiostream.tu ...

  8. 随手复习一下委托:delegate

    先骂个街,天儿太闷了…… 随手复习一下委托,delegate 是一种函数指针,是 .net 提供的一种安全的函数指针,翻译的也很贴切,像是委托人,又像代理人,通过“委托”来执行一些函数而不是直接调用它 ...

  9. xhEditor实现插入代码功能

    如果大家经常使用CSDN或者其他技术博客,都会有插入程序代码或脚本功能 开源中国 CSDN 这里介绍xhEditor实现插入代码功能,对xhEditor进行插件扩展 一.首先定义插件样式 <st ...

  10. IceMx.Mvc 我的js MVC 框架 二、视图的数据绑定

    介绍 本人菜鸟,一些自己的浅薄见解,望各位大神指正. 本框架有以下优点 1.简单(调用简单.实现简单.不过度设计) 2.视图.控制器.模型分离(分离对于维护十分有必要) 3.组件化(每一个mvc模块儿 ...