简易富文本编辑器bootstrap-wysiwyg源码注释
好久没写随笔了,因为最近比较忙,小公司基本都是一个前端干所有属于和部分不属于前端的事情,所以就没空弄了,即使想分享,也因为没有时间和精力就搁置了。
这周周六日休息,正好时间比较充裕(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>| )*$/, '');
};
$.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源码注释的更多相关文章
- vue+element ui项目总结点(三)富文本编辑器 vue-wangeditor
1.参考 https://www.npmjs.com/package/vue-wangeditor 使用该富文本编辑器 <template> <div class="egi ...
- 轻量级富文本编辑器wangEditor源码结构介绍
1. 引言 wangEditor——一款轻量级html富文本编辑器(开源软件) 网站:http://www.wangeditor.com/ demo演示:http://www.wangeditor.c ...
- 使用百度UMeditor富文本编辑器,修改自定义图片上传,修改源码
富文本编辑器,不多说了,这个大家应该都用到过,至于用到的什么版本,那就分很多种 CKEditor:很早以前叫FCK,那个时候也用过,现在改名了,比较流行的一个插件,国外很多公司在用 UEDITOR:百 ...
- easyUI整合富文本编辑器KindEditor详细教程(附源码)
原因 在今年4月份的时候写过一篇关于easyui整合UEditor的文章Spring+SpringMVC+MyBatis+easyUI整合优化篇(六)easyUI与富文本编辑器UEditor整合,从那 ...
- quillJS 富文本编辑器源码分析系列1
quillJS 富文本编辑器目前是一款很火富文本编辑器,使用广泛,github 上面的 star 有 22,492,虽然说不以 star 论英雄,不过这可以说明它还是比较受欢迎的: 它的特点是:轻量, ...
- 富文本编辑器Simditor的简易使用
最近打算自己做一个博客系统,并不打算使用帝国cms或者wordpress之类的做后台管理!自己处于学习阶段也就想把从前台到后台一起谢了.好了,废话不多说了,先来看看富文本编辑器SimDitor,这里是 ...
- 【前端】wangEditor(富文本编辑器) 简易使用示例
转载请说明作者或者注明出处,谢谢 说到前端常用的编辑器,自然也少不了富文本编辑器(RichText Editor) 笔者在此之前也看了一些相关的在线编辑器,其中包括了当百度搜索“富文本编辑器”字样时出 ...
- Bootstrap富文本编辑器-bootstrap-wysiwyg
在进行英语试题的录入中,因为英语试题经常会有类似如下的试题: My friend watches dragon boat races at the Dragon Boat Festival.(对划线部 ...
- Quill – 可以灵活自定义的开源的富文本编辑器
Quill 的建立是为了解决现有的所见即所得(WYSIWYG)的编辑器本身就是所见即所得(指不能再扩张)的问题.如果编辑器不正是你想要的方式,这是很难或不可能对其进行自定义以满足您的需求. Quill ...
随机推荐
- IDE编程环境
Vim配置及说明——IDE编程环境 目录 Vim配置及说明——IDE编程环境 1.基本及字体 2.插件管理 3.主题风格 4.窗口设置 5.目录树导航 6.标签导航 7.taglist 8.多文档编辑 ...
- Visual Studio 20**自动添加头部注释信息
关于Visual Studio 20**自动添加头部注释信息 作为一个万年潜水党,不关这一篇文章技术含量如何,也算是一个好的开始吧. 在日常的开发中我们经常需要为类库添加注释和版权等信息,这样 ...
- C#打包应用程序
摘要:本文介绍在C#中手把手教你用C#打包应用程序(安装程序卸载程序) 1:新建安装部署项目 打开VS,点击新建项目,选择:其他项目类型->安装与部署->安装向导(安装项目也一样),然后点 ...
- 回调函数 use
$info["fulltext"] = preg_replace_callback( $search2, function($matches) use ($search, $uni ...
- Bootstrap3.0学习第三轮(栅格系统案例)
Bootstrap3.0学习第三轮(栅格系统案例) 前言 在前面的一篇文章当中http://www.cnblogs.com/aehyok/p/3400499.html主要学习了栅格系统的基本原理,以及 ...
- Hadoop能力测试图谱
一张图测试你的Hadoop能力-Hadoop能力测试图谱 1.引言 看到一张图,关于Hadoop技术框架的图,基本上涉及到Hadoop当前应用的主要领域,感觉可以作为测试Hadoop开发人员当前能力和 ...
- cegui-0.8.2编译过程详解
cegui 编译过程详解(cegui-0.8.2) cegui配置整了好长时间了,在一位大牛帮助下终于搞定了,网上的教程大多是老版本的,cegui-0.8.2版的配置寥寥无几,现在总结一下,献给正在纠 ...
- eclipse在Ubuntu 13.04下的安装过程
eclipse在Ubuntu 13.04下的安装过程及问题小记 一.eclipse安装过程 首先确保在安装eclipse之前已经安装好Java虚拟机 1. eclipse官网下载压缩包 下载地址:ht ...
- Microsoft 电信项目组 Net代码生成器1.1
Microsoft 电信项目组 Net代码生成器1.1 微软电信项目组代码生成器 为什么要使用这个代码生成器: 1.这个代码生成器采用 微软 企业库5.0 版本,目前CAPO所在的项目组都在使用这个 ...
- Memcache的一些学习
Memcache的一些学习 首先,Memcache是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态.数据库驱动 ...