/** @Name:layui.layedit 富文本编辑器 @Author:贤心 @License:MIT */ layui.define(['layer', 'form'], function(exports){ "use strict"; var $ = layui.$ ,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 = $(typeof(id)=='string'?'#'+id: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.render({ url: uploadImage.url ,method: uploadImage.type ,elem: $(that).find('input')[0] ,done: 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: ['