/** @Name:layui.layedit 富文本编辑器 @Author:贤心 @License:LGPL */ layui.define(['layer', 'form'], function (exports) { "use strict"; var $ = layui.jquery , layer = layui.layer , form = layui.form() , hint = layui.hint() , device = layui.device() , MOD_NAME = 'layedit', THIS = 'layui-this', SHOW = 'layui-show', ABLED = 'layui-disabled' , Edit = function () { var that = this; that.index = 0; //全局配置 that.config = { //默认工具bar tool: [ 'strong', 'italic', 'underline', 'del' , '|' , 'left', 'center', 'right' , '|' , 'link', 'unlink', 'face', 'image' ] , hideTool: [] , height: 280 //默认高 }; }; //全局设置 Edit.prototype.set = function (options) { var that = this; $.extend(true, that.config, options); return that; }; //事件监听 Edit.prototype.on = function (events, callback) { return layui.onevent(MOD_NAME, events, callback); }; //建立编辑器 Edit.prototype.build = function (id, settings) { settings = settings || {}; var that = this , config = that.config , ELEM = 'layui-layedit', textArea = $('#' + id) , name = 'LAY_layedit_' + (++that.index) , haveBuild = textArea.next('.' + ELEM) , set = $.extend({}, config, settings) , tool = function () { var node = [], hideTools = {}; layui.each(set.hideTool, function (_, item) { hideTools[item] = true; }); layui.each(set.tool, function (_, item) { if (tools[item] && !hideTools[item]) { node.push(tools[item]); } }); return node.join(''); }() , editor = $(['
'); } }); //给textarea同步内容 $(textArea).parents('form').on('submit', function () { var html = body.html(); //IE8下将标签处理成小写 if (device.ie == 8) { html = html.replace(/<.+>/g, function (str) { return str.toLowerCase(); }); } textArea.value = html; }); //处理粘贴 body.on('paste', function (e) { iframeDOM.execCommand('formatBlock', false, '
'); setTimeout(function () { filter.call(iframeWin, body); textArea.value = body.html(); }, 100); }); } //标签过滤 , filter = function (body) { var iframeWin = this , iframeDOM = iframeWin.document; //清除影响版面的css属性 body.find('*[style]').each(function () { var textAlign = this.style.textAlign; this.removeAttribute('style'); $(this).css({ 'text-align': textAlign || '' }) }); //修饰表格 body.find('table').addClass('layui-table'); //移除不安全的标签 body.find('script,link').remove(); } //Range对象兼容性处理 , Range = function (iframeDOM) { return iframeDOM.selection ? iframeDOM.selection.createRange() : iframeDOM.getSelection().getRangeAt(0); } //当前Range对象的endContainer兼容性处理 , getContainer = function (range) { return range.endContainer || range.parentElement().childNodes[0] } //在选区插入内联元素 , insertInline = function (tagName, attr, range) { var iframeDOM = this.document , elem = document.createElement(tagName) for (var key in attr) { elem.setAttribute(key, attr[key]); } elem.removeAttribute('text'); if (iframeDOM.selection) { //IE var text = range.text || attr.text; if (tagName === 'a' && !text) return; if (text) { elem.innerHTML = text; } range.pasteHTML($(elem).prop('outerHTML')); range.select(); } else { //非IE var text = range.toString() || attr.text; if (tagName === 'a' && !text) return; if (text) { elem.innerHTML = text; } range.deleteContents(); range.insertNode(elem); } } //工具选中 , toolCheck = function (tools, othis) { var iframeDOM = this.document , CHECK = 'layedit-tool-active' , container = getContainer(Range(iframeDOM)) , item = function (type) { return tools.find('.layedit-tool-' + type) } if (othis) { othis[othis.hasClass(CHECK) ? 'removeClass' : 'addClass'](CHECK); } tools.find('>i').removeClass(CHECK); item('unlink').addClass(ABLED); $(container).parents().each(function () { var tagName = this.tagName.toLowerCase() , textAlign = this.style.textAlign; //文字 if (tagName === 'b' || tagName === 'strong') { item('b').addClass(CHECK) } if (tagName === 'i' || tagName === 'em') { item('i').addClass(CHECK) } if (tagName === 'u') { item('u').addClass(CHECK) } if (tagName === 'strike') { item('d').addClass(CHECK) } //对齐 if (tagName === 'p') { if (textAlign === 'center') { item('center').addClass(CHECK); } else if (textAlign === 'right') { item('right').addClass(CHECK); } else { item('left').addClass(CHECK); } } //超链接 if (tagName === 'a') { item('link').addClass(CHECK); item('unlink').removeClass(ABLED); } }); } //触发工具 , toolActive = function (iframeWin, editor, set) { var iframeDOM = iframeWin.document , body = $(iframeDOM.body) , toolEvent = { //超链接 link: function (range) { var container = getContainer(range) , parentNode = $(container).parent(); link.call(body, { href: parentNode.attr('href') , target: parentNode.attr('target') }, function (field) { var parent = parentNode[0]; if (parent.tagName === 'A') { parent.href = field.url; } else { insertInline.call(iframeWin, 'a', { target: field.target , href: field.url , text: field.url }, range); } }); } //清除超链接 , unlink: function (range) { iframeDOM.execCommand('unlink'); } //表情 , face: function (range) { face.call(this, function (img) { insertInline.call(iframeWin, 'img', { src: img.src , alt: img.alt }, range); }); } //图片 , image: function (range) { var that = this; layui.use('upload', function (upload) { var uploadImage = set.uploadImage || {}; upload({ url: uploadImage.url , method: uploadImage.type , elem: $(that).find('input')[0] , unwrap: true , success: function (res) { if (res.code == 0) { res.data = res.data || {}; insertInline.call(iframeWin, 'img', { src: res.data.src , alt: res.data.title }, range); } else { layer.msg(res.msg || '上传失败'); } } }); }); } //插入代码 , code: function (range) { code.call(body, function (pre) { insertInline.call(iframeWin, 'pre', { text: pre.code , 'lay-lang': pre.lang }, range); }); } //帮助 , help: function () { layer.open({ type: 2 , title: '帮助' , area: ['600px', '380px'] , shadeClose: true , shade: 0.1 , skin: 'layui-layer-msg' , content: ['http://www.layui.com/about/layedit/help.html', 'no'] }); } } , tools = editor.find('.layui-layedit-tool') , click = function () { var othis = $(this) , events = othis.attr('layedit-event') , command = othis.attr('lay-command'); if (othis.hasClass(ABLED)) return; body.focus(); var range = Range(iframeDOM) , container = range.commonAncestorContainer if (command) { iframeDOM.execCommand(command); if (/justifyLeft|justifyCenter|justifyRight/.test(command)) { iframeDOM.execCommand('formatBlock', false, '
'); } setTimeout(function () { body.focus(); }, 10); } else { toolEvent[events] && toolEvent[events].call(this, range); } toolCheck.call(iframeWin, tools, othis); } , isClick = /image/ tools.find('>i').on('mousedown', function () { var othis = $(this) , events = othis.attr('layedit-event'); if (isClick.test(events)) return; click.call(this) }).on('click', function () { var othis = $(this) , events = othis.attr('layedit-event'); if (!isClick.test(events)) return; click.call(this) }); //触发内容区域 body.on('click', function () { toolCheck.call(iframeWin, tools); layer.close(face.index); }); } //超链接面板 , link = function (options, callback) { var body = this, index = layer.open({ type: 1 , id: 'LAY_layedit_link' , area: '350px' , shade: 0.05 , shadeClose: true , moveType: 1 , title: '超链接' , skin: 'layui-layer-msg' , content: ['