(function(){UEDITOR_CONFIG = window.UEDITOR_CONFIG || {}; var baidu = window.baidu || {}; window.baidu = baidu; window.UE = baidu.editor = {}; UE.plugins = {}; UE.commands = {}; UE.instants = {}; UE.I18N = {}; //UE.defaultplugins = {}; // //UE.commands = function(){ // var commandList = {},tmpList= {}; // return { // // register : function(commandsName,pluginName){ // commandsName = commandsName.split(','); // for(var i= 0,ci;ci=commandsName[i++];){ // commandList[ci] = pluginName; // } // // }, // get : function(commandName){ // return commandList[commandName]; // }, // getList : function(){ // return commandList; // } // } //}(); UE.version = "1.2.3.0"; var dom = UE.dom = {}; ///import editor.js /** * @class baidu.editor.browser 判断浏览器 */ var browser = UE.browser = function(){ var agent = navigator.userAgent.toLowerCase(), opera = window.opera, browser = { /** * 检测浏览器是否为IE * @name baidu.editor.browser.ie * @property 检测浏览器是否为IE * @grammar baidu.editor.browser.ie * @return {Boolean} 返回是否为ie浏览器 */ ie : !!window.ActiveXObject, /** * 检测浏览器是否为Opera * @name baidu.editor.browser.opera * @property 检测浏览器是否为Opera * @grammar baidu.editor.browser.opera * @return {Boolean} 返回是否为opera浏览器 */ opera : ( !!opera && opera.version ), /** * 检测浏览器是否为WebKit内核 * @name baidu.editor.browser.webkit * @property 检测浏览器是否为WebKit内核 * @grammar baidu.editor.browser.webkit * @return {Boolean} 返回是否为WebKit内核 */ webkit : ( agent.indexOf( ' applewebkit/' ) > -1 ), /** * 检查是否为Macintosh系统 * @name baidu.editor.browser.mac * @property 检查是否为Macintosh系统 * @grammar baidu.editor.browser.mac * @return {Boolean} 返回是否为Macintosh系统 */ mac : ( agent.indexOf( 'macintosh' ) > -1 ), /** * 检查浏览器是否为quirks模式 * @name baidu.editor.browser.quirks * @property 检查浏览器是否为quirks模式 * @grammar baidu.editor.browser.quirks * @return {Boolean} 返回是否为quirks模式 */ quirks : ( document.compatMode == 'BackCompat' ) }; /** * 检测浏览器是否为Gecko内核,如Firefox * @name baidu.editor.browser.gecko * @property 检测浏览器是否为Gecko内核 * @grammar baidu.editor.browser.gecko * @return {Boolean} 返回是否为Gecko内核 */ browser.gecko = ( navigator.product == 'Gecko' && !browser.webkit && !browser.opera ); var version = 0; // Internet Explorer 6.0+ if ( browser.ie ) { version = parseFloat( agent.match( /msie (\d+)/ )[1] ); /** * 检测浏览器是否为 IE9 模式 */ browser.ie9Compat = document.documentMode == 9; /** * 检测浏览器是否为 IE8 浏览器 * @name baidu.editor.browser.IE8 * @property 检测浏览器是否为 IE8 浏览器 * @grammar baidu.editor.browser.IE8 * @return {Boolean} 返回是否为 IE8 浏览器 */ browser.ie8 = !!document.documentMode; /** * 检测浏览器是否为 IE8 模式 * @name baidu.editor.browser.ie8Compat * @property 检测浏览器是否为 IE8 模式 * @grammar baidu.editor.browser.ie8Compat * @return {Boolean} 返回是否为 IE8 模式 */ browser.ie8Compat = document.documentMode == 8; /** * 检测浏览器是否运行在 兼容IE7模式 * @name baidu.editor.browser.ie7Compat * @property 检测浏览器是否为兼容IE7模式 * @grammar baidu.editor.browser.ie7Compat * @return {Boolean} 返回是否为兼容IE7模式 */ browser.ie7Compat = ( ( version == 7 && !document.documentMode ) || document.documentMode == 7 ); /** * 检测浏览器是否IE6模式或怪异模式 * @name baidu.editor.browser.ie6Compat * @property 检测浏览器是否IE6 模式或怪异模式 * @grammar baidu.editor.browser.ie6Compat * @return {Boolean} 返回是否为IE6 模式或怪异模式 */ browser.ie6Compat = ( version < 7 || browser.quirks ); } // Gecko. if ( browser.gecko ) { var geckoRelease = agent.match( /rv:([\d\.]+)/ ); if ( geckoRelease ) { geckoRelease = geckoRelease[1].split( '.' ); version = geckoRelease[0] * 10000 + ( geckoRelease[1] || 0 ) * 100 + ( geckoRelease[2] || 0 ) * 1; } } /** * 检测浏览器是否为chrome * @name baidu.editor.browser.chrome * @property 检测浏览器是否为chrome * @grammar baidu.editor.browser.chrome * @return {Boolean} 返回是否为chrome浏览器 */ if (/chrome\/(\d+\.\d)/i.test(agent)) { browser.chrome = + RegExp['\x241']; } /** * 检测浏览器是否为safari * @name baidu.editor.browser.safari * @property 检测浏览器是否为safari * @grammar baidu.editor.browser.safari * @return {Boolean} 返回是否为safari浏览器 */ if(/(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && !/chrome/i.test(agent)){ browser.safari = + (RegExp['\x241'] || RegExp['\x242']); } // Opera 9.50+ if ( browser.opera ) version = parseFloat( opera.version() ); // WebKit 522+ (Safari 3+) if ( browser.webkit ) version = parseFloat( agent.match( / applewebkit\/(\d+)/ )[1] ); /** * 浏览器版本 * * gecko内核浏览器的版本会转换成这样(如 1.9.0.2 -> 10900). * * webkit内核浏览器版本号使用其build号 (如 522). * @name baidu.editor.browser.version * @grammar baidu.editor.browser.version * @return {Boolean} 返回浏览器版本号 * @example * if ( baidu.editor.browser.ie && baidu.editor.browser.version <= 6 ) * alert( "Ouch!" ); */ browser.version = version; /** * 是否是兼容模式的浏览器 * @name baidu.editor.browser.isCompatible * @grammar baidu.editor.browser.isCompatible * @return {Boolean} 返回是否是兼容模式的浏览器 * @example * if ( baidu.editor.browser.isCompatible ) * alert( "Your browser is pretty cool!" ); */ browser.isCompatible = !browser.mobile && ( ( browser.ie && version >= 6 ) || ( browser.gecko && version >= 10801 ) || ( browser.opera && version >= 9.5 ) || ( browser.air && version >= 1 ) || ( browser.webkit && version >= 522 ) || false ); return browser; }(); //快捷方式 var ie = browser.ie, webkit = browser.webkit, gecko = browser.gecko, opera = browser.opera; ///import editor.js ///import core/utils.js /** * @class baidu.editor.utils 工具类 */ var utils = UE.utils = /**@lends baidu.editor.utils.prototype*/ { /** * 以obj为原型创建实例 * @public * @function * @param {Object} obj * @return {Object} 返回新的对象 */ makeInstance: function(obj) { var noop = new Function(); noop.prototype = obj; obj = new noop; noop.prototype = null; return obj; }, /** * 将s对象中的属性扩展到t对象上 * @public * @function * @param {Object} t * @param {Object} s * @param {Boolean} b 是否保留已有属性 * @returns {Object} t 返回扩展了s对象属性的t */ extend: function(t, s, b) { if (s) { for (var k in s) { if (!b || !t.hasOwnProperty(k)) { t[k] = s[k]; } } } return t; }, /** * 判断是否为数组 * @public * @function * @param {Object} array * @return {Boolean} true:为数组,false:不为数组 */ isArray: function(array) { return Object.prototype.toString.apply(array) === '[object Array]'; }, /** * 判断是否为字符串 * @public * @function * @param {Object} str * @return {Boolean} true:为字符串。 false:不为字符串 */ isString: function(str) { return typeof str == 'string' || str.constructor == String; }, /** * subClass继承superClass * @public * @function * @param {Object} subClass 子类 * @param {Object} superClass 超类 * @return {Object} 扩展后的新对象 */ inherits: function(subClass, superClass) { var oldP = subClass.prototype, newP = utils.makeInstance(superClass.prototype); utils.extend(newP, oldP, true); subClass.prototype = newP; return (newP.constructor = subClass); }, /** * 为对象绑定函数 * @public * @function * @param {Function} fn 函数 * @param {Object} this_ 对象 * @return {Function} 绑定后的函数 */ bind: function(fn, this_) { return function() { return fn.apply(this_, arguments); }; }, /** * 创建延迟执行的函数 * @public * @function * @param {Function} fn 要执行的函数 * @param {Number} delay 延迟时间,单位为毫秒 * @param {Boolean} exclusion 是否互斥执行,true则执行下一次defer时会先把前一次的延迟函数删除 * @return {Function} 延迟执行的函数 */ defer: function(fn, delay, exclusion) { var timerID; return function() { if (exclusion) { clearTimeout(timerID); } timerID = setTimeout(fn, delay); }; }, /** * 查找元素在数组中的索引, 若找不到返回-1 * @public * @function * @param {Array} array 要查找的数组 * @param {*} item 查找的元素 * @param {Number} at 开始查找的位置 * @returns {Number} 返回在数组中的索引 */ indexOf: function(array, item, at) { for(var i=at||0,l = array.length;i]/g, function(m){ return { '<': '<', '&': '&', '"': '"', '>': '>' }[m] }) : ''; }, html: function(str) { return str ? str.replace(/&((g|l|quo)t|amp);/g, function(m){ return { '<':'<', '&':'&', '"':'"', '>': '>' }[m] }) : ''; }, /** * 将css样式转换为驼峰的形式。如font-size -> fontSize * @public * @function * @param {String} cssName 需要转换的样式 * @returns {String} 转换后的样式 */ cssStyleToDomStyle: function() { var test = document.createElement('div').style, cache = { 'float': test.cssFloat != undefined ? 'cssFloat' : test.styleFloat != undefined ? 'styleFloat': 'float' }; return function(cssName) { return cache[cssName] || (cache[cssName] = cssName.toLowerCase().replace(/-./g, function(match){return match.charAt(1).toUpperCase();})); }; }(), /** * 加载css文件,执行回调函数 * @public * @function * @param {document} doc document对象 * @param {String} path 文件路径 * @param {Function} fun 回调函数 * @param {String} id 元素id */ loadFile : function(){ var tmpList = {}; return function(doc,obj,fun){ var item = tmpList[obj.src||obj.href]; if(item){ if(utils.isArray(item.funs)){ item.ready?fun():tmpList[obj.src||obj.href].funs.push(fun); } return; } tmpList[obj.src||obj.href] = fun? {'funs' : [fun]} :1; if(!doc.body){ doc.write(''); return; } if (obj.id && doc.getElementById(obj.id)) { return; } var element = doc.createElement(obj.tag); delete obj.tag; for(var p in obj){ element.setAttribute(p,obj[p]); } element.onload = element.onreadystatechange = function() { if (!this.readyState || /loaded|complete/.test(this.readyState)) { item = tmpList[obj.src||obj.href]; if(item.funs){ item.ready = 1; for(var fi;fi=item.funs.pop();){ fi(); } } element.onload = element.onreadystatechange = null; } }; doc.getElementsByTagName("head")[0].appendChild(element); } }(), /** * 判断对象是否为空 * @param {Object} obj * @return {Boolean} true 空,false 不空 */ isEmptyObject : function(obj){ for ( var p in obj ) { return false; } return true; }, isFunction : function (source) { // chrome下,'function' == typeof /a/ 为true. return '[object Function]' == Object.prototype.toString.call(source); }, fixColor : function (name, value) { if (/color/i.test(name) && /rgba?/.test(value)) { var array = value.split(","); if (array.length > 3) return ""; value = "#"; for (var i = 0, color; color = array[i++];) { color = parseInt(color.replace(/[^\d]/gi, ''), 10).toString(16); value += color.length == 1 ? "0" + color : color; } value = value.toUpperCase(); } return value; }, /** * 只针对border,padding,margin做了处理,因为性能问题 * @public * @function * @param {String} val style字符串 */ optCss : function(val){ var padding,margin,border; val = val.replace(/(padding|margin|border)\-([^:]+):([^;]+);?/gi,function(str,key,name,val){ if(val.split(' ').length == 1){ switch (key){ case 'padding': !padding && (padding = {}); padding[name] = val; return ''; case 'margin': !margin && (margin = {}); margin[name] = val; return ''; case 'border': return val == 'initial' ? '' : str; } } return str; }); function opt(obj,name){ if(!obj){ return ''; } var t = obj.top ,b = obj.bottom,l = obj.left,r = obj.right,val = ''; if(!t || !l || !b || !r){ for(var p in obj){ val +=';'+name+'-' + p + ':' + obj[p]+';'; } }else{ val += ';'+name+':' + (t == b && b == l && l == r ? t : t == b && l == r ? (t + ' ' + l) : l == r ? (t + ' ' + l + ' ' + b) : (t + ' ' + r + ' ' + b + ' ' + l))+';' } return val; } val += opt(padding,'padding') + opt(margin,'margin'); return val.replace(/^[ \n\r\t;]*|[ \n\r\t]*$/,'').replace(/;([ \n\r\t]+)|\1;/g,';') .replace(/(&((l|g)t|quot|#39))?;{2,}/g,function(a,b){ return b ? b + ";;" : ';' }); }, /** * DOMContentLoaded 事件注册 * @public * @function * @param {Function} 触发的事件 */ domReady : function (){ var isReady = false, fnArr = []; function doReady(){ //确保onready只执行一次 isReady = true; for(var ci;ci=fnArr.pop();){ ci(); } } return function(onready){ if ( document.readyState === "complete" ) { return onready && setTimeout( onready, 1 ); } onready && fnArr.push(onready); isReady && doReady(); if( browser.ie ){ (function(){ if ( isReady ) return; try { document.documentElement.doScroll("left"); } catch( error ) { setTimeout( arguments.callee, 0 ); return; } doReady(); })(); window.attachEvent('onload',doReady); }else{ document.addEventListener( "DOMContentLoaded", function(){ document.removeEventListener( "DOMContentLoaded", arguments.callee, false ); doReady(); }, false ); window.addEventListener('load',doReady,false); } } }() }; utils.domReady(); ///import editor.js ///import core/utils.js /** * 事件基础类 * @public * @class * @name baidu.editor.EventBase */ var EventBase = UE.EventBase = function(){}; EventBase.prototype = /**@lends baidu.editor.EventBase.prototype*/{ /** * 注册事件监听器 * @public * @function * @param {String} types 事件名 * @param {Function} listener 监听器数组 */ addListener : function ( types, listener ) { types = utils.trim(types).split(' '); for(var i= 0,ti;ti=types[i++];){ getListener( this, ti, true ).push( listener ); } }, /** * 移除事件监听器 * @public * @function * @param {String} types 事件名 * @param {Function} listener 监听器数组 */ removeListener : function ( types, listener ) { types = utils.trim(types).split(' '); for(var i= 0,ti;ti=types[i++];){ utils.removeItem( getListener( this, ti ) || [], listener ); } }, /** * 触发事件 * @public * @function * @param {String} type 事件名 * */ fireEvent : function ( types ) { types = utils.trim(types).split(' '); for(var i= 0,ti;ti=types[i++];){ var listeners = getListener( this, ti ), r, t, k; if ( listeners ) { k = listeners.length; while ( k -- ) { t = listeners[k].apply( this, arguments ); if ( t !== undefined ) { r = t; } } } if ( t = this['on' + ti.toLowerCase()] ) { r = t.apply( this, arguments ); } } return r; } }; /** * 获得对象所拥有监听类型的所有监听器 * @public * @function * @param {Object} obj 查询监听器的对象 * @param {String} type 事件类型 * @param {Boolean} force 为true且当前所有type类型的侦听器不存在时,创建一个空监听器数组 * @returns {Array} 监听器数组 */ function getListener( obj, type, force ) { var allListeners; type = type.toLowerCase(); return ( ( allListeners = ( obj.__allListeners || force && ( obj.__allListeners = {} ) ) ) && ( allListeners[type] || force && ( allListeners[type] = [] ) ) ); } ///import editor.js ///import core/dom/dom.js /** * dtd html语义化的体现类 * @constructor * @namespace dtd */ var dtd = dom.dtd = (function() { function _( s ) { for (var k in s) { s[k.toUpperCase()] = s[k]; } return s; } function X( t ) { var a = arguments; for ( var i=1; ixxxxbb --> xxxxbb */ clearEmptySibling:function ( node, ingoreNext, ingorePre ) { function clear( next, dir ) { var tmpNode; while ( next && !domUtils.isBookmarkNode( next ) && (domUtils.isEmptyInlineElement( next ) //这里不能把空格算进来会吧空格干掉,出现文字间的空格丢掉了 || !new RegExp( '[^\t\n\r' + domUtils.fillChar + ']' ).test( next.nodeValue ) ) ) { tmpNode = next[dir]; domUtils.remove( next ); next = tmpNode; } } !ingoreNext && clear( node.nextSibling, 'nextSibling' ); !ingorePre && clear( node.previousSibling, 'previousSibling' ); }, //---------------------------Text---------------------------------- /** * 将一个文本节点拆分成两个文本节点 * @param {TextNode} node 文本节点 * @param {Integer} offset 拆分的位置 * @return {TextNode} 拆分后的后一个文本节 */ split:function ( node, offset ) { var doc = node.ownerDocument; if ( browser.ie && offset == node.nodeValue.length ) { var next = doc.createTextNode( '' ); return domUtils.insertAfter( node, next ); } var retval = node.splitText( offset ); //ie8下splitText不会跟新childNodes,我们手动触发他的更新 if ( browser.ie8 ) { var tmpNode = doc.createTextNode( '' ); domUtils.insertAfter( retval, tmpNode ); domUtils.remove( tmpNode ); } return retval; }, /** * 判断是否为空白节点 * @param {TextNode} node 节点 * @return {Boolean} 返回是否为文本节点 */ isWhitespace:function ( node ) { return !new RegExp( '[^ \t\n\r' + domUtils.fillChar + ']' ).test( node.nodeValue ); }, //------------------------------Element------------------------------------------- /** * 获取元素相对于viewport的像素坐标 * @param {Element} element 元素 * @returns {Object} 返回坐标对象{x:left,y:top} */ getXY:function ( element ) { var x = 0, y = 0; while ( element.offsetParent ) { y += element.offsetTop; x += element.offsetLeft; element = element.offsetParent; } return { 'x':x, 'y':y }; }, /** * 绑原生DOM事件 * @param {Element|Window|Document} target 元素 * @param {Array|String} type 事件类型 * @param {Function} handler 执行函数 */ on:function ( obj, type, handler ) { var types = utils.isArray(type) ? type : [type], k = types.length; if ( k ) while ( k-- ) { type = types[k]; if ( obj.addEventListener ) { obj.addEventListener( type, handler, false ); } else { if ( !handler._d ) { handler._d = {}; } var key = type + handler.toString(); if ( !handler._d[key] ) { handler._d[key] = function ( evt ) { return handler.call( evt.srcElement, evt || window.event ); }; obj.attachEvent( 'on' + type, handler._d[key] ); } } } obj = null; }, /** * 解除原生DOM事件绑定 * @param {Element|Window|Document} obj 元素 * @param {Array|String} type 事件类型 * @param {Function} handler 执行函数 */ un:function ( obj, type, handler ) { var types = utils.isArray(type) ? type : [type], k = types.length; if ( k ) while ( k-- ) { type = types[k]; if ( obj.removeEventListener ) { obj.removeEventListener( type, handler, false ); } else { var key = type + handler.toString(); obj.detachEvent( 'on' + type, handler._d ? handler._d[key] : handler ); if ( handler._d && handler._d[key] ) { delete handler._d[key]; } } } }, /** * 比较两个节点是否tagName相同且有相同的属性和属性值 * @param {Element} nodeA 节点A * @param {Element} nodeB 节点B * @return {Boolean} 返回两个节点的标签,属性和属性值是否相同 * @example * <span style="font-size:12px">ssss</span>和<span style="font-size:12px">bbbbb</span> 相等 * <span style="font-size:13px">ssss</span>和<span style="font-size:12px">bbbbb</span> 不相等 */ isSameElement:function ( nodeA, nodeB ) { if ( nodeA.tagName != nodeB.tagName ) { return 0; } var thisAttribs = nodeA.attributes, otherAttribs = nodeB.attributes; if ( !ie && thisAttribs.length != otherAttribs.length ) { return 0; } var attrA, attrB, al = 0, bl = 0; for ( var i = 0; attrA = thisAttribs[i++]; ) { if ( attrA.nodeName == 'style' ) { if ( attrA.specified ) { al++; } if ( domUtils.isSameStyle( nodeA, nodeB ) ) { continue; } else { return 0; } } if ( ie ) { if ( attrA.specified ) { al++; attrB = otherAttribs.getNamedItem( attrA.nodeName ); } else { continue; } } else { attrB = nodeB.attributes[attrA.nodeName]; } if ( !attrB.specified || attrA.nodeValue != attrB.nodeValue ) { return 0; } } // 有可能attrB的属性包含了attrA的属性之外还有自己的属性 if ( ie ) { for ( i = 0; attrB = otherAttribs[i++]; ) { if ( attrB.specified ) { bl++; } } if ( al != bl ) { return 0; } } return 1; }, /** * 判断两个元素的style属性是不是一致 * @param {Element} elementA 元素A * @param {Element} elementB 元素B * @return {boolean} 返回判断结果,true为一致 */ isSameStyle:function ( elementA, elementB ) { var styleA = elementA.style.cssText.replace( /( ?; ?)/g, ';' ).replace( /( ?: ?)/g, ':' ), styleB = elementB.style.cssText.replace( /( ?; ?)/g, ';' ).replace( /( ?: ?)/g, ':' ); if ( browser.opera ) { styleA = elementA.style; styleB = elementB.style; if ( styleA.length != styleB.length ) return 0; for ( var p in styleA ) { if ( /^(\d+|csstext)$/i.test( p ) ) { continue; } if ( styleA[p] != styleB[p] ) { return 0; } } return 1; } if ( !styleA || !styleB ) { return styleA == styleB ? 1 : 0; } styleA = styleA.split( ';' ); styleB = styleB.split( ';' ); if ( styleA.length != styleB.length ) { return 0; } for ( var i = 0, ci; ci = styleA[i++]; ) { if ( utils.indexOf( styleB, ci ) == -1 ) { return 0; } } return 1; }, /** * 检查是否为块元素 * @function * @param {Element} node 元素 * @param {String} customNodeNames 自定义的块元素的tagName * @return {Boolean} 是否为块元素 */ isBlockElm:function ( node ) { return node.nodeType == 1 && (dtd.$block[node.tagName] || styleBlock[domUtils.getComputedStyle( node, 'display' )]) && !dtd.$nonChild[node.tagName]; }, /** * 判断是否body * @param {Node} 节点 * @return {Boolean} 是否是body节点 */ isBody:function ( node ) { return node && node.nodeType == 1 && node.tagName.toLowerCase() == 'body'; }, /** * 以node节点为中心,将该节点的父节点拆分成2块 * @param {Element} node 节点 * @param {Element} parent 要被拆分的父节点 * @example
xxxxxxxxxx
==>
xxx
xx
xxx
*/ breakParent:function ( node, parent ) { var tmpNode, parentClone = node, clone = node, leftNodes, rightNodes; do { parentClone = parentClone.parentNode; if ( leftNodes ) { tmpNode = parentClone.cloneNode( false ); tmpNode.appendChild( leftNodes ); leftNodes = tmpNode; tmpNode = parentClone.cloneNode( false ); tmpNode.appendChild( rightNodes ); rightNodes = tmpNode; } else { leftNodes = parentClone.cloneNode( false ); rightNodes = leftNodes.cloneNode( false ); } while ( tmpNode = clone.previousSibling ) { leftNodes.insertBefore( tmpNode, leftNodes.firstChild ); } while ( tmpNode = clone.nextSibling ) { rightNodes.appendChild( tmpNode ); } clone = parentClone; } while ( parent !== parentClone ); tmpNode = parent.parentNode; tmpNode.insertBefore( leftNodes, parent ); tmpNode.insertBefore( rightNodes, parent ); tmpNode.insertBefore( node, rightNodes ); domUtils.remove( parent ); return node; }, /** * 检查是否是空inline节点 * @param {Node} node 节点 * @return {Boolean} 返回1为是,0为否 * @example * <b><i></i></b> //true * true * <b></b> true <b>xx<i></i></b> //false */ isEmptyInlineElement:function ( node ) { if ( node.nodeType != 1 || !dtd.$removeEmpty[ node.tagName ] ) { return 0; } node = node.firstChild; while ( node ) { //如果是创建的bookmark就跳过 if ( domUtils.isBookmarkNode( node ) ) { return 0; } if ( node.nodeType == 1 && !domUtils.isEmptyInlineElement( node ) || node.nodeType == 3 && !domUtils.isWhitespace( node ) ) { return 0; } node = node.nextSibling; } return 1; }, /** * 删除空白子节点 * @param {Element} node 需要删除空白子节点的元素 */ trimWhiteTextNode:function ( node ) { function remove( dir ) { var child; while ( (child = node[dir]) && child.nodeType == 3 && domUtils.isWhitespace( child ) ) { node.removeChild( child ) } } remove( 'firstChild' ); remove( 'lastChild' ); }, /** * 合并子节点 * @param {Node} node 节点 * @param {String} tagName 标签 * @param {String} attrs 属性 * @example <span style="font-size:12px;">xx<span style="font-size:12px;">aa</span>xx</span 使用后 * <span style="font-size:12px;">xxaaxx</span */ mergChild:function ( node, tagName, attrs ) { var list = domUtils.getElementsByTagName( node, node.tagName.toLowerCase() ); for ( var i = 0, ci; ci = list[i++]; ) { if ( !ci.parentNode || domUtils.isBookmarkNode( ci ) ) { continue; } //span单独处理 if ( ci.tagName.toLowerCase() == 'span' ) { if ( node === ci.parentNode ) { domUtils.trimWhiteTextNode( node ); if ( node.childNodes.length == 1 ) { node.style.cssText = ci.style.cssText + ";" + node.style.cssText; domUtils.remove( ci, true ); continue; } } ci.style.cssText = node.style.cssText + ';' + ci.style.cssText; if ( attrs ) { var style = attrs.style; if ( style ) { style = style.split( ';' ); for ( var j = 0, s; s = style[j++]; ) { ci.style[utils.cssStyleToDomStyle( s.split( ':' )[0] )] = s.split( ':' )[1]; } } } if ( domUtils.isSameStyle( ci, node ) ) { domUtils.remove( ci, true ); } continue; } if ( domUtils.isSameElement( node, ci ) ) { domUtils.remove( ci, true ); } } if ( tagName == 'span' ) { var as = domUtils.getElementsByTagName( node, 'a' ); for ( var i = 0, ai; ai = as[i++]; ) { ai.style.cssText = ';' + node.style.cssText; ai.style.textDecoration = 'underline'; } } }, /** * 封装原生的getElemensByTagName * @param {Node} node 根节点 * @param {String} name 标签的tagName * @return {Array} 返回符合条件的元素数组 */ getElementsByTagName:function ( node, name ) { var list = node.getElementsByTagName( name ), arr = []; for ( var i = 0, ci; ci = list[i++]; ) { arr.push( ci ) } return arr; }, /** * 将子节点合并到父节点上 * @param {Element} node 节点 * @example <span style="color:#ff"><span style="font-size:12px">xxx</span></span> ==> <span style="color:#ff;font-size:12px">xxx</span> */ mergToParent:function ( node ) { var parent = node.parentNode; while ( parent && dtd.$removeEmpty[parent.tagName] ) { if ( parent.tagName == node.tagName || parent.tagName == 'A' ) {//针对a标签单独处理 domUtils.trimWhiteTextNode( parent ); //span需要特殊处理 不处理这样的情况 xxxxxxxxx if ( parent.tagName == 'SPAN' && !domUtils.isSameStyle( parent, node ) || (parent.tagName == 'A' && node.tagName == 'SPAN') ) { if ( parent.childNodes.length > 1 || parent !== node.parentNode ) { node.style.cssText = parent.style.cssText + ";" + node.style.cssText; parent = parent.parentNode; continue; } else { parent.style.cssText += ";" + node.style.cssText; //trace:952 a标签要保持下划线 if ( parent.tagName == 'A' ) { parent.style.textDecoration = 'underline'; } } } if ( parent.tagName != 'A' ) { parent === node.parentNode && domUtils.remove( node, true ); break; } } parent = parent.parentNode; } }, /** * 合并左右兄弟节点 * @function * @param {Node} node * @param {Boolean} ingoreNext 默认为false合并上一个兄弟节点。true为不合并上一个兄弟节点 * @param {Boolean} ingorePre 默认为false合并下一个兄弟节点。true为不合并下一个兄弟节点 * @example <b>xxxx</b><b>xxx</b><b>xxxx</b> ==> <b>xxxxxxxxxxx</b> */ mergSibling:function ( node, ingorePre, ingoreNext ) { function merg( rtl, start, node ) { var next; if ( (next = node[rtl]) && !domUtils.isBookmarkNode( next ) && next.nodeType == 1 && domUtils.isSameElement( node, next ) ) { while ( next.firstChild ) { if ( start == 'firstChild' ) { node.insertBefore( next.lastChild, node.firstChild ); } else { node.appendChild( next.firstChild ); } } domUtils.remove( next ); } } !ingorePre && merg( 'previousSibling', 'firstChild', node ); !ingoreNext && merg( 'nextSibling', 'lastChild', node ); }, /** * 使得元素及其子节点不能被选择 * @function * @param {Node} node 节点 */ unselectable:ie || browser.opera ? function ( node ) { //for ie9 node.onselectstart = function () { return false; }; node.onclick = node.onkeyup = node.onkeydown = function () { return false; }; node.unselectable = 'on'; node.setAttribute( "unselectable", "on" ); for ( var i = 0, ci; ci = node.all[i++]; ) { switch ( ci.tagName.toLowerCase() ) { case 'iframe' : case 'textarea' : case 'input' : case 'select' : break; default : ci.unselectable = 'on'; node.setAttribute( "unselectable", "on" ); } } } : function ( node ) { node.style.MozUserSelect = node.style.webkitUserSelect = node.style.KhtmlUserSelect = 'none'; }, /** * 删除元素上的属性,可以删除多个 * @function * @param {Element} element 元素 * @param {Array} attrNames 要删除的属性数组 */ removeAttributes:function ( elm, attrNames ) { for ( var i = 0, ci; ci = attrNames[i++]; ) { ci = attrFix[ci] || ci; switch ( ci ) { case 'className': elm[ci] = ''; break; case 'style': elm.style.cssText = ''; !browser.ie && elm.removeAttributeNode( elm.getAttributeNode( 'style' ) ) } elm.removeAttribute( ci ); } }, creElm:function ( doc, tag, attrs ) { return this.setAttributes( doc.createElement( tag ), attrs ) }, /** * 给节点添加属性 * @function * @param {Node} node 节点 * @param {Object} attrNames 要添加的属性名称,采用json对象存放 */ setAttributes:function ( node, attrs ) { for ( var name in attrs ) { var value = attrs[name]; switch ( name ) { case 'class': //ie下要这样赋值,setAttribute不起作用 node.className = value; break; case 'style' : node.style.cssText = node.style.cssText + ";" + value; break; case 'innerHTML': node[name] = value; break; case 'value': node.value = value; break; default: node.setAttribute( attrFix[name] || name, value ); } } return node; }, /** * 获取元素的样式 * @function * @param {Element} element 元素 * @param {String} styleName 样式名称 * @return {String} 样式值 */ getComputedStyle:function ( element, styleName ) { function fixUnit( key, val ) { if ( key == 'font-size' && /pt$/.test( val ) ) { val = Math.round( parseFloat( val ) / 0.75 ) + 'px'; } return val; } if ( element.nodeType == 3 ) { element = element.parentNode; } //ie下font-size若body下定义了font-size,则从currentStyle里会取到这个font-size. 取不到实际值,故此修改. if ( browser.ie && browser.version < 9 && styleName == 'font-size' && !element.style.fontSize && !dtd.$empty[element.tagName] && !dtd.$nonChild[element.tagName] ) { var span = element.ownerDocument.createElement( 'span' ); span.style.cssText = 'padding:0;border:0;font-family:simsun;'; span.innerHTML = '.'; element.appendChild( span ); var result = span.offsetHeight; element.removeChild( span ); span = null; return result + 'px'; } try { var value = domUtils.getStyle( element, styleName ) || (window.getComputedStyle ? domUtils.getWindow( element ).getComputedStyle( element, '' ).getPropertyValue( styleName ) : ( element.currentStyle || element.style )[utils.cssStyleToDomStyle( styleName )]); } catch ( e ) { return null; } return fixUnit( styleName, utils.fixColor( styleName, value ) ); }, /** * 删除cssClass,可以支持删除多个class * @param {Element} element 元素 * @param {Array} classNames 删除的className */ removeClasses:function ( element, classNames ) { classNames = utils.isArray( classNames ) ? classNames : [classNames]; element.className = (' ' + element.className + ' ').replace( new RegExp( '(?:\\s+(?:' + classNames.join( '|' ) + '))+\\s+', 'g' ), ' ' ); }, /** * 增加一个class * @param element * @param className */ addClass:function ( element, className ) { if ( !this.hasClass( element, className ) ) { element.className += " " + className; } }, /** * 删除元素的样式 * @param {Element} element元素 * @param {String} name 删除的样式名称 */ removeStyle:function ( node, name ) { node.style[utils.cssStyleToDomStyle( name )] = ''; if ( !node.style.cssText ) { domUtils.removeAttributes( node, ['style'] ); } }, /** * 判断元素属性中是否包含某一个classname * @param {Element} element 元素 * @param {String} className 样式名 * @returns {Boolean} 是否包含该classname */ hasClass:function ( element, className ) { return ( ' ' + element.className + ' ' ).indexOf( ' ' + className + ' ' ) > -1; }, /** * 阻止事件默认行为 * @param {Event} evt 需要组织的事件对象 */ preventDefault:function ( evt ) { evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); }, /** * 获得元素样式 * @param {Element} element 元素 * @param {String} name 样式名称 * @return {String} 返回元素样式值 */ getStyle:function ( element, name ) { var value = element.style[ utils.cssStyleToDomStyle( name ) ]; return utils.fixColor( name, value ); }, setStyle:function ( element, name, value ) { element.style[utils.cssStyleToDomStyle( name )] = value; }, setStyles:function ( element, styles ) { for ( var name in styles ) { if ( styles.hasOwnProperty( name ) ) { domUtils.setStyle( element, name, styles[name] ); } } }, /** * 删除_moz_dirty属性 * @function * @param {Node} node 节点 */ removeDirtyAttr:function ( node ) { for ( var i = 0, ci, nodes = node.getElementsByTagName( '*' ); ci = nodes[i++]; ) { ci.removeAttribute( '_moz_dirty' ); } node.removeAttribute( '_moz_dirty' ); }, /** * 返回子节点的数量 * @function * @param {Node} node 父节点 * @param {Function} fn 过滤子节点的规则,若为空,则得到所有子节点的数量 * @return {Number} 符合条件子节点的数量 */ getChildCount:function ( node, fn ) { var count = 0, first = node.firstChild; fn = fn || function () { return 1; }; while ( first ) { if ( fn( first ) ) { count++; } first = first.nextSibling; } return count; }, /** * 判断是否为空节点 * @function * @param {Node} node 节点 * @return {Boolean} 是否为空节点 */ isEmptyNode:function ( node ) { return !node.firstChild || domUtils.getChildCount( node, function ( node ) { return !domUtils.isBr( node ) && !domUtils.isBookmarkNode( node ) && !domUtils.isWhitespace( node ) } ) == 0 }, /** * 清空节点所有的className * @function * @param {Array} nodes 节点数组 */ clearSelectedArr:function ( nodes ) { var node; while ( node = nodes.pop() ) { domUtils.removeAttributes( node, ['class'] ); } }, /** * 将显示区域滚动到显示节点的位置 * @function * @param {Node} node 节点 * @param {window} win window对象 * @param {Number} offsetTop 距离上方的偏移量 */ scrollToView:function ( node, win, offsetTop ) { var getViewPaneSize = function () { var doc = win.document, mode = doc.compatMode == 'CSS1Compat'; return { width:( mode ? doc.documentElement.clientWidth : doc.body.clientWidth ) || 0, height:( mode ? doc.documentElement.clientHeight : doc.body.clientHeight ) || 0 }; }, getScrollPosition = function ( win ) { if ( 'pageXOffset' in win ) { return { x:win.pageXOffset || 0, y:win.pageYOffset || 0 }; } else { var doc = win.document; return { x:doc.documentElement.scrollLeft || doc.body.scrollLeft || 0, y:doc.documentElement.scrollTop || doc.body.scrollTop || 0 }; } }; var winHeight = getViewPaneSize().height, offset = winHeight * -1 + offsetTop; offset += (node.offsetHeight || 0); var elementPosition = domUtils.getXY( node ); offset += elementPosition.y; var currentScroll = getScrollPosition( win ).y; // offset += 50; if ( offset > currentScroll || offset < currentScroll - winHeight ) { win.scrollTo( 0, offset + (offset < 0 ? -20 : 20) ); } }, /** * 判断节点是否为br * @function * @param {Node} node 节点 */ isBr:function ( node ) { return node.nodeType == 1 && node.tagName == 'BR'; }, isFillChar:function ( node ) { return node.nodeType == 3 && !node.nodeValue.replace( new RegExp( domUtils.fillChar ), '' ).length }, isStartInblock:function ( range ) { var tmpRange = range.cloneRange(), flag = 0, start = tmpRange.startContainer, tmp; while ( start && domUtils.isFillChar( start ) ) { tmp = start; start = start.previousSibling } if ( tmp ) { tmpRange.setStartBefore( tmp ); start = tmpRange.startContainer; } if ( start.nodeType == 1 && domUtils.isEmptyNode( start ) && tmpRange.startOffset == 1 ) { tmpRange.setStart( start, 0 ).collapse( true ); } while ( !tmpRange.startOffset ) { start = tmpRange.startContainer; if ( domUtils.isBlockElm( start ) || domUtils.isBody( start ) ) { flag = 1; break; } var pre = tmpRange.startContainer.previousSibling, tmpNode; if ( !pre ) { tmpRange.setStartBefore( tmpRange.startContainer ); } else { while ( pre && domUtils.isFillChar( pre ) ) { tmpNode = pre; pre = pre.previousSibling; } if ( tmpNode ) { tmpRange.setStartBefore( tmpNode ); } else { tmpRange.setStartBefore( tmpRange.startContainer ); } } } return flag && !domUtils.isBody( tmpRange.startContainer ) ? 1 : 0; }, isEmptyBlock:function ( node ) { var reg = new RegExp( '[ \t\r\n' + domUtils.fillChar + ']', 'g' ); if ( node[browser.ie ? 'innerText' : 'textContent'].replace( reg, '' ).length > 0 ) { return 0; } for ( var n in dtd.$isNotEmpty ) { if ( node.getElementsByTagName( n ).length ) { return 0; } } return 1; }, setViewportOffset:function ( element, offset ) { var left = parseInt( element.style.left ) | 0; var top = parseInt( element.style.top ) | 0; var rect = element.getBoundingClientRect(); var offsetLeft = offset.left - rect.left; var offsetTop = offset.top - rect.top; if ( offsetLeft ) { element.style.left = left + offsetLeft + 'px'; } if ( offsetTop ) { element.style.top = top + offsetTop + 'px'; } }, fillNode:function ( doc, node ) { var tmpNode = browser.ie ? doc.createTextNode( domUtils.fillChar ) : doc.createElement( 'br' ); node.innerHTML = ''; node.appendChild( tmpNode ); }, moveChild:function ( src, tag, dir ) { while ( src.firstChild ) { if ( dir && tag.firstChild ) { tag.insertBefore( src.lastChild, tag.firstChild ); } else { tag.appendChild( src.firstChild ); } } }, //判断是否有额外属性 hasNoAttributes:function ( node ) { return browser.ie ? /^<\w+\s*?>/.test( node.outerHTML ) : node.attributes.length == 0; }, //判断是否是编辑器自定义的参数 isCustomeNode:function ( node ) { return node.nodeType == 1 && node.getAttribute( '_ue_custom_node_' ); }, isTagNode:function ( node, tagName ) { return node.nodeType == 1 && node.tagName.toLowerCase() == tagName; } }; var fillCharReg = new RegExp( domUtils.fillChar, 'g' ); ///import editor.js ///import core/utils.js ///import core/browser.js ///import core/dom/dom.js ///import core/dom/dtd.js ///import core/dom/domUtils.js /** * @class baidu.editor.dom.Range Range类 */ /** * @description Range类实现 * @author zhanyi */ (function () { var guid = 0, fillChar = domUtils.fillChar, fillData; /** * 更新range的collapse状态 * @param {Range} range range对象 */ function updateCollapse( range ) { range.collapsed = range.startContainer && range.endContainer && range.startContainer === range.endContainer && range.startOffset == range.endOffset; } function setEndPoint( toStart, node, offset, range ) { //如果node是自闭合标签要处理 if ( node.nodeType == 1 && (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName]) ) { offset = domUtils.getNodeIndex( node ) + (toStart ? 0 : 1); node = node.parentNode; } if ( toStart ) { range.startContainer = node; range.startOffset = offset; if ( !range.endContainer ) { range.collapse( true ); } } else { range.endContainer = node; range.endOffset = offset; if ( !range.startContainer ) { range.collapse( false ); } } updateCollapse( range ); return range; } function execContentsAction( range, action ) { //调整边界 //range.includeBookmark(); var start = range.startContainer, end = range.endContainer, startOffset = range.startOffset, endOffset = range.endOffset, doc = range.document, frag = doc.createDocumentFragment(), tmpStart, tmpEnd; if ( start.nodeType == 1 ) { start = start.childNodes[startOffset] || (tmpStart = start.appendChild( doc.createTextNode( '' ) )); } if ( end.nodeType == 1 ) { end = end.childNodes[endOffset] || (tmpEnd = end.appendChild( doc.createTextNode( '' ) )); } if ( start === end && start.nodeType == 3 ) { frag.appendChild( doc.createTextNode( start.substringData( startOffset, endOffset - startOffset ) ) ); //is not clone if ( action ) { start.deleteData( startOffset, endOffset - startOffset ); range.collapse( true ); } return frag; } var current, currentLevel, clone = frag, startParents = domUtils.findParents( start, true ), endParents = domUtils.findParents( end, true ); for ( var i = 0; startParents[i] == endParents[i]; ) { i++; } for ( var j = i, si; si = startParents[j]; j++ ) { current = si.nextSibling; if ( si == start ) { if ( !tmpStart ) { if ( range.startContainer.nodeType == 3 ) { clone.appendChild( doc.createTextNode( start.nodeValue.slice( startOffset ) ) ); //is not clone if ( action ) { start.deleteData( startOffset, start.nodeValue.length - startOffset ); } } else { clone.appendChild( !action ? start.cloneNode( true ) : start ); } } } else { currentLevel = si.cloneNode( false ); clone.appendChild( currentLevel ); } while ( current ) { if ( current === end || current === endParents[j] ) { break; } si = current.nextSibling; clone.appendChild( !action ? current.cloneNode( true ) : current ); current = si; } clone = currentLevel; } clone = frag; if ( !startParents[i] ) { clone.appendChild( startParents[i - 1].cloneNode( false ) ); clone = clone.firstChild; } for ( var j = i, ei; ei = endParents[j]; j++ ) { current = ei.previousSibling; if ( ei == end ) { if ( !tmpEnd && range.endContainer.nodeType == 3 ) { clone.appendChild( doc.createTextNode( end.substringData( 0, endOffset ) ) ); //is not clone if ( action ) { end.deleteData( 0, endOffset ); } } } else { currentLevel = ei.cloneNode( false ); clone.appendChild( currentLevel ); } //如果两端同级,右边第一次已经被开始做了 if ( j != i || !startParents[i] ) { while ( current ) { if ( current === start ) { break; } ei = current.previousSibling; clone.insertBefore( !action ? current.cloneNode( true ) : current, clone.firstChild ); current = ei; } } clone = currentLevel; } if ( action ) { range.setStartBefore( !endParents[i] ? endParents[i - 1] : !startParents[i] ? startParents[i - 1] : endParents[i] ).collapse( true ); } tmpStart && domUtils.remove( tmpStart ); tmpEnd && domUtils.remove( tmpEnd ); return frag; } /** * Range类 * @param {Document} document 编辑器页面document对象 */ var Range = dom.Range = function ( document ) { var me = this; me.startContainer = me.startOffset = me.endContainer = me.endOffset = null; me.document = document; me.collapsed = true; }; /** * 删除fillData * @param doc * @param excludeNode */ function removeFillData( doc, excludeNode ) { try { if ( fillData && domUtils.inDoc( fillData, doc ) ) { if ( !fillData.nodeValue.replace( fillCharReg, '' ).length ) { var tmpNode = fillData.parentNode; domUtils.remove( fillData ); while ( tmpNode && domUtils.isEmptyInlineElement( tmpNode ) && !tmpNode.contains( excludeNode ) ) { fillData = tmpNode.parentNode; domUtils.remove( tmpNode ); tmpNode = fillData; } } else { fillData.nodeValue = fillData.nodeValue.replace( fillCharReg, '' ); } } } catch ( e ) { } } /** * * @param node * @param dir */ function mergSibling( node, dir ) { var tmpNode; node = node[dir]; while ( node && domUtils.isFillChar( node ) ) { tmpNode = node[dir]; domUtils.remove( node ); node = tmpNode; } } Range.prototype = { /** * 克隆选中的内容到一个fragment里 * @public * @function * @name baidu.editor.dom.Range.cloneContents * @return {Fragment} frag|null 返回选中内容的文本片段或者空 */ cloneContents:function () { return this.collapsed ? null : execContentsAction( this, 0 ); }, /** * 删除所选内容 * @public * @function * @name baidu.editor.dom.Range.deleteContents * @return {Range} 删除选中内容后的Range */ deleteContents:function () { var txt; if ( !this.collapsed ) { execContentsAction( this, 1 ); } if ( browser.webkit ) { txt = this.startContainer; if ( txt.nodeType == 3 && !txt.nodeValue.length ) { this.setStartBefore( txt ).collapse( true ); domUtils.remove( txt ); } } return this; }, /** * 取出内容 * @public * @function * @name baidu.editor.dom.Range.extractContents * @return {String} 获得Range选中的内容 */ extractContents:function () { return this.collapsed ? null : execContentsAction( this, 2 ); }, /** * 设置range的开始位置 * @public * @function * @name baidu.editor.dom.Range.setStart * @param {Node} node range开始节点 * @param {Number} offset 偏移量 * @return {Range} 返回Range */ setStart:function ( node, offset ) { return setEndPoint( true, node, offset, this ); }, /** * 设置range结束点的位置 * @public * @function * @name baidu.editor.dom.Range.setEnd * @param {Node} node range结束节点 * @param {Number} offset 偏移量 * @return {Range} 返回Range */ setEnd:function ( node, offset ) { return setEndPoint( false, node, offset, this ); }, /** * 将开始位置设置到node后 * @public * @function * @name baidu.editor.dom.Range.setStartAfter * @param {Node} node 节点 * @return {Range} 返回Range */ setStartAfter:function ( node ) { return this.setStart( node.parentNode, domUtils.getNodeIndex( node ) + 1 ); }, /** * 将开始位置设置到node前 * @public * @function * @name baidu.editor.dom.Range.setStartBefore * @param {Node} node 节点 * @return {Range} 返回Range */ setStartBefore:function ( node ) { return this.setStart( node.parentNode, domUtils.getNodeIndex( node ) ); }, /** * 将结束点位置设置到node后 * @public * @function * @name baidu.editor.dom.Range.setEndAfter * @param {Node} node 节点 * @return {Range} 返回Range */ setEndAfter:function ( node ) { return this.setEnd( node.parentNode, domUtils.getNodeIndex( node ) + 1 ); }, /** * 将开始设置到node的最开始位置 ^text * @public * @function * @name baidu.editor.dom.Range.setEndAfter * @param {Node} node 节点 * @return {Range} 返回Range */ setStartAtFirst:function ( node ) { return this.setStart( node, 0 ); }, /** * 将开始设置到node的最开始位置 text^ * @public * @function * @name baidu.editor.dom.Range.setEndAfter * @param {Node} node 节点 * @return {Range} 返回Range */ setStartAtLast:function ( node ) { return this.setStart( node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length ); }, /** * 将结束设置到node的最开始位置 ^text * @public * @function * @name baidu.editor.dom.Range.setEndAfter * @param {Node} node 节点 * @return {Range} 返回Range */ setEndAtFirst:function ( node ) { return this.setEnd( node, 0 ); }, /** * 将结束设置到node的最开始位置 text^ * @public * @function * @name baidu.editor.dom.Range.setEndAfter * @param {Node} node 节点 * @return {Range} 返回Range */ setEndAtLast:function ( node ) { return this.setEnd( node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length ); }, /** * 将结束点位置设置到node前 * @public * @function * @name baidu.editor.dom.Range.setEndBefore * @param {Node} node 节点 * @return {Range} 返回Range */ setEndBefore:function ( node ) { return this.setEnd( node.parentNode, domUtils.getNodeIndex( node ) ); }, /** * 选中指定节点 * @public * @function * @name baidu.editor.dom.Range.selectNode * @param {Node} node 节点 * @return {Range} 返回Range */ selectNode:function ( node ) { return this.setStartBefore( node ).setEndAfter( node ); }, /** * 选中node下的所有节点 * @public * @function * @name baidu.editor.dom.Range.selectNodeContents * @param {Element} node 要设置的节点 * @return {Range} 返回Range */ selectNodeContents:function ( node ) { return this.setStart( node, 0 ).setEnd( node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length ); }, /** * 克隆range * @public * @function * @name baidu.editor.dom.Range.cloneRange * @return {Range} 克隆的range对象 */ cloneRange:function () { var me = this, range = new Range( me.document ); return range.setStart( me.startContainer, me.startOffset ).setEnd( me.endContainer, me.endOffset ); }, /** * 让选区闭合 * @public * @function * @name baidu.editor.dom.Range.collapse * @param {Boolean} toStart 是否在选区开始位置闭合选区,true在开始位置闭合,false反之 * @return {Range} range对象 */ collapse:function ( toStart ) { var me = this; if ( toStart ) { me.endContainer = me.startContainer; me.endOffset = me.startOffset; } else { me.startContainer = me.endContainer; me.startOffset = me.endOffset; } me.collapsed = true; return me; }, /** * 调整range的边界,“缩”到合适的位置 * @public * @function * @name baidu.editor.dom.Range.shrinkBoundary * @param {Boolean} ignoreEnd 是否考虑前面的元素 */ shrinkBoundary:function ( ignoreEnd ) { var me = this, child, collapsed = me.collapsed; while ( me.startContainer.nodeType == 1 //是element && (child = me.startContainer.childNodes[me.startOffset]) //子节点也是element && child.nodeType == 1 && !domUtils.isBookmarkNode( child ) && !dtd.$empty[child.tagName] && !dtd.$nonChild[child.tagName] ) { me.setStart( child, 0 ); } if ( collapsed ) { return me.collapse( true ); } if ( !ignoreEnd ) { while ( me.endContainer.nodeType == 1//是element && me.endOffset > 0 //如果是空元素就退出 endOffset=0那么endOffst-1为负值,childNodes[endOffset]报错 && (child = me.endContainer.childNodes[me.endOffset - 1]) //子节点也是element && child.nodeType == 1 && !domUtils.isBookmarkNode( child ) && !dtd.$empty[child.tagName] && !dtd.$nonChild[child.tagName] ) { me.setEnd( child, child.childNodes.length ); } } return me; }, /** * 找到startContainer和endContainer的公共祖先节点 * @public * @function * @name baidu.editor.dom.Range.getCommonAncestor * @param {Boolean} includeSelf 是否包含自身 * @param {Boolean} ignoreTextNode 是否忽略文本节点 * @return {Node} 祖先节点 */ getCommonAncestor:function ( includeSelf, ignoreTextNode ) { var start = this.startContainer, end = this.endContainer; if ( start === end ) { if ( includeSelf && start.nodeType == 1 && this.startOffset == this.endOffset - 1 ) { return start.childNodes[this.startOffset]; } //只有在上来就相等的情况下才会出现是文本的情况 return ignoreTextNode && start.nodeType == 3 ? start.parentNode : start; } return domUtils.getCommonAncestor( start, end ); }, /** * 切割文本节点,将边界扩大到element * @public * @function * @name baidu.editor.dom.Range.trimBoundary * @param {Boolean} ignoreEnd 为真就不处理结束边界 * @return {Range} range对象 * @example |xxx * startContainer = xxx; startOffset = 0 * 执行后 * startContainer = ; startOffset = 0 * @example xx|x * startContainer = xxx; startOffset = 2 * 执行后 * startContainer = ; startOffset = 1 因为将xxx切割成2个节点了 */ trimBoundary:function ( ignoreEnd ) { this.txtToElmBoundary(); var start = this.startContainer, offset = this.startOffset, collapsed = this.collapsed, end = this.endContainer; if ( start.nodeType == 3 ) { if ( offset == 0 ) { this.setStartBefore( start ); } else { if ( offset >= start.nodeValue.length ) { this.setStartAfter( start ); } else { var textNode = domUtils.split( start, offset ); //跟新结束边界 if ( start === end ) { this.setEnd( textNode, this.endOffset - offset ); } else if ( start.parentNode === end ) { this.endOffset += 1; } this.setStartBefore( textNode ); } } if ( collapsed ) { return this.collapse( true ); } } if ( !ignoreEnd ) { offset = this.endOffset; end = this.endContainer; if ( end.nodeType == 3 ) { if ( offset == 0 ) { this.setEndBefore( end ); } else { if ( offset >= end.nodeValue.length ) { this.setEndAfter( end ); } else { domUtils.split( end, offset ); this.setEndAfter( end ); } } } } return this; }, /** * 如果选区在文本的边界上,就扩展选区到文本的父节点上 * @public * @function * @name baidu.editor.dom.Range.txtToElmBoundary * @return {Range} range对象 * @example |xxx * startContainer = xxx; startOffset = 0 * 执行后 * startContainer = ; startOffset = 0 * @example xxx| * startContainer = xxx; startOffset = 3 * 执行后 * startContainer = ; startOffset = 1 */ txtToElmBoundary:function () { function adjust( r, c ) { var container = r[c + 'Container'], offset = r[c + 'Offset']; if ( container.nodeType == 3 ) { if ( !offset ) { r['set' + c.replace( /(\w)/, function ( a ) { return a.toUpperCase(); } ) + 'Before']( container ); } else if ( offset >= container.nodeValue.length ) { r['set' + c.replace( /(\w)/, function ( a ) { return a.toUpperCase(); } ) + 'After' ]( container ); } } } if ( !this.collapsed ) { adjust( this, 'start' ); adjust( this, 'end' ); } return this; }, /** * 在当前选区的开始位置前插入一个节点或者fragment * @public * @function * @name baidu.editor.dom.Range.insertNode * @param {Node/DocumentFragment} node 要插入的节点或fragment * @return {Range} 返回range对象 */ insertNode:function ( node ) { var first = node, length = 1; if ( node.nodeType == 11 ) { first = node.firstChild; length = node.childNodes.length; } this.trimBoundary( true ); var start = this.startContainer, offset = this.startOffset; var nextNode = start.childNodes[ offset ]; if ( nextNode ) { start.insertBefore( node, nextNode ); } else { start.appendChild( node ); } if ( first.parentNode === this.endContainer ) { this.endOffset = this.endOffset + length; } return this.setStartBefore( first ); }, /** * 设置光标位置 * @public * @function * @name baidu.editor.dom.Range.setCursor * @param {Boolean} toEnd true为闭合到选区的结束位置后,false为闭合到选区的开始位置前 * @return {Range} 返回range对象 */ setCursor:function ( toEnd, notFillData ) { return this.collapse( !toEnd ).select( notFillData ); }, /** * 创建书签 * @public * @function * @name baidu.editor.dom.Range.createBookmark * @param {Boolean} serialize true:为true则返回对象中用id来分别表示书签的开始和结束节点 * @param {Boolean} same true:是否采用唯一的id,false将会为每一个标签产生一个唯一的id * @returns {Object} bookmark对象 */ createBookmark:function ( serialize, same ) { var endNode, startNode = this.document.createElement( 'span' ); startNode.style.cssText = 'display:none;line-height:0px;'; startNode.appendChild( this.document.createTextNode( '\uFEFF' ) ); startNode.id = '_baidu_bookmark_start_' + (same ? '' : guid++); if ( !this.collapsed ) { endNode = startNode.cloneNode( true ); endNode.id = '_baidu_bookmark_end_' + (same ? '' : guid++); } this.insertNode( startNode ); if ( endNode ) { this.collapse( false ).insertNode( endNode ); this.setEndBefore( endNode ); } this.setStartAfter( startNode ); return { start:serialize ? startNode.id : startNode, end:endNode ? serialize ? endNode.id : endNode : null, id:serialize } }, /** * 移动边界到书签,并删除书签 * @public * @function * @name baidu.editor.dom.Range.moveToBookmark * @params {Object} bookmark对象 * @returns {Range} Range对象 */ moveToBookmark:function ( bookmark ) { var start = bookmark.id ? this.document.getElementById( bookmark.start ) : bookmark.start, end = bookmark.end && bookmark.id ? this.document.getElementById( bookmark.end ) : bookmark.end; this.setStartBefore( start ); domUtils.remove( start ); if ( end ) { this.setEndBefore( end ); domUtils.remove( end ); } else { this.collapse( true ); } return this; }, /** * 调整边界到一个block元素上,或者移动到最大的位置 * @public * @function * @name baidu.editor.dom.Range.enlarge * @params {Boolean} toBlock 扩展到block元素 * @params {Function} stopFn 停止函数,若返回true,则不再扩展 * @return {Range} Range对象 */ enlarge:function ( toBlock, stopFn ) { var isBody = domUtils.isBody, pre, node, tmp = this.document.createTextNode( '' ); if ( toBlock ) { node = this.startContainer; if ( node.nodeType == 1 ) { if ( node.childNodes[this.startOffset] ) { pre = node = node.childNodes[this.startOffset] } else { node.appendChild( tmp ); pre = node = tmp; } } else { pre = node; } while ( 1 ) { if ( domUtils.isBlockElm( node ) ) { node = pre; while ( (pre = node.previousSibling) && !domUtils.isBlockElm( pre ) ) { node = pre; } this.setStartBefore( node ); break; } pre = node; node = node.parentNode; } node = this.endContainer; if ( node.nodeType == 1 ) { if ( pre = node.childNodes[this.endOffset] ) { node.insertBefore( tmp, pre ); } else { node.appendChild( tmp ); } pre = node = tmp; } else { pre = node; } while ( 1 ) { if ( domUtils.isBlockElm( node ) ) { node = pre; while ( (pre = node.nextSibling) && !domUtils.isBlockElm( pre ) ) { node = pre; } this.setEndAfter( node ); break; } pre = node; node = node.parentNode; } if ( tmp.parentNode === this.endContainer ) { this.endOffset--; } domUtils.remove( tmp ); } // 扩展边界到最大 if ( !this.collapsed ) { while ( this.startOffset == 0 ) { if ( stopFn && stopFn( this.startContainer ) ) { break; } if ( isBody( this.startContainer ) ) { break; } this.setStartBefore( this.startContainer ); } while ( this.endOffset == (this.endContainer.nodeType == 1 ? this.endContainer.childNodes.length : this.endContainer.nodeValue.length) ) { if ( stopFn && stopFn( this.endContainer ) ) { break; } if ( isBody( this.endContainer ) ) { break; } this.setEndAfter( this.endContainer ); } } return this; }, /** * 调整边界 * @public * @function * @name baidu.editor.dom.Range.adjustmentBoundary * @return {Range} Range对象 * @example * xx[xxxxx] ==> xx[xxxxx] * [xx]xxx ==> [xx]xxx * */ adjustmentBoundary:function () { if ( !this.collapsed ) { while ( !domUtils.isBody( this.startContainer ) && this.startOffset == this.startContainer[this.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length ) { this.setStartAfter( this.startContainer ); } while ( !domUtils.isBody( this.endContainer ) && !this.endOffset ) { this.setEndBefore( this.endContainer ); } } return this; }, /** * 给选区中的内容加上inline样式 * @public * @function * @name baidu.editor.dom.Range.applyInlineStyle * @param {String} tagName 标签名称 * @param {Object} attrObj 属性 * @return {Range} Range对象 */ applyInlineStyle:function ( tagName, attrs, list ) { if ( this.collapsed )return this; this.trimBoundary().enlarge( false, function ( node ) { return node.nodeType == 1 && domUtils.isBlockElm( node ) } ).adjustmentBoundary(); var bookmark = this.createBookmark(), end = bookmark.end, filterFn = function ( node ) { return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace( node ); }, current = domUtils.getNextDomNode( bookmark.start, false, filterFn ), node, pre, range = this.cloneRange(); while ( current && (domUtils.getPosition( current, end ) & domUtils.POSITION_PRECEDING) ) { if ( current.nodeType == 3 || dtd[tagName][current.tagName] ) { range.setStartBefore( current ); node = current; while ( node && (node.nodeType == 3 || dtd[tagName][node.tagName]) && node !== end ) { pre = node; node = domUtils.getNextDomNode( node, node.nodeType == 1, null, function ( parent ) { return dtd[tagName][parent.tagName]; } ); } var frag = range.setEndAfter( pre ).extractContents(), elm; if ( list && list.length > 0 ) { var level, top; top = level = list[0].cloneNode( false ); for ( var i = 1, ci; ci = list[i++]; ) { level.appendChild( ci.cloneNode( false ) ); level = level.firstChild; } elm = level; } else { elm = range.document.createElement( tagName ); } if ( attrs ) { domUtils.setAttributes( elm, attrs ); } elm.appendChild( frag ); range.insertNode( list ? top : elm ); //处理下滑线在a上的情况 var aNode; if ( tagName == 'span' && attrs.style && /text\-decoration/.test( attrs.style ) && (aNode = domUtils.findParentByTagName( elm, 'a', true )) ) { domUtils.setAttributes( aNode, attrs ); domUtils.remove( elm, true ); elm = aNode; } else { domUtils.mergSibling( elm ); domUtils.clearEmptySibling( elm ); } //去除子节点相同的 domUtils.mergChild( elm, tagName, attrs ); current = domUtils.getNextDomNode( elm, false, filterFn ); domUtils.mergToParent( elm ); if ( node === end ) { break; } } else { current = domUtils.getNextDomNode( current, true, filterFn ); } } return this.moveToBookmark( bookmark ); }, /** * 去掉inline样式 * @public * @function * @name baidu.editor.dom.Range.removeInlineStyle * @param {String/Array} tagName 要去掉的标签名 * @return {Range} Range对象 */ removeInlineStyle:function ( tagName ) { if ( this.collapsed )return this; tagName = utils.isArray( tagName ) ? tagName : [tagName]; this.shrinkBoundary().adjustmentBoundary(); var start = this.startContainer, end = this.endContainer; while ( 1 ) { if ( start.nodeType == 1 ) { if ( utils.indexOf( tagName, start.tagName.toLowerCase() ) > -1 ) { break; } if ( start.tagName.toLowerCase() == 'body' ) { start = null; break; } } start = start.parentNode; } while ( 1 ) { if ( end.nodeType == 1 ) { if ( utils.indexOf( tagName, end.tagName.toLowerCase() ) > -1 ) { break; } if ( end.tagName.toLowerCase() == 'body' ) { end = null; break; } } end = end.parentNode; } var bookmark = this.createBookmark(), frag, tmpRange; if ( start ) { tmpRange = this.cloneRange().setEndBefore( bookmark.start ).setStartBefore( start ); frag = tmpRange.extractContents(); tmpRange.insertNode( frag ); domUtils.clearEmptySibling( start, true ); start.parentNode.insertBefore( bookmark.start, start ); } if ( end ) { tmpRange = this.cloneRange().setStartAfter( bookmark.end ).setEndAfter( end ); frag = tmpRange.extractContents(); tmpRange.insertNode( frag ); domUtils.clearEmptySibling( end, false, true ); end.parentNode.insertBefore( bookmark.end, end.nextSibling ); } var current = domUtils.getNextDomNode( bookmark.start, false, function ( node ) { return node.nodeType == 1; } ), next; while ( current && current !== bookmark.end ) { next = domUtils.getNextDomNode( current, true, function ( node ) { return node.nodeType == 1; } ); if ( utils.indexOf( tagName, current.tagName.toLowerCase() ) > -1 ) { domUtils.remove( current, true ); } current = next; } return this.moveToBookmark( bookmark ); }, /** * 得到一个自闭合的节点 * @public * @function * @name baidu.editor.dom.Range.getClosedNode * @return {Node} 闭合节点 * @example * ,
*/ getClosedNode:function () { var node; if ( !this.collapsed ) { var range = this.cloneRange().adjustmentBoundary().shrinkBoundary(); if ( range.startContainer.nodeType == 1 && range.startContainer === range.endContainer && range.endOffset - range.startOffset == 1 ) { var child = range.startContainer.childNodes[range.startOffset]; if ( child && child.nodeType == 1 && (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName]) ) { node = child; } } } return node; }, /** * 根据range选中元素 * @public * @function * @name baidu.editor.dom.Range.select * @param {Boolean} notInsertFillData true为不加占位符 */ select:browser.ie ? function ( notInsertFillData, textRange ) { var nativeRange; if ( !this.collapsed ) this.shrinkBoundary(); var node = this.getClosedNode(); if ( node && !textRange ) { try { nativeRange = this.document.body.createControlRange(); nativeRange.addElement( node ); nativeRange.select(); } catch ( e ) {} return this; } var bookmark = this.createBookmark(), start = bookmark.start, end; nativeRange = this.document.body.createTextRange(); nativeRange.moveToElementText( start ); nativeRange.moveStart( 'character', 1 ); if ( !this.collapsed ) { var nativeRangeEnd = this.document.body.createTextRange(); end = bookmark.end; nativeRangeEnd.moveToElementText( end ); nativeRange.setEndPoint( 'EndToEnd', nativeRangeEnd ); } else { if ( !notInsertFillData && this.startContainer.nodeType != 3 ) { //使用|x固定住光标 var tmpText = this.document.createTextNode( fillChar ), tmp = this.document.createElement( 'span' ); tmp.appendChild( this.document.createTextNode( fillChar ) ); start.parentNode.insertBefore( tmp, start ); start.parentNode.insertBefore( tmpText, start ); //当点b,i,u时,不能清除i上边的b removeFillData( this.document, tmpText ); fillData = tmpText; mergSibling( tmp, 'previousSibling' ); mergSibling( start, 'nextSibling' ); nativeRange.moveStart( 'character', -1 ); nativeRange.collapse( true ); } } this.moveToBookmark( bookmark ); tmp && domUtils.remove( tmp ); //IE在隐藏状态下不支持range操作,catch一下 try{ nativeRange.select(); }catch(e){} return this; } : function ( notInsertFillData ) { var win = domUtils.getWindow( this.document ), sel = win.getSelection(), txtNode; //FF下关闭自动长高时滚动条在关闭dialog时会跳 //ff下如果不body.focus将不能定位闭合光标到编辑器内 browser.gecko ? this.document.body.focus() : win.focus(); if ( sel ) { sel.removeAllRanges(); // trace:870 chrome/safari后边是br对于闭合得range不能定位 所以去掉了判断 // this.startContainer.nodeType != 3 &&! ((child = this.startContainer.childNodes[this.startOffset]) && child.nodeType == 1 && child.tagName == 'BR' if ( this.collapsed ) { //opear如果没有节点接着,原生的不能够定位,不能在body的第一级插入空白节点 if ( notInsertFillData && browser.opera && !domUtils.isBody( this.startContainer ) && this.startContainer.nodeType == 1 ) { var tmp = this.document.createTextNode( '' ); this.insertNode( tmp ).setStart( tmp, 0 ).collapse( true ); } if ( !notInsertFillData ) { txtNode = this.document.createTextNode( fillChar ); //跟着前边走 this.insertNode( txtNode ); removeFillData( this.document, txtNode ); mergSibling( txtNode, 'previousSibling' ); mergSibling( txtNode, 'nextSibling' ); fillData = txtNode; this.setStart( txtNode, browser.webkit ? 1 : 0 ).collapse( true ); } } var nativeRange = this.document.createRange(); nativeRange.setStart( this.startContainer, this.startOffset ); nativeRange.setEnd( this.endContainer, this.endOffset ); sel.addRange( nativeRange ); } return this; }, /** * 滚动到可视范围 * @public * @function * @name baidu.editor.dom.Range.scrollToView * @param {Boolean} win 操作的window对象,若为空,则使用当前的window对象 * @param {Number} offset 滚动的偏移量 * @return {Range} Range对象 */ scrollToView:function ( win, offset ) { win = win ? window : domUtils.getWindow( this.document ); var span = this.document.createElement( 'span' ); //trace:717 span.innerHTML = ' '; var tmpRange = this.cloneRange(); tmpRange.insertNode( span ); domUtils.scrollToView( span, win, offset ); domUtils.remove( span ); return this; } }; })(); ///import editor.js ///import core/browser.js ///import core/dom/dom.js ///import core/dom/dtd.js ///import core/dom/domUtils.js ///import core/dom/Range.js /** * @class baidu.editor.dom.Selection Selection类 */ (function () { function getBoundaryInformation( range, start ) { var getIndex = domUtils.getNodeIndex; range = range.duplicate(); range.collapse( start ); var parent = range.parentElement(); //如果节点里没有子节点,直接退出 if ( !parent.hasChildNodes() ) { return {container:parent, offset:0}; } var siblings = parent.children, child, testRange = range.duplicate(), startIndex = 0, endIndex = siblings.length - 1, index = -1, distance; while ( startIndex <= endIndex ) { index = Math.floor( (startIndex + endIndex) / 2 ); child = siblings[index]; testRange.moveToElementText( child ); var position = testRange.compareEndPoints( 'StartToStart', range ); if ( position > 0 ) { endIndex = index - 1; } else if ( position < 0 ) { startIndex = index + 1; } else { //trace:1043 return {container:parent, offset:getIndex( child )}; } } if ( index == -1 ) { testRange.moveToElementText( parent ); testRange.setEndPoint( 'StartToStart', range ); distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length; siblings = parent.childNodes; if ( !distance ) { child = siblings[siblings.length - 1]; return {container:child, offset:child.nodeValue.length}; } var i = siblings.length; while ( distance > 0 ){ distance -= siblings[ --i ].nodeValue.length; } return {container:siblings[i], offset:-distance}; } testRange.collapse( position > 0 ); testRange.setEndPoint( position > 0 ? 'StartToStart' : 'EndToStart', range ); distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length; if ( !distance ) { return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName] ? {container:parent, offset:getIndex( child ) + (position > 0 ? 0 : 1)} : {container:child, offset:position > 0 ? 0 : child.childNodes.length} } while ( distance > 0 ) { try { var pre = child; child = child[position > 0 ? 'previousSibling' : 'nextSibling']; distance -= child.nodeValue.length; } catch ( e ) { return {container:parent, offset:getIndex( pre )}; } } return {container:child, offset:position > 0 ? -distance : child.nodeValue.length + distance} } /** * 将ieRange转换为Range对象 * @param {Range} ieRange ieRange对象 * @param {Range} range Range对象 * @return {Range} range 返回转换后的Range对象 */ function transformIERangeToRange( ieRange, range ) { if ( ieRange.item ) { range.selectNode( ieRange.item( 0 ) ); } else { var bi = getBoundaryInformation( ieRange, true ); range.setStart( bi.container, bi.offset ); if ( ieRange.compareEndPoints( 'StartToEnd', ieRange ) != 0 ) { bi = getBoundaryInformation( ieRange, false ); range.setEnd( bi.container, bi.offset ); } } return range; } /** * 获得ieRange * @param {Selection} sel Selection对象 * @return {ieRange} 得到ieRange */ function _getIERange( sel ) { var ieRange; //ie下有可能报错 try { ieRange = sel.getNative().createRange(); } catch ( e ) { return null; } var el = ieRange.item ? ieRange.item( 0 ) : ieRange.parentElement(); if ( ( el.ownerDocument || el ) === sel.document ) { return ieRange; } return null; } var Selection = dom.Selection = function ( doc ) { var me = this, iframe; me.document = doc; if ( ie ) { iframe = domUtils.getWindow( doc ).frameElement; domUtils.on( iframe, 'beforedeactivate', function () { me._bakIERange = me.getIERange(); } ); domUtils.on( iframe, 'activate', function () { try { if ( !_getIERange( me ) && me._bakIERange ) { me._bakIERange.select(); } } catch ( ex ) { } me._bakIERange = null; } ); } iframe = doc = null; }; Selection.prototype = { /** * 获取原生seleciton对象 * @public * @function * @name baidu.editor.dom.Selection.getNative * @return {Selection} 获得selection对象 */ getNative:function () { var doc = this.document; try { return !doc ? null : ie ? doc.selection : domUtils.getWindow( doc ).getSelection(); } catch ( e ) { return null; } }, /** * 获得ieRange * @public * @function * @name baidu.editor.dom.Selection.getIERange * @return {ieRange} 返回ie原生的Range */ getIERange:function () { var ieRange = _getIERange( this ); if ( !ieRange ) { if ( this._bakIERange ) { return this._bakIERange; } } return ieRange; }, /** * 缓存当前选区的range和选区的开始节点 * @public * @function * @name baidu.editor.dom.Selection.cache */ cache:function () { this.clear(); this._cachedRange = this.getRange(); this._cachedStartElement = this.getStart(); this._cachedStartElementPath = this.getStartElementPath(); }, getStartElementPath:function () { if ( this._cachedStartElementPath ) { return this._cachedStartElementPath; } var start = this.getStart(); if ( start ) { return domUtils.findParents( start, true, null, true ) } return []; }, /** * 清空缓存 * @public * @function * @name baidu.editor.dom.Selection.clear */ clear:function () { this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null; }, /** * 编辑器是否得到了选区 */ isFocus:function () { try { return browser.ie && _getIERange( this ) || !browser.ie && this.getNative().rangeCount ? true : false; } catch ( e ) { return false; } }, /** * 获取选区对应的Range * @public * @function * @name baidu.editor.dom.Selection.getRange * @returns {baidu.editor.dom.Range} 得到Range对象 */ getRange:function () { var me = this; function optimze( range ) { var child = me.document.body.firstChild, collapsed = range.collapsed; while ( child && child.firstChild ) { range.setStart( child, 0 ); child = child.firstChild; } if ( !range.startContainer ) { range.setStart( me.document.body, 0 ) } if ( collapsed ) { range.collapse( true ); } } if ( me._cachedRange != null ) { return this._cachedRange; } var range = new baidu.editor.dom.Range( me.document ); if ( ie ) { var nativeRange = me.getIERange(); if ( nativeRange ) { transformIERangeToRange( nativeRange, range ); } else { optimze( range ); } } else { var sel = me.getNative(); if ( sel && sel.rangeCount ) { var firstRange = sel.getRangeAt( 0 ); var lastRange = sel.getRangeAt( sel.rangeCount - 1 ); range.setStart( firstRange.startContainer, firstRange.startOffset ).setEnd( lastRange.endContainer, lastRange.endOffset ); if ( range.collapsed && domUtils.isBody( range.startContainer ) && !range.startOffset ) { optimze( range ); } } else { //trace:1734 有可能已经不在dom树上了,标识的节点 if ( this._bakRange && domUtils.inDoc( this._bakRange.startContainer, this.document ) ){ return this._bakRange; } optimze( range ); } } return this._bakRange = range; }, /** * 获取开始元素,用于状态反射 * @public * @function * @name baidu.editor.dom.Selection.getStart * @return {Element} 获得开始元素 */ getStart:function () { if ( this._cachedStartElement ) { return this._cachedStartElement; } var range = ie ? this.getIERange() : this.getRange(), tmpRange, start, tmp, parent; if ( ie ) { if ( !range ) { //todo 给第一个值可能会有问题 return this.document.body.firstChild; } //control元素 if ( range.item ){ return range.item( 0 ); } tmpRange = range.duplicate(); //修正ie下x[xx] 闭合后 x|xx tmpRange.text.length > 0 && tmpRange.moveStart( 'character', 1 ); tmpRange.collapse( 1 ); start = tmpRange.parentElement(); parent = tmp = range.parentElement(); while ( tmp = tmp.parentNode ) { if ( tmp == start ) { start = parent; break; } } } else { range.shrinkBoundary(); start = range.startContainer; if ( start.nodeType == 1 && start.hasChildNodes() ){ start = start.childNodes[Math.min( start.childNodes.length - 1, range.startOffset )]; } if ( start.nodeType == 3 ){ return start.parentNode; } } return start; }, /** * 得到选区中的文本 * @public * @function * @name baidu.editor.dom.Selection.getText * @return {String} 选区中包含的文本 */ getText:function () { var nativeSel, nativeRange; if ( this.isFocus() && (nativeSel = this.getNative()) ) { nativeRange = browser.ie ? nativeSel.createRange() : nativeSel.getRangeAt( 0 ); return browser.ie ? nativeRange.text : nativeRange.toString(); } return ''; } }; })(); ///import editor.js ///import core/utils.js ///import core/EventBase.js ///import core/browser.js ///import core/dom/dom.js ///import core/dom/domUtils.js ///import core/dom/Selection.js ///import core/dom/dtd.js (function () { var uid = 0, _selectionChangeTimer; function replaceSrc( div ) { var imgs = div.getElementsByTagName( "img" ), orgSrc; for ( var i = 0, img; img = imgs[i++]; ) { if ( orgSrc = img.getAttribute( "orgSrc" ) ) { img.src = orgSrc; img.removeAttribute( "orgSrc" ); } } var as = div.getElementsByTagName( "a" ); for ( var i = 0, ai; ai = as[i++]; i++ ) { if ( ai.getAttribute( 'data_ue_src' ) ) { ai.setAttribute( 'href', ai.getAttribute( 'data_ue_src' ) ) } } } function setValue( form, editor ) { var textarea; if ( editor.textarea ) { if ( utils.isString( editor.textarea ) ) { for ( var i = 0, ti, tis = domUtils.getElementsByTagName( form, 'textarea' ); ti = tis[i++]; ) { if ( ti.id == 'ueditor_textarea_' + editor.options.textarea ) { textarea = ti; break; } } } else { textarea = editor.textarea; } } if ( !textarea ) { form.appendChild( textarea = domUtils.creElm( document, 'textarea', { 'name':editor.options.textarea, 'id':'ueditor_textarea_' + editor.options.textarea, 'style':"display:none" } ) ); } textarea.value = editor.options.allHtmlEnabled ? editor.getAllHtml() : editor.getContent(null,null,true) } /** * 编辑器类 * @public * @class * @extends baidu.editor.EventBase * @name baidu.editor.Editor * @param {Object} options */ var Editor = UE.Editor = function ( options ) { var me = this; me.uid = uid++; EventBase.call( me ); me.commands = {}; me.options = utils.extend( options || {},UEDITOR_CONFIG, true ); //设置默认的常用属性 me.setOpt( { isShow:true, initialContent:'欢迎使用ueditor!', autoClearinitialContent:false, iframeCssUrl:me.options.UEDITOR_HOME_URL + '/themes/default/iframe.css', textarea:'editorValue', focus:false, minFrameHeight:320, autoClearEmptyNode:true, fullscreen:false, readonly:false, zIndex:999, imagePopup:true, enterTag:'p', pageBreakTag:'_baidu_page_break_tag_', customDomain:false, lang:'zh-cn', langPath:me.options.UEDITOR_HOME_URL + 'lang/', allHtmlEnabled:false } ); utils.loadFile( document, { src:me.options.langPath + me.options.lang + "/" + me.options.lang + ".js", tag:"script", type:"text/javascript", defer:"defer" }, function () { //初始化插件 for ( var pi in UE.plugins ) { UE.plugins[pi].call( me ) } me.langIsReady = true; me.fireEvent( "langReady" ); } ); UE.instants['ueditorInstant' + me.uid] = me; }; Editor.prototype = /**@lends baidu.editor.Editor.prototype*/{ /** * 当编辑器ready后执行传入的fn,如果编辑器已经ready好了,就马上执行fn,fn的中的this是编辑器实例 * @param {function} fn 需要执行的函数 */ ready:function ( fn ) { var me = this; if ( fn ) me.isReady ? fn.apply( me ) : me.addListener( 'ready', fn ); }, setOpt:function ( key, val ) { var obj = {}; if ( utils.isString( key ) ) { obj[key] = val } else { obj = key; } utils.extend( this.options, obj, true ); }, destroy:function () { var me = this; me.fireEvent( 'destroy' ); me.container.innerHTML = ''; domUtils.remove( me.container ); //trace:2004 for ( var p in me ) { if ( me.hasOwnProperty( p ) ) { delete this[p]; } } }, /** * 渲染编辑器的DOM到指定容器,必须且只能调用一次 * @public * @function * @param {Element|String} container */ render:function ( container ) { var me = this, options = me.options; if ( container.constructor === String ) { container = document.getElementById( container ); } if ( container ) { var useBodyAsViewport = ie && browser.version < 9, html = ( ie && browser.version < 9 ? '' : '') + '' + ( options.iframeCssUrl ? '' : '' ) + ''; if ( options.customDomain && document.domain != location.hostname ) { html += ''; container.appendChild( domUtils.creElm( document, 'iframe', { id:'baidu_editor_' + me.uid, width:"100%", height:"100%", frameborder:"0", src:'javascript:void(function(){document.open();document.domain="' + document.domain + '";' + 'document.write("' + html + '");document.close();}())' } ) ); } else { container.innerHTML = ''; var doc = container.firstChild.contentWindow.document; !browser.webkit && doc.open(); doc.write( html + '' ); !browser.webkit && doc.close(); me._setup( doc ); } container.style.overflow = 'hidden'; } }, _setup:function ( doc ) { var me = this, options = me.options; if ( ie ) { doc.body.disabled = true; doc.body.contentEditable = true; doc.body.disabled = false; } else { doc.body.contentEditable = true; doc.body.spellcheck = false; } me.document = doc; me.window = doc.defaultView || doc.parentWindow; me.iframe = me.window.frameElement; me.body = doc.body; //设置编辑器最小高度 me.setHeight( options.minFrameHeight ); me.selection = new dom.Selection( doc ); //gecko初始化就能得到range,无法判断isFocus了 var geckoSel; if ( browser.gecko && (geckoSel = this.selection.getNative()) ) { geckoSel.removeAllRanges(); } this._initEvents(); if ( options.initialContent ) { if ( options.autoClearinitialContent ) { var oldExecCommand = me.execCommand; me.execCommand = function () { me.fireEvent( 'firstBeforeExecCommand' ); oldExecCommand.apply( me, arguments ); }; this.setDefaultContent( options.initialContent ); } else this.setContent( options.initialContent, true ); } //为form提交提供一个隐藏的textarea for ( var form = this.iframe.parentNode; !domUtils.isBody( form ); form = form.parentNode ) { if ( form.tagName == 'FORM' ) { domUtils.on( form, 'submit', function () { setValue( this, me ); } ); break; } } //编辑器不能为空内容 if ( domUtils.isEmptyNode( me.body ) ) { me.body.innerHTML = '

' + (browser.ie ? '' : '
') + '

'; } //如果要求focus, 就把光标定位到内容开始 if ( options.focus ) { setTimeout( function () { me.focus(); //如果自动清除开着,就不需要做selectionchange; !me.options.autoClearinitialContent && me._selectionChange(); } ); } if ( !me.container ) { me.container = this.iframe.parentNode; } if ( options.fullscreen && me.ui ) { me.ui.setFullScreen( true ); } me.isReady = 1; me.fireEvent( 'ready' ); if ( !browser.ie ) { domUtils.on( me.window, ['blur', 'focus'], function ( e ) { //chrome下会出现alt+tab切换时,导致选区位置不对 if ( e.type == 'blur' ) { me._bakRange = me.selection.getRange(); try{ me.selection.getNative().removeAllRanges(); }catch(e){} } else { try { me._bakRange && me._bakRange.select(); } catch ( e ) { } } } ); } //trace:1518 ff3.6body不够寛,会导致点击空白处无法获得焦点 if ( browser.gecko && browser.version <= 10902 ) { //修复ff3.6初始化进来,不能点击获得焦点 me.body.contentEditable = false; setTimeout( function () { me.body.contentEditable = true; }, 100 ); setInterval( function () { me.body.style.height = me.iframe.offsetHeight - 20 + 'px' }, 100 ) } !options.isShow && me.setHide(); options.readonly && me.setDisabled(); }, /** * 创建textarea,同步编辑的内容到textarea,为后台获取内容做准备 * @param formId 制定在那个form下添加 * @public * @function */ sync:function ( formId ) { var me = this, form = formId ? document.getElementById( formId ) : domUtils.findParent( me.iframe.parentNode, function ( node ) { return node.tagName == 'FORM' }, true ); form && setValue( form, me ); }, /** * 设置编辑器高度 * @public * @function * @param {Number} height 高度 */ setHeight:function ( height ) { if ( height !== parseInt( this.iframe.parentNode.style.height ) ) { this.iframe.parentNode.style.height = height + 'px'; } this.document.body.style.height = height - 20 + 'px'; }, /** * 获取编辑器内容 * @public * @function * @returns {String} */ getContent:function ( cmd, fn, isPreview ) { var me = this; if ( cmd && utils.isFunction( cmd ) ) { fn = cmd; cmd = ''; } if ( fn ? !fn() : !this.hasContents() ) { return ''; } me.fireEvent( 'beforegetcontent', cmd ); var reg = new RegExp( domUtils.fillChar, 'g' ), //ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除 html = me.body.innerHTML.replace( reg, '' ).replace( />[\t\r\n]*?<' ); me.fireEvent( 'aftergetcontent', cmd ); if ( me.serialize ) { var node = me.serialize.parseHTML( html ); node = me.serialize.transformOutput( node ); html = me.serialize.toHTML( node ); } if ( ie && isPreview ) { //trace:2471 //两个br会导致空行,所以这里先注视掉 html = html//.replace(/<\s*br\s*\/?\s*>/gi,'

') .replace( /

\s*?<\/p>/g, '

 

' ); } else { //多个 要转换成空格加 的形式,要不预览时会所成一个 html = html.replace( /( )+/g, function ( s ) { for ( var i = 0, str = [], l = s.split( ';' ).length - 1; i < l; i++ ) { str.push( i % 2 == 0 ? ' ' : ' ' ); } return str.join( '' ); } ); } return html; }, getAllHtml:function () { var me = this, headHtml = {html:''}, html = ''; me.fireEvent( 'getAllHtml', headHtml ); return '' + (me.options.charset ? '' : '') + me.document.getElementsByTagName( 'head' )[0].innerHTML + headHtml.html + '' + '' + me.getContent( null, null, true ) + ''; }, /** * 得到编辑器的纯文本内容,但会保留段落格式 * @public * @function * @returns {String} */ getPlainTxt:function () { var reg = new RegExp( domUtils.fillChar, 'g' ), html = this.body.innerHTML.replace( /[\n\r]/g, '' );//ie要先去了\n在处理 html = html.replace( /<(p|div)[^>]*>(| )<\/\1>/gi, '\n' ) .replace( //gi, '\n' ) .replace( /<[^>/]+>/g, '' ) .replace( /(\n)?<\/([^>]+)>/g, function ( a, b, c ) { return dtd.$block[c] ? '\n' : b ? b : ''; } ); //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0 return html.replace( reg, '' ).replace( /\u00a0/g, ' ' ).replace( / /g, ' ' ); }, /** * 获取编辑器中的文本内容 * @public * @function * @returns {String} */ getContentTxt:function () { var reg = new RegExp( domUtils.fillChar, 'g' ); //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0 return this.body[browser.ie ? 'innerText' : 'textContent'].replace( reg, '' ).replace( /\u00a0/g, ' ' ); }, /** * 设置编辑器内容 * @public * @function * @param {String} html */ setContent:function ( html, notFireSelectionchange ) { var me = this, inline = utils.extend( {a:1, A:1}, dtd.$inline, true ), lastTagName; html = html .replace( /^[ \t\r\n]*?[ \t\r\n]*?$/, '>' ) .replace( />[\t\r\n]*?<' )//代码高量的\n不能去除 .replace( /[\s\/]?(\w+)?>[ \t\r\n]*?<\/?(\w+)/gi, function ( a, b, c ) { if ( b ) { lastTagName = c; } else { b = lastTagName; } return !inline[b] && !inline[c] ? a.replace( />[ \t\r\n]*?<' ) : a; } ); me.fireEvent( 'beforesetcontent' ); var serialize = this.serialize; if ( serialize ) { var node = serialize.parseHTML( html ); node = serialize.transformInput( node ); node = serialize.filter( node ); html = serialize.toHTML( node ); } //html.replace(new RegExp('[\t\n\r' + domUtils.fillChar + ']*','g'),''); //去掉了\t\n\r 如果有插入的代码,在源码切换所见即所得模式时,换行都丢掉了 //\r在ie下的不可见字符,在源码切换时会变成多个  //trace:1559 this.body.innerHTML = html.replace( new RegExp( '[\r' + domUtils.fillChar + ']*', 'g' ), '' ); //处理ie6下innerHTML自动将相对路径转化成绝对路径的问题 if ( browser.ie && browser.version < 7 ) { replaceSrc( this.document.body ); } //给文本或者inline节点套p标签 if ( me.options.enterTag == 'p' ) { var child = this.body.firstChild, tmpNode; if ( !child || child.nodeType == 1 && (dtd.$cdata[child.tagName] || domUtils.isCustomeNode( child ) ) && child === this.body.lastChild ) { this.body.innerHTML = '

' + (browser.ie ? ' ' : '
') + '

' + this.body.innerHTML; } else { var p = me.document.createElement( 'p' ); while ( child ) { while ( child && (child.nodeType == 3 || child.nodeType == 1 && dtd.p[child.tagName] && !dtd.$cdata[child.tagName]) ) { tmpNode = child.nextSibling; p.appendChild( child ); child = tmpNode; } if ( p.firstChild ) { if ( !child ) { me.body.appendChild( p ); break; } else { me.body.insertBefore( p, child ); p = me.document.createElement( 'p' ); } } child = child.nextSibling; } } } me.adjustTable && me.adjustTable( me.body ); me.fireEvent( 'aftersetcontent' ); me.fireEvent( 'contentchange' ); !notFireSelectionchange && me._selectionChange(); //清除保存的选区 me._bakRange = me._bakIERange = null; //trace:1742 setContent后gecko能得到焦点问题 var geckoSel; if ( browser.gecko && (geckoSel = this.selection.getNative()) ) { geckoSel.removeAllRanges(); } }, /** * 让编辑器获得焦点 * @public * @function * @param{boolean}toEnd 默认是到头部,true到尾部 */ focus:function ( toEnd ) { try { var me = this, rng = me.selection.getRange(); if ( toEnd ) { rng.setStartAtLast( me.body.lastChild ).setCursor( false, true ); } else { rng.select( true ); } } catch ( e ) { } }, /** * 初始化事件,绑定selectionchange * @private * @function */ _initEvents:function () { var me = this, doc = me.document, win = me.window; me._proxyDomEvent = utils.bind( me._proxyDomEvent, me ); domUtils.on( doc, ['click', 'contextmenu', 'mousedown', 'keydown', 'keyup', 'keypress', 'mouseup', 'mouseover', 'mouseout', 'selectstart'], me._proxyDomEvent ); domUtils.on( win, ['focus', 'blur'], me._proxyDomEvent ); domUtils.on( doc, ['mouseup', 'keydown'], function ( evt ) { //特殊键不触发selectionchange if ( evt.type == 'keydown' && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey) ) { return; } if ( evt.button == 2 )return; me._selectionChange( 250, evt ); } ); //处理拖拽 //ie ff不能从外边拖入 //chrome只针对从外边拖入的内容过滤 var innerDrag = 0, source = browser.ie ? me.body : me.document, dragoverHandler; domUtils.on( source, 'dragstart', function () { innerDrag = 1; } ); domUtils.on( source, browser.webkit ? 'dragover' : 'drop', function () { return browser.webkit ? function () { clearTimeout( dragoverHandler ); dragoverHandler = setTimeout( function () { if ( !innerDrag ) { var sel = me.selection, range = sel.getRange(); if ( range ) { var common = range.getCommonAncestor(); if ( common && me.serialize ) { var f = me.serialize, node = f.filter( f.transformInput( f.parseHTML( f.word( common.innerHTML ) ) ) ); common.innerHTML = f.toHTML( node ); } } } innerDrag = 0; }, 200 ); } : function ( e ) { if ( !innerDrag ) { e.preventDefault ? e.preventDefault() : (e.returnValue = false); } innerDrag = 0; } }() ); }, _proxyDomEvent:function ( evt ) { return this.fireEvent( evt.type.replace( /^on/, '' ), evt ); }, _selectionChange:function ( delay, evt ) { var me = this; //有光标才做selectionchange 为了解决未focus时点击source不能触发更改工具栏状态的问题(source命令notNeedUndo=1) // if ( !me.selection.isFocus() ){ // return; // } var hackForMouseUp = false; var mouseX, mouseY; if ( browser.ie && browser.version < 9 && evt && evt.type == 'mouseup' ) { var range = this.selection.getRange(); if ( !range.collapsed ) { hackForMouseUp = true; mouseX = evt.clientX; mouseY = evt.clientY; } } clearTimeout( _selectionChangeTimer ); _selectionChangeTimer = setTimeout( function () { if ( !me.selection.getNative() ) { return; } //修复一个IE下的bug: 鼠标点击一段已选择的文本中间时,可能在mouseup后的一段时间内取到的range是在selection的type为None下的错误值. //IE下如果用户是拖拽一段已选择文本,则不会触发mouseup事件,所以这里的特殊处理不会对其有影响 var ieRange; if ( hackForMouseUp && me.selection.getNative().type == 'None' ) { ieRange = me.document.body.createTextRange(); try { ieRange.moveToPoint( mouseX, mouseY ); } catch ( ex ) { ieRange = null; } } var bakGetIERange; if ( ieRange ) { bakGetIERange = me.selection.getIERange; me.selection.getIERange = function () { return ieRange; }; } me.selection.cache(); if ( bakGetIERange ) { me.selection.getIERange = bakGetIERange; } if ( me.selection._cachedRange && me.selection._cachedStartElement ) { me.fireEvent( 'beforeselectionchange' ); // 第二个参数causeByUi为true代表由用户交互造成的selectionchange. me.fireEvent( 'selectionchange', !!evt ); me.fireEvent( 'afterselectionchange' ); me.selection.clear(); } }, delay || 50 ); }, _callCmdFn:function ( fnName, args ) { var cmdName = args[0].toLowerCase(), cmd, cmdFn; cmd = this.commands[cmdName] || UE.commands[cmdName]; cmdFn = cmd && cmd[fnName]; //没有querycommandstate或者没有command的都默认返回0 if ( (!cmd || !cmdFn) && fnName == 'queryCommandState' ) { return 0; } else if ( cmdFn ) { return cmdFn.apply( this, args ); } }, /** * 执行命令 * @public * @function * @param {String} cmdName 执行的命令名 * */ execCommand:function ( cmdName ) { cmdName = cmdName.toLowerCase(); var me = this, result, cmd = me.commands[cmdName] || UE.commands[cmdName]; if ( !cmd || !cmd.execCommand ) { return; } if ( !cmd.notNeedUndo && !me.__hasEnterExecCommand ) { me.__hasEnterExecCommand = true; if ( me.queryCommandState( cmdName ) != -1 ) { me.fireEvent( 'beforeexeccommand', cmdName ); result = this._callCmdFn( 'execCommand', arguments ); me.fireEvent( 'afterexeccommand', cmdName ); } me.__hasEnterExecCommand = false; } else { result = this._callCmdFn( 'execCommand', arguments ); } me._selectionChange(); return result; }, /** * 查询命令的状态 * @public * @function * @param {String} cmdName 执行的命令名 * @returns {Number|*} -1 : disabled, false : normal, true : enabled. * */ queryCommandState:function ( cmdName ) { return this._callCmdFn( 'queryCommandState', arguments ); }, /** * 查询命令的值 * @public * @function * @param {String} cmdName 执行的命令名 * @returns {*} */ queryCommandValue:function ( cmdName ) { return this._callCmdFn( 'queryCommandValue', arguments ); }, /** * 检查编辑区域中是否有内容 * @public * @params{Array} 自定义的标签 * @function * @returns {Boolean} true 有,false 没有 */ hasContents:function ( tags ) { if ( tags ) { for ( var i = 0, ci; ci = tags[i++]; ) { if ( this.document.getElementsByTagName( ci ).length > 0 ) { return true; } } } if ( !domUtils.isEmptyBlock( this.body ) ) { return true } //随时添加,定义的特殊标签如果存在,不能认为是空 tags = ['div']; for ( i = 0; ci = tags[i++]; ) { var nodes = domUtils.getElementsByTagName( this.document, ci ); for ( var n = 0, cn; cn = nodes[n++]; ) { if ( domUtils.isCustomeNode( cn ) ) { return true; } } } return false; }, /** * 从新设置 * @public * @function */ reset:function () { this.fireEvent( 'reset' ); }, /** * 设置编辑区域可以编辑 */ setEnabled:function () { var me = this, range; if ( me.body.contentEditable == 'false' ) { me.body.contentEditable = true; range = me.selection.getRange(); //有可能内容丢失了 try { range.moveToBookmark( me.lastBk ); delete me.lastBk } catch ( e ) { range.setStartAtFirst( me.body ).collapse( true ) } range.select( true ); if ( me.bkqueryCommandState ) { me.queryCommandState = me.bkqueryCommandState; delete me.bkqueryCommandState; } me.fireEvent( 'selectionchange' ); } }, /** * 设置编辑区域不可以编辑 */ setDisabled:function ( exclude ) { var me = this; exclude = exclude ? utils.isArray( exclude ) ? exclude : [exclude] : []; if ( me.body.contentEditable == 'true' ) { if ( !me.lastBk ) { me.lastBk = me.selection.getRange().createBookmark( true ); } me.body.contentEditable = false; me.bkqueryCommandState = me.queryCommandState; me.queryCommandState = function ( type ) { if ( utils.indexOf( exclude, type ) != -1 ) { return me.bkqueryCommandState.apply( me, arguments ); } return -1; }; me.fireEvent( 'selectionchange' ); } }, /** * 设置默认内容 * @function * @param {String} cont 要存入的内容 */ setDefaultContent:function () { function clear() { var me = this; if ( me.document.getElementById( 'initContent' ) ) { me.document.body.innerHTML = '

' + (ie ? '' : '
') + '

'; var range = me.selection.getRange(); me.removeListener( 'firstBeforeExecCommand', clear ); me.removeListener( 'focus', clear ); setTimeout( function () { range.setStart( me.document.body.firstChild, 0 ).collapse( true ).select( true ); me._selectionChange(); } ) } } return function ( cont ) { var me = this; me.document.body.innerHTML = '

' + cont + '

'; if ( browser.ie && browser.version < 7 ) { replaceSrc( me.document.body ); } me.addListener( 'firstBeforeExecCommand', clear ); me.addListener( 'focus', clear ); } }(), /** * 设置编辑器显示 * @function */ setShow:function () { var me = this, range = me.selection.getRange(); if ( me.container.style.display == 'none' ) { //有可能内容丢失了 try { range.moveToBookmark( me.lastBk ); delete me.lastBk } catch ( e ) { range.setStartAtFirst( me.body ).collapse( true ) } range.select( true ); me.container.style.display = ''; } }, /** * 设置编辑器隐藏 * @function */ setHide:function () { var me = this; if ( !me.lastBk ) { me.lastBk = me.selection.getRange().createBookmark( true ); } me.container.style.display = 'none' }, getLang:function ( path ) { var lang = UE.I18N[this.options.lang]; path = (path || "").split( "." ); for ( var i = 0, ci; ci = path[i++]; ) { lang = lang[ci]; if ( !lang )break; } return lang; } }; utils.inherits( Editor, EventBase ); })(); /** * Created by . * User: taoqili * Date: 11-8-18 * Time: 下午3:18 * To change this template use File | Settings | File Templates. */ /** * ajax工具类 */ UE.ajax = function() { return { /** * 向url发送ajax请求 * @param url * @param ajaxOptions */ request:function(url, ajaxOptions) { var ajaxRequest = creatAjaxRequest(), //是否超时 timeIsOut = false, //默认参数 defaultAjaxOptions = { method:"POST", timeout:5000, async:true, data:{},//需要传递对象的话只能覆盖 onsuccess:function() { }, onerror:function() { } }; if (typeof url === "object") { ajaxOptions = url; url = ajaxOptions.url; } if (!ajaxRequest || !url) return; var ajaxOpts = ajaxOptions ? utils.extend(defaultAjaxOptions,ajaxOptions) : defaultAjaxOptions; var submitStr = json2str(ajaxOpts); // { name:"Jim",city:"Beijing" } --> "name=Jim&city=Beijing" //如果用户直接通过data参数传递json对象过来,则也要将此json对象转化为字符串 if (!utils.isEmptyObject(ajaxOpts.data)){ submitStr += (submitStr? "&":"") + json2str(ajaxOpts.data); } //超时检测 var timerID = setTimeout(function() { if (ajaxRequest.readyState != 4) { timeIsOut = true; ajaxRequest.abort(); clearTimeout(timerID); } }, ajaxOpts.timeout); var method = ajaxOpts.method.toUpperCase(); var str = url + (url.indexOf("?")==-1?"?":"&") + (method=="POST"?"":submitStr+ "&noCache=" + +new Date); ajaxRequest.open(method, str, ajaxOpts.async); ajaxRequest.onreadystatechange = function() { if (ajaxRequest.readyState == 4) { if (!timeIsOut && ajaxRequest.status == 200) { ajaxOpts.onsuccess(ajaxRequest); } else { ajaxOpts.onerror(ajaxRequest); } } }; if (method == "POST") { ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); ajaxRequest.send(submitStr); } else { ajaxRequest.send(null); } } }; /** * 将json参数转化成适合ajax提交的参数列表 * @param json */ function json2str(json) { var strArr = []; for (var i in json) { //忽略默认的几个参数 if(i=="method" || i=="timeout" || i=="async") continue; //传递过来的对象和函数不在提交之列 if (!((typeof json[i]).toLowerCase() == "function" || (typeof json[i]).toLowerCase() == "object")) { strArr.push( encodeURIComponent(i) + "="+encodeURIComponent(json[i]) ); } } return strArr.join("&"); } /** * 创建一个ajaxRequest对象 */ function creatAjaxRequest() { var xmlHttp = null; if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } else { try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { } } } return xmlHttp; } }(); ///import core /** * @description 插入内容 * @name baidu.editor.execCommand * @param {String} cmdName inserthtml插入内容的命令 * @param {String} html 要插入的内容 * @author zhanyi */ UE.commands['inserthtml'] = { execCommand: function (command,html,notSerialize){ var me = this, range, div, tds = me.currentSelectedArr; range = me.selection.getRange(); div = range.document.createElement( 'div' ); div.style.display = 'inline'; var serialize = me.serialize; if (!notSerialize && serialize) { var node = serialize.parseHTML(html); node = serialize.transformInput(node); node = serialize.filter(node); html = serialize.toHTML(node); } div.innerHTML = utils.trim( html ); try{ me.adjustTable && me.adjustTable(div); }catch(e){} if(tds && tds.length){ for(var i=0,ti;ti=tds[i++];){ ti.className = ''; } tds[0].innerHTML = ''; range.setStart(tds[0],0).collapse(true); me.currentSelectedArr = []; } if ( !range.collapsed ) { range.deleteContents(); if(range.startContainer.nodeType == 1){ var child = range.startContainer.childNodes[range.startOffset],pre; if(child && domUtils.isBlockElm(child) && (pre = child.previousSibling) && domUtils.isBlockElm(pre)){ range.setEnd(pre,pre.childNodes.length).collapse(); while(child.firstChild){ pre.appendChild(child.firstChild); } domUtils.remove(child); } } } var child,parent,pre,tmp,hadBreak = 0; while ( child = div.firstChild ) { range.insertNode( child ); if ( !hadBreak && child.nodeType == domUtils.NODE_ELEMENT && domUtils.isBlockElm( child ) ){ parent = domUtils.findParent( child,function ( node ){ return domUtils.isBlockElm( node ); } ); if ( parent && parent.tagName.toLowerCase() != 'body' && !(dtd[parent.tagName][child.nodeName] && child.parentNode === parent)){ if(!dtd[parent.tagName][child.nodeName]){ pre = parent; }else{ tmp = child.parentNode; while (tmp !== parent){ pre = tmp; tmp = tmp.parentNode; } } domUtils.breakParent( child, pre || tmp ); //去掉break后前一个多余的节点

|<[p> ==>

|

var pre = child.previousSibling; domUtils.trimWhiteTextNode(pre); if(!pre.childNodes.length){ domUtils.remove(pre); } //trace:2012,在非ie的情况,切开后剩下的节点有可能不能点入光标添加br占位 if(!browser.ie && (next = child.nextSibling) && domUtils.isBlockElm(next) && next.lastChild && !domUtils.isBr(next.lastChild)){ next.appendChild(me.document.createElement('br')); } hadBreak = 1; } } var next = child.nextSibling; if(!div.firstChild && next && domUtils.isBlockElm(next)){ range.setStart(next,0).collapse(true); break; } range.setEndAfter( child ).collapse(); } child = range.startContainer; //用chrome可能有空白展位符 if(domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)){ child.innerHTML = browser.ie ? '' : '
'; } //加上true因为在删除表情等时会删两次,第一次是删的fillData range.select(true); setTimeout(function(){ range = me.selection.getRange(); range.scrollToView(me.autoHeightEnabled,me.autoHeightEnabled ? domUtils.getXY(me.iframe).y:0); },200); } }; ///import core ///commands 自动排版 ///commandsName autotypeset ///commandsTitle 自动排版 /** * 自动排版 * @function * @name baidu.editor.execCommands */ UE.plugins['autotypeset'] = function(){ this.setOpt({'autotypeset':{ mergeEmptyline : true, //合并空行 removeClass : true, //去掉冗余的class removeEmptyline : false, //去掉空行 textAlign : "left", //段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版 imageBlockLine : 'center', //图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版 pasteFilter : false, //根据规则过滤没事粘贴进来的内容 clearFontSize : false, //去掉所有的内嵌字号,使用编辑器默认的字号 clearFontFamily : false, //去掉所有的内嵌字体,使用编辑器默认的字体 removeEmptyNode : false, // 去掉空节点 //可以去掉的标签 removeTagNames : utils.extend({div:1},dtd.$removeEmpty), indent : false, // 行首缩进 indentValue : '2em' //行首缩进的大小 }}); var me = this, opt = me.options.autotypeset, remainClass = { 'selectTdClass':1, 'pagebreak':1, 'anchorclass':1 }, remainTag = { 'li':1 }, tags = { div:1, p:1, //trace:2183 这些也认为是行 blockquote:1,center:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1 }, highlightCont; //升级了版本,但配置项目里没有autotypeset if(!opt){ return; } function isLine(node,notEmpty){ if(node && node.parentNode && tags[node.tagName.toLowerCase()]){ if(highlightCont && highlightCont.contains(node) || node.getAttribute('pagebreak') ){ return 0; } return notEmpty ? !domUtils.isEmptyBlock(node) : domUtils.isEmptyBlock(node); } } function removeNotAttributeSpan(node){ if(!node.style.cssText){ domUtils.removeAttributes(node,['style']); if(node.tagName.toLowerCase() == 'span' && domUtils.hasNoAttributes(node)){ domUtils.remove(node,true); } } } function autotype(type,html){ var cont; if(html){ if(!opt.pasteFilter){ return; } cont = me.document.createElement('div'); cont.innerHTML = html.html; }else{ cont = me.document.body; } var nodes = domUtils.getElementsByTagName(cont,'*'); // 行首缩进,段落方向,段间距,段内间距 for(var i=0,ci;ci=nodes[i++];){ if(!highlightCont && ci.tagName == 'DIV' && ci.getAttribute('highlighter')){ highlightCont = ci; } //font-size if(opt.clearFontSize && ci.style.fontSize){ ci.style.fontSize = ''; removeNotAttributeSpan(ci); } //font-family if(opt.clearFontFamily && ci.style.fontFamily){ ci.style.fontFamily = ''; removeNotAttributeSpan(ci); } if(isLine(ci)){ //合并空行 if(opt.mergeEmptyline ){ var next = ci.nextSibling,tmpNode; while(isLine(next)){ tmpNode = next; next = tmpNode.nextSibling; domUtils.remove(tmpNode); } } //去掉空行,保留占位的空行 if(opt.removeEmptyline && domUtils.inDoc(ci,cont) && !remainTag[ci.parentNode.tagName.toLowerCase()] ){ domUtils.remove(ci); continue; } } if(isLine(ci,true) ){ if(opt.indent){ ci.style.textIndent = opt.indentValue; } if(opt.textAlign){ ci.style.textAlign = opt.textAlign; } // if(opt.lineHeight) // ci.style.lineHeight = opt.lineHeight + 'cm'; } //去掉class,保留的class不去掉 if(opt.removeClass && ci.className && !remainClass[ci.className.toLowerCase()]){ if(highlightCont && highlightCont.contains(ci)){ continue; } domUtils.removeAttributes(ci,['class']); } //表情不处理 if(opt.imageBlockLine && ci.tagName.toLowerCase() == 'img' && !ci.getAttribute('emotion')){ if(html){ var img = ci; switch (opt.imageBlockLine){ case 'left': case 'right': case 'none': var pN = img.parentNode,tmpNode,pre,next; while(dtd.$inline[pN.tagName] || pN.tagName == 'A'){ pN = pN.parentNode; } tmpNode = pN; if(tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode,'text-align') == 'center'){ if(!domUtils.isBody(tmpNode) && domUtils.getChildCount(tmpNode,function(node){return !domUtils.isBr(node) && !domUtils.isWhitespace(node)}) == 1){ pre = tmpNode.previousSibling; next = tmpNode.nextSibling; if(pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm(pre)){ pre.appendChild(tmpNode.firstChild); while(next.firstChild){ pre.appendChild(next.firstChild); } domUtils.remove(tmpNode); domUtils.remove(next); }else{ domUtils.setStyle(tmpNode,'text-align',''); } } } domUtils.setStyle(img,'float',opt.imageBlockLine); break; case 'center': if(me.queryCommandValue('imagefloat') != 'center'){ pN = img.parentNode; domUtils.setStyle(img,'float','none'); tmpNode = img; while(pN && domUtils.getChildCount(pN,function(node){return !domUtils.isBr(node) && !domUtils.isWhitespace(node)}) == 1 && (dtd.$inline[pN.tagName] || pN.tagName == 'A')){ tmpNode = pN; pN = pN.parentNode; } var pNode = me.document.createElement('p'); domUtils.setAttributes(pNode,{ style:'text-align:center' }); tmpNode.parentNode.insertBefore(pNode,tmpNode); pNode.appendChild(tmpNode); domUtils.setStyle(tmpNode,'float',''); } } }else{ var range = me.selection.getRange(); range.selectNode(ci).select(); me.execCommand('imagefloat',opt.imageBlockLine); } } //去掉冗余的标签 if(opt.removeEmptyNode){ if(opt.removeTagNames[ci.tagName.toLowerCase()] && domUtils.hasNoAttributes(ci) && domUtils.isEmptyBlock(ci)){ domUtils.remove(ci); } } } if(html){ html.html = cont.innerHTML; } } if(opt.pasteFilter){ me.addListener('beforepaste',autotype); } me.commands['autotypeset'] = { execCommand:function () { me.removeListener('beforepaste',autotype); if(opt.pasteFilter){ me.addListener('beforepaste',autotype); } autotype(); } }; }; UE.commands['autosubmit'] = { execCommand:function () { var me=this, form = domUtils.findParentByTagName(me.iframe,"form", false); if (form) { if(me.fireEvent("beforesubmit")===false){ return; } me.sync(); form.submit(); } } }; (function() { UE.plugins['background'] = function(){ var me = this; UE.commands['background'] = { queryCommandState : function(){ return this.highlight ? -1 : 0; } }; me.addListener("getAllHtml",function(type,headHtml){ var body = this.body, su = domUtils.getComputedStyle(body,"background-image"), url=""; if(su.indexOf(me.options.imagePath)>0){ url = su.substring(su.indexOf(me.options.imagePath),su.length-1).replace(/"|\(|\)/ig,""); }else{ url = su!="none" ? su.replace(/url\("?|"?\)/ig,""):""; } headHtml.html = ' '; }); } })(); ///import core ///import plugins\inserthtml.js ///import plugins\catchremoteimage.js ///commands 插入图片,操作图片的对齐方式 ///commandsName InsertImage,ImageNone,ImageLeft,ImageRight,ImageCenter ///commandsTitle 图片,默认,居左,居右,居中 ///commandsDialog dialogs\image\image.html /** * Created by . * User: zhanyi * for image */ UE.commands['imagefloat'] = { execCommand:function ( cmd, align ) { var me = this, range = me.selection.getRange(); if ( !range.collapsed ) { var img = range.getClosedNode(); if ( img && img.tagName == 'IMG' ) { switch ( align ) { case 'left': case 'right': case 'none': var pN = img.parentNode, tmpNode, pre, next; while ( dtd.$inline[pN.tagName] || pN.tagName == 'A' ) { pN = pN.parentNode; } tmpNode = pN; if ( tmpNode.tagName == 'P' && domUtils.getStyle( tmpNode, 'text-align' ) == 'center' ) { if ( !domUtils.isBody( tmpNode ) && domUtils.getChildCount( tmpNode, function ( node ) { return !domUtils.isBr( node ) && !domUtils.isWhitespace( node ); } ) == 1 ) { pre = tmpNode.previousSibling; next = tmpNode.nextSibling; if ( pre && next && pre.nodeType == 1 && next.nodeType == 1 && pre.tagName == next.tagName && domUtils.isBlockElm( pre ) ) { pre.appendChild( tmpNode.firstChild ); while ( next.firstChild ) { pre.appendChild( next.firstChild ); } domUtils.remove( tmpNode ); domUtils.remove( next ); } else { domUtils.setStyle( tmpNode, 'text-align', '' ); } } range.selectNode( img ).select(); } domUtils.setStyle( img, 'float', align ); break; case 'center': if ( me.queryCommandValue( 'imagefloat' ) != 'center' ) { pN = img.parentNode; domUtils.setStyle( img, 'float', 'none' ); tmpNode = img; while ( pN && domUtils.getChildCount( pN, function ( node ) { return !domUtils.isBr( node ) && !domUtils.isWhitespace( node ); } ) == 1 && (dtd.$inline[pN.tagName] || pN.tagName == 'A') ) { tmpNode = pN; pN = pN.parentNode; } range.setStartBefore( tmpNode ).setCursor( false ); pN = me.document.createElement( 'div' ); pN.appendChild( tmpNode ); domUtils.setStyle( tmpNode, 'float', '' ); me.execCommand( 'insertHtml', '

' + pN.innerHTML + '

' ); tmpNode = me.document.getElementById( '_img_parent_tmp' ); tmpNode.removeAttribute( 'id' ); tmpNode = tmpNode.firstChild; range.selectNode( tmpNode ).select(); //去掉后边多余的元素 next = tmpNode.parentNode.nextSibling; if ( next && domUtils.isEmptyNode( next ) ) { domUtils.remove( next ); } } break; } } } }, queryCommandValue:function () { var range = this.selection.getRange(), startNode, floatStyle; if ( range.collapsed ) { return 'none'; } startNode = range.getClosedNode(); if ( startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG' ) { floatStyle = domUtils.getComputedStyle( startNode, 'float' ); if ( floatStyle == 'none' ) { floatStyle = domUtils.getComputedStyle( startNode.parentNode, 'text-align' ) == 'center' ? 'center' : floatStyle; } return { left:1, right:1, center:1 }[floatStyle] ? floatStyle : 'none'; } return 'none'; }, queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(), startNode; if ( range.collapsed ) { return -1; } startNode = range.getClosedNode(); if ( startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG' ) { return 0; } return -1; } }; UE.commands['insertimage'] = { execCommand:function ( cmd, opt ) { opt = utils.isArray( opt ) ? opt : [opt]; if ( !opt.length ) { return; } var me = this, range = me.selection.getRange(), img = range.getClosedNode(); if ( img && /img/i.test( img.tagName ) && img.className != "edui-faked-video" && !img.getAttribute( "word_img" ) ) { var first = opt.shift(); var floatStyle = first['floatStyle']; delete first['floatStyle']; //// img.style.border = (first.border||0) +"px solid #000"; //// img.style.margin = (first.margin||0) +"px"; // img.style.cssText += ';margin:' + (first.margin||0) +"px;" + 'border:' + (first.border||0) +"px solid #000"; domUtils.setAttributes( img, first ); me.execCommand( 'imagefloat', floatStyle ); if ( opt.length > 0 ) { range.setStartAfter( img ).setCursor( false, true ); me.execCommand( 'insertimage', opt ); } } else { var html = [], str = '', ci; ci = opt[0]; if ( opt.length == 1 ) { str = '' + ci.alt + ''; if ( ci['floatStyle'] == 'center' ) { str = '

' + str + '

'; } html.push( str ); } else { for ( var i = 0; ci = opt[i++]; ) { str = '

'; html.push( str ); } } me.execCommand( 'insertHtml', html.join( '' ) ); } }, queryCommandState:function () { return this.highlight ? -1 : 0; } }; ///import core ///commands 段落格式,居左,居右,居中,两端对齐 ///commandsName JustifyLeft,JustifyCenter,JustifyRight,JustifyJustify ///commandsTitle 居左对齐,居中对齐,居右对齐,两端对齐 /** * @description 居左右中 * @name baidu.editor.execCommand * @param {String} cmdName justify执行对齐方式的命令 * @param {String} align 对齐方式:left居左,right居右,center居中,justify两端对齐 * @author zhanyi */ (function(){ var block = domUtils.isBlockElm, defaultValue = { left : 1, right : 1, center : 1, justify : 1 }, doJustify = function(range,style){ var bookmark = range.createBookmark(), filterFn = function( node ) { return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace( node ); }; range.enlarge(true); var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start,false,filterFn), tmpRange = range.cloneRange(), tmpNode; while(current && !(domUtils.getPosition(current,bookmark2.end)&domUtils.POSITION_FOLLOWING)){ if(current.nodeType == 3 || !block(current)){ tmpRange.setStartBefore(current); while(current && current!==bookmark2.end && !block(current)){ tmpNode = current; current = domUtils.getNextDomNode(current,false,null,function(node){ return !block(node); }); } tmpRange.setEndAfter(tmpNode); var common = tmpRange.getCommonAncestor(); if( !domUtils.isBody(common) && block(common)){ domUtils.setStyles(common,utils.isString(style) ? {'text-align':style} : style); current = common; }else{ var p = range.document.createElement('p'); domUtils.setStyles(p,utils.isString(style) ? {'text-align':style} : style); var frag = tmpRange.extractContents(); p.appendChild(frag); tmpRange.insertNode(p); current = p; } current = domUtils.getNextDomNode(current,false,filterFn); }else{ current = domUtils.getNextDomNode(current,true,filterFn); } } return range.moveToBookmark(bookmark2).moveToBookmark(bookmark); }; UE.commands['justify'] = { execCommand : function( cmdName,align ) { var range = this.selection.getRange(), txt; if(this.currentSelectedArr && this.currentSelectedArr.length > 0){ for(var i=0,ti;ti=this.currentSelectedArr[i++];){ if(domUtils.isEmptyNode(ti)){ txt = this.document.createTextNode('p'); range.setStart(ti,0).collapse(true).insertNode(txt).selectNode(txt); }else{ range.selectNodeContents(ti); } doJustify(range,align.toLowerCase()); txt && domUtils.remove(txt); } range.selectNode(this.currentSelectedArr[0]).select(); }else{ //闭合时单独处理 if(range.collapsed){ txt = this.document.createTextNode('p'); range.insertNode(txt); } doJustify(range,align); if(txt){ range.setStartBefore(txt).collapse(true); domUtils.remove(txt); } range.select(); } return true; }, queryCommandValue : function() { var startNode = this.selection.getStart(), value = domUtils.getComputedStyle(startNode,'text-align'); return defaultValue[value] ? value : 'left'; }, queryCommandState : function(){ return this.highlight ? -1 : 0; } }; })(); ///import core ///import plugins\removeformat.js ///commands 字体颜色,背景色,字号,字体,下划线,删除线 ///commandsName ForeColor,BackColor,FontSize,FontFamily,Underline,StrikeThrough ///commandsTitle 字体颜色,背景色,字号,字体,下划线,删除线 /** * @description 字体 * @name baidu.editor.execCommand * @param {String} cmdName 执行的功能名称 * @param {String} value 传入的值 */ UE.plugins['font'] = function() { var me = this, fonts = { 'forecolor':'color', 'backcolor':'background-color', 'fontsize':'font-size', 'fontfamily':'font-family', 'underline':'text-decoration', 'strikethrough':'text-decoration' }; me.setOpt({ 'fontfamily':[ { name:'songti',val:'宋体,SimSun'}, { name:'yahei',val:'微软雅黑,Microsoft YaHei'}, { name:'kaiti',val:'楷体,楷体_GB2312, SimKai'}, { name:'heiti',val:'黑体, SimHei'}, { name:'lishu',val:'隶书, SimLi'}, { name:'andaleMono',val:'andale mono'}, { name:'arial',val:'arial, helvetica,sans-serif'}, { name:'arialBlack',val:'arial black,avant garde'}, { name:'comicSansMs',val:'comic sans ms'}, { name:'impact',val:'impact,chicago'}, { name:'timesNewRoman',val:'times new roman'} ], 'fontsize':[10, 11, 12, 14, 16, 18, 20, 24, 36] }); for ( var p in fonts ) { (function( cmd, style ) { UE.commands[cmd] = { execCommand : function( cmdName, value ) { value = value || (this.queryCommandState(cmdName) ? 'none' : cmdName == 'underline' ? 'underline' : 'line-through'); var me = this, range = this.selection.getRange(), text; if ( value == 'default' ) { if(range.collapsed){ text = me.document.createTextNode('font'); range.insertNode(text).select(); } me.execCommand( 'removeFormat', 'span,a', style); if(text){ range.setStartBefore(text).setCursor(); domUtils.remove(text); } } else { if(me.currentSelectedArr && me.currentSelectedArr.length > 0){ for(var i=0,ci;ci=me.currentSelectedArr[i++];){ range.selectNodeContents(ci); range.applyInlineStyle( 'span', {'style':style + ':' + value} ); } range.selectNodeContents(this.currentSelectedArr[0]).select(); }else{ if ( !range.collapsed ) { if((cmd == 'underline'||cmd=='strikethrough') && me.queryCommandValue(cmd)){ me.execCommand( 'removeFormat', 'span,a', style ); } range = me.selection.getRange(); range.applyInlineStyle( 'span', {'style':style + ':' + value} ).select(); } else { var span = domUtils.findParentByTagName(range.startContainer,'span',true); text = me.document.createTextNode('font'); if(span && !span.children.length && !span[browser.ie ? 'innerText':'textContent'].replace(fillCharReg,'').length){ //for ie hack when enter range.insertNode(text); if(cmd == 'underline'||cmd=='strikethrough'){ range.selectNode(text).select(); me.execCommand( 'removeFormat','span,a', style, null ); span = domUtils.findParentByTagName(text,'span',true); range.setStartBefore(text); } span.style.cssText += ';' + style + ':' + value; range.collapse(true).select(); }else{ range.insertNode(text); range.selectNode(text).select(); span = range.document.createElement( 'span' ); if(cmd == 'underline'||cmd=='strikethrough'){ //a标签内的不处理跳过 if(domUtils.findParentByTagName(text,'a',true)){ range.setStartBefore(text).setCursor(); domUtils.remove(text); return; } me.execCommand( 'removeFormat','span,a', style ); } span.style.cssText = style + ':' + value; text.parentNode.insertBefore(span,text); //修复,span套span 但样式不继承的问题 if(!browser.ie || browser.ie && browser.version == 9){ var spanParent = span.parentNode; while(!domUtils.isBlockElm(spanParent)){ if(spanParent.tagName == 'SPAN'){ //opera合并style不会加入";" span.style.cssText = spanParent.style.cssText + ";" + span.style.cssText; } spanParent = spanParent.parentNode; } } if(opera){ setTimeout(function(){ range.setStart(span,0).setCursor(); }); }else{ range.setStart(span,0).setCursor(); } //trace:981 //domUtils.mergToParent(span) } domUtils.remove(text); } } } return true; }, queryCommandValue : function (cmdName) { var startNode = this.selection.getStart(); //trace:946 if(cmdName == 'underline'||cmdName=='strikethrough' ){ var tmpNode = startNode,value; while(tmpNode && !domUtils.isBlockElm(tmpNode) && !domUtils.isBody(tmpNode)){ if(tmpNode.nodeType == 1){ value = domUtils.getComputedStyle( tmpNode, style ); if(value != 'none'){ return value; } } tmpNode = tmpNode.parentNode; } return 'none'; } return domUtils.getComputedStyle( startNode, style ); }, queryCommandState : function(cmdName){ if(this.highlight){ return -1; } if(!(cmdName == 'underline'||cmdName=='strikethrough')){ return 0; } return this.queryCommandValue(cmdName) == (cmdName == 'underline' ? 'underline' : 'line-through'); } }; })( p, fonts[p] ); } }; ///import core ///commands 超链接,取消链接 ///commandsName Link,Unlink ///commandsTitle 超链接,取消链接 ///commandsDialog dialogs\link\link.html /** * 超链接 * @function * @name baidu.editor.execCommand * @param {String} cmdName link插入超链接 * @param {Object} options url地址,title标题,target是否打开新页 * @author zhanyi */ /** * 取消链接 * @function * @name baidu.editor.execCommand * @param {String} cmdName unlink取消链接 * @author zhanyi */ (function() { function optimize( range ) { var start = range.startContainer,end = range.endContainer; if ( start = domUtils.findParentByTagName( start, 'a', true ) ) { range.setStartBefore( start ); } if ( end = domUtils.findParentByTagName( end, 'a', true ) ) { range.setEndAfter( end ); } } UE.commands['unlink'] = { execCommand : function() { var as, range = new dom.Range(this.document), tds = this.currentSelectedArr, bookmark; if(tds && tds.length >0){ for(var i=0,ti;ti=tds[i++];){ as = domUtils.getElementsByTagName(ti,'a'); for(var j=0,aj;aj=as[j++];){ domUtils.remove(aj,true); } } if(domUtils.isEmptyNode(tds[0])){ range.setStart(tds[0],0).setCursor(); }else{ range.selectNodeContents(tds[0]).select(); } }else{ range = this.selection.getRange(); if(range.collapsed && !domUtils.findParentByTagName( range.startContainer, 'a', true )){ return; } bookmark = range.createBookmark(); optimize( range ); range.removeInlineStyle( 'a' ).moveToBookmark( bookmark ).select(); } }, queryCommandState : function(){ return !this.highlight && this.queryCommandValue('link') ? 0 : -1; } }; function doLink(range,opt){ optimize( range = range.adjustmentBoundary() ); var start = range.startContainer; if(start.nodeType == 1){ start = start.childNodes[range.startOffset]; if(start && start.nodeType == 1 && start.tagName == 'A' && /^(?:https?|ftp|file)\s*:\s*\/\//.test(start[browser.ie?'innerText':'textContent'])){ start[browser.ie ? 'innerText' : 'textContent'] = utils.html(opt.textValue||opt.href); } } range.removeInlineStyle( 'a' ); if ( range.collapsed ) { var a = range.document.createElement( 'a'), text = ''; if(opt.textValue){ text = utils.html(opt.textValue); delete opt.textValue; }else{ text = utils.html(opt.href); } domUtils.setAttributes( a, opt ); range.insertNode( a ); a[browser.ie ? 'innerText' : 'textContent'] = text; range.selectNode( a ); } else { range.applyInlineStyle( 'a', opt ); } } UE.commands['link'] = { queryCommandState : function(){ return this.highlight ? -1 :0; }, execCommand : function( cmdName, opt ) { var range = new dom.Range(this.document), tds = this.currentSelectedArr; opt.data_ue_src && (opt.data_ue_src = utils.unhtml(opt.data_ue_src,/[<">]/g)); opt.href && (opt.href = utils.unhtml(opt.href,/[<">]/g)); opt.textValue && (opt.textValue = utils.unhtml(opt.textValue,/[<">]/g)); if(tds && tds.length){ for(var i=0,ti;ti=tds[i++];){ if(domUtils.isEmptyNode(ti)){ ti[browser.ie ? 'innerText' : 'textContent'] = utils.html(opt.textValue || opt.href); } doLink(range.selectNodeContents(ti),opt); } range.selectNodeContents(tds[0]).select(); }else{ doLink(range=this.selection.getRange(),opt); //闭合都不加占位符,如果加了会在a后边多个占位符节点,导致a是图片背景组成的列表,出现空白问题 range.collapse().select(true); } }, queryCommandValue : function() { var range = new dom.Range(this.document), tds = this.currentSelectedArr, as, node; if(tds && tds.length){ for(var i=0,ti;ti=tds[i++];){ as = ti.getElementsByTagName('a'); if(as[0]){ return as[0]; } } }else{ range = this.selection.getRange(); if ( range.collapsed ) { node = this.selection.getStart(); if ( node && (node = domUtils.findParentByTagName( node, 'a', true )) ) { return node; } } else { //trace:1111 如果是

xx

startContainer是p就会找不到a range.shrinkBoundary(); var start = range.startContainer.nodeType == 3 || !range.startContainer.childNodes[range.startOffset] ? range.startContainer : range.startContainer.childNodes[range.startOffset], end = range.endContainer.nodeType == 3 || range.endOffset == 0 ? range.endContainer : range.endContainer.childNodes[range.endOffset-1], common = range.getCommonAncestor(); node = domUtils.findParentByTagName( common, 'a', true ); if ( !node && common.nodeType == 1){ var as = common.getElementsByTagName( 'a' ), ps,pe; for ( var i = 0,ci; ci = as[i++]; ) { ps = domUtils.getPosition( ci, start ),pe = domUtils.getPosition( ci,end); if ( (ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) && (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS) ) { node = ci; break; } } } return node; } } } }; })(); ///import core ///import plugins\inserthtml.js ///commands 地图 ///commandsName Map,GMap ///commandsTitle Baidu地图,Google地图 ///commandsDialog dialogs\map\map.html,dialogs\gmap\gmap.html UE.commands['gmap'] = UE.commands['map'] = { queryCommandState : function(){ return this.highlight ? -1 :0; } }; ///import core ///import plugins\inserthtml.js ///commands 插入框架 ///commandsName InsertFrame ///commandsTitle 插入Iframe ///commandsDialog dialogs\insertframe\insertframe.html UE.plugins['insertframe'] = function() { var me =this; function deleteIframe(){ me._iframe && delete me._iframe; } me.addListener("selectionchange",function(){ deleteIframe(); }); me.commands["insertframe"] = { queryCommandState : function(){ return this.highlight ? -1 :0; } }; }; /** * Created with JetBrains PhpStorm. * User: xuheng * Date: 12-7-2 * Time: 下午5:22 * To change this template use File | Settings | File Templates. */ UE.commands['scrawl'] = { queryCommandState : function(){ return this.highlight|| ( browser.ie && browser.version <= 8 ) ? -1 :0; } }; ///import core ///commands 清除格式 ///commandsName RemoveFormat ///commandsTitle 清除格式 /** * @description 清除格式 * @name baidu.editor.execCommand * @param {String} cmdName removeformat清除格式命令 * @param {String} tags 以逗号隔开的标签。如:span,a * @param {String} style 样式 * @param {String} attrs 属性 * @param {String} notIncluedA 是否把a标签切开 * @author zhanyi */ UE.plugins['removeformat'] = function(){ var me = this; me.setOpt({ 'removeFormatTags': 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var', 'removeFormatAttributes':'class,style,lang,width,height,align,hspace,valign' }); me.commands['removeformat'] = { execCommand : function( cmdName, tags, style, attrs,notIncludeA ) { var tagReg = new RegExp( '^(?:' + (tags || this.options.removeFormatTags).replace( /,/g, '|' ) + ')$', 'i' ) , removeFormatAttributes = style ? [] : (attrs || this.options.removeFormatAttributes).split( ',' ), range = new dom.Range( this.document ), bookmark,node,parent, filter = function( node ) { return node.nodeType == 1; }; function isRedundantSpan (node) { if (node.nodeType == 3 || node.tagName.toLowerCase() != 'span'){ return 0; } if (browser.ie) { //ie 下判断实效,所以只能简单用style来判断 //return node.style.cssText == '' ? 1 : 0; var attrs = node.attributes; if ( attrs.length ) { for ( var i = 0,l = attrs.length; i
var node = range.startContainer, tmp, collapsed = range.collapsed; while(node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]){ tmp = node.parentNode; range.setStartBefore(node); //trace:937 //更新结束边界 if(range.startContainer === range.endContainer){ range.endOffset--; } domUtils.remove(node); node = tmp; } if(!collapsed){ node = range.endContainer; while(node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]){ tmp = node.parentNode; range.setEndBefore(node); domUtils.remove(node); node = tmp; } } } if ( this.currentSelectedArr && this.currentSelectedArr.length ) { for ( var i = 0,ci; ci = this.currentSelectedArr[i++]; ) { range.selectNodeContents( ci ); doRemove( range ); } range.selectNodeContents( this.currentSelectedArr[0] ).select(); } else { range = this.selection.getRange(); doRemove( range ); range.select(); } }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; }; ///import core ///commands 引用 ///commandsName BlockQuote ///commandsTitle 引用 /** * * 引用模块实现 * @function * @name baidu.editor.execCommand * @param {String} cmdName blockquote引用 */ (function() { var getObj = function(editor){ // var startNode = editor.selection.getStart(); // return domUtils.findParentByTagName( startNode, 'blockquote', true ) return utils.findNode(editor.selection.getStartElementPath(),['blockquote']); }; UE.commands['blockquote'] = { execCommand : function( cmdName, attrs ) { var range = this.selection.getRange(), obj = getObj(this), blockquote = dtd.blockquote, bookmark = range.createBookmark(), tds = this.currentSelectedArr; if ( obj ) { if(tds && tds.length){ domUtils.remove(obj,true); }else{ var start = range.startContainer, startBlock = domUtils.isBlockElm(start) ? start : domUtils.findParent(start,function(node){return domUtils.isBlockElm(node)}), end = range.endContainer, endBlock = domUtils.isBlockElm(end) ? end : domUtils.findParent(end,function(node){return domUtils.isBlockElm(node)}); //处理一下li startBlock = domUtils.findParentByTagName(startBlock,'li',true) || startBlock; endBlock = domUtils.findParentByTagName(endBlock,'li',true) || endBlock; if(startBlock.tagName == 'LI' || startBlock.tagName == 'TD' || startBlock === obj){ domUtils.remove(obj,true); }else{ domUtils.breakParent(startBlock,obj); } if(startBlock !== endBlock){ obj = domUtils.findParentByTagName(endBlock,'blockquote'); if(obj){ if(endBlock.tagName == 'LI' || endBlock.tagName == 'TD'){ domUtils.remove(obj,true); }else{ domUtils.breakParent(endBlock,obj); } } } var blockquotes = domUtils.getElementsByTagName(this.document,'blockquote'); for(var i=0,bi;bi=blockquotes[i++];){ if(!bi.childNodes.length){ domUtils.remove(bi); }else if(domUtils.getPosition(bi,startBlock)&domUtils.POSITION_FOLLOWING && domUtils.getPosition(bi,endBlock)&domUtils.POSITION_PRECEDING){ domUtils.remove(bi,true); } } } } else { var tmpRange = range.cloneRange(), node = tmpRange.startContainer.nodeType == 1 ? tmpRange.startContainer : tmpRange.startContainer.parentNode, preNode = node, doEnd = 1; //调整开始 while ( 1 ) { if ( domUtils.isBody(node) ) { if ( preNode !== node ) { if ( range.collapsed ) { tmpRange.selectNode( preNode ); doEnd = 0; } else { tmpRange.setStartBefore( preNode ); } }else{ tmpRange.setStart(node,0); } break; } if ( !blockquote[node.tagName] ) { if ( range.collapsed ) { tmpRange.selectNode( preNode ); } else{ tmpRange.setStartBefore( preNode); } break; } preNode = node; node = node.parentNode; } //调整结束 if ( doEnd ) { preNode = node = node = tmpRange.endContainer.nodeType == 1 ? tmpRange.endContainer : tmpRange.endContainer.parentNode; while ( 1 ) { if ( domUtils.isBody( node ) ) { if ( preNode !== node ) { tmpRange.setEndAfter( preNode ); } else { tmpRange.setEnd( node, node.childNodes.length ); } break; } if ( !blockquote[node.tagName] ) { tmpRange.setEndAfter( preNode ); break; } preNode = node; node = node.parentNode; } } node = range.document.createElement( 'blockquote' ); domUtils.setAttributes( node, attrs ); node.appendChild( tmpRange.extractContents() ); tmpRange.insertNode( node ); //去除重复的 var childs = domUtils.getElementsByTagName(node,'blockquote'); for(var i=0,ci;ci=childs[i++];){ if(ci.parentNode){ domUtils.remove(ci,true); } } } range.moveToBookmark( bookmark ).select(); }, queryCommandState : function() { if(this.highlight){ return -1; } return getObj(this) ? 1 : 0; } }; })(); ///import core ///commands 大小写转换 ///commandsName touppercase ///commandsName tolowercase ///commandsTitle 大小写转换 /** * 大小写转换 * @function * @name baidu.editor.execCommands * @param {String} cmdName cmdName="convertcase" */ UE.commands['touppercase'] = UE.commands['tolowercase'] = { execCommand:function (cmd) { var me = this,rng = new dom.Range(me.document), convertCase = function(){ var rng = me.selection.getRange(); if(rng.collapsed){ return rng; } var bk = rng.createBookmark(), bkEnd = bk.end, filterFn = function( node ) { return !domUtils.isBr(node) && !domUtils.isWhitespace( node ); }, curNode = domUtils.getNextDomNode( bk.start, false, filterFn ); while ( curNode && (domUtils.getPosition( curNode, bkEnd ) & domUtils.POSITION_PRECEDING) ) { if ( curNode.nodeType == 3 ) { curNode.nodeValue = curNode.nodeValue[cmd == 'touppercase' ? 'toUpperCase' : 'toLowerCase'](); } curNode = domUtils.getNextDomNode( curNode, true, filterFn ); if(curNode === bkEnd){ break; } } return rng.moveToBookmark(bk); }; //table的处理 if(me.currentSelectedArr && me.currentSelectedArr.length > 0){ for(var i=0,ci;ci=me.currentSelectedArr[i++];){ if(ci.style.display != 'none' && !domUtils.isEmptyBlock(ci)){ rng.selectNodeContents(ci).select(); convertCase(); } } rng.selectNodeContents(me.currentSelectedArr[0]).select(); }else{ convertCase().select(); } }, queryCommandState:function () { return this.highlight ? -1 : 0; } }; ///import core ///import plugins\paragraph.js ///commands 首行缩进 ///commandsName Outdent,Indent ///commandsTitle 取消缩进,首行缩进 /** * 首行缩进 * @function * @name baidu.editor.execCommand * @param {String} cmdName outdent取消缩进,indent缩进 */ UE.commands['indent'] = { execCommand : function() { var me = this,value = me.queryCommandState("indent") ? "0em" : (me.options.indentValue || '2em'); me.execCommand('Paragraph','p',{style:'text-indent:'+ value}); }, queryCommandState : function() { if(this.highlight){return -1;} var pN = utils.findNode(this.selection.getStartElementPath(),['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']); return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0; } }; ///import core ///commands 打印 ///commandsName Print ///commandsTitle 打印 /** * @description 打印 * @name baidu.editor.execCommand * @param {String} cmdName print打印编辑器内容 * @author zhanyi */ UE.commands['print'] = { execCommand : function(){ this.window.print(); }, notNeedUndo : 1 }; ///import core ///commands 预览 ///commandsName Preview ///commandsTitle 预览 /** * 预览 * @function * @name baidu.editor.execCommand * @param {String} cmdName preview预览编辑器内容 */ UE.commands['preview'] = { execCommand : function(){ var w = window.open('', '_blank', ''), d = w.document; d.open(); d.write(this.getAllHtml()); d.close(); }, notNeedUndo : 1 }; ///import core ///import plugins\inserthtml.js ///commands 特殊字符 ///commandsName Spechars ///commandsTitle 特殊字符 ///commandsDialog dialogs\spechars\spechars.html UE.commands['spechars'] = { queryCommandState : function(){ return this.highlight ? -1 :0; } }; ///import core ///import plugins\image.js ///commands 插入表情 ///commandsName Emotion ///commandsTitle 表情 ///commandsDialog dialogs\emotion\emotion.html UE.commands['emotion'] = { queryCommandState : function(){ return this.highlight ? -1 :0; } }; ///import core ///commands 全选 ///commandsName SelectAll ///commandsTitle 全选 /** * 选中所有 * @function * @name baidu.editor.execCommand * @param {String} cmdName selectall选中编辑器里的所有内容 * @author zhanyi */ UE.plugins['selectall'] = function(){ var me = this; me.commands['selectall'] = { execCommand : function(){ //去掉了原生的selectAll,因为会出现报错和当内容为空时,不能出现闭合状态的光标 var me = this,body = me.body, range = me.selection.getRange(); range.selectNodeContents(body); if(domUtils.isEmptyBlock(body)){ //opera不能自动合并到元素的里边,要手动处理一下 if(browser.opera && body.firstChild && body.firstChild.nodeType == 1){ range.setStartAtFirst(body.firstChild); } range.collapse(true); } range.select(true); this.selectAll = true; }, notNeedUndo : 1 }; me.addListener('ready',function(){ domUtils.on(me.document,'click',function(evt){ me.selectAll = false; }); }); }; ///import core ///commands 格式 ///commandsName Paragraph ///commandsTitle 段落格式 /** * 段落样式 * @function * @name baidu.editor.execCommand * @param {String} cmdName paragraph插入段落执行命令 * @param {String} style 标签值为:'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' * @param {String} attrs 标签的属性 * @author zhanyi */ UE.plugins['paragraph'] = function() { var me = this, block = domUtils.isBlockElm, notExchange = ['TD','LI','PRE'], doParagraph = function(range,style,attrs,sourceCmdName){ var bookmark = range.createBookmark(), filterFn = function( node ) { return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace( node ); }, para; range.enlarge( true ); var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode( bookmark2.start, false, filterFn ), tmpRange = range.cloneRange(), tmpNode; while ( current && !(domUtils.getPosition( current, bookmark2.end ) & domUtils.POSITION_FOLLOWING) ) { if ( current.nodeType == 3 || !block( current ) ) { tmpRange.setStartBefore( current ); while ( current && current !== bookmark2.end && !block( current ) ) { tmpNode = current; current = domUtils.getNextDomNode( current, false, null, function( node ) { return !block( node ); } ); } tmpRange.setEndAfter( tmpNode ); para = range.document.createElement( style ); if(attrs){ domUtils.setAttributes(para,attrs); if(sourceCmdName && sourceCmdName == 'customstyle' && attrs.style){ para.style.cssText = attrs.style; } } para.appendChild( tmpRange.extractContents() ); //需要内容占位 if(domUtils.isEmptyNode(para)){ domUtils.fillChar(range.document,para); } tmpRange.insertNode( para ); var parent = para.parentNode; //如果para上一级是一个block元素且不是body,td就删除它 if ( block( parent ) && !domUtils.isBody( para.parentNode ) && utils.indexOf(notExchange,parent.tagName)==-1) { //存储dir,style if(!(sourceCmdName && sourceCmdName == 'customstyle')){ parent.getAttribute('dir') && para.setAttribute('dir',parent.getAttribute('dir')); //trace:1070 parent.style.cssText && (para.style.cssText = parent.style.cssText + ';' + para.style.cssText); //trace:1030 parent.style.textAlign && !para.style.textAlign && (para.style.textAlign = parent.style.textAlign); parent.style.textIndent && !para.style.textIndent && (para.style.textIndent = parent.style.textIndent); parent.style.padding && !para.style.padding && (para.style.padding = parent.style.padding); } //trace:1706 选择的就是h1-6要删除 if(attrs && /h\d/i.test(parent.tagName) && !/h\d/i.test(para.tagName) ){ domUtils.setAttributes(parent,attrs); if(sourceCmdName && sourceCmdName == 'customstyle' && attrs.style){ parent.style.cssText = attrs.style; } domUtils.remove(para,true); para = parent; }else{ domUtils.remove( para.parentNode, true ); } } if( utils.indexOf(notExchange,parent.tagName)!=-1){ current = parent; }else{ current = para; } current = domUtils.getNextDomNode( current, false, filterFn ); } else { current = domUtils.getNextDomNode( current, true, filterFn ); } } return range.moveToBookmark( bookmark2 ).moveToBookmark( bookmark ); }; me.setOpt('paragraph',{'p':'', 'h1':'', 'h2':'', 'h3':'', 'h4':'', 'h5':'', 'h6':''}); me.commands['paragraph'] = { execCommand : function( cmdName, style,attrs,sourceCmdName ) { var range = new dom.Range(this.document); if(this.currentSelectedArr && this.currentSelectedArr.length > 0){ for(var i=0,ti;ti=this.currentSelectedArr[i++];){ //trace:1079 不显示的不处理,插入文本,空的td也能加上相应的标签 if(ti.style.display == 'none'){ continue; } if(domUtils.isEmptyNode(ti)){ var tmpTxt = this.document.createTextNode('paragraph'); ti.innerHTML = ''; ti.appendChild(tmpTxt); } doParagraph(range.selectNodeContents(ti),style,attrs,sourceCmdName); if(tmpTxt){ var pN = tmpTxt.parentNode; domUtils.remove(tmpTxt); if(domUtils.isEmptyNode(pN)){ domUtils.fillNode(this.document,pN); } } } var td = this.currentSelectedArr[0]; if(domUtils.isEmptyBlock(td)){ range.setStart(td,0).setCursor(false,true); }else{ range.selectNode(td).select(); } }else{ range = this.selection.getRange(); //闭合时单独处理 if(range.collapsed){ var txt = this.document.createTextNode('p'); range.insertNode(txt); //去掉冗余的fillchar if(browser.ie){ var node = txt.previousSibling; if(node && domUtils.isWhitespace(node)){ domUtils.remove(node); } node = txt.nextSibling; if(node && domUtils.isWhitespace(node)){ domUtils.remove(node); } } } range = doParagraph(range,style,attrs,sourceCmdName); if(txt){ range.setStartBefore(txt).collapse(true); pN = txt.parentNode; domUtils.remove(txt); if(domUtils.isBlockElm(pN)&&domUtils.isEmptyNode(pN)){ domUtils.fillNode(this.document,pN); } } if(browser.gecko && range.collapsed && range.startContainer.nodeType == 1){ var child = range.startContainer.childNodes[range.startOffset]; if(child && child.nodeType == 1 && child.tagName.toLowerCase() == style){ range.setStart(child,0).collapse(true); } } //trace:1097 原来有true,原因忘了,但去了就不能清除多余的占位符了 range.select(); } return true; }, queryCommandValue : function() { var node = utils.findNode(this.selection.getStartElementPath(),['p','h1','h2','h3','h4','h5','h6']); return node ? node.tagName.toLowerCase() : ''; }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; }; ///import core ///commands 输入的方向 ///commandsName DirectionalityLtr,DirectionalityRtl ///commandsTitle 从左向右输入,从右向左输入 /** * 输入的方向 * @function * @name baidu.editor.execCommand * @param {String} cmdName directionality执行函数的参数 * @param {String} forward ltr从左向右输入,rtl从右向左输入 */ (function() { var block = domUtils.isBlockElm , getObj = function(editor){ // var startNode = editor.selection.getStart(), // parents; // if ( startNode ) { // //查找所有的是block的父亲节点 // parents = domUtils.findParents( startNode, true, block, true ); // for ( var i = 0,ci; ci = parents[i++]; ) { // if ( ci.getAttribute( 'dir' ) ) { // return ci; // } // } // } return utils.findNode(editor.selection.getStartElementPath(),null,function(n){return n.getAttribute('dir')}); }, doDirectionality = function(range,editor,forward){ var bookmark, filterFn = function( node ) { return node.nodeType == 1 ? !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node); }, obj = getObj( editor ); if ( obj && range.collapsed ) { obj.setAttribute( 'dir', forward ); return range; } bookmark = range.createBookmark(); range.enlarge( true ); var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode( bookmark2.start, false, filterFn ), tmpRange = range.cloneRange(), tmpNode; while ( current && !(domUtils.getPosition( current, bookmark2.end ) & domUtils.POSITION_FOLLOWING) ) { if ( current.nodeType == 3 || !block( current ) ) { tmpRange.setStartBefore( current ); while ( current && current !== bookmark2.end && !block( current ) ) { tmpNode = current; current = domUtils.getNextDomNode( current, false, null, function( node ) { return !block( node ); } ); } tmpRange.setEndAfter( tmpNode ); var common = tmpRange.getCommonAncestor(); if ( !domUtils.isBody( common ) && block( common ) ) { //遍历到了block节点 common.setAttribute( 'dir', forward ); current = common; } else { //没有遍历到,添加一个block节点 var p = range.document.createElement( 'p' ); p.setAttribute( 'dir', forward ); var frag = tmpRange.extractContents(); p.appendChild( frag ); tmpRange.insertNode( p ); current = p; } current = domUtils.getNextDomNode( current, false, filterFn ); } else { current = domUtils.getNextDomNode( current, true, filterFn ); } } return range.moveToBookmark( bookmark2 ).moveToBookmark( bookmark ); }; UE.commands['directionality'] = { execCommand : function( cmdName,forward ) { var range = new dom.Range(this.document); if(this.currentSelectedArr && this.currentSelectedArr.length > 0){ for(var i=0,ti;ti=this.currentSelectedArr[i++];){ if(ti.style.display != 'none'){ doDirectionality(range.selectNode(ti),this,forward); } } range.selectNode(this.currentSelectedArr[0]).select(); }else{ range = this.selection.getRange(); //闭合时单独处理 if(range.collapsed){ var txt = this.document.createTextNode('d'); range.insertNode(txt); } doDirectionality(range,this,forward); if(txt){ range.setStartBefore(txt).collapse(true); domUtils.remove(txt); } range.select(); } return true; }, queryCommandValue : function() { var node = getObj(this); return node ? node.getAttribute('dir') : 'ltr'; }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; })(); ///import core ///import plugins\inserthtml.js ///commands 分割线 ///commandsName Horizontal ///commandsTitle 分隔线 /** * 分割线 * @function * @name baidu.editor.execCommand * @param {String} cmdName horizontal插入分割线 */ UE.commands['horizontal'] = { execCommand : function( cmdName ) { var me = this; if(me.queryCommandState(cmdName)!==-1){ me.execCommand('insertHtml','
'); var range = me.selection.getRange(), start = range.startContainer; if(start.nodeType == 1 && !start.childNodes[range.startOffset] ){ var tmp; if(tmp = start.childNodes[range.startOffset - 1]){ if(tmp.nodeType == 1 && tmp.tagName == 'HR'){ if(me.options.enterTag == 'p'){ tmp = me.document.createElement('p'); range.insertNode(tmp); range.setStart(tmp,0).setCursor(); }else{ tmp = me.document.createElement('br'); range.insertNode(tmp); range.setStartBefore(tmp).setCursor(); } } } } return true; } }, //边界在table里不能加分隔线 queryCommandState : function() { return this.highlight || utils.findNode(this.selection.getStartElementPath(),['table']) ? -1 : 0; } }; ///import core ///import plugins\inserthtml.js ///commands 日期,时间 ///commandsName Date,Time ///commandsTitle 日期,时间 /** * 插入日期 * @function * @name baidu.editor.execCommand * @param {String} cmdName date插入日期 * @author zhuwenxuan */ /** * 插入时间 * @function * @name baidu.editor.execCommand * @param {String} cmdName time插入时间 * @author zhuwenxuan */ UE.commands['time'] = UE.commands["date"] = { execCommand : function(cmd){ var date = new Date; this.execCommand('insertHtml',cmd == "time" ? (date.getHours()+":"+ (date.getMinutes()<10 ? "0"+date.getMinutes() : date.getMinutes())+":"+(date.getSeconds()<10 ? "0"+date.getSeconds() : date.getSeconds())) : (date.getFullYear()+"-"+((date.getMonth()+1)<10 ? "0"+(date.getMonth()+1) : date.getMonth()+1)+"-"+(date.getDate()<10?"0"+date.getDate():date.getDate()))); }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; ///import core ///import plugins\paragraph.js ///commands 段间距 ///commandsName RowSpacingBottom,RowSpacingTop ///commandsTitle 段间距 /** * @description 设置段前距,段后距 * @name baidu.editor.execCommand * @param {String} cmdName rowspacing设置段间距 * @param {String} value 值,以px为单位 * @param {String} dir top或bottom段前后段后 * @author zhanyi */ UE.plugins['rowspacing'] = function(){ var me = this; me.setOpt({ 'rowspacingtop':['5', '10', '15', '20', '25'], 'rowspacingbottom':['5', '10', '15', '20', '25'] }); me.commands['rowspacing'] = { execCommand : function( cmdName,value,dir ) { this.execCommand('paragraph','p',{style:'margin-'+dir+':'+value + 'px'}); return true; }, queryCommandValue : function(cmdName,dir) { var pN = utils.findNode(this.selection.getStartElementPath(),null,function(node){return domUtils.isBlockElm(node) }), value; //trace:1026 if(pN){ value = domUtils.getComputedStyle(pN,'margin-'+dir).replace(/[^\d]/g,''); return !value ? 0 : value; } return 0; }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; }; ///import core ///import plugins\paragraph.js ///commands 行间距 ///commandsName LineHeight ///commandsTitle 行间距 /** * @description 设置行内间距 * @name baidu.editor.execCommand * @param {String} cmdName lineheight设置行内间距 * @param {String} value 值 * @author zhuwenxuan */ UE.plugins['lineheight'] = function(){ var me = this; me.setOpt({'lineheight':['1', '1.5','1.75','2', '3', '4', '5']}); me.commands['lineheight'] = { execCommand : function( cmdName,value ) { this.execCommand('paragraph','p',{style:'line-height:'+ (value == "1" ? "normal" : value + 'em') }); return true; }, queryCommandValue : function() { var pN = utils.findNode(this.selection.getStartElementPath(),null,function(node){return domUtils.isBlockElm(node)}); if(pN){ var value = domUtils.getComputedStyle(pN,'line-height'); return value == 'normal' ? 1 : value.replace(/[^\d.]*/ig,""); } }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; }; ///import core ///commands 清空文档 ///commandsName ClearDoc ///commandsTitle 清空文档 /** * * 清空文档 * @function * @name baidu.editor.execCommand * @param {String} cmdName cleardoc清空文档 */ UE.commands['cleardoc'] = { execCommand : function( cmdName) { var me = this, enterTag = me.options.enterTag, range = me.selection.getRange(); if(enterTag == "br"){ me.body.innerHTML = "
"; range.setStart(me.body,0).setCursor(); }else{ me.body.innerHTML = "

"+(ie ? "" : "
")+"

"; range.setStart(me.body.firstChild,0).setCursor(false,true); } } }; ///import core ///commands 锚点 ///commandsName Anchor ///commandsTitle 锚点 ///commandsDialog dialogs\anchor\anchor.html /** * 锚点 * @function * @name baidu.editor.execCommands * @param {String} cmdName cmdName="anchor"插入锚点 */ UE.commands['anchor'] = { execCommand:function (cmd, name) { var range = this.selection.getRange(),img = range.getClosedNode(); if (img && img.getAttribute('anchorname')) { if (name) { img.setAttribute('anchorname', name); } else { range.setStartBefore(img).setCursor(); domUtils.remove(img); } } else { if (name) { //只在选区的开始插入 var anchor = this.document.createElement('img'); range.collapse(true); domUtils.setAttributes(anchor,{ 'anchorname':name, 'class':'anchorclass' }); range.insertNode(anchor).setStartAfter(anchor).setCursor(false,true); } } }, queryCommandState:function () { return this.highlight ? -1 : 0; } }; ///import core ///commands 删除 ///commandsName Delete ///commandsTitle 删除 /** * 删除 * @function * @name baidu.editor.execCommand * @param {String} cmdName delete删除 * @author zhanyi */ UE.commands['delete'] = { execCommand : function (){ var range = this.selection.getRange(), mStart = 0, mEnd = 0, me = this; if(this.selectAll ){ //trace:1633 me.body.innerHTML = '

'+(browser.ie ? ' ' : '
')+'

'; range.setStart(me.body.firstChild,0).setCursor(false,true); me.selectAll = false; return; } if(me.currentSelectedArr && me.currentSelectedArr.length > 0){ for(var i=0,ci;ci=me.currentSelectedArr[i++];){ if(ci.style.display != 'none'){ ci.innerHTML = browser.ie ? domUtils.fillChar : '
'; } } range.setStart(me.currentSelectedArr[0],0).setCursor(); return; } if(range.collapsed){ return; } range.txtToElmBoundary(); //&& !domUtils.isBlockElm(range.startContainer) while(!range.startOffset && !domUtils.isBody(range.startContainer) && !dtd.$tableContent[range.startContainer.tagName] ){ mStart = 1; range.setStartBefore(range.startContainer); } //&& !domUtils.isBlockElm(range.endContainer) //不对文本节点进行操作 //trace:2428 while(range.endContainer.nodeType != 3 && !domUtils.isBody(range.endContainer)&& !dtd.$tableContent[range.endContainer.tagName] ){ var child,endContainer = range.endContainer,endOffset = range.endOffset; // if(endContainer.nodeType == 3 && endOffset == endContainer.nodeValue.length){ // range.setEndAfter(endContainer); // continue; // } child = endContainer.childNodes[endOffset]; if(!child || domUtils.isBr(child) && endContainer.lastChild === child){ range.setEndAfter(endContainer); continue; } break; } if(mStart){ var start = me.document.createElement('span'); start.innerHTML = 'start'; start.id = '_baidu_cut_start'; range.insertNode(start).setStartBefore(start); } if(mEnd){ var end = me.document.createElement('span'); end.innerHTML = 'end'; end.id = '_baidu_cut_end'; range.cloneRange().collapse(false).insertNode(end); range.setEndAfter(end); } range.deleteContents(); if(domUtils.isBody(range.startContainer) && domUtils.isEmptyBlock(me.body)){ me.body.innerHTML = '

'+(browser.ie?'':'
')+'

'; range.setStart(me.body.firstChild,0).collapse(true); }else if ( !browser.ie && domUtils.isEmptyBlock(range.startContainer)){ range.startContainer.innerHTML = '
'; } range.select(true); }, queryCommandState : function(){ if(this.currentSelectedArr && this.currentSelectedArr.length > 0){ return 0; } return this.highlight || this.selection.getRange().collapsed ? -1 : 0; } }; ///import core ///commands 字数统计 ///commandsName WordCount,wordCount ///commandsTitle 字数统计 /** * Created by JetBrains WebStorm. * User: taoqili * Date: 11-9-7 * Time: 下午8:18 * To change this template use File | Settings | File Templates. */ UE.plugins['wordcount'] = function(){ var me = this; me.setOpt({ wordCount:true, maximumWords:10000, wordCountMsg: me.options.wordCountMsg||me.getLang("wordCountMsg"), wordOverFlowMsg:me.options.wordOverFlowMsg||me.getLang("wordOverFlowMsg") }); var opt = me.options, max = opt.maximumWords, msg = opt.wordCountMsg , errMsg = opt.wordOverFlowMsg; if(!opt.wordCount){ return; } me.commands["wordcount"]={ queryCommandValue:function(cmd,onlyCount){ var length,contentText,reg; if(onlyCount){ reg = new RegExp("[\r\t\n]","g"); contentText = this.getContentTxt().replace(reg,""); return contentText.length; } reg = new RegExp("[\r\t\n]","g"); contentText = this.getContentTxt().replace(reg,""); length = contentText.length; if(max-length<0){ me.fireEvent('wordcountoverflow'); return errMsg; } return msg.replace("{#leave}",max-length >= 0 ? max-length:0).replace("{#count}",length); } }; }; ///import core ///commands 添加分页功能 ///commandsName PageBreak ///commandsTitle 分页 /** * @description 添加分页功能 * @author zhanyi */ UE.plugins['pagebreak'] = function () { var me = this, notBreakTags = ['td']; function fillNode(node){ if(domUtils.isEmptyBlock(node)){ var firstChild = node.firstChild,tmpNode; while(firstChild && firstChild.nodeType == 1 && domUtils.isEmptyBlock(firstChild)){ tmpNode = firstChild; firstChild = firstChild.firstChild; } !tmpNode && (tmpNode = node); domUtils.fillNode(me.document,tmpNode); } } function isHr(node){ return node && node.nodeType == 1 && node.tagName == 'HR' && node.className == 'pagebreak'; } me.commands['pagebreak'] = { execCommand:function () { var range = me.selection.getRange(),hr = me.document.createElement('hr'); domUtils.setAttributes(hr,{ 'class' : 'pagebreak', noshade:"noshade", size:"5" }); domUtils.unselectable(hr); //table单独处理 var node = domUtils.findParentByTagName(range.startContainer, notBreakTags, true), parents = [], pN; if (node) { switch (node.tagName) { case 'TD': pN = node.parentNode; if (!pN.previousSibling) { var table = domUtils.findParentByTagName(pN, 'table'); // var tableWrapDiv = table.parentNode; // if(tableWrapDiv && tableWrapDiv.nodeType == 1 // && tableWrapDiv.tagName == 'DIV' // && tableWrapDiv.getAttribute('dropdrag') // ){ // domUtils.remove(tableWrapDiv,true); // } table.parentNode.insertBefore(hr, table); parents = domUtils.findParents(hr, true); } else { pN.parentNode.insertBefore(hr, pN); parents = domUtils.findParents(hr); } pN = parents[1]; if (hr !== pN) { domUtils.breakParent(hr, pN); } domUtils.clearSelectedArr(me.currentSelectedArr); //table要重写绑定一下拖拽 me.fireEvent('afteradjusttable',me.document); } } else { if (!range.collapsed) { range.deleteContents(); var start = range.startContainer; while ( !domUtils.isBody(start) && domUtils.isBlockElm(start) && domUtils.isEmptyNode(start)) { range.setStartBefore(start).collapse(true); domUtils.remove(start); start = range.startContainer; } } range.insertNode(hr); var pN = hr.parentNode, nextNode; while (!domUtils.isBody(pN)) { domUtils.breakParent(hr, pN); nextNode = hr.nextSibling; if (nextNode && domUtils.isEmptyBlock(nextNode)) { domUtils.remove(nextNode); } pN = hr.parentNode; } nextNode = hr.nextSibling; var pre = hr.previousSibling; if(isHr(pre)){ domUtils.remove(pre); }else{ pre && fillNode(pre); } if(!nextNode){ var p = me.document.createElement('p'); hr.parentNode.appendChild(p); domUtils.fillNode(me.document,p); range.setStart(p,0).collapse(true); }else{ if(isHr(nextNode)){ domUtils.remove(nextNode); }else{ fillNode(nextNode); } range.setEndAfter(hr).collapse(false); } range.select(true); } }, queryCommandState:function () { return this.highlight ? -1 : 0; } }; }; ///import core ///commands 本地图片引导上传 ///commandsName WordImage ///commandsTitle 本地图片引导上传 UE.plugins["wordimage"] = function(){ var me = this, images; me.commands['wordimage'] = { execCommand : function() { images = domUtils.getElementsByTagName(me.document.body,"img"); var urlList = []; for(var i=0,ci;ci=images[i++];){ var url=ci.getAttribute("word_img"); url && urlList.push(url); } if(images.length){ this["word_img"] = urlList; } }, queryCommandState: function(){ images = domUtils.getElementsByTagName(me.document.body,"img"); for(var i=0,ci;ci =images[i++];){ if(ci.getAttribute("word_img")){ return 1; } } return -1; } }; }; ///import core ///commands 撤销和重做 ///commandsName Undo,Redo ///commandsTitle 撤销,重做 /** * @description 回退 * @author zhanyi */ UE.plugins['undo'] = function() { var me = this, maxUndoCount = me.options.maxUndoCount || 20, maxInputCount = me.options.maxInputCount || 20, fillchar = new RegExp(domUtils.fillChar + '|<\/hr>','gi'),// ie会产生多余的 //在比较时,需要过滤掉这些属性 specialAttr = /\b(?:href|src|name)="[^"]*?"/gi; //场景的range实例 function sceneRange(rng){ var me = this; me.collapsed = rng.collapsed; me.startAddr = getAddr(rng.startContainer,rng.startOffset); me.endAddr = rng.collapsed ? me.startAddr : getAddr(rng.endContainer,rng.endOffset) } sceneRange.prototype ={ compare : function(obj){ if(me.collapsed !== obj.collapsed){ return 0; } if(!compareAddr(me.startAddr,obj.startAddr) || !compareAddr(me.endAddr,obj.endAddr)){ return 0; } return 1; }, transformRange : function(rng){ var me = this; rng.collapsed = me.collapsed; setAddr(rng,'start',me.startAddr); rng.collapsed ? rng.collapse(true) : setAddr(rng,'end',me.endAddr) } }; function getAddr(node,index){ for(var i= 0,parentsIndex = [index],ci, parents = domUtils.findParents(node,true,function(node){return !domUtils.isBody(node)},true); ci=parents[i++];){ //修正偏移位置 if(i == 1 && ci.nodeType == 3){ var tmpNode = ci; while(tmpNode = tmpNode.previousSibling){ if(tmpNode.nodeType == 3){ // console.log(index) index += tmpNode.nodeValue.replace(fillCharReg,'').length; }else{ break; } } parentsIndex[0] = index; } parentsIndex.push(domUtils.getNodeIndex(ci,true)); } return parentsIndex.reverse(); } function compareAddr(indexA,indexB){ if(indexA.length != indexB.length) return 0; for(var i= 0,l=indexA.length;i|
,回退后还能在b里 } ); } //trace:1278 ie9block元素为空,将出现光标定位的问题,必须填充内容 if(browser.ie && browser.version == 9 && range.collapsed && domUtils.isBlockElm(range.startContainer) && domUtils.isEmptyNode(range.startContainer)){ domUtils.fillNode(range.document,range.startContainer); } range.select(!browser.gecko); if(!(browser.opera || browser.safari)){ setTimeout(function(){ range.scrollToView(me.autoHeightEnabled,me.autoHeightEnabled ? domUtils.getXY(me.iframe).y:0); },200); } }catch(e){} this.update(); //table的单独处理 if(me.currentSelectedArr){ me.currentSelectedArr = []; var tds = me.document.getElementsByTagName('td'); for(var i=0,td;td=tds[i++];){ if(td.className == me.options.selectedTdClass){ me.currentSelectedArr.push(td); } } } this.clearKey(); //不能把自己reset了 me.fireEvent('reset',true); }; this.getScene = function() { var range = me.selection.getRange(), cont = me.body.innerHTML.replace(fillchar,''); //有可能边界落到了|这样的位置,所以缩一下位置 range.shrinkBoundary(); browser.ie && (cont = cont.replace(/> <').replace(/\s*\s*/g,'>')); if(browser.opera || browser.safari){ return { senceRange : new sceneRange(range), content : cont, bookcontent : cont } }else{ var bookmark = range.createBookmark( true, true ), bookCont = me.body.innerHTML.replace(fillchar,''); bookmark && range.moveToBookmark( bookmark ).select( true ); return { bookcontent : bookCont, content : cont }; } }; this.save = function() { var currentScene = this.getScene(), lastScene = this.list[this.index]; //内容相同位置相同不存 if ( lastScene && lastScene.content == currentScene.content && ( (browser.opera || browser.safari) ? lastScene.senceRange.compare(currentScene.senceRange) : lastScene.bookcontent == currentScene.bookcontent) ) { return; } this.list = this.list.slice( 0, this.index + 1 ); this.list.push( currentScene ); //如果大于最大数量了,就把最前的剔除 if ( this.list.length > maxUndoCount ) { this.list.shift(); } this.index = this.list.length - 1; this.clearKey(); //跟新undo/redo状态 this.update(); }; this.update = function() { this.hasRedo = this.list[this.index + 1] ? true : false; this.hasUndo = this.list[this.index - 1] || this.list.length == 1 ? true : false; }; this.reset = function() { this.list = []; this.index = 0; this.hasUndo = false; this.hasRedo = false; this.clearKey(); }; this.clearKey = function(){ keycont = 0; lastKeyCode = null; me.fireEvent('contentchange'); }; } me.undoManger = new UndoManager(); function saveScene() { this.undoManger.save(); } me.addListener( 'beforeexeccommand', saveScene ); me.addListener( 'afterexeccommand', saveScene ); me.addListener('reset',function(type,exclude){ if(!exclude){ me.undoManger.reset(); } }); me.commands['redo'] = me.commands['undo'] = { execCommand : function( cmdName ) { me.undoManger[cmdName](); }, queryCommandState : function( cmdName ) { return me.undoManger['has' + (cmdName.toLowerCase() == 'undo' ? 'Undo' : 'Redo')] ? 0 : -1; }, notNeedUndo : 1 }; var keys = { // /*Backspace*/ 8:1, /*Delete*/ 46:1, /*Shift*/ 16:1, /*Ctrl*/ 17:1, /*Alt*/ 18:1, 37:1, 38:1, 39:1, 40:1, 13:1 /*enter*/ }, keycont = 0, lastKeyCode; me.addListener( 'keydown', function( type, evt ) { var keyCode = evt.keyCode || evt.which; if ( !keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey ) { if ( me.undoManger.list.length == 0 || ((keyCode == 8 ||keyCode == 46) && lastKeyCode != keyCode) ) { me.undoManger.save(true); lastKeyCode = keyCode; return; } //trace:856 //修正第一次输入后,回退,再输入要到keycont>maxInputCount才能在回退的问题 if(me.undoManger.list.length == 2 && me.undoManger.index == 0 && keycont == 0){ me.undoManger.list.splice(1,1); me.undoManger.update(); } lastKeyCode = keyCode; keycont++; if ( keycont >= maxInputCount ) { if(me.selection.getRange().collapsed) me.undoManger.save(); } } } ); }; ///import core ///import plugins/inserthtml.js ///import plugins/undo.js ///import plugins/serialize.js ///commands 粘贴 ///commandsName PastePlain ///commandsTitle 纯文本粘贴模式 /* ** @description 粘贴 * @author zhanyi */ (function() { function getClipboardData( callback ) { var doc = this.document; if ( doc.getElementById( 'baidu_pastebin' ) ) { return; } var range = this.selection.getRange(), bk = range.createBookmark(), //创建剪贴的容器div pastebin = doc.createElement( 'div' ); pastebin.id = 'baidu_pastebin'; // Safari 要求div必须有内容,才能粘贴内容进来 browser.webkit && pastebin.appendChild( doc.createTextNode( domUtils.fillChar + domUtils.fillChar ) ); doc.body.appendChild( pastebin ); //trace:717 隐藏的span不能得到top //bk.start.innerHTML = ' '; bk.start.style.display = ''; pastebin.style.cssText = "position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:" + //要在现在光标平行的位置加入,否则会出现跳动的问题 domUtils.getXY( bk.start ).y + 'px'; range.selectNodeContents( pastebin ).select( true ); setTimeout( function() { if (browser.webkit) { for(var i=0,pastebins = doc.querySelectorAll('#baidu_pastebin'),pi;pi=pastebins[i++];){ if(domUtils.isEmptyNode(pi)){ domUtils.remove(pi); }else{ pastebin = pi; break; } } } try{ pastebin.parentNode.removeChild(pastebin); }catch(e){} range.moveToBookmark( bk ).select(true); callback( pastebin ); }, 0 ); } UE.plugins['paste'] = function() { var me = this; var word_img_flag = {flag:""}; var pasteplain = me.options.pasteplain === true; var modify_num = {flag:""}; me.commands['pasteplain'] = { queryCommandState: function (){ return pasteplain; }, execCommand: function (){ pasteplain = !pasteplain|0; }, notNeedUndo : 1 }; function filter(div){ var html; if ( div.firstChild ) { //去掉cut中添加的边界值 var nodes = domUtils.getElementsByTagName(div,'span'); for(var i=0,ni;ni=nodes[i++];){ if(ni.id == '_baidu_cut_start' || ni.id == '_baidu_cut_end'){ domUtils.remove(ni); } } if(browser.webkit){ var brs = div.querySelectorAll('div br'); for(var i=0,bi;bi=brs[i++];){ var pN = bi.parentNode; if(pN.tagName == 'DIV' && pN.childNodes.length ==1){ pN.innerHTML = '


'; domUtils.remove(pN); } } var divs = div.querySelectorAll('#baidu_pastebin'); for(var i=0,di;di=divs[i++];){ var tmpP = me.document.createElement('p'); di.parentNode.insertBefore(tmpP,di); while(di.firstChild){ tmpP.appendChild(di.firstChild); } domUtils.remove(di); } var metas = div.querySelectorAll('meta'); for(var i=0,ci;ci=metas[i++];){ domUtils.remove(ci); } var brs = div.querySelectorAll('br'); for(i=0;ci=brs[i++];){ if(/^apple-/.test(ci)){ domUtils.remove(ci); } } } if(browser.gecko){ var dirtyNodes = div.querySelectorAll('[_moz_dirty]'); for(i=0;ci=dirtyNodes[i++];){ ci.removeAttribute( '_moz_dirty' ); } } if(!browser.ie ){ var spans = div.querySelectorAll('span.apple-style-span'); for(var i=0,ci;ci=spans[i++];){ domUtils.remove(ci,true); } } html = div.innerHTML; var f = me.serialize; if(f){ //如果过滤出现问题,捕获它,直接插入内容,避免出现错误导致粘贴整个失败 try{ var node = f.transformInput( f.parseHTML( //todo: 暂时不走dtd的过滤 f.word(html)//, true ),word_img_flag ); //trace:924 //纯文本模式也要保留段落 node = f.filter(node,pasteplain ? { whiteList: { 'p': {'br':1,'BR':1,$:{}}, 'br':{'$':{}}, 'div':{'br':1,'BR':1,'$':{}}, 'li':{'$':{}}, 'tr':{'td':1,'$':{}}, 'td':{'$':{}} }, blackList: { 'style':1, 'script':1, 'object':1 } } : null, !pasteplain ? modify_num : null); if(browser.webkit){ var length = node.children.length, child; while((child = node.children[length-1]) && child.tag == 'br'){ node.children.splice(length-1,1); length = node.children.length; } } html = f.toHTML(node,pasteplain); }catch(e){} } //自定义的处理 html = {'html':html}; me.fireEvent('beforepaste',html); //不用在走过滤了 me.execCommand( 'insertHtml',html.html,true); me.fireEvent("afterpaste"); } } me.addListener('ready',function(){ domUtils.on(me.body,'cut',function(){ var range = me.selection.getRange(); if(!range.collapsed && me.undoManger){ me.undoManger.save(); } }); //ie下beforepaste在点击右键时也会触发,所以用监控键盘才处理 domUtils.on(me.body, browser.ie || browser.opera ? 'keydown' : 'paste',function(e){ if((browser.ie || browser.opera) && (!e.ctrlKey || e.keyCode != '86')){ return; } getClipboardData.call( me, function( div ) { filter(div); } ); }); }); }; })(); ///import core ///commands 有序列表,无序列表 ///commandsName InsertOrderedList,InsertUnorderedList ///commandsTitle 有序列表,无序列表 /** * 有序列表 * @function * @name baidu.editor.execCommand * @param {String} cmdName insertorderlist插入有序列表 * @param {String} style 值为:decimal,lower-alpha,lower-roman,upper-alpha,upper-roman * @author zhanyi */ /** * 无序链接 * @function * @name baidu.editor.execCommand * @param {String} cmdName insertunorderlist插入无序列表 * * @param {String} style 值为:circle,disc,square * @author zhanyi */ UE.plugins['list'] = function () { var me = this, notExchange = { 'TD':1, 'PRE':1, 'BLOCKQUOTE':1 }; me.setOpt( { 'insertorderedlist':{ 'decimal':'', //'1,2,3...' 'lower-alpha':'', // 'a,b,c...' 'lower-roman':'', //'i,ii,iii...' 'upper-alpha':'', //'A,B,C' 'upper-roman':'' //'I,II,III...' }, 'insertunorderedlist':{ 'circle':'', 'disc':'', 'square':'' } } ); function adjustList( list, tag, style ) { var nextList = list.nextSibling; if ( nextList && nextList.nodeType == 1 && nextList.tagName.toLowerCase() == tag && (domUtils.getStyle( nextList, 'list-style-type' ) || (tag == 'ol' ? 'decimal' : 'disc')) == style ) { domUtils.moveChild( nextList, list ); if ( nextList.childNodes.length == 0 ) { domUtils.remove( nextList ); } } var preList = list.previousSibling; if ( preList && preList.nodeType == 1 && preList.tagName.toLowerCase() == tag && (domUtils.getStyle( preList, 'list-style-type' ) || (tag == 'ol' ? 'decimal' : 'disc')) == style ) { domUtils.moveChild( list, preList ); } if ( list.childNodes.length == 0 ) { domUtils.remove( list ); } } me.addListener( 'keydown', function ( type, evt ) { function preventAndSave() { evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); me.undoManger && me.undoManger.save(); } var keyCode = evt.keyCode || evt.which; if ( keyCode == 13 ) {//回车 var range = me.selection.getRange(), start = domUtils.findParentByTagName( range.startContainer, ['ol', 'ul'], true, function ( node ) { return node.tagName == 'TABLE'; } ), end = domUtils.findParentByTagName( range.endContainer, ['ol', 'ul'], true, function ( node ) { return node.tagName == 'TABLE'; } ); if ( start && end && start === end ) { if ( !range.collapsed ) { start = domUtils.findParentByTagName( range.startContainer, 'li', true ); end = domUtils.findParentByTagName( range.endContainer, 'li', true ); if ( start && end && start === end ) { range.deleteContents(); li = domUtils.findParentByTagName( range.startContainer, 'li', true ); if ( li && domUtils.isEmptyBlock( li ) ) { pre = li.previousSibling; next = li.nextSibling; p = me.document.createElement( 'p' ); domUtils.fillNode( me.document, p ); parentList = li.parentNode; if ( pre && next ) { range.setStart( next, 0 ).collapse( true ).select( true ); domUtils.remove( li ); } else { if ( !pre && !next || !pre ) { parentList.parentNode.insertBefore( p, parentList ); } else { li.parentNode.parentNode.insertBefore( p, parentList.nextSibling ); } domUtils.remove( li ); if ( !parentList.firstChild ) { domUtils.remove( parentList ); } range.setStart( p, 0 ).setCursor(); } preventAndSave(); return; } } else { var tmpRange = range.cloneRange(), bk = tmpRange.collapse( false ).createBookmark(); range.deleteContents(); tmpRange.moveToBookmark( bk ); var li = domUtils.findParentByTagName( tmpRange.startContainer, 'li', true ), pre = li.previousSibling, next = li.nextSibling; if ( pre ) { li = pre; if ( pre.firstChild && domUtils.isBlockElm( pre.firstChild ) ) { pre = pre.firstChild; } if ( domUtils.isEmptyNode( pre ) ){ domUtils.remove( li ); } } if ( next ) { li = next; if ( next.firstChild && domUtils.isBlockElm( next.firstChild ) ) { next = next.firstChild; } if ( domUtils.isEmptyNode( next ) ){ domUtils.remove( li ); } } tmpRange.select(); preventAndSave(); return; } } li = domUtils.findParentByTagName( range.startContainer, 'li', true ); if ( li ) { if ( domUtils.isEmptyBlock( li ) ) { bk = range.createBookmark(); var parentList = li.parentNode; if ( li !== parentList.lastChild ) { domUtils.breakParent( li, parentList ); } else { parentList.parentNode.insertBefore( li, parentList.nextSibling ); if ( domUtils.isEmptyNode( parentList ) ) { domUtils.remove( parentList ); } } //嵌套不处理 if ( !dtd.$list[li.parentNode.tagName] ) { if ( !domUtils.isBlockElm( li.firstChild ) ) { p = me.document.createElement( 'p' ); li.parentNode.insertBefore( p, li ); while ( li.firstChild ) { p.appendChild( li.firstChild ); } domUtils.remove( li ); } else { domUtils.remove( li, true ); } } range.moveToBookmark( bk ).select(); } else { var first = li.firstChild; if ( !first || !domUtils.isBlockElm( first ) ) { var p = me.document.createElement( 'p' ); !li.firstChild && domUtils.fillNode( me.document, p ); while ( li.firstChild ) { p.appendChild( li.firstChild ); } li.appendChild( p ); first = p; } var span = me.document.createElement( 'span' ); range.insertNode( span ); domUtils.breakParent( span, li ); var nextLi = span.nextSibling; first = nextLi.firstChild; if ( !first ) { p = me.document.createElement( 'p' ); domUtils.fillNode( me.document, p ); nextLi.appendChild( p ); first = p; } if ( domUtils.isEmptyNode( first ) ) { first.innerHTML = ''; domUtils.fillNode( me.document, first ); } range.setStart( first, 0 ).collapse( true ).shrinkBoundary().select(); domUtils.remove( span ); pre = nextLi.previousSibling; if ( pre && domUtils.isEmptyBlock( pre ) ) { pre.innerHTML = '

'; domUtils.fillNode( me.document, pre.firstChild ); } } // } preventAndSave(); } } } if ( keyCode == 8 ) { //修中ie中li下的问题 range = me.selection.getRange(); if ( range.collapsed && domUtils.isStartInblock( range ) ) { tmpRange = range.cloneRange().trimBoundary(); li = domUtils.findParentByTagName( range.startContainer, 'li', true ); //要在li的最左边,才能处理 if ( li && domUtils.isStartInblock( tmpRange ) ) { if ( li && (pre = li.previousSibling) ) { if ( keyCode == 46 && li.childNodes.length ){ return; } //有可能上边的兄弟节点是个2级菜单,要追加到2级菜单的最后的li if ( dtd.$list[pre.tagName] ) { pre = pre.lastChild; } me.undoManger && me.undoManger.save(); first = li.firstChild; if ( domUtils.isBlockElm( first ) ) { if ( domUtils.isEmptyNode( first ) ) { // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); pre.appendChild( first ); range.setStart( first, 0 ).setCursor( false, true ); //first不是唯一的节点 while ( li.firstChild ) { pre.appendChild( li.firstChild ); } } else { start = domUtils.findParentByTagName( range.startContainer, 'p', true ); if ( start && start !== first ) { return; } span = me.document.createElement( 'span' ); range.insertNode( span ); //判断pre是否是空的节点,如果是


类型的空节点,干掉p标签防止它占位 if(domUtils.isEmptyBlock(pre)){ pre.innerHTML = ''; } domUtils.moveChild( li, pre ); range.setStartBefore( span ).collapse( true ).select( true ); domUtils.remove( span ); } } else { if ( domUtils.isEmptyNode( li ) ) { var p = me.document.createElement( 'p' ); pre.appendChild( p ); range.setStart( p, 0 ).setCursor(); // range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true); } else { range.setEnd( pre, pre.childNodes.length ).collapse().select( true ); while ( li.firstChild ) { pre.appendChild( li.firstChild ); } } } domUtils.remove( li ); me.undoManger && me.undoManger.save(); domUtils.preventDefault( evt ); return; } //trace:980 if ( li && !li.previousSibling ) { first = li.firstChild; //trace:1648 要判断li下只有一个节点 if ( !first || li.lastChild === first && domUtils.isEmptyNode( domUtils.isBlockElm( first ) ? first : li ) ) { var p = me.document.createElement( 'p' ); li.parentNode.parentNode.insertBefore( p, li.parentNode ); domUtils.fillNode( me.document, p ); range.setStart( p, 0 ).setCursor(); domUtils.remove( !li.nextSibling ? li.parentNode : li ); me.undoManger && me.undoManger.save(); domUtils.preventDefault( evt ); return; } } } } } } ); me.commands['insertorderedlist'] = me.commands['insertunorderedlist'] = { execCommand:function ( command, style ) { if ( !style ) { style = command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc'; } var me = this, range = this.selection.getRange(), filterFn = function ( node ) { return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace( node ); }, tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul', frag = me.document.createDocumentFragment(); //去掉是因为会出现选到末尾,导致adjustmentBoundary缩到ol/ul的位置 //range.shrinkBoundary();//.adjustmentBoundary(); range.adjustmentBoundary().shrinkBoundary(); var bko = range.createBookmark( true ), start = domUtils.findParentByTagName( me.document.getElementById( bko.start ), 'li' ), modifyStart = 0, end = domUtils.findParentByTagName( me.document.getElementById( bko.end ), 'li' ), modifyEnd = 0, startParent, endParent, list, tmp; if ( start || end ) { start && (startParent = start.parentNode); if ( !bko.end ) { end = start; } end && (endParent = end.parentNode); if ( startParent === endParent ) { while ( start !== end ) { tmp = start; start = start.nextSibling; if ( !domUtils.isBlockElm( tmp.firstChild ) ) { var p = me.document.createElement( 'p' ); while ( tmp.firstChild ) { p.appendChild( tmp.firstChild ); } tmp.appendChild( p ); } frag.appendChild( tmp ); } tmp = me.document.createElement( 'span' ); startParent.insertBefore( tmp, end ); if ( !domUtils.isBlockElm( end.firstChild ) ) { p = me.document.createElement( 'p' ); while ( end.firstChild ) { p.appendChild( end.firstChild ); } end.appendChild( p ); } frag.appendChild( end ); domUtils.breakParent( tmp, startParent ); if ( domUtils.isEmptyNode( tmp.previousSibling ) ) { domUtils.remove( tmp.previousSibling ); } if ( domUtils.isEmptyNode( tmp.nextSibling ) ) { domUtils.remove( tmp.nextSibling ) } var nodeStyle = domUtils.getComputedStyle( startParent, 'list-style-type' ) || (command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc'); if ( startParent.tagName.toLowerCase() == tag && nodeStyle == style ) { for ( var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); ci = frag.childNodes[i++]; ) { while ( ci.firstChild ) { tmpFrag.appendChild( ci.firstChild ); } } tmp.parentNode.insertBefore( tmpFrag, tmp ); } else { list = me.document.createElement( tag ); domUtils.setStyle( list, 'list-style-type', style ); list.appendChild( frag ); tmp.parentNode.insertBefore( list, tmp ); } domUtils.remove( tmp ); list && adjustList( list, tag, style ); range.moveToBookmark( bko ).select(); return; } //开始 if ( start ) { while ( start ) { tmp = start.nextSibling; var tmpfrag = me.document.createDocumentFragment(), hasBlock = 0; while ( start.firstChild ) { if ( domUtils.isBlockElm( start.firstChild ) ){ hasBlock = 1; } tmpfrag.appendChild( start.firstChild ); } if ( !hasBlock ) { var tmpP = me.document.createElement( 'p' ); tmpP.appendChild( tmpfrag ); frag.appendChild( tmpP ); } else { frag.appendChild( tmpfrag ); } domUtils.remove( start ); start = tmp; } startParent.parentNode.insertBefore( frag, startParent.nextSibling ); if ( domUtils.isEmptyNode( startParent ) ) { range.setStartBefore( startParent ); domUtils.remove( startParent ); } else { range.setStartAfter( startParent ); } modifyStart = 1; } if ( end ) { //结束 start = endParent.firstChild; while ( start !== end ) { tmp = start.nextSibling; tmpfrag = me.document.createDocumentFragment(); hasBlock = 0; while ( start.firstChild ) { if ( domUtils.isBlockElm( start.firstChild ) ){ hasBlock = 1; } tmpfrag.appendChild( start.firstChild ); } if ( !hasBlock ) { tmpP = me.document.createElement( 'p' ); tmpP.appendChild( tmpfrag ); frag.appendChild( tmpP ); } else { frag.appendChild( tmpfrag ); } domUtils.remove( start ); start = tmp; } frag.appendChild( end.firstChild ); domUtils.remove( end ); endParent.parentNode.insertBefore( frag, endParent ); range.setEndBefore( endParent ); if ( domUtils.isEmptyNode( endParent ) ) { domUtils.remove( endParent ); } modifyEnd = 1; } } if ( !modifyStart ) { range.setStartBefore( me.document.getElementById( bko.start ) ); } if ( bko.end && !modifyEnd ) { range.setEndAfter( me.document.getElementById( bko.end ) ); } range.enlarge( true, function ( node ) { return notExchange[node.tagName]; } ); frag = me.document.createDocumentFragment(); var bk = range.createBookmark(), current = domUtils.getNextDomNode( bk.start, false, filterFn ), tmpRange = range.cloneRange(), tmpNode, block = domUtils.isBlockElm; while ( current && current !== bk.end && (domUtils.getPosition( current, bk.end ) & domUtils.POSITION_PRECEDING) ) { if ( current.nodeType == 3 || dtd.li[current.tagName] ) { if ( current.nodeType == 1 && dtd.$list[current.tagName] ) { while ( current.firstChild ) { frag.appendChild( current.firstChild ); } tmpNode = domUtils.getNextDomNode( current, false, filterFn ); domUtils.remove( current ); current = tmpNode; continue; } tmpNode = current; tmpRange.setStartBefore( current ); while ( current && current !== bk.end && (!block( current ) || domUtils.isBookmarkNode( current ) ) ) { tmpNode = current; current = domUtils.getNextDomNode( current, false, null, function ( node ) { return !notExchange[node.tagName]; } ); } if ( current && block( current ) ) { tmp = domUtils.getNextDomNode( tmpNode, false, filterFn ); if ( tmp && domUtils.isBookmarkNode( tmp ) ) { current = domUtils.getNextDomNode( tmp, false, filterFn ); tmpNode = tmp; } } tmpRange.setEndAfter( tmpNode ); current = domUtils.getNextDomNode( tmpNode, false, filterFn ); var li = range.document.createElement( 'li' ); li.appendChild( tmpRange.extractContents() ); frag.appendChild( li ); } else { current = domUtils.getNextDomNode( current, true, filterFn ); } } range.moveToBookmark( bk ).collapse( true ); list = me.document.createElement( tag ); domUtils.setStyle( list, 'list-style-type', style ); list.appendChild( frag ); range.insertNode( list ); //当前list上下看能否合并 adjustList( list, tag, style ); range.moveToBookmark( bko ).select(); }, queryCommandState:function ( command ) { return this.highlight ? -1 : utils.findNode( this.selection.getStartElementPath(), [command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul'] ) ? 1 : 0; }, queryCommandValue:function ( command ) { var node = utils.findNode( this.selection.getStartElementPath(), [command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul'] ); return node ? domUtils.getComputedStyle( node, 'list-style-type' ) : null; } }; }; ///import core ///import plugins/serialize.js ///import plugins/undo.js ///commands 查看源码 ///commandsName Source ///commandsTitle 查看源码 (function (){ function SourceFormater(config){ config = config || {}; this.indentChar = config.indentChar || ' '; this.breakChar = config.breakChar || '\n'; this.selfClosingEnd = config.selfClosingEnd || ' />'; } var unhtml1 = function (){ var map = { '<': '<', '>': '>', '"': '"', "'": ''' }; function rep( m ){ return map[m]; } return function ( str ) { str = str + ''; return str ? str.replace( /[<>"']/g, rep ) : ''; }; }(); var inline = utils.extend({a:1,A:1},dtd.$inline,true); function printAttrs(attrs){ var buff = []; for (var k in attrs) { buff.push(k + '="' + unhtml1(attrs[k]) + '"'); } return buff.join(' '); } SourceFormater.prototype = { format: function (html){ var node = UE.serialize.parseHTML(html); this.buff = []; this.indents = ''; this.indenting = 1; this.visitNode(node); return this.buff.join(''); }, visitNode: function (node){ if (node.type == 'fragment') { this.visitChildren(node.children); } else if (node.type == 'element') { var selfClosing = dtd.$empty[node.tag]; this.visitTag(node.tag, node.attributes, selfClosing); this.visitChildren(node.children); if (!selfClosing) { this.visitEndTag(node.tag); } } else if (node.type == 'comment') { this.visitComment(node.data); } else { this.visitText(node.data,dtd.$notTransContent[node.parent.tag]); } }, visitChildren: function (children){ for (var i=0; i'); this.indents += this.indentChar; } if (!inline[tag]) { this.newline(); } }, indent: function (){ this.buff.push(this.indents); this.indenting = 0; }, newline: function (){ this.buff.push(this.breakChar); this.indenting = 1; }, visitEndTag: function (tag){ this.indents = this.indents.slice(0, -this.indentChar.length); if (this.indenting) { this.indent(); } else if (!inline[tag]) { this.newline(); this.indent(); } this.buff.push(''); }, visitText: function (text,notTrans){ if (this.indenting) { this.indent(); } // if(!notTrans){ // text = text.replace(/ /g, ' ').replace(/[ ][ ]+/g, function (m){ // return new Array(m.length + 1).join(' '); // }).replace(/(?:^ )|(?: $)/g, ' '); // } text = text.replace(/ /g, ' '); this.buff.push(text); }, visitComment: function (text){ if (this.indenting) { this.indent(); } this.buff.push(''); } }; var sourceEditors = { textarea: function (editor, holder){ var textarea = holder.ownerDocument.createElement('textarea'); textarea.style.cssText = 'position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;'; // todo: IE下只有onresize属性可用... 很纠结 if (browser.ie && browser.version < 8) { textarea.style.width = holder.offsetWidth + 'px'; textarea.style.height = holder.offsetHeight + 'px'; holder.onresize = function (){ textarea.style.width = holder.offsetWidth + 'px'; textarea.style.height = holder.offsetHeight + 'px'; }; } holder.appendChild(textarea); return { setContent: function (content){ textarea.value = content; }, getContent: function (){ return textarea.value; }, select: function (){ var range; if (browser.ie) { range = textarea.createTextRange(); range.collapse(true); range.select(); } else { //todo: chrome下无法设置焦点 textarea.setSelectionRange(0, 0); textarea.focus(); } }, dispose: function (){ holder.removeChild(textarea); // todo holder.onresize = null; textarea = null; holder = null; } }; }, codemirror: function (editor, holder){ var options = { mode: "text/html", tabMode: "indent", lineNumbers: true, lineWrapping:true }; var codeEditor = window.CodeMirror(holder, options); var dom = codeEditor.getWrapperElement(); dom.style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;'; codeEditor.getScrollerElement().style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;'; codeEditor.refresh(); return { setContent: function (content){ codeEditor.setValue(content); }, getContent: function (){ return codeEditor.getValue(); }, select: function (){ codeEditor.focus(); }, dispose: function (){ holder.removeChild(dom); dom = null; codeEditor = null; } }; } }; UE.plugins['source'] = function (){ var me = this; var opt = this.options; var formatter = new SourceFormater(opt.source); var sourceMode = false; var sourceEditor; opt.sourceEditor = opt.sourceEditor || 'codemirror'; me.setOpt({ sourceEditorFirst:false }); function createSourceEditor(holder){ return sourceEditors[opt.sourceEditor == 'codemirror' && window.CodeMirror ? 'codemirror' : 'textarea'](me, holder); } var bakCssText; me.commands['source'] = { execCommand: function (){ sourceMode = !sourceMode; if (sourceMode) { me.undoManger && me.undoManger.save(); this.currentSelectedArr && domUtils.clearSelectedArr(this.currentSelectedArr); if(browser.gecko){ me.body.contentEditable = false; } bakCssText = me.iframe.style.cssText; me.iframe.style.cssText += 'position:absolute;left:-32768px;top:-32768px;'; var content = formatter.format(me.hasContents() ? me.getContent() : ''); sourceEditor = createSourceEditor(me.iframe.parentNode); sourceEditor.setContent(content); setTimeout(function (){ sourceEditor.select(); }); } else { me.iframe.style.cssText = bakCssText; var cont = sourceEditor.getContent() || '

' + (browser.ie ? '' : '
')+'

'; cont = cont.replace(/>[\n\r\t]+([ ]{4})+/g,'>').replace(/[\n\r\t]+([ ]{4})+[\n\r\t]+<'); me.setContent(cont); sourceEditor.dispose(); sourceEditor = null; setTimeout(function(){ var first = me.body.firstChild; //trace:1106 都删除空了,下边会报错,所以补充一个p占位 if(!first){ me.body.innerHTML = '

'+(browser.ie?'':'
')+'

'; first = me.body.firstChild; } //要在ifm为显示时ff才能取到selection,否则报错 me.undoManger && me.undoManger.save(); while(first && first.firstChild){ first = first.firstChild; } var range = me.selection.getRange(); if(first.nodeType == 3 || dtd.$empty[first.tagName]){ range.setStartBefore(first); }else{ range.setStart(first,0); } if(browser.gecko){ var input = document.createElement('input'); input.style.cssText = 'position:absolute;left:0;top:-32768px'; document.body.appendChild(input); me.body.contentEditable = false; setTimeout(function(){ domUtils.setViewportOffset(input, { left: -32768, top: 0 }); input.focus(); setTimeout(function(){ me.body.contentEditable = true; range.setCursor(false,true); domUtils.remove(input); }); }); }else{ range.setCursor(false,true); } }); } this.fireEvent('sourcemodechanged', sourceMode); }, queryCommandState: function (){ return sourceMode|0; }, notNeedUndo : 1 }; var oldQueryCommandState = me.queryCommandState; me.queryCommandState = function (cmdName){ cmdName = cmdName.toLowerCase(); if (sourceMode) { return cmdName == 'source' ? 1 : -1; } return oldQueryCommandState.apply(this, arguments); }; //解决在源码模式下getContent不能得到最新的内容问题 var oldGetContent = me.getContent; me.getContent = function (){ if(sourceMode && sourceEditor ){ var html = sourceEditor.getContent(); if (this.serialize) { var node = this.serialize.parseHTML(html); node = this.serialize.filter(node); html = this.serialize.toHTML(node); } return html; }else{ return oldGetContent.apply(this, arguments); } }; if(opt.sourceEditor == "codemirror"){ me.addListener("ready",function(){ utils.loadFile(document,{ src : opt.codeMirrorJsUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror2.15/codemirror.js", tag : "script", type : "text/javascript", defer : "defer" },function(){ if(opt.sourceEditorFirst){ setTimeout(function(){ me.execCommand("source"); },0); } }); utils.loadFile(document,{ tag : "link", rel : "stylesheet", type : "text/css", href : opt.codeMirrorCssUrl || opt.UEDITOR_HOME_URL + "third-party/codemirror2.15/codemirror.css" }); }); } }; })(); ///import core ///commands 快捷键 ///commandsName ShortCutKeys ///commandsTitle 快捷键 //配置快捷键 UE.plugins['shortcutkeys'] = function(){ var me = this, shortcutkeys = { "ctrl+66" : "Bold" ,//^B "ctrl+90" : "Undo" ,//undo "ctrl+89" : "Redo", //redo "ctrl+73" : "Italic", //^I "ctrl+85" : "Underline" ,//^U "ctrl+shift+67" : "removeformat", //清除格式 "ctrl+shift+76" : "justify:left", //居左 "ctrl+shift+82" : "justify:right", //居右 "ctrl+65" : "selectAll", "ctrl+13" : "autosubmit"//手动提交 // ,"9" : "indent" //tab }; me.addListener('keydown',function(type,e){ var keyCode = e.keyCode || e.which,value; for ( var i in shortcutkeys ) { if ( /^(ctrl)(\+shift)?\+(\d+)$/.test( i.toLowerCase() ) || /^(\d+)$/.test( i ) ) { if ( ( (RegExp.$1 == 'ctrl' ? (e.ctrlKey||e.metaKey||browser.opera && keyCode == 17) : 0) && (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1) && keyCode == RegExp.$3 ) || keyCode == RegExp.$1 ){ value = shortcutkeys[i].split(':'); me.execCommand( value[0],value[1]); domUtils.preventDefault(e); } } } }); }; ///import core ///import plugins/undo.js ///commands 设置回车标签p或br ///commandsName EnterKey ///commandsTitle 设置回车标签p或br /** * @description 处理回车 * @author zhanyi */ UE.plugins['enterkey'] = function() { var hTag, me = this, tag = me.options.enterTag; me.addListener('keyup', function(type, evt) { var keyCode = evt.keyCode || evt.which; if (keyCode == 13) { var range = me.selection.getRange(), start = range.startContainer, doSave; //修正在h1-h6里边回车后不能嵌套p的问题 if (!browser.ie) { if (/h\d/i.test(hTag)) { if (browser.gecko) { var h = domUtils.findParentByTagName(start, [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6','blockquote'], true); if (!h) { me.document.execCommand('formatBlock', false, '

'); doSave = 1; } } else { //chrome remove div if (start.nodeType == 1) { var tmp = me.document.createTextNode(''),div; range.insertNode(tmp); div = domUtils.findParentByTagName(tmp, 'div', true); if (div) { var p = me.document.createElement('p'); while (div.firstChild) { p.appendChild(div.firstChild); } div.parentNode.insertBefore(p, div); domUtils.remove(div); range.setStartBefore(tmp).setCursor(); doSave = 1; } domUtils.remove(tmp); } } if (me.undoManger && doSave) { me.undoManger.save(); } } //没有站位符,会出现多行的问题 browser.opera && range.select(); } setTimeout(function() { me.selection.getRange().scrollToView(me.autoHeightEnabled, me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0); }, 50); } }); me.addListener('keydown', function(type, evt) { var keyCode = evt.keyCode || evt.which; if (keyCode == 13) {//回车 if (me.undoManger) { me.undoManger.save(); } hTag = ''; var range = me.selection.getRange(); if (!range.collapsed) { //跨td不能删 var start = range.startContainer, end = range.endContainer, startTd = domUtils.findParentByTagName(start, 'td', true), endTd = domUtils.findParentByTagName(end, 'td', true); if (startTd && endTd && startTd !== endTd || !startTd && endTd || startTd && !endTd) { evt.preventDefault ? evt.preventDefault() : ( evt.returnValue = false); return; } } me.currentSelectedArr && domUtils.clearSelectedArr(me.currentSelectedArr); if (tag == 'p') { if (!browser.ie) { start = domUtils.findParentByTagName(range.startContainer, ['ol','ul','p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6','blockquote'], true); //opera下执行formatblock会在table的场景下有问题,回车在opera原生支持很好,所以暂时在opera去掉调用这个原生的command //trace:2431 if (!start && !browser.opera) { me.document.execCommand('formatBlock', false, '

'); if (browser.gecko) { range = me.selection.getRange(); start = domUtils.findParentByTagName(range.startContainer, 'p', true); start && domUtils.removeDirtyAttr(start); } } else { hTag = start.tagName; start.tagName.toLowerCase() == 'p' && browser.gecko && domUtils.removeDirtyAttr(start); } } } else { evt.preventDefault ? evt.preventDefault() : ( evt.returnValue = false); if (!range.collapsed) { range.deleteContents(); start = range.startContainer; if (start.nodeType == 1 && (start = start.childNodes[range.startOffset])) { while (start.nodeType == 1) { if (dtd.$empty[start.tagName]) { range.setStartBefore(start).setCursor(); if (me.undoManger) { me.undoManger.save(); } return false; } if (!start.firstChild) { var br = range.document.createElement('br'); start.appendChild(br); range.setStart(start, 0).setCursor(); if (me.undoManger) { me.undoManger.save(); } return false; } start = start.firstChild; } if (start === range.startContainer.childNodes[range.startOffset]) { br = range.document.createElement('br'); range.insertNode(br).setCursor(); } else { range.setStart(start, 0).setCursor(); } } else { br = range.document.createElement('br'); range.insertNode(br).setStartAfter(br).setCursor(); } } else { br = range.document.createElement('br'); range.insertNode(br); var parent = br.parentNode; if (parent.lastChild === br) { br.parentNode.insertBefore(br.cloneNode(true), br); range.setStartBefore(br); } else { range.setStartAfter(br); } range.setCursor(); } } } }); }; /* * 处理特殊键的兼容性问题 */ UE.plugins['keystrokes'] = function() { var me = this, flag = 0, keys = domUtils.keys, trans = { 'B' : 'strong', 'I' : 'em', 'FONT' : 'span' }, sizeMap = [0, 10, 12, 16, 18, 24, 32, 48], listStyle = { 'OL':['decimal','lower-alpha','lower-roman','upper-alpha','upper-roman'], 'UL':[ 'circle','disc','square'] }; me.addListener('keydown', function(type, evt) { var keyCode = evt.keyCode || evt.which; if(this.selectAll){ this.selectAll = false; if((keyCode == 8 || keyCode == 46)){ me.undoManger && me.undoManger.save(); //trace:1633 me.body.innerHTML = '

'+(browser.ie ? '' : '
')+'

'; new dom.Range(me.document).setStart(me.body.firstChild,0).setCursor(false,true); me.undoManger && me.undoManger.save(); //todo 对性能会有影响 browser.ie && me._selectionChange(); domUtils.preventDefault(evt); return; } } //处理backspace/del if (keyCode == 8 ) {//|| keyCode == 46 var range = me.selection.getRange(), tmpRange, start,end; //当删除到body最开始的位置时,会删除到body,阻止这个动作 if(range.collapsed){ start = range.startContainer; //有可能是展位符号 if(domUtils.isWhitespace(start)){ start = start.parentNode; } if(domUtils.isEmptyNode(start) && start === me.body.firstChild){ if(start.tagName != 'P'){ p = me.document.createElement('p'); me.body.insertBefore(p,start); domUtils.fillNode(me.document,p); range.setStart(p,0).setCursor(false,true); //trace:1645 domUtils.remove(start); } domUtils.preventDefault(evt); return; } } if (range.collapsed && range.startContainer.nodeType == 3 && range.startContainer.nodeValue.replace(new RegExp(domUtils.fillChar, 'g'), '').length == 0) { range.setStartBefore(range.startContainer).collapse(true); } //解决选中control元素不能删除的问题 if (start = range.getClosedNode()) { me.undoManger && me.undoManger.save(); range.setStartBefore(start); domUtils.remove(start); range.setCursor(); me.undoManger && me.undoManger.save(); domUtils.preventDefault(evt); return; } //阻止在table上的删除 if (!browser.ie) { start = domUtils.findParentByTagName(range.startContainer, 'table', true); end = domUtils.findParentByTagName(range.endContainer, 'table', true); if (start && !end || !start && end || start !== end) { evt.preventDefault(); return; } //表格里回车,删除时,光标被定位到了p外边,导致多次删除才能到上一行,这里的处理忘记是为什么,暂时注视掉 //解决trace:1966的问题 // if (browser.webkit && range.collapsed && start) { // tmpRange = range.cloneRange().txtToElmBoundary(); // start = tmpRange.startContainer; // debugger // if (domUtils.isBlockElm(start) && !dtd.$tableContent[start.tagName] && !domUtils.getChildCount(start, function(node) { // return node.nodeType == 1 ? node.tagName !== 'BR' : 1; // })) { // // tmpRange.setStartBefore(start).setCursor(); // domUtils.remove(start, true); // evt.preventDefault(); // return; // } // } } if (me.undoManger) { if (!range.collapsed) { me.undoManger.save(); flag = 1; } } } //处理tab键的逻辑 if (keyCode == 9) { range = me.selection.getRange(); me.undoManger && me.undoManger.save(); for (var i = 0,txt = '',tabSize = me.options.tabSize|| 4,tabNode = me.options.tabNode || ' '; i < tabSize; i++) { txt += tabNode; } var span = me.document.createElement('span'); span.innerHTML = txt; if (range.collapsed) { var li = domUtils.findParentByTagName(range.startContainer, 'li', true); if (li && domUtils.isStartInblock(range)) { bk = range.createBookmark(); var parentLi = li.parentNode, list = me.document.createElement(parentLi.tagName); var index = utils.indexOf(listStyle[list.tagName], domUtils.getComputedStyle(parentLi, 'list-style-type')); index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1; domUtils.setStyle(list, 'list-style-type', listStyle[list.tagName][index]); parentLi.insertBefore(list, li); list.appendChild(li); range.moveToBookmark(bk).select(); } else{ range.insertNode(span.cloneNode(true).firstChild).setCursor(true); } } else { //处理table start = domUtils.findParentByTagName(range.startContainer, 'table', true); end = domUtils.findParentByTagName(range.endContainer, 'table', true); if (start || end) { evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); return; } //处理列表 再一个list里处理 start = domUtils.findParentByTagName(range.startContainer, ['ol','ul'], true); end = domUtils.findParentByTagName(range.endContainer, ['ol','ul'], true); if (start && end && start === end) { var bk = range.createBookmark(); start = domUtils.findParentByTagName(range.startContainer, 'li', true); end = domUtils.findParentByTagName(range.endContainer, 'li', true); //在开始单独处理 if (start === start.parentNode.firstChild) { var parentList = me.document.createElement(start.parentNode.tagName); start.parentNode.parentNode.insertBefore(parentList, start.parentNode); parentList.appendChild(start.parentNode); } else { parentLi = start.parentNode; list = me.document.createElement(parentLi.tagName); index = utils.indexOf(listStyle[list.tagName], domUtils.getComputedStyle(parentLi, 'list-style-type')); index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1; domUtils.setStyle(list, 'list-style-type', listStyle[list.tagName][index]); start.parentNode.insertBefore(list, start); var nextLi; while (start !== end) { nextLi = start.nextSibling; list.appendChild(start); start = nextLi; } list.appendChild(end); } range.moveToBookmark(bk).select(); } else { if (start || end) { evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); return } //普通的情况 start = domUtils.findParent(range.startContainer, filterFn); end = domUtils.findParent(range.endContainer, filterFn); if (start && end && start === end) { range.deleteContents(); range.insertNode(span.cloneNode(true).firstChild).setCursor(true); } else { var bookmark = range.createBookmark(), filterFn = function(node) { return domUtils.isBlockElm(node); }; range.enlarge(true); var bookmark2 = range.createBookmark(), current = domUtils.getNextDomNode(bookmark2.start, false, filterFn); while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) { current.insertBefore(span.cloneNode(true).firstChild, current.firstChild); current = domUtils.getNextDomNode(current, false, filterFn); } range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select(); } } } me.undoManger && me.undoManger.save(); evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); } //trace:1634 //ff的del键在容器空的时候,也会删除 if(browser.gecko && keyCode == 46){ range = me.selection.getRange(); if(range.collapsed){ start = range.startContainer; if(domUtils.isEmptyBlock(start)){ var parent = start.parentNode; while(domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)){ start = parent; parent = parent.parentNode; } if(start === parent.lastChild) evt.preventDefault(); return; } } } }); me.addListener('keyup', function(type, evt) { var keyCode = evt.keyCode || evt.which; //修复ie/chrome x| 当点退格后在输入文字后会出现 x if (!browser.gecko && !keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) { range = me.selection.getRange(); if (range.collapsed) { var start = range.startContainer, isFixed = 0; while (!domUtils.isBlockElm(start)) { if (start.nodeType == 1 && utils.indexOf(['FONT','B','I'], start.tagName) != -1) { var tmpNode = me.document.createElement(trans[start.tagName]); if (start.tagName == 'FONT') { //chrome only remember color property tmpNode.style.cssText = (start.getAttribute('size') ? 'font-size:' + (sizeMap[start.getAttribute('size')] || 12) + 'px' : '') + ';' + (start.getAttribute('color') ? 'color:' + start.getAttribute('color') : '') + ';' + (start.getAttribute('face') ? 'font-family:' + start.getAttribute('face') : '') + ';' + start.style.cssText; } while (start.firstChild) { tmpNode.appendChild(start.firstChild) } start.parentNode.insertBefore(tmpNode, start); domUtils.remove(start); if (!isFixed) { range.setEnd(tmpNode, tmpNode.childNodes.length).collapse(true) } start = tmpNode; isFixed = 1; } start = start.parentNode; } isFixed && range.select() } } if (keyCode == 8 ) {//|| keyCode == 46 //针对ff下在列表首行退格,不能删除空格行的问题 if(browser.gecko){ for(var i=0,li,lis = domUtils.getElementsByTagName(this.body,'li');li=lis[i++];){ if(domUtils.isEmptyNode(li) && !li.previousSibling){ var liOfPn = li.parentNode; domUtils.remove(li); if(domUtils.isEmptyNode(liOfPn)){ domUtils.remove(liOfPn) } } } } var range,start,parent, tds = this.currentSelectedArr; if (tds && tds.length > 0) { for (var i = 0,ti; ti = tds[i++];) { ti.innerHTML = browser.ie ? ( browser.version < 9 ? '' : '' ) : '
'; } range = new dom.Range(this.document); range.setStart(tds[0], 0).setCursor(); if (flag) { me.undoManger.save(); flag = 0; } //阻止chrome执行默认的动作 if (browser.webkit) { evt.preventDefault(); } return; } range = me.selection.getRange(); //ctrl+a 后全部删除做处理 // // if (domUtils.isEmptyBlock(me.body) && !range.startOffset) { // //trace:1633 // me.body.innerHTML = '

'+(browser.ie ? ' ' : '
')+'

'; // range.setStart(me.body.firstChild,0).setCursor(false,true); // me.undoManger && me.undoManger.save(); // //todo 对性能会有影响 // browser.ie && me._selectionChange(); // return; // } //处理删除不干净的问题 start = range.startContainer; if(domUtils.isWhitespace(start)){ start = start.parentNode } //标志位防止空的p无法删除 var removeFlag = 0; while (start.nodeType == 1 && domUtils.isEmptyNode(start) && dtd.$removeEmpty[start.tagName]) { removeFlag = 1; parent = start.parentNode; domUtils.remove(start); start = parent; } if ( removeFlag && start.nodeType == 1 && domUtils.isEmptyNode(start)) { //ie下的问题,虽然没有了相应的节点但一旦你输入文字还是会自动把删除的节点加上, if (browser.ie) { var span = range.document.createElement('span'); start.appendChild(span); range.setStart(start,0).setCursor(); //for ie li = domUtils.findParentByTagName(start,'li',true); if(li){ var next = li.nextSibling; while(next){ if(domUtils.isEmptyBlock(next)){ li = next; next = next.nextSibling; domUtils.remove(li); continue; } break; } } } else { start.innerHTML = '
'; range.setStart(start, 0).setCursor(false,true); } setTimeout(function() { if (browser.ie) { domUtils.remove(span); } if (flag) { me.undoManger.save(); flag = 0; } }, 0) } else { if (flag) { me.undoManger.save(); flag = 0; } } } }) }; ///import core ///commands 修复chrome下图片不能点击的问题 ///commandsName FixImgClick ///commandsTitle 修复chrome下图片不能点击的问题 //修复chrome下图片不能点击的问题 //todo 可以改大小 UE.plugins['fiximgclick'] = function() { var me = this; if ( browser.webkit ) { me.addListener( 'click', function( type, e ) { if ( e.target.tagName == 'IMG' ) { var range = new dom.Range( me.document ); range.selectNode( e.target ).select(); } } ); } }; ///import core ///commands 为非ie浏览器自动添加a标签 ///commandsName AutoLink ///commandsTitle 自动增加链接 /** * @description 为非ie浏览器自动添加a标签 * @author zhanyi */ UE.plugins['autolink'] = function() { var cont = 0; if (browser.ie) { return; } var me = this; me.addListener('reset',function(){ cont = 0; }); me.addListener('keydown', function(type, evt) { var keyCode = evt.keyCode || evt.which; if (keyCode == 32 || keyCode == 13) { var sel = me.selection.getNative(), range = sel.getRangeAt(0).cloneRange(), offset, charCode; var start = range.startContainer; while (start.nodeType == 1 && range.startOffset > 0) { start = range.startContainer.childNodes[range.startOffset - 1]; if (!start){ break; } range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length); range.collapse(true); start = range.startContainer; } do{ if (range.startOffset == 0) { start = range.startContainer.previousSibling; while (start && start.nodeType == 1) { start = start.lastChild; } if (!start || domUtils.isFillChar(start)){ break; } offset = start.nodeValue.length; } else { start = range.startContainer; offset = range.startOffset; } range.setStart(start, offset - 1); charCode = range.toString().charCodeAt(0); } while (charCode != 160 && charCode != 32); if (range.toString().replace(new RegExp(domUtils.fillChar, 'g'), '').match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) { while(range.toString().length){ if(/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())){ break; } try{ range.setStart(range.startContainer,range.startOffset+1); }catch(e){ //trace:2121 var start = range.startContainer; while(!(next = start.nextSibling)){ if(domUtils.isBody(start)){ return; } start = start.parentNode; } range.setStart(next,0); } } var a = me.document.createElement('a'),text = me.document.createTextNode(' '),href; me.undoManger && me.undoManger.save(); a.appendChild(range.extractContents()); a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g,''); href = a.getAttribute("href").replace(new RegExp(domUtils.fillChar,'g'),''); href = /^(?:https?:\/\/)/ig.test(href) ? href : "http://"+ href; a.setAttribute('data_ue_src',href); a.href = href; range.insertNode(a); a.parentNode.insertBefore(text, a.nextSibling); range.setStart(text, 0); range.collapse(true); sel.removeAllRanges(); sel.addRange(range); me.undoManger && me.undoManger.save(); } } }); }; ///import core ///commands 当输入内容超过编辑器高度时,编辑器自动增高 ///commandsName AutoHeight,autoHeightEnabled ///commandsTitle 自动增高 /** * @description 自动伸展 * @author zhanyi */ UE.plugins['autoheight'] = function () { var me = this; //提供开关,就算加载也可以关闭 me.autoHeightEnabled = me.options.autoHeightEnabled !== false ; if (!me.autoHeightEnabled){ return; } var bakOverflow, span, tmpNode, lastHeight = 0, currentHeight, timer; function adjustHeight() { clearTimeout(timer); timer = setTimeout(function () { if (me.queryCommandState('source') != 1) { if (!span) { span = me.document.createElement('span'); //trace:1764 span.style.cssText = 'display:block;width:0;margin:0;padding:0;border:0;clear:both;'; span.innerHTML = '.'; } tmpNode = span.cloneNode(true); me.body.appendChild(tmpNode); currentHeight = Math.max(domUtils.getXY(tmpNode).y + tmpNode.offsetHeight, me.options.minFrameHeight); if (currentHeight != lastHeight) { me.setHeight(currentHeight); lastHeight = currentHeight; } domUtils.remove(tmpNode); } }, 50); } me.addListener('destroy', function () { me.removeListener('contentchange', adjustHeight); me.removeListener('keyup', adjustHeight); me.removeListener('mouseup', adjustHeight); }); me.enableAutoHeight = function () { if(!me.autoHeightEnabled){ return; } var doc = me.document; me.autoHeightEnabled = true; bakOverflow = doc.body.style.overflowY; doc.body.style.overflowY = 'hidden'; me.addListener('contentchange', adjustHeight); me.addListener('keyup', adjustHeight); me.addListener('mouseup', adjustHeight); //ff不给事件算得不对 setTimeout(function () { adjustHeight(); }, browser.gecko ? 100 : 0); me.fireEvent('autoheightchanged', me.autoHeightEnabled); }; me.disableAutoHeight = function () { me.body.style.overflowY = bakOverflow || ''; me.removeListener('contentchange', adjustHeight); me.removeListener('keyup', adjustHeight); me.removeListener('mouseup', adjustHeight); me.autoHeightEnabled = false; me.fireEvent('autoheightchanged', me.autoHeightEnabled); }; me.addListener('ready', function () { me.enableAutoHeight(); //trace:1764 var timer; domUtils.on(browser.ie ? me.body : me.document,browser.webkit ? 'dragover' : 'drop',function(){ clearTimeout(timer); timer = setTimeout(function(){ adjustHeight(); },100); }); }); }; ///import core ///commands 悬浮工具栏 ///commandsName AutoFloat,autoFloatEnabled ///commandsTitle 悬浮工具栏 /* * modified by chengchao01 * * 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉! */ UE.plugins['autofloat'] = function() { var me = this, lang = me.getLang(); me.setOpt({ topOffset:0 }); var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false, topOffset = me.options.topOffset; //如果不固定toolbar的位置,则直接退出 if(!optsAutoFloatEnabled){ return; } var uiUtils = UE.ui.uiUtils, LteIE6 = browser.ie && browser.version <= 6, quirks = browser.quirks; function checkHasUI(editor){ if(!editor.ui){ alert(lang.autofloatMsg); return 0; } return 1; } function fixIE6FixedPos(){ var docStyle = document.body.style; docStyle.backgroundImage = 'url("about:blank")'; docStyle.backgroundAttachment = 'fixed'; } var bakCssText, placeHolder = document.createElement('div'), toolbarBox,orgTop, getPosition, flag =true; //ie7模式下需要偏移 function setFloating(){ var toobarBoxPos = domUtils.getXY(toolbarBox), origalFloat = domUtils.getComputedStyle(toolbarBox,'position'), origalLeft = domUtils.getComputedStyle(toolbarBox,'left'); toolbarBox.style.width = toolbarBox.offsetWidth + 'px'; toolbarBox.style.zIndex = me.options.zIndex * 1 + 1; toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox); if (LteIE6 || (quirks && browser.ie)) { if(toolbarBox.style.position != 'absolute'){ toolbarBox.style.position = 'absolute'; } toolbarBox.style.top = (document.body.scrollTop||document.documentElement.scrollTop) - orgTop + topOffset + 'px'; } else { if (browser.ie7Compat && flag) { flag = false; toolbarBox.style.left = domUtils.getXY(toolbarBox).x - document.documentElement.getBoundingClientRect().left+2 + 'px'; } if(toolbarBox.style.position != 'fixed'){ toolbarBox.style.position = 'fixed'; toolbarBox.style.top = topOffset +"px"; ((origalFloat == 'absolute' || origalFloat == 'relative') && parseFloat(origalLeft)) && (toolbarBox.style.left = toobarBoxPos.x + 'px'); } } } function unsetFloating(){ flag = true; if(placeHolder.parentNode){ placeHolder.parentNode.removeChild(placeHolder); } toolbarBox.style.cssText = bakCssText; } function updateFloating(){ var rect3 = getPosition(me.container); if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > 0) { setFloating(); }else{ unsetFloating(); } } var defer_updateFloating = utils.defer(function(){ updateFloating(); },browser.ie ? 200 : 100,true); me.addListener('destroy',function(){ domUtils.un(window, ['scroll','resize'], updateFloating); me.removeListener('keydown', defer_updateFloating); }); me.addListener('ready', function(){ if(checkHasUI(me)){ getPosition = uiUtils.getClientRect; toolbarBox = me.ui.getDom('toolbarbox'); orgTop = getPosition(toolbarBox).top; bakCssText = toolbarBox.style.cssText; placeHolder.style.height = toolbarBox.offsetHeight + 'px'; if(LteIE6){ fixIE6FixedPos(); } me.addListener('autoheightchanged', function (t, enabled){ if (enabled) { domUtils.on(window, ['scroll','resize'], updateFloating); me.addListener('keydown', defer_updateFloating); } else { domUtils.un(window, ['scroll','resize'], updateFloating); me.removeListener('keydown', defer_updateFloating); } }); me.addListener('beforefullscreenchange', function (t, enabled){ if (enabled) { unsetFloating(); } }); me.addListener('fullscreenchanged', function (t, enabled){ if (!enabled) { updateFloating(); } }); me.addListener('sourcemodechanged', function (t, enabled){ setTimeout(function (){ updateFloating(); },0); }); } }); }; ///import core ///import plugins/inserthtml.js ///commands 插入代码 ///commandsName HighlightCode ///commandsTitle 插入代码 ///commandsDialog dialogs\code\code.html UE.plugins['highlightcode'] = function() { var me = this; if(!/highlightcode/i.test(me.options.toolbars.join(''))){ return; } me.commands['highlightcode'] = { execCommand: function (cmdName, code, syntax) { if(code && syntax){ var pre = document.createElement("pre"); pre.className = "brush: "+syntax+";toolbar:false;"; pre.style.display = ""; pre.appendChild(document.createTextNode(code)); document.body.appendChild(pre); if(me.queryCommandState("highlightcode")){ me.execCommand("highlightcode"); } me.execCommand('inserthtml', SyntaxHighlighter.highlight(pre,null,true),true); var div = me.document.getElementById(SyntaxHighlighter.getHighlighterDivId()); div.setAttribute('highlighter',pre.className); domUtils.remove(pre); adjustHeight(); }else{ var range = this.selection.getRange(), start = domUtils.findParentByTagName(range.startContainer, 'table', true), end = domUtils.findParentByTagName(range.endContainer, 'table', true), codediv; if(start && end && start === end && start.parentNode.className.indexOf("syntaxhighlighter")>-1){ codediv = start.parentNode; if(domUtils.isBody(codediv.parentNode)){ var p = me.document.createElement('p'); p.innerHTML = browser.ie ? '' : '
'; me.body.insertBefore(p,codediv); range.setStart(p,0); }else{ range.setStartBefore(codediv) } range.setCursor(); domUtils.remove(codediv); } } }, queryCommandState: function(){ var range = this.selection.getRange(),start,end; range.adjustmentBoundary(); start = domUtils.findParent(range.startContainer,function(node){ return node.nodeType == 1 && node.tagName == 'DIV' && domUtils.hasClass(node,'syntaxhighlighter'); },true); end = domUtils.findParent(range.endContainer,function(node){ return node.nodeType == 1 && node.tagName == 'DIV' && domUtils.hasClass(node,'syntaxhighlighter'); },true); return start && end && start == end ? 1 : 0; } }; me.addListener('beforeselectionchange afterselectionchange',function(type){ me.highlight = /^b/.test(type) ? me.queryCommandState('highlightcode') : 0; }); me.addListener("ready",function(){ //避免重复加载高亮文件 if(typeof XRegExp == "undefined"){ utils.loadFile(document,{ id : "syntaxhighlighter_js", src : me.options.highlightJsUrl || me.options.UEDITOR_HOME_URL + "third-party/SyntaxHighlighter/shCore.js", tag : "script", type : "text/javascript", defer : "defer" },function(){ changePre(); }); } if(!me.document.getElementById("syntaxhighlighter_css")){ utils.loadFile(me.document,{ id : "syntaxhighlighter_css", tag : "link", rel : "stylesheet", type : "text/css", href : me.options.highlightCssUrl ||me.options.UEDITOR_HOME_URL + "third-party/SyntaxHighlighter/shCoreDefault.css" }); } }); me.addListener("beforegetcontent",function(){ for(var i=0,di,divs=domUtils.getElementsByTagName(me.body,'div');di=divs[i++];){ if(di.className == 'container'){ var pN = di.parentNode; while(pN){ if(pN.tagName == 'DIV' && /highlighter/.test(pN.id)){ break; } pN = pN.parentNode; } if(!pN){ return; } var pre = me.document.createElement('pre'); for(var str=[],c=0,ci;ci=di.childNodes[c++];){ str.push(ci[browser.ie?'innerText':'textContent']); } pre.appendChild(me.document.createTextNode(str.join('\n'))); pre.className = pN.getAttribute('highlighter'); pN.parentNode.insertBefore(pre,pN); domUtils.remove(pN); } } }); me.addListener("aftergetcontent aftersetcontent",changePre); function adjustHeight(){ setTimeout(function(){ var div = me.document.getElementById(SyntaxHighlighter.getHighlighterDivId()); if(div){ var tds = div.getElementsByTagName('td'); for(var i=0,li,ri;li=tds[0].childNodes[i];i++){ ri = tds[1].firstChild.childNodes[i]; //trace:1949 if(ri){ ri.style.height = li.style.height = ri.offsetHeight + 'px'; } } } }); } function changePre(){ for(var i=0,pr,pres = domUtils.getElementsByTagName(me.document,"pre");pr=pres[i++];){ if(pr.className.indexOf("brush")>-1){ var pre = document.createElement("pre"),txt,div; pre.className = pr.className; pre.style.display = "none"; pre.appendChild(document.createTextNode(pr[browser.ie?'innerText':'textContent'])); document.body.appendChild(pre); try{ txt = SyntaxHighlighter.highlight(pre,null,true); }catch(e){ domUtils.remove(pre); return ; } div = me.document.createElement("div"); div.innerHTML = txt; div.firstChild.setAttribute('highlighter',pre.className); pr.parentNode.insertBefore(div.firstChild,pr); domUtils.remove(pre); domUtils.remove(pr); adjustHeight(); } } } me.addListener('getAllHtml',function(type,html){ var coreHtml = ''; for(var i= 0,ci,divs=domUtils.getElementsByTagName(me.document,'div');ci=divs[i++];){ if(domUtils.hasClass(ci,'syntaxhighlighter')){ if(!me.document.getElementById('syntaxhighlighter_css')){ coreHtml = '' } if(!me.window.XRegExp){ coreHtml += ''+ '' } break; } } if(!coreHtml){ var tmpNode; if(tmpNode = me.document.getElementById('syntaxhighlighter_css')){ domUtils.remove(tmpNode) } if(tmpNode = me.document.getElementById('syntaxhighlighter_js')){ domUtils.remove(tmpNode) } } html.html = coreHtml; }); //全屏时,重新算一下宽度 me.addListener('fullscreenchanged',function(){ var div = domUtils.getElementsByTagName(me.document,'div'); for(var j=0,di;di=div[j++];){ if(/^highlighter/.test(di.id)){ var tds = di.getElementsByTagName('td'); for(var i=0,li,ri;li=tds[0].childNodes[i];i++){ ri = tds[1].firstChild.childNodes[i]; ri.style.height = li.style.height = ri.offsetHeight + 'px'; } } } }); }; ///import core ///commands 定制过滤规则 ///commandsName Serialize ///commandsTitle 定制过滤规则 UE.plugins['serialize'] = function () { var ie = browser.ie, version = browser.version; function ptToPx(value){ return /pt/.test(value) ? value.replace( /([\d.]+)pt/g, function( str ) { return Math.round(parseFloat(str) * 96 / 72) + "px"; } ) : value; } var me = this, autoClearEmptyNode = me.options.autoClearEmptyNode, EMPTY_TAG = dtd.$empty, parseHTML = function () { //干掉 后便变得空格,保留 这样的空格 var RE_PART = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g, RE_ATTR = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g, EMPTY_ATTR = {checked:1,compact:1,declare:1,defer:1,disabled:1,ismap:1,multiple:1,nohref:1,noresize:1,noshade:1,nowrap:1,readonly:1,selected:1}, CDATA_TAG = {script:1,style: 1}, NEED_PARENT_TAG = { "li": { "$": 'ul', "ul": 1, "ol": 1 }, "dd": { "$": "dl", "dl": 1 }, "dt": { "$": "dl", "dl": 1 }, "option": { "$": "select", "select": 1 }, "td": { "$": "tr", "tr": 1 }, "th": { "$": "tr", "tr": 1 }, "tr": { "$": "tbody", "tbody": 1, "thead": 1, "tfoot": 1, "table": 1 }, "tbody": { "$": "table", 'table':1,"colgroup": 1 }, "thead": { "$": "table", "table": 1 }, "tfoot": { "$": "table", "table": 1 }, "col": { "$": "colgroup","colgroup":1 } }; var NEED_CHILD_TAG = { "table": "td", "tbody": "td", "thead": "td", "tfoot": "td", "tr": "td", "colgroup": "col", "ul": "li", "ol": "li", "dl": "dd", "select": "option" }; function parse( html, callbacks ) { var match, nextIndex = 0, tagName, cdata; RE_PART.exec( "" ); while ( (match = RE_PART.exec( html )) ) { var tagIndex = match.index; if ( tagIndex > nextIndex ) { var text = html.slice( nextIndex, tagIndex ); if ( cdata ) { cdata.push( text ); } else { callbacks.onText( text ); } } nextIndex = RE_PART.lastIndex; if ( (tagName = match[1]) ) { tagName = tagName.toLowerCase(); if ( cdata && tagName == cdata._tag_name ) { callbacks.onCDATA( cdata.join( '' ) ); cdata = null; } if ( !cdata ) { callbacks.onTagClose( tagName ); continue; } } if ( cdata ) { cdata.push( match[0] ); continue; } if ( (tagName = match[3]) ) { if ( /="/.test( tagName ) ) { continue; } tagName = tagName.toLowerCase(); var attrPart = match[4], attrMatch, attrMap = {}, selfClosing = attrPart && attrPart.slice( -1 ) == '/'; if ( attrPart ) { RE_ATTR.exec( "" ); while ( (attrMatch = RE_ATTR.exec( attrPart )) ) { var attrName = attrMatch[1].toLowerCase(), attrValue = attrMatch[2] || attrMatch[3] || attrMatch[4] || ''; if ( !attrValue && EMPTY_ATTR[attrName] ) { attrValue = attrName; } if ( attrName == 'style' ) { if ( ie && version <= 6 ) { attrValue = attrValue.replace( /(?!;)\s*([\w-]+):/g, function ( m, p1 ) { return p1.toLowerCase() + ':'; } ); } } //没有值的属性不添加 if ( attrValue ) { attrMap[attrName] = attrValue.replace( /:\s*/g, ':' ) } } } callbacks.onTagOpen( tagName, attrMap, selfClosing ); if ( !cdata && CDATA_TAG[tagName] ) { cdata = []; cdata._tag_name = tagName; } continue; } if ( (tagName = match[2]) ) { callbacks.onComment( tagName ); } } if ( html.length > nextIndex ) { callbacks.onText( html.slice( nextIndex, html.length ) ); } } return function ( html, forceDtd ) { var fragment = { type: 'fragment', parent: null, children: [] }; var currentNode = fragment; function addChild( node ) { node.parent = currentNode; currentNode.children.push( node ); } function addElement( element, open ) { var node = element; // 遇到结构化标签的时候 if ( NEED_PARENT_TAG[node.tag] ) { // 考虑这种情况的时候, 结束之前的标签 // e.g.
`4566 while ( NEED_PARENT_TAG[currentNode.tag] && NEED_PARENT_TAG[currentNode.tag][node.tag] ) { currentNode = currentNode.parent; } // 如果前一个标签和这个标签是同一级, 结束之前的标签 // e.g.
  • 123
  • if ( currentNode.tag == node.tag ) { currentNode = currentNode.parent; } // 向上补齐父标签 while ( NEED_PARENT_TAG[node.tag] ) { if ( NEED_PARENT_TAG[node.tag][currentNode.tag] ) break; node = node.parent = { type: 'element', tag: NEED_PARENT_TAG[node.tag]['$'], attributes: {}, children: [node] }; } } if ( forceDtd ) { // 如果遇到这个标签不能放在前一个标签内部,则结束前一个标签,span单独处理 while ( dtd[node.tag] && !(currentNode.tag == 'span' ? utils.extend( dtd['strong'], {'a':1,'A':1} ) : (dtd[currentNode.tag] || dtd['div']))[node.tag] ) { if ( tagEnd( currentNode ) ) continue; if ( !currentNode.parent ) break; currentNode = currentNode.parent; } } node.parent = currentNode; currentNode.children.push( node ); if ( open ) { currentNode = element; } if ( element.attributes.style ) { element.attributes.style = element.attributes.style.toLowerCase(); } return element; } // 结束一个标签的时候,需要判断一下它是否缺少子标签 // e.g.
12312`
function tagEnd( node ) { var needTag; if ( !node.children.length && (needTag = NEED_CHILD_TAG[node.tag]) ) { addElement( { type: 'element', tag: needTag, attributes: {}, children: [] }, true ); return true; } return false; } parse( html, { onText: function ( text ) { while ( !(dtd[currentNode.tag] || dtd['div'])['#'] ) { //节点之间的空白不能当作节点处理 // if(/^[ \t\r\n]+$/.test( text )){ // return; // } if ( tagEnd( currentNode ) ) continue; currentNode = currentNode.parent; } //if(/^[ \t\n\r]*/.test(text)) addChild( { type: 'text', data: text } ); }, onComment: function ( text ) { addChild( { type: 'comment', data: text } ); }, onCDATA: function ( text ) { while ( !(dtd[currentNode.tag] || dtd['div'])['#'] ) { if ( tagEnd( currentNode ) ) continue; currentNode = currentNode.parent; } addChild( { type: 'cdata', data: text } ); }, onTagOpen: function ( tag, attrs, closed ) { closed = closed || EMPTY_TAG[tag] ; addElement( { type: 'element', tag: tag, attributes: attrs, closed: closed, children: [] }, !closed ); }, onTagClose: function ( tag ) { var node = currentNode; // 向上找匹配的标签, 这里不考虑dtd的情况是因为tagOpen的时候已经处理过了, 这里不会遇到 while ( node && tag != node.tag ) { node = node.parent; } if ( node ) { // 关闭中间的标签 for ( var tnode = currentNode; tnode !== node.parent; tnode = tnode.parent ) { tagEnd( tnode ); } //去掉空白的inline节点 //分页,锚点保留 //|| dtd.$removeEmptyBlock[node.tag]) // if ( !node.children.length && dtd.$removeEmpty[node.tag] && !node.attributes.anchorname && node.attributes['class'] != 'pagebreak' && node.tag != 'a') { // // node.parent.children.pop(); // } currentNode = node.parent; } else { // 如果没有找到开始标签, 则创建新标签 // eg. =>
//针对视屏网站embed会给结束符,这里特殊处理一下 if ( !(dtd.$removeEmpty[tag] || dtd.$removeEmptyBlock[tag] || tag == 'embed') ) { node = { type: 'element', tag: tag, attributes: {}, children: [] }; addElement( node, true ); tagEnd( node ); currentNode = node.parent; } } } } ); // 处理这种情况, 只有开始标签没有结束标签的情况, 需要关闭开始标签 // eg. while ( currentNode !== fragment ) { tagEnd( currentNode ); currentNode = currentNode.parent; } return fragment; }; }(); var unhtml1 = function () { var map = { '<': '<', '>': '>', '"': '"', "'": ''' }; function rep( m ) { return map[m]; } return function ( str ) { str = str + ''; return str ? str.replace( /[<>"']/g, rep ) : ''; }; }(); var toHTML = function () { function printChildren( node, pasteplain ) { var children = node.children; var buff = []; for ( var i = 0,ci; ci = children[i]; i++ ) { buff.push( toHTML( ci, pasteplain ) ); } return buff.join( '' ); } function printAttrs( attrs ) { var buff = []; for ( var k in attrs ) { var value = attrs[k]; if(k == 'style'){ //pt==>px value = ptToPx(value); //color rgb ==> hex if(/rgba?\s*\([^)]*\)/.test(value)){ value = value.replace( /rgba?\s*\(([^)]*)\)/g, function( str ) { return utils.fixColor('color',str); } ) } //过滤掉所有的white-space,在纯文本编辑器里粘贴过来的内容,到chrome中会带有span和white-space属性,导致出现不能折行的情况 //所以在这里去掉这个属性 attrs[k] = utils.optCss(value.replace(/windowtext/g,'#000')) .replace(/white-space[^;]+;/g,''); } buff.push( k + '="' + unhtml1( attrs[k] ) + '"' ); } return buff.join( ' ' ) } function printData( node, notTrans ) { //trace:1399 输入html代码时空格转换成为  //node.data.replace(/ /g,' ') 针对pre中的空格和出现的 把他们在得到的html代码中都转换成为空格,为了在源码模式下显示为空格而不是  return notTrans ? node.data.replace(/ /g,' ') : unhtml1( node.data ).replace(/ /g,' '); } //纯文本模式下标签转换 var transHtml = { 'div':'p', 'li':'p', 'tr':'p', 'br':'br', 'p':'p'//trace:1398 碰到p标签自己要加上p,否则transHtml[tag]是undefined }; function printElement( node, pasteplain ) { if ( node.type == 'element' && !node.children.length && (dtd.$removeEmpty[node.tag]) && node.tag != 'a' && utils.isEmptyObject(node.attributes) && autoClearEmptyNode) {// 锚点保留 return html; } var tag = node.tag; if ( pasteplain && tag == 'td' ) { if ( !html ) html = ''; html += printChildren( node, pasteplain ) + '   '; } else { var attrs = printAttrs( node.attributes ); var html = '<' + (pasteplain && transHtml[tag] ? transHtml[tag] : tag) + (attrs ? ' ' + attrs : '') + (EMPTY_TAG[tag] ? ' />' : '>'); if ( !EMPTY_TAG[tag] ) { //trace:1627 ,2070 //p标签为空,将不占位这里占位符不起作用,用 或者br if( tag == 'p' && !node.children.length){ html += browser.ie ? ' ' : '
'; } html += printChildren( node, pasteplain ); html += ''; } } return html; } return function ( node, pasteplain ) { if ( node.type == 'fragment' ) { return printChildren( node, pasteplain ); } else if ( node.type == 'element' ) { return printElement( node, pasteplain ); } else if ( node.type == 'text' || node.type == 'cdata' ) { return printData( node, dtd.$notTransContent[node.parent.tag] ); } else if ( node.type == 'comment' ) { return ''; } return ''; }; }(); //过滤word var transformWordHtml = function () { function isWordDocument( strValue ) { var re = new RegExp( /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|[\s\S]*$/, '' ) //remove link break .replace( /^(\r\n|\n|\r)|(\r\n|\n|\r)$/ig, "" ) //remove   entities at the start of contents .replace( /^\s*( )+/ig, "" ) //remove   entities at the end of contents .replace( /( |]*>)+\s*$/ig, "" ) // Word comments like conditional comments etc .replace( //ig, "" ) //转换图片 .replace(/]*>[\s\S]*?.<\/v:shape>/gi,function(str){ //opera能自己解析出image所这里直接返回空 if(browser.opera){ return ''; } try{ var width = str.match(/width:([ \d.]*p[tx])/i)[1], height = str.match(/height:([ \d.]*p[tx])/i)[1], src = str.match(/src=\s*"([^"]*)"/i)[1]; return '' } catch(e){ return ''; } }) //去掉多余的属性 .replace( /v:\w+=["']?[^'"]+["']?/g, '' ) // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, MS Office namespaced tags, and a few other tags .replace( /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, "" ) //convert word headers to strong .replace( /

]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "

$1

" ) //remove lang attribute .replace( /(lang)\s*=\s*([\'\"]?)[\w-]+\2/ig, "" ) //清除多余的font不能匹配 有可能是空格 .replace( /]*>\s*<\/font>/gi, '' ) //清除多余的class .replace( /class\s*=\s*["']?(?:(?:MsoTableGrid)|(?:MsoListParagraph)|(?:MsoNormal(Table)?))\s*["']?/gi, '') //修复了原有的问题, 比如style='fontsize:"宋体"'原来的匹配失效了 str = str.replace( /(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function( str, tag, tmp, style ) { var n = [], i = 0, s = style.replace( /^\s+|\s+$/, '' ).replace( /"/gi, "'" ).split( /;\s*/g ); // Examine each style definition within the tag's style attribute for ( var i = 0; i < s.length; i++ ) { var v = s[i]; var name, value, parts = v.split( ":" ); if ( parts.length == 2 ) { name = parts[0].toLowerCase(); value = parts[1].toLowerCase(); // Translate certain MS Office styles into their CSS equivalents switch ( name ) { case "mso-padding-alt": case "mso-padding-top-alt": case "mso-padding-right-alt": case "mso-padding-bottom-alt": case "mso-padding-left-alt": case "mso-margin-alt": case "mso-margin-top-alt": case "mso-margin-right-alt": case "mso-margin-bottom-alt": case "mso-margin-left-alt": //ie下会出现挤到一起的情况 // case "mso-table-layout-alt": case "mso-height": case "mso-width": case "mso-vertical-align-alt": //trace:1819 ff下会解析出padding在table上 if(!/
0 ) { return tag + ' style="' + n.join( ';' ) + '"'; } else { return tag; } } ); str = str.replace( /([ ]+)<\/span>/ig, function ( m, p ) { return new Array( p.length + 1 ).join( ' ' ) + ''; } ); return str; } return function ( html ) { //过了word,才能转p->li first = null; parentTag = '',liStyle = '',firstTag = ''; if ( isWordDocument( html ) ) { html = filterPasteWord( html ); } return html.replace( />[ \t\r\n]*<' ); }; }(); var NODE_NAME_MAP = { 'text': '#text', 'comment': '#comment', 'cdata': '#cdata-section', 'fragment': '#document-fragment' }; // function _likeLi( node ) { // var a; // if ( node && node.tag == 'p' ) { // //office 2011下有效 // if ( node.attributes['class'] == 'MsoListParagraph' || /mso-list/.test( node.attributes.style ) ) { // a = 1; // } else { // var firstChild = node.children[0]; // if ( firstChild && firstChild.tag == 'span' && /Wingdings/i.test( firstChild.attributes.style ) ) { // a = 1; // } // } // } // return a; // } //为p==>li 做个标志 var first, // orderStyle = { // 'decimal' : /\d+/, // 'lower-roman': /^m{0,4}(cm|cd|d?c{0,3})(xc|xl|l?x{0,3})(ix|iv|v?i{0,3})$/, // 'upper-roman': /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/, // 'lower-alpha' : /^\(?[a-z]+\)?$/, // 'upper-alpha': /^\(?[A-Z]+\)?$/ // }, // unorderStyle = { 'disc' : /^[l\u00B7\u2002]/, 'circle' : /^[\u006F\u00D8]/,'square' : /^[\u006E\u25C6]/}, parentTag = '',liStyle = '',firstTag; //写入编辑器时,调用,进行转换操作 function transNode( node, word_img_flag ) { var sizeMap = [0, 10, 12, 16, 18, 24, 32, 48], attr, indexOf = utils.indexOf; switch ( node.tag ) { case 'script': node.tag = 'div'; node.attributes._ue_div_script = 1; node.attributes._ue_script_data = node.children[0] ? encodeURIComponent(node.children[0].data) : ''; node.attributes._ue_custom_node_ = 1; node.children = []; break; case 'style': node.tag = 'div'; node.attributes._ue_div_style = 1; node.attributes._ue_style_data = node.children[0] ? encodeURIComponent(node.children[0].data) : ''; node.attributes._ue_custom_node_ = 1; node.children = []; break; case 'img': //todo base64暂时去掉,后边做远程图片上传后,干掉这个 if(node.attributes.src && /^data:/.test(node.attributes.src)){ return { type : 'fragment', children:[] } } if ( node.attributes.src && /^(?:file)/.test( node.attributes.src ) ) { if ( !/(gif|bmp|png|jpg|jpeg)$/.test( node.attributes.src ) ) { return { type : 'fragment', children:[] } } node.attributes.word_img = node.attributes.src; node.attributes.src = me.options.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif'; var flag = parseInt(node.attributes.width)<128||parseInt(node.attributes.height)<43; node.attributes.style="background:url(" + (flag? me.options.UEDITOR_HOME_URL +"themes/default/images/word.gif":me.options.langPath+me.options.lang + "/images/localimage.png")+") no-repeat center center;border:1px solid #ddd"; //node.attributes.style = 'width:395px;height:173px;'; word_img_flag && (word_img_flag.flag = 1); } if(browser.ie && browser.version < 7 ) node.attributes.orgSrc = node.attributes.src; node.attributes.data_ue_src = node.attributes.data_ue_src || node.attributes.src; break; case 'li': var child = node.children[0]; if ( !child || child.type != 'element' || child.tag != 'p' && dtd.p[child.tag] ) { var tmpPNode = { type: 'element', tag: 'p', attributes: {}, parent : node }; tmpPNode.children = child ? node.children :[ browser.ie ? { type:'text', data:domUtils.fillChar, parent : tmpPNode }: { type : 'element', tag : 'br', attributes:{}, closed: true, children: [], parent : tmpPNode } ]; node.children = [tmpPNode]; } break; case 'table': case 'td': optStyle( node ); break; case 'a'://锚点,a==>img if ( node.attributes['anchorname'] ) { node.tag = 'img'; node.attributes = { 'class' : 'anchorclass', 'anchorname':node.attributes['name'] }; node.closed = 1; } node.attributes.href && (node.attributes.data_ue_src = node.attributes.href); break; case 'b': node.tag = node.name = 'strong'; break; case 'i': node.tag = node.name = 'em'; break; case 'u': node.tag = node.name = 'span'; node.attributes.style = (node.attributes.style || '') + ';text-decoration:underline;'; break; case 's': case 'del': node.tag = node.name = 'span'; node.attributes.style = (node.attributes.style || '') + ';text-decoration:line-through;'; if ( node.children.length == 1 ) { child = node.children[0]; if ( child.tag == node.tag ) { node.attributes.style += ";" + child.attributes.style; node.children = child.children; } } break; case 'span': // if ( /mso-list/.test( node.attributes.style ) ) { // // // //判断了两次就不在判断了 // if ( firstTag != 'end' ) { // // var ci = node.children[0],p; // while ( ci.type == 'element' ) { // ci = ci.children[0]; // } // for ( p in unorderStyle ) { // if ( unorderStyle[p].test( ci.data ) ) { // // // ci.data = ci.data.replace(unorderStyle[p],''); // parentTag = 'ul'; // liStyle = p; // break; // } // } // // // if ( !parentTag ) { // for ( p in orderStyle ) { // if ( orderStyle[p].test( ci.data.replace( /\.$/, '' ) ) ) { // // ci.data = ci.data.replace(orderStyle[p],''); // parentTag = 'ol'; // liStyle = p; // break; // } // } // } // if ( firstTag ) { // if ( ci.data == firstTag ) { // if ( parentTag != 'ul' ) { // liStyle = ''; // } // parentTag = 'ul' // } else { // if ( parentTag != 'ol' ) { // liStyle = ''; // } // parentTag = 'ol' // } // firstTag = 'end' // } else { // firstTag = ci.data // } // if ( parentTag ) { // var tmpNode = node; // while ( tmpNode && tmpNode.tag != 'ul' && tmpNode.tag != 'ol' ) { // tmpNode = tmpNode.parent; // } // if(tmpNode ){ // tmpNode.tag = parentTag; // tmpNode.attributes.style = 'list-style-type:' + liStyle; // } // // // // } // // } // // node = { // type : 'fragment', // children : [] // }; // break; // // // } var style = node.attributes.style; if ( style ) { if ( !node.attributes.style || browser.webkit && style == "white-space:nowrap;") { delete node.attributes.style; } } //针对ff3.6span的样式不能正确继承的修复 if(browser.gecko && browser.version <= 10902 && node.parent){ var parent = node.parent; if(parent.tag == 'span' && parent.attributes && parent.attributes.style){ node.attributes.style = parent.attributes.style + ';' + node.attributes.style; } } if ( utils.isEmptyObject( node.attributes ) && autoClearEmptyNode) { node.type = 'fragment' } break; case 'font': node.tag = node.name = 'span'; attr = node.attributes; node.attributes = { 'style': (attr.size ? 'font-size:' + (sizeMap[attr.size] || 12) + 'px' : '') + ';' + (attr.color ? 'color:'+ attr.color : '') + ';' + (attr.face ? 'font-family:'+ attr.face : '') + ';' + (attr.style||'') }; while(node.parent.tag == node.tag && node.parent.children.length == 1){ node.attributes.style && (node.parent.attributes.style ? (node.parent.attributes.style += ";" + node.attributes.style) : (node.parent.attributes.style = node.attributes.style)); node.parent.children = node.children; node = node.parent; } break; case 'p': if ( node.attributes.align ) { node.attributes.style = (node.attributes.style || '') + ';text-align:' + node.attributes.align + ';'; delete node.attributes.align; } // if ( _likeLi( node ) ) { // // if ( !first ) { // // var ulNode = { // type: 'element', // tag: 'ul', // attributes: {}, // children: [] // }, // index = indexOf( node.parent.children, node ); // node.parent.children[index] = ulNode; // ulNode.parent = node.parent; // ulNode.children[0] = node; // node.parent = ulNode; // // while ( 1 ) { // node = ulNode.parent.children[index + 1]; // if ( _likeLi( node ) ) { // ulNode.children[ulNode.children.length] = node; // node.parent = ulNode; // ulNode.parent.children.splice( index + 1, 1 ); // // } else { // break; // } // } // // return ulNode; // } // node.tag = node.name = 'li'; // //为chrome能找到标号做的处理 // if ( browser.webkit ) { // var span = node.children[0]; // // while ( span && span.type == 'element' ) { // span = span.children[0] // } // span && (span.parent.attributes.style = (span.parent.attributes.style || '') + ';mso-list:10'); // } // // // delete node.attributes['class']; // delete node.attributes.style; // // // } } return node; } function optStyle( node ) { if ( ie && node.attributes.style ) { var style = node.attributes.style; node.attributes.style = style.replace(/;\s*/g,';'); node.attributes.style = node.attributes.style.replace( /^\s*|\s*$/, '' ) } } //getContent调用转换 function transOutNode( node ) { switch ( node.tag ) { case 'div' : if(node.attributes._ue_div_script){ node.tag = 'script'; node.children = [{type:'cdata',data:node.attributes._ue_script_data?decodeURIComponent(node.attributes._ue_script_data):'',parent:node}]; delete node.attributes._ue_div_script; delete node.attributes._ue_script_data; delete node.attributes._ue_custom_node_; } if(node.attributes._ue_div_style){ node.tag = 'style'; node.children = [{type:'cdata',data:node.attributes._ue_style_data?decodeURIComponent(node.attributes._ue_style_data):'',parent:node}]; delete node.attributes._ue_div_style; delete node.attributes._ue_style_data; delete node.attributes._ue_custom_node_; } break; case 'table': !node.attributes.style && delete node.attributes.style; if ( ie && node.attributes.style ) { optStyle( node ); } if(node.attributes['class'] == 'noBorderTable'){ delete node.attributes['class']; } break; case 'td': case 'th': if ( /display\s*:\s*none/i.test( node.attributes.style ) ) { return { type: 'fragment', children: [] }; } if ( ie && !node.children.length ) { var txtNode = { type: 'text', data:domUtils.fillChar, parent : node }; node.children[0] = txtNode; } if ( ie && node.attributes.style ) { optStyle( node ); } if(node.attributes['class'] == 'selectTdClass'){ delete node.attributes['class'] } break; case 'img'://锚点,img==>a if ( node.attributes.anchorname ) { node.tag = 'a'; node.attributes = { name : node.attributes.anchorname, anchorname : 1 }; node.closed = null; }else{ if(node.attributes.data_ue_src){ node.attributes.src = node.attributes.data_ue_src; delete node.attributes.data_ue_src; } } break; case 'a': if(node.attributes.data_ue_src){ node.attributes.href = node.attributes.data_ue_src; delete node.attributes.data_ue_src; } } return node; } function childrenAccept( node, visit, ctx ) { if ( !node.children || !node.children.length ) { return node; } var children = node.children; for ( var i = 0; i < children.length; i++ ) { var newNode = visit( children[i], ctx ); if ( newNode.type == 'fragment' ) { var args = [i, 1]; args.push.apply( args, newNode.children ); children.splice.apply( children, args ); //节点为空的就干掉,不然后边的补全操作会添加多余的节点 if ( !children.length ) { node = { type: 'fragment', children: [] } } i --; } else { children[i] = newNode; } } return node; } function Serialize( rules ) { this.rules = rules; } Serialize.prototype = { // NOTE: selector目前只支持tagName rules: null, // NOTE: node必须是fragment filter: function ( node, rules, modify ) { rules = rules || this.rules; var whiteList = rules && rules.whiteList; var blackList = rules && rules.blackList; function visitNode( node, parent ) { node.name = node.type == 'element' ? node.tag : NODE_NAME_MAP[node.type]; if ( parent == null ) { return childrenAccept( node, visitNode, node ); } if ( blackList && blackList[node.name] ) { modify && (modify.flag = 1); return { type: 'fragment', children: [] }; } if ( whiteList ) { if ( node.type == 'element' ) { if ( parent.type == 'fragment' ? whiteList[node.name] : whiteList[node.name] && whiteList[parent.name][node.name] ) { var props; if ( (props = whiteList[node.name].$) ) { var oldAttrs = node.attributes; var newAttrs = {}; for ( var k in props ) { if ( oldAttrs[k] ) { newAttrs[k] = oldAttrs[k]; } } node.attributes = newAttrs; } } else { modify && (modify.flag = 1); node.type = 'fragment'; // NOTE: 这里算是一个hack node.name = parent.name; } } else { // NOTE: 文本默认允许 } } if ( blackList || whiteList ) { childrenAccept( node, visitNode, node ); } return node; } return visitNode( node, null ); }, transformInput: function ( node, word_img_flag ) { function visitNode( node ) { node = transNode( node, word_img_flag ); // if ( node.tag == 'ol' || node.tag == 'ul' ) { // first = 1; // } node = childrenAccept( node, visitNode, node ); // if ( node.tag == 'ol' || node.tag == 'ul' ) { // first = 0; // parentTag = '',liStyle = '',firstTag = ''; // } if ( me.options.pageBreakTag && node.type == 'text' && node.data.replace( /\s/g, '' ) == me.options.pageBreakTag ) { node.type = 'element'; node.name = node.tag = 'hr'; delete node.data; node.attributes = { 'class' : 'pagebreak', noshade:"noshade", size:"5", 'unselectable' : 'on', 'style' : 'moz-user-select:none;-khtml-user-select: none;' }; node.children = []; } //去掉多余的空格和换行 if(node.type == 'text' && !dtd.$notTransContent[node.parent.tag]){ node.data = node.data.replace(/[\r\t\n]*/g,'')//.replace(/[ ]*$/g,'') } return node; } return visitNode( node ); }, transformOutput: function ( node ) { function visitNode( node ) { if ( node.tag == 'hr' && node.attributes['class'] == 'pagebreak' ) { delete node.tag; node.type = 'text'; node.data = me.options.pageBreakTag; delete node.children; } node = transOutNode( node ); if ( node.tag == 'ol' || node.tag == 'ul' ) { first = 1; } node = childrenAccept( node, visitNode, node ); if ( node.tag == 'ol' || node.tag == 'ul' ) { first = 0; } return node; } return visitNode( node ); }, toHTML: toHTML, parseHTML: parseHTML, word: transformWordHtml }; me.serialize = new Serialize( me.options.serialize || {}); UE.serialize = new Serialize( {} ); }; ///import core ///import plugins/inserthtml.js ///commands 视频 ///commandsName InsertVideo ///commandsTitle 插入视频 ///commandsDialog dialogs\video\video.html UE.plugins['video'] = function (){ var me =this, div; /** * 创建插入视频字符窜 * @param url 视频地址 * @param width 视频宽度 * @param height 视频高度 * @param align 视频对齐 * @param toEmbed 是否以图片代替显示 * @param addParagraph 是否需要添加P 标签 */ function creatInsertStr(url,width,height,align,toEmbed,addParagraph){ return !toEmbed ? (addParagraph? ('

'): '') + '' + (addParagraph?'

':'') : ''; } function switchImgAndEmbed(img2embed){ var tmpdiv, nodes =domUtils.getElementsByTagName(me.document, !img2embed ? "embed" : "img"); for(var i=0,node;node = nodes[i++];){ if(node.className!="edui-faked-video"){ continue; } tmpdiv = me.document.createElement("div"); //先看float在看align,浮动有的是时候是在float上定义的 var align = node.style.cssFloat; tmpdiv.innerHTML = creatInsertStr(img2embed ? node.getAttribute("_url"):node.getAttribute("src"),node.width,node.height,align || node.getAttribute("align"),img2embed); node.parentNode.replaceChild(tmpdiv.firstChild,node); } } me.addListener("beforegetcontent",function(){ switchImgAndEmbed(true); }); me.addListener('aftersetcontent',function(){ switchImgAndEmbed(false); }); me.addListener('aftergetcontent',function(cmdName){ if(cmdName == 'aftergetcontent' && me.queryCommandState('source')){ return; } switchImgAndEmbed(false); }); me.commands["insertvideo"] = { execCommand: function (cmd, videoObjs){ videoObjs = utils.isArray(videoObjs)?videoObjs:[videoObjs]; var html = []; for(var i=0,vi,len = videoObjs.length;i 0 ? -1 : 0; }, execCommand:function ( cmdName, opt ) { opt = opt || {numRows:5, numCols:5,border:1}; var html = ['
' ); opt.width = Math.floor( (opt.width || '100') / opt.numCols ); for ( var i = 0; i < opt.numRows; i++ ) { html.push( '' ); for ( var j = 0; j < opt.numCols; j++ ) { html.push( '' ); } html.push( '' ); } me.execCommand( 'insertHtml', html.join( '' ) + '
' + (browser.ie ? domUtils.fillChar : '
') + '
' ); reset(); //如果表格的align不是默认,将不占位,给后边的block元素设置clear:both if ( opt.align ) { var range = me.selection.getRange(), bk = range.createBookmark(), start = range.startContainer; while ( start && !domUtils.isBody( start ) ) { if ( domUtils.isBlockElm( start ) ) { start.style.clear = 'both'; range.moveToBookmark( bk ).select(); break; } start = start.parentNode; } } } }; me.commands['edittable'] = { queryCommandState:function () { var range = this.selection.getRange(); if ( this.highlight ) { return -1; } return domUtils.findParentByTagName( range.startContainer, 'table', true ) || me.currentSelectedArr.length > 0 ? 0 : -1; }, execCommand:function ( cmdName, opt ) { var start = me.selection.getStart(), table = domUtils.findParentByTagName( start, 'table', true ); if ( table ) { table.style.cssText = table.style.cssText.replace( /border[^;]+/gi, '' ); table.style.borderCollapse = opt.cellSpacing && opt.cellSpacing != '0' || opt.cellPadding && opt.cellPadding != '0' ? 'separate' : 'collapse'; opt.cellSpacing && opt.cellSpacing != '0' ? table.setAttribute( 'cellSpacing', opt.cellSpacing ) : table.removeAttribute( 'cellSpacing' ); opt.cellPadding && opt.cellPadding != '0' ? table.setAttribute( 'cellPadding', opt.cellPadding ) : table.removeAttribute( 'cellPadding' ); opt.height && table.setAttribute( 'height', opt.height + opt.heightUnit ); opt.align && table.setAttribute( 'align', opt.align ); opt.width && table.setAttribute( 'width', opt.width + opt.widthUnit ); if(opt.bgColor){ table.setAttribute( 'bgColor', opt.bgColor ); }else{ domUtils.removeAttributes(table,["bgColor"]); } opt.borderColor && table.setAttribute( 'borderColor', opt.borderColor ); table.setAttribute( 'border', opt.border ); if(domUtils.hasClass(table,"noBorderTable")){ domUtils.removeClasses(table,["noBorderTable"]); } domUtils.addClass(table,opt.border == "0" ? " noBorderTable" : ""); if ( opt.borderType == "1" ) { for ( var i = 0, ti, tds = table.getElementsByTagName( 'td' ); ti = tds[i++]; ) { ti.style.border = opt.border + 'px solid ' + (opt.borderColor || '#000000'); } table.setAttribute( 'borderType', '1' ); } else { for ( var i = 0, ti, tds = table.getElementsByTagName( 'td' ); ti = tds[i++]; ) { if ( browser.ie ) { ti.style.cssText = ti.style.cssText.replace( /border[^;]+/gi, '' ); } else { domUtils.removeStyle( ti, 'border' ); domUtils.removeStyle( ti, 'border-image' ); } } table.removeAttribute( 'borderType' ); } } } }; me.commands['edittd'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(); return (domUtils.findParentByTagName( range.startContainer, 'table', true ) && domUtils.findParentByTagName( range.endContainer, 'table', true )) || me.currentSelectedArr.length > 0 ? 0 : -1; }, /** * 单元格属性编辑 * @param cmdName * @param tdItems */ execCommand:function ( cmdName, tdItems ) { var range = this.selection.getRange(), tds = !me.currentSelectedArr.length ? [domUtils.findParentByTagName( range.startContainer, ['td', 'th'], true )] : me.currentSelectedArr; for ( var i = 0, td; td = tds[i++]; ) { domUtils.setAttributes( td, { "bgColor":tdItems.bgColor, "align":tdItems.align, "vAlign":tdItems.vAlign } ); } } }; /** * 删除表格 */ me.commands['deletetable'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(); return (domUtils.findParentByTagName( range.startContainer, 'table', true ) && domUtils.findParentByTagName( range.endContainer, 'table', true )) || me.currentSelectedArr.length > 0 ? 0 : -1; }, execCommand:function () { var range = this.selection.getRange(), table = domUtils.findParentByTagName( me.currentSelectedArr.length > 0 ? me.currentSelectedArr[0] : range.startContainer, 'table', true ); deleteTable( table, range ); reset(); } }; /** * 向右合并单元格 */ me.commands['mergeright'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ); if ( !td || this.currentSelectedArr.length > 1 ){ return -1; } var tr = td.parentNode; //最右边行不能向右合并 var rightCellIndex = getIndex( td ) + td.colSpan; if ( rightCellIndex >= tr.cells.length ) { return -1; } //单元格不在同一行不能向右合并 var rightCell = tr.cells[rightCellIndex]; if ( _isHide( rightCell ) ) { return -1; } return td.rowSpan == rightCell.rowSpan ? 0 : -1; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ) || me.currentSelectedArr[0], tr = td.parentNode, rows = tr.parentNode.parentNode.rows; //找到当前单元格右边的未隐藏单元格 var rightCellRowIndex = tr.rowIndex, rightCellCellIndex = getIndex( td ) + td.colSpan, rightCell = rows[rightCellRowIndex].cells[rightCellCellIndex]; //在隐藏的原生td对象上增加两个属性,分别表示当前td对应的真实td坐标 for ( var i = rightCellRowIndex; i < rightCellRowIndex + rightCell.rowSpan; i++ ) { for ( var j = rightCellCellIndex; j < rightCellCellIndex + rightCell.colSpan; j++ ) { var tmpCell = rows[i].cells[j]; tmpCell.setAttribute( 'rootRowIndex', tr.rowIndex ); tmpCell.setAttribute( 'rootCellIndex', getIndex( td ) ); } } //合并单元格 td.colSpan += rightCell.colSpan || 1; //合并内容 _moveContent( td, rightCell ); //删除被合并的单元格,此处用隐藏方式实现来提升性能 rightCell.style.display = "none"; //重新让单元格获取焦点 //trace:1565 if ( domUtils.isEmptyBlock( td ) ) { range.setStart( td, 0 ).setCursor(); } else { range.selectNodeContents( td ).setCursor( true, true ); } //处理有寛高,导致ie的文字不能输入占满 browser.ie && domUtils.removeAttributes( td, ['width', 'height'] ); } }; /** * 向下合并单元格 */ me.commands['mergedown'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, 'td', true ); if ( !td || getCount( me.currentSelectedArr ) > 1 ){ return -1; } var tr = td.parentNode, table = tr.parentNode.parentNode, rows = table.rows; //已经是最底行,不能向下合并 var downCellRowIndex = tr.rowIndex + td.rowSpan; if ( downCellRowIndex >= rows.length ) { return -1; } //如果下一个单元格是隐藏的,表明他是由左边span过来的,不能向下合并 var downCell = rows[downCellRowIndex].cells[getIndex( td )]; if ( _isHide( downCell ) ) { return -1; } //只有列span都相等时才能合并 return td.colSpan == downCell.colSpan ? 0 : -1; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ) || me.currentSelectedArr[0]; var tr = td.parentNode, rows = tr.parentNode.parentNode.rows; var downCellRowIndex = tr.rowIndex + td.rowSpan, downCellCellIndex = getIndex( td ), downCell = rows[downCellRowIndex].cells[downCellCellIndex]; //找到当前列的下一个未被隐藏的单元格 for ( var i = downCellRowIndex; i < downCellRowIndex + downCell.rowSpan; i++ ) { for ( var j = downCellCellIndex; j < downCellCellIndex + downCell.colSpan; j++ ) { var tmpCell = rows[i].cells[j]; tmpCell.setAttribute( 'rootRowIndex', tr.rowIndex ); tmpCell.setAttribute( 'rootCellIndex', getIndex( td ) ); } } //合并单元格 td.rowSpan += downCell.rowSpan || 1; //合并内容 _moveContent( td, downCell ); //删除被合并的单元格,此处用隐藏方式实现来提升性能 downCell.style.display = "none"; //重新让单元格获取焦点 if ( domUtils.isEmptyBlock( td ) ) { range.setStart( td, 0 ).setCursor(); } else { range.selectNodeContents( td ).setCursor( true, true ); } //处理有寛高,导致ie的文字不能输入占满 browser.ie && domUtils.removeAttributes( td, ['width', 'height'] ); } }; /** * 删除行 */ me.commands['deleterow'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ); if ( !td && me.currentSelectedArr.length == 0 ){ return -1; } return 0; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ), tr, table, cells, rows , rowIndex , cellIndex; if ( td && me.currentSelectedArr.length == 0 ) { var count = (td.rowSpan || 1) - 1; me.currentSelectedArr.push( td ); tr = td.parentNode; table = tr.parentNode.parentNode; rows = table.rows, rowIndex = tr.rowIndex + 1, cellIndex = getIndex( td ); while ( count ) { me.currentSelectedArr.push( rows[rowIndex].cells[cellIndex] ); count--; rowIndex++; } } while ( td = me.currentSelectedArr.pop() ) { if ( !domUtils.findParentByTagName( td, 'table' ) ) {//|| _isHide(td) continue; } tr = td.parentNode, table = tr.parentNode.parentNode; cells = tr.cells, rows = table.rows, rowIndex = tr.rowIndex, cellIndex = getIndex( td ); /* * 从最左边开始扫描并隐藏当前行的所有单元格 * 若当前单元格的display为none,往上找到它所在的真正单元格,获取colSpan和rowSpan, * 将rowspan减一,并跳转到cellIndex+colSpan列继续处理 * 若当前单元格的display不为none,分两种情况: * 1、rowspan == 1 ,直接设置display为none,跳转到cellIndex+colSpan列继续处理 * 2、rowspan > 1 , 修改当前单元格的下一个单元格的display为"", * 并将当前单元格的rowspan-1赋给下一个单元格的rowspan,当前单元格的colspan赋给下一个单元格的colspan, * 然后隐藏当前单元格,跳转到cellIndex+colSpan列继续处理 */ for ( var currentCellIndex = 0; currentCellIndex < cells.length; ) { var currentNode = cells[currentCellIndex]; if ( _isHide( currentNode ) ) { var topNode = rows[currentNode.getAttribute( 'rootRowIndex' )].cells[currentNode.getAttribute( 'rootCellIndex' )]; topNode.rowSpan--; currentCellIndex += topNode.colSpan; } else { if ( currentNode.rowSpan == 1 ) { currentCellIndex += currentNode.colSpan; } else { var downNode = rows[rowIndex + 1].cells[currentCellIndex]; downNode.style.display = ""; downNode.rowSpan = currentNode.rowSpan - 1; downNode.colSpan = currentNode.colSpan; currentCellIndex += currentNode.colSpan; } } } //完成更新后再删除外层包裹的tr domUtils.remove( tr ); //重新定位焦点 var topRowTd, focusTd, downRowTd; if ( rowIndex == rows.length ) { //如果被删除的行是最后一行,这里之所以没有-1是因为已经删除了一行 //如果删除的行也是第一行,那么表格总共只有一行,删除整个表格 if ( rowIndex == 0 ) { deleteTable( table, range ); return; } //如果上一单元格未隐藏,则直接定位,否则定位到最近的上一个非隐藏单元格 var preRowIndex = rowIndex - 1; topRowTd = rows[preRowIndex].cells[ cellIndex]; focusTd = _isHide( topRowTd ) ? rows[topRowTd.getAttribute( 'rootRowIndex' )].cells[topRowTd.getAttribute( 'rootCellIndex' )] : topRowTd; } else { //如果被删除的不是最后一行,则光标定位到下一行,此处未加1是因为已经删除了一行 downRowTd = rows[rowIndex].cells[cellIndex]; focusTd = _isHide( downRowTd ) ? rows[downRowTd.getAttribute( 'rootRowIndex' )].cells[downRowTd.getAttribute( 'rootCellIndex' )] : downRowTd; } } range.setStart( focusTd, 0 ).setCursor(); update( table ); } }; /** * 删除列 */ me.commands['deletecol'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ); if ( !td && me.currentSelectedArr.length == 0 )return -1; return 0; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ); if ( td && me.currentSelectedArr.length == 0 ) { var count = (td.colSpan || 1) - 1; me.currentSelectedArr.push( td ); while ( count ) { do { td = td.nextSibling } while ( td.nodeType == 3 ); me.currentSelectedArr.push( td ); count--; } } while ( td = me.currentSelectedArr.pop() ) { if ( !domUtils.findParentByTagName( td, 'table' ) ) { //|| _isHide(td) continue; } var tr = td.parentNode, table = tr.parentNode.parentNode, cellIndex = getIndex( td ), rows = table.rows, cells = tr.cells, rowIndex = tr.rowIndex; /* * 从第一行开始扫描并隐藏当前列的所有单元格 * 若当前单元格的display为none,表明它是由左边Span过来的, * 将左边第一个非none单元格的colSpan减去1并删去对应的单元格后跳转到rowIndex + rowspan行继续处理; * 若当前单元格的display不为none,分两种情况, * 1、当前单元格的colspan == 1 , 则直接删除该节点,跳转到rowIndex + rowspan行继续处理 * 2、当前单元格的colsapn > 1, 修改当前单元格右边单元格的display为"", * 并将当前单元格的colspan-1赋给它的colspan,当前单元格的rolspan赋给它的rolspan, * 然后删除当前单元格,跳转到rowIndex+rowSpan行继续处理 */ var rowSpan; for ( var currentRowIndex = 0; currentRowIndex < rows.length; ) { var currentNode = rows[currentRowIndex].cells[cellIndex]; if ( _isHide( currentNode ) ) { var leftNode = rows[currentNode.getAttribute( 'rootRowIndex' )].cells[currentNode.getAttribute( 'rootCellIndex' )]; //依次删除对应的单元格 rowSpan = leftNode.rowSpan; for ( var i = 0; i < leftNode.rowSpan; i++ ) { var delNode = rows[currentRowIndex + i].cells[cellIndex]; domUtils.remove( delNode ); } //修正被删后的单元格信息 leftNode.colSpan--; currentRowIndex += rowSpan; } else { if ( currentNode.colSpan == 1 ) { rowSpan = currentNode.rowSpan; for ( var i = currentRowIndex, l = currentRowIndex + currentNode.rowSpan; i < l; i++ ) { domUtils.remove( rows[i].cells[cellIndex] ); } currentRowIndex += rowSpan; } else { var rightNode = rows[currentRowIndex].cells[cellIndex + 1]; rightNode.style.display = ""; rightNode.rowSpan = currentNode.rowSpan; rightNode.colSpan = currentNode.colSpan - 1; currentRowIndex += currentNode.rowSpan; domUtils.remove( currentNode ); } } } //重新定位焦点 var preColTd, focusTd, nextColTd; if ( cellIndex == cells.length ) { //如果当前列是最后一列,光标定位到当前列的前一列,同样,这里没有减去1是因为已经被删除了一列 //如果当前列也是第一列,则删除整个表格 if ( cellIndex == 0 ) { deleteTable( table, range ); return; } //找到当前单元格前一列中和本单元格最近的一个未隐藏单元格 var preCellIndex = cellIndex - 1; preColTd = rows[rowIndex].cells[preCellIndex]; focusTd = _isHide( preColTd ) ? rows[preColTd.getAttribute( 'rootRowIndex' )].cells[preColTd.getAttribute( 'rootCellIndex' )] : preColTd; } else { //如果当前列不是最后一列,则光标定位到当前列的后一列 nextColTd = rows[rowIndex].cells[cellIndex]; focusTd = _isHide( nextColTd ) ? rows[nextColTd.getAttribute( 'rootRowIndex' )].cells[nextColTd.getAttribute( 'rootCellIndex' )] : nextColTd; } } range.setStart( focusTd, 0 ).setCursor(); update( table ) } }; /** * 完全拆分单元格 */ me.commands['splittocells'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ); return td && ( td.rowSpan > 1 || td.colSpan > 1 ) && (!me.currentSelectedArr.length || getCount( me.currentSelectedArr ) == 1) ? 0 : -1; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ), tr = td.parentNode, table = tr.parentNode.parentNode; var rowIndex = tr.rowIndex, cellIndex = getIndex( td ), rowSpan = td.rowSpan, colSpan = td.colSpan; for ( var i = 0; i < rowSpan; i++ ) { for ( var j = 0; j < colSpan; j++ ) { var cell = table.rows[rowIndex + i].cells[cellIndex + j]; cell.rowSpan = 1; cell.colSpan = 1; if ( _isHide( cell ) ) { cell.style.display = ""; cell.innerHTML = browser.ie ? '' : "
"; } } } } }; /** * 将单元格拆分成行 */ me.commands['splittorows'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, 'td', true ) || me.currentSelectedArr[0]; return td && ( td.rowSpan > 1) && (!me.currentSelectedArr.length || getCount( me.currentSelectedArr ) == 1) ? 0 : -1; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, 'td', true ) || me.currentSelectedArr[0], tr = td.parentNode, rows = tr.parentNode.parentNode.rows; var rowIndex = tr.rowIndex, cellIndex = getIndex( td ), rowSpan = td.rowSpan, colSpan = td.colSpan; for ( var i = 0; i < rowSpan; i++ ) { var cells = rows[rowIndex + i], cell = cells.cells[cellIndex]; cell.rowSpan = 1; cell.colSpan = colSpan; if ( _isHide( cell ) ) { cell.style.display = ""; //原有的内容要清除掉 cell.innerHTML = browser.ie ? '' : '
' } //修正被隐藏单元格中存储的rootRowIndex和rootCellIndex信息 for ( var j = cellIndex + 1; j < cellIndex + colSpan; j++ ) { cell = cells.cells[j]; cell.setAttribute( 'rootRowIndex', rowIndex + i ) } } clearSelectedTd( me.currentSelectedArr ); this.selection.getRange().setStart( td, 0 ).setCursor(); } }; /** * 在表格前插入行 */ me.commands['insertparagraphbeforetable'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, 'td', true ) || me.currentSelectedArr[0]; return td && domUtils.findParentByTagName( td, 'table' ) ? 0 : -1; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, table = domUtils.findParentByTagName( start, 'table', true ); start = me.document.createElement( me.options.enterTag ); table.parentNode.insertBefore( start, table ); clearSelectedTd( me.currentSelectedArr ); if ( start.tagName == 'P' ) { //trace:868 start.innerHTML = browser.ie ? '' : '
'; range.setStart( start, 0 ) } else { range.setStartBefore( start ) } range.setCursor(); } }; /** * 将单元格拆分成列 */ me.commands['splittocols'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ) || me.currentSelectedArr[0]; return td && ( td.colSpan > 1) && (!me.currentSelectedArr.length || getCount( me.currentSelectedArr ) == 1) ? 0 : -1; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ) || me.currentSelectedArr[0], tr = td.parentNode, rows = tr.parentNode.parentNode.rows; var rowIndex = tr.rowIndex, cellIndex = getIndex( td ), rowSpan = td.rowSpan, colSpan = td.colSpan; for ( var i = 0; i < colSpan; i++ ) { var cell = rows[rowIndex].cells[cellIndex + i]; cell.rowSpan = rowSpan; cell.colSpan = 1; if ( _isHide( cell ) ) { cell.style.display = ""; cell.innerHTML = browser.ie ? '' : '
' } for ( var j = rowIndex + 1; j < rowIndex + rowSpan; j++ ) { var tmpCell = rows[j].cells[cellIndex + i]; tmpCell.setAttribute( 'rootCellIndex', cellIndex + i ); } } clearSelectedTd( me.currentSelectedArr ); this.selection.getRange().setStart( td, 0 ).setCursor(); } }; /** * 插入行 */ me.commands['insertrow'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(); return domUtils.findParentByTagName( range.startContainer, 'table', true ) || domUtils.findParentByTagName( range.endContainer, 'table', true ) || me.currentSelectedArr.length != 0 ? 0 : -1; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, tr = domUtils.findParentByTagName( start, 'tr', true ) || me.currentSelectedArr[0].parentNode, table = tr.parentNode.parentNode, rows = table.rows; //记录插入位置原来所有的单元格 var rowIndex = tr.rowIndex, cells = rows[rowIndex].cells; //插入新的一行 var newRow = table.insertRow( rowIndex ); var newCell; //遍历表格中待插入位置中的所有单元格,检查其状态,并据此修正新插入行的单元格状态 for ( var cellIndex = 0; cellIndex < cells.length; ) { var tmpCell = cells[cellIndex]; if ( _isHide( tmpCell ) ) { //如果当前单元格是隐藏的,表明当前单元格由其上部span过来,找到其上部单元格 //找到被隐藏单元格真正所属的单元格 var topCell = rows[tmpCell.getAttribute( 'rootRowIndex' )].cells[tmpCell.getAttribute( 'rootCellIndex' )]; //增加一行,并将所有新插入的单元格隐藏起来 topCell.rowSpan++; for ( var i = 0; i < topCell.colSpan; i++ ) { newCell = tmpCell.cloneNode( false ); domUtils.removeAttributes( newCell, ["bgColor", "valign", "align"] ); newCell.rowSpan = newCell.colSpan = 1; newCell.innerHTML = browser.ie ? '' : "
"; newCell.className = ''; if ( newRow.children[cellIndex + i] ) { newRow.insertBefore( newCell, newRow.children[cellIndex + i] ); } else { newRow.appendChild( newCell ) } newCell.style.display = "none"; } cellIndex += topCell.colSpan; } else {//若当前单元格未隐藏,则在其上行插入colspan个单元格 for ( var j = 0; j < tmpCell.colSpan; j++ ) { newCell = tmpCell.cloneNode( false ); domUtils.removeAttributes( newCell, ["bgColor", "valign", "align"] ); newCell.rowSpan = newCell.colSpan = 1; newCell.innerHTML = browser.ie ? '' : "
"; newCell.className = ''; if ( newRow.children[cellIndex + j] ) { newRow.insertBefore( newCell, newRow.children[cellIndex + j] ); } else { newRow.appendChild( newCell ) } } cellIndex += tmpCell.colSpan; } } update( table ); range.setStart( newRow.cells[0], 0 ).setCursor(); clearSelectedTd( me.currentSelectedArr ); } }; /** * 插入列 */ me.commands['insertcol'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var range = this.selection.getRange(); return domUtils.findParentByTagName( range.startContainer, 'table', true ) || domUtils.findParentByTagName( range.endContainer, 'table', true ) || me.currentSelectedArr.length != 0 ? 0 : -1; }, execCommand:function () { var range = this.selection.getRange(), start = range.startContainer, td = domUtils.findParentByTagName( start, ['td', 'th'], true ) || me.currentSelectedArr[0], table = domUtils.findParentByTagName( td, 'table' ), rows = table.rows; var cellIndex = getIndex( td ), newCell; //遍历当前列中的所有单元格,检查其状态,并据此修正新插入列的单元格状态 for ( var rowIndex = 0; rowIndex < rows.length; ) { var tmpCell = rows[rowIndex].cells[cellIndex], tr; if ( _isHide( tmpCell ) ) {//如果当前单元格是隐藏的,表明当前单元格由其左边span过来,找到其左边单元格 var leftCell = rows[tmpCell.getAttribute( 'rootRowIndex' )].cells[tmpCell.getAttribute( 'rootCellIndex' )]; leftCell.colSpan++; for ( var i = 0; i < leftCell.rowSpan; i++ ) { newCell = td.cloneNode( false ); domUtils.removeAttributes( newCell, ["bgColor", "valign", "align"] ); newCell.rowSpan = newCell.colSpan = 1; newCell.innerHTML = browser.ie ? '' : "
"; newCell.className = ''; tr = rows[rowIndex + i]; if ( tr.children[cellIndex] ) { tr.insertBefore( newCell, tr.children[cellIndex] ); } else { tr.appendChild( newCell ) } newCell.style.display = "none"; } rowIndex += leftCell.rowSpan; } else { //若当前单元格未隐藏,则在其左边插入rowspan个单元格 for ( var j = 0; j < tmpCell.rowSpan; j++ ) { newCell = td.cloneNode( false ); domUtils.removeAttributes( newCell, ["bgColor", "valign", "align"] ); newCell.rowSpan = newCell.colSpan = 1; newCell.innerHTML = browser.ie ? '' : "
"; newCell.className = ''; tr = rows[rowIndex + j]; if ( tr.children[cellIndex] ) { tr.insertBefore( newCell, tr.children[cellIndex] ); } else { tr.appendChild( newCell ) } newCell.innerHTML = browser.ie ? '' : "
"; } rowIndex += tmpCell.rowSpan; } } update( table ); range.setStart( rows[0].cells[cellIndex], 0 ).setCursor(); clearSelectedTd( me.currentSelectedArr ); } }; /** * 合并多个单元格,通过两个cell将当前包含的所有横纵单元格进行合并 */ me.commands['mergecells'] = { queryCommandState:function () { if ( this.highlight ) { return -1; } var count = 0; for ( var i = 0, ti; ti = this.currentSelectedArr[i++]; ) { if ( !_isHide( ti ) ) count++; } return count > 1 ? 0 : -1; }, execCommand:function () { var start = me.currentSelectedArr[0], end = me.currentSelectedArr[me.currentSelectedArr.length - 1], table = domUtils.findParentByTagName( start, 'table' ), rows = table.rows, cellsRange = { beginRowIndex:start.parentNode.rowIndex, beginCellIndex:getIndex( start ), endRowIndex:end.parentNode.rowIndex, endCellIndex:getIndex( end ) }, beginRowIndex = cellsRange.beginRowIndex, beginCellIndex = cellsRange.beginCellIndex, rowsLength = cellsRange.endRowIndex - cellsRange.beginRowIndex + 1, cellLength = cellsRange.endCellIndex - cellsRange.beginCellIndex + 1, tmp = rows[beginRowIndex].cells[beginCellIndex]; for ( var i = 0, ri; (ri = rows[beginRowIndex + i++]) && i <= rowsLength; ) { for ( var j = 0, ci; (ci = ri.cells[beginCellIndex + j++]) && j <= cellLength; ) { if ( i == 1 && j == 1 ) { ci.style.display = ""; ci.rowSpan = rowsLength; ci.colSpan = cellLength; } else { ci.style.display = "none"; ci.rowSpan = 1; ci.colSpan = 1; ci.setAttribute( 'rootRowIndex', beginRowIndex ); ci.setAttribute( 'rootCellIndex', beginCellIndex ); //传递内容 _moveContent( tmp, ci ); } } } this.selection.getRange().setStart( tmp, 0 ).setCursor(); //处理有寛高,导致ie的文字不能输入占满 browser.ie && domUtils.removeAttributes( tmp, ['width', 'height'] ); clearSelectedTd( me.currentSelectedArr ); } }; /** * 将cellFrom单元格中的内容移动到cellTo中 * @param cellTo 目标单元格 * @param cellFrom 源单元格 */ function _moveContent( cellTo, cellFrom ) { if ( _isEmpty( cellFrom ) ) return; if ( _isEmpty( cellTo ) ) { cellTo.innerHTML = cellFrom.innerHTML; return; } var child = cellTo.lastChild; if ( child.nodeType != 1 || child.tagName != 'BR' ) { cellTo.appendChild( cellTo.ownerDocument.createElement( 'br' ) ) } //依次移动内容 while ( child = cellFrom.firstChild ) { cellTo.appendChild( child ); } } /** * 根据两个单元格来获取中间包含的所有单元格集合选区 * @param cellA * @param cellB * @return {Object} 选区的左上和右下坐标 */ function _getCellsRange( cellA, cellB ) { var trA = cellA.parentNode, trB = cellB.parentNode, aRowIndex = trA.rowIndex, bRowIndex = trB.rowIndex, rows = trA.parentNode.parentNode.rows, rowsNum = rows.length, cellsNum = rows[0].cells.length, cellAIndex = getIndex( cellA ), cellBIndex = getIndex( cellB ); if ( cellA == cellB ) { return { beginRowIndex:aRowIndex, beginCellIndex:cellAIndex, endRowIndex:aRowIndex + cellA.rowSpan - 1, endCellIndex:cellBIndex + cellA.colSpan - 1 } } var beginRowIndex = Math.min( aRowIndex, bRowIndex ), beginCellIndex = Math.min( cellAIndex, cellBIndex ), endRowIndex = Math.max( aRowIndex + cellA.rowSpan - 1, bRowIndex + cellB.rowSpan - 1 ), endCellIndex = Math.max( cellAIndex + cellA.colSpan - 1, cellBIndex + cellB.colSpan - 1 ); while ( 1 ) { var tmpBeginRowIndex = beginRowIndex, tmpBeginCellIndex = beginCellIndex, tmpEndRowIndex = endRowIndex, tmpEndCellIndex = endCellIndex; // 检查是否有超出TableRange上边界的情况 if ( beginRowIndex > 0 ) { for ( cellIndex = beginCellIndex; cellIndex <= endCellIndex; ) { var currentTopTd = rows[beginRowIndex].cells[cellIndex]; if ( _isHide( currentTopTd ) ) { //overflowRowIndex = beginRowIndex == currentTopTd.rootRowIndex ? 1:0; beginRowIndex = currentTopTd.getAttribute( 'rootRowIndex' ); currentTopTd = rows[currentTopTd.getAttribute( 'rootRowIndex' )].cells[currentTopTd.getAttribute( 'rootCellIndex' )]; } cellIndex = getIndex( currentTopTd ) + (currentTopTd.colSpan || 1); } } //检查是否有超出左边界的情况 if ( beginCellIndex > 0 ) { for ( var rowIndex = beginRowIndex; rowIndex <= endRowIndex; ) { var currentLeftTd = rows[rowIndex].cells[beginCellIndex]; if ( _isHide( currentLeftTd ) ) { // overflowCellIndex = beginCellIndex== currentLeftTd.rootCellIndex ? 1:0; beginCellIndex = currentLeftTd.getAttribute( 'rootCellIndex' ); currentLeftTd = rows[currentLeftTd.getAttribute( 'rootRowIndex' )].cells[currentLeftTd.getAttribute( 'rootCellIndex' )]; } rowIndex = currentLeftTd.parentNode.rowIndex + (currentLeftTd.rowSpan || 1); } } // 检查是否有超出TableRange下边界的情况 if ( endRowIndex < rowsNum ) { for ( var cellIndex = beginCellIndex; cellIndex <= endCellIndex; ) { var currentDownTd = rows[endRowIndex].cells[cellIndex]; if ( _isHide( currentDownTd ) ) { currentDownTd = rows[currentDownTd.getAttribute( 'rootRowIndex' )].cells[currentDownTd.getAttribute( 'rootCellIndex' )]; } endRowIndex = currentDownTd.parentNode.rowIndex + currentDownTd.rowSpan - 1; cellIndex = getIndex( currentDownTd ) + (currentDownTd.colSpan || 1); } } //检查是否有超出右边界的情况 if ( endCellIndex < cellsNum ) { for ( rowIndex = beginRowIndex; rowIndex <= endRowIndex; ) { var currentRightTd = rows[rowIndex].cells[endCellIndex]; if ( _isHide( currentRightTd ) ) { currentRightTd = rows[currentRightTd.getAttribute( 'rootRowIndex' )].cells[currentRightTd.getAttribute( 'rootCellIndex' )]; } endCellIndex = getIndex( currentRightTd ) + currentRightTd.colSpan - 1; rowIndex = currentRightTd.parentNode.rowIndex + (currentRightTd.rowSpan || 1); } } if ( tmpBeginCellIndex == beginCellIndex && tmpEndCellIndex == endCellIndex && tmpEndRowIndex == endRowIndex && tmpBeginRowIndex == beginRowIndex ) { break; } } //返回选区的起始和结束坐标 return { beginRowIndex:beginRowIndex, beginCellIndex:beginCellIndex, endRowIndex:endRowIndex, endCellIndex:endCellIndex } } /** * 鼠标按下事件 * @param type * @param evt */ function _mouseDownEvent( type, evt ) { anchorTd = evt.target || evt.srcElement; if ( me.queryCommandState( 'highlightcode' ) || domUtils.findParent( anchorTd, function ( node ) { return node.tagName == "DIV" && /highlighter/.test( node.id ); } ) ) { return; } if ( evt.button == 2 )return; me.document.body.style.webkitUserSelect = ''; clearSelectedTd( me.currentSelectedArr ); domUtils.clearSelectedArr( me.currentSelectedArr ); //在td里边点击,anchorTd不是td if ( anchorTd.tagName !== 'TD' ) { anchorTd = domUtils.findParentByTagName( anchorTd, 'td' ) || anchorTd; } if ( anchorTd.tagName == 'TD' ) { me.addListener( 'mouseover', function ( type, evt ) { var tmpTd = evt.target || evt.srcElement; _mouseOverEvent.call( me, tmpTd ); evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false); } ); } else { reset(); } } /** * 鼠标移动事件 * @param tmpTd */ function _mouseOverEvent( tmpTd ) { //需要判断两个TD是否位于同一个表格内 if ( anchorTd && tmpTd.tagName == "TD" && domUtils.findParentByTagName( anchorTd, 'table' ) == domUtils.findParentByTagName( tmpTd, 'table' ) ) { me.document.body.style.webkitUserSelect = 'none'; var table = tmpTd.parentNode.parentNode.parentNode; me.selection.getNative()[browser.ie ? 'empty' : 'removeAllRanges'](); var range = _getCellsRange( anchorTd, tmpTd ); _toggleSelect( table, range ); } } /** * 切换选区状态 * @param table * @param cellsRange */ function _toggleSelect( table, cellsRange ) { var rows = table.rows; clearSelectedTd( me.currentSelectedArr ); for ( var i = cellsRange.beginRowIndex; i <= cellsRange.endRowIndex; i++ ) { for ( var j = cellsRange.beginCellIndex; j <= cellsRange.endCellIndex; j++ ) { var td = rows[i].cells[j]; td.className = "selectTdClass"; me.currentSelectedArr.push( td ); } } } //更新rootRowIndxe,rootCellIndex function update( table ) { var tds = table.getElementsByTagName( 'td' ), rowIndex, cellIndex, rows = table.rows; for ( var j = 0, tj; tj = tds[j++]; ) { if ( !_isHide( tj ) ) { rowIndex = tj.parentNode.rowIndex; cellIndex = getIndex( tj ); for ( var r = 0; r < tj.rowSpan; r++ ) { var c = r == 0 ? 1 : 0; for ( ; c < tj.colSpan; c++ ) { var tmp = rows[rowIndex + r].children[cellIndex + c]; tmp.setAttribute( 'rootRowIndex', rowIndex ); tmp.setAttribute( 'rootCellIndex', cellIndex ); } } } if ( !_isHide( tj ) ) { domUtils.removeAttributes( tj, ['rootRowIndex', 'rootCellIndex'] ); } if ( tj.colSpan && tj.colSpan == 1 ) { tj.removeAttribute( 'colSpan' ) } if ( tj.rowSpan && tj.rowSpan == 1 ) { tj.removeAttribute( 'rowSpan' ) } var width; if ( !_isHide( tj ) && (width = tj.style.width) && /%/.test( width ) ) { tj.style.width = Math.floor( 100 / tj.parentNode.cells.length ) + '%' } } } me.adjustTable = function ( cont ) { var table = cont.getElementsByTagName( 'table' ); for ( var i = 0, ti; ti = table[i++]; ) { //如果表格的align不是默认,将不占位,给后边的block元素设置clear:both if ( ti.getAttribute( 'align' ) ) { var next = ti.nextSibling; while ( next ) { if ( domUtils.isBlockElm( next ) ) { break; } next = next.nextSibling; } if ( next ) { next.style.clear = 'both'; } } ti.removeAttribute( '_innerCreateTable' ); var tds = domUtils.getElementsByTagName( ti, 'td' ), td, tmpTd; for ( var j = 0, tj; tj = tds[j++]; ) { if ( domUtils.isEmptyNode( tj ) ) { tj.innerHTML = browser.ie ? domUtils.fillChar : '
'; } var index = getIndex( tj ), rowIndex = tj.parentNode.rowIndex, rows = domUtils.findParentByTagName( tj, 'table' ).rows; for ( var r = 0; r < tj.rowSpan; r++ ) { var c = r == 0 ? 1 : 0; for ( ; c < tj.colSpan; c++ ) { if ( !td ) { td = tj.cloneNode( false ); td.rowSpan = td.colSpan = 1; td.style.display = 'none'; td.innerHTML = browser.ie ? '' : '
'; } else { td = td.cloneNode( true ) } td.setAttribute( 'rootRowIndex', tj.parentNode.rowIndex ); td.setAttribute( 'rootCellIndex', index ); if ( r == 0 ) { if ( tj.nextSibling ) { tj.parentNode.insertBefore( td, tj.nextSibling ); } else { tj.parentNode.appendChild( td ) } } else { tmpTd = rows[rowIndex + r].children[index]; if ( tmpTd ) { tmpTd.parentNode.insertBefore( td, tmpTd ) } else { //trace:1032 rows[rowIndex + r].appendChild( td ) } } } } } var bw = domUtils.getComputedStyle( ti, "border-width" ); if ( bw == '0px' && ti.style.border!="none" || ((bw == ""||bw =="medium") && ti.getAttribute( "border" ) === "0")) { //trace 2377 ie7下获取宽度值为medium domUtils.addClass(ti,"noBorderTable"); } } me.fireEvent( "afteradjusttable", cont ); }; // me.addListener( 'beforegetcontent', function () { // for ( var i = 0, ti, ts = me.document.getElementsByTagName( 'table' ); ti = ts[i++]; ) { // var pN = ti.parentNode; // if ( pN && pN.getAttribute( 'dropdrag' ) ) { // domUtils.remove( pN, true ) // } // } // } ); // // me.addListener( 'aftergetcontent', function () { // if ( !me.queryCommandState( 'source' ) ) // me.fireEvent( 'afteradjusttable', me.document ) // } ); // //table拖拽 // me.addListener( "afteradjusttable", function ( type, cont ) { // var table = cont.getElementsByTagName( "table" ), // dragCont = domUtils.creElm( me.document, 'div', { // style:'margin:0;padding:5px;border:0;', // dropdrag:true // } ); // // for ( var i = 0, ti; ti = table[i++]; ) { // var parentNode = ti.parentNode; // if ( parentNode && parentNode.nodeType == 1 ) { // //插入代码 // if ( /syntaxhighlighter/.test( parentNode.className ) ) continue; // (function ( ti ) { // var div = dragCont.cloneNode( false ); // ti.parentNode.insertBefore( div, ti ); // div.appendChild( ti ); // var borderStyle; // domUtils.on( div, 'mousemove', function ( evt ) { // var tag = evt.srcElement || evt.target; // if ( tag.tagName.toLowerCase() == "div" ) { // if ( ie && me.body.getAttribute( "contentEditable" ) == 'true' ) // me.body.setAttribute( "contentEditable", "false" ); // borderStyle = clickPosition( ti, this, evt ) // // } // } ); // if ( ie ) { // domUtils.on( div, 'mouseleave', function ( evt ) { // // if ( domUtils.isTagNode( evt.srcElement, "div" ) && me.body.getAttribute( "contentEditable" ) == 'false' ) { // // me.body.setAttribute( "contentEditable", "true" ); // } // // // } ); // } // // domUtils.on( div, "mousedown", function ( evt ) { // // if ( domUtils.isTagNode( evt.srcElement || evt.target, 'div' ) ) { // if ( ie && me.body.getAttribute( "contentEditable" ) == 'true' ) // me.body.setAttribute( "contentEditable", "false" ); // var tWidth = ti.offsetWidth, // tHeight = ti.offsetHeight, // align = ti.getAttribute( 'align' ); // try { // baidu.editor.ui.uiUtils.startDrag( evt, { // ondragstart:function () { // }, // ondragmove:function ( x, y ) { // // if ( align && align != "left" && /\w?w-/.test( borderStyle ) ) { // x = -x; // } // if ( /^s?[we]/.test( borderStyle ) ) { // ti.setAttribute( "width", (tWidth + x) > 0 ? tWidth + x : 0 ); // } // if ( /^s/.test( borderStyle ) ) { // ti.setAttribute( "height", (tHeight + y) > 0 ? tHeight + y : 0 ); // } // }, // ondragstop:function () { // } // }, me.document ); // } catch ( e ) { // alert( me.getLang("tableDrag")); // } // // } // } ); // // domUtils.on( ti, "mouseover", function () { // var div = ti.parentNode; // if ( div && div.parentNode && div.getAttribute( 'dropdrag' ) ) { // domUtils.setStyle( div, "cursor", "text" ); // if ( ie && me.body.getAttribute( "contentEditable" ) == 'false' ) // me.body.setAttribute( "contentEditable", "true" ); // } // // // } ); // })( ti ); // // } // } // } ); // function clickPosition( table, div, evt ) { // var pos = domUtils.getXY( table ), // tWidth = table.offsetWidth, // tHeight = table.offsetHeight, // evtPos = { // top:evt.clientY, // left:evt.clientX // }, // borderStyle = ""; // // if ( Math.abs( evtPos.left - pos.x - tWidth ) < 15 ) { // //右,右下 // borderStyle = Math.abs( evtPos.top - pos.y - tHeight ) < 15 ? "se-resize" : "e-resize"; // } else if ( Math.abs( evtPos.top - pos.y - tHeight ) < 15 && Math.abs( evtPos.left - pos.x ) < tWidth ) { // //下 // borderStyle = "s-resize"; // } // domUtils.setStyle( div, "cursor", borderStyle || 'text' ); // return borderStyle; // } }; ///import core ///commands 右键菜单 ///commandsName ContextMenu ///commandsTitle 右键菜单 /** * 右键菜单 * @function * @name baidu.editor.plugins.contextmenu * @author zhanyi */ UE.plugins['contextmenu'] = function () { var me = this, lang = me.getLang( "contextMenu" ), menu, items = me.options.contextMenu || [ {label:lang['delete'], cmdName:'delete'}, {label:lang['selectall'], cmdName:'selectall'}, { label:lang.deletecode, cmdName:'highlightcode', icon:'deletehighlightcode' }, { label:lang.cleardoc, cmdName:'cleardoc', exec:function () { if ( confirm( lang.confirmclear ) ) { this.execCommand( 'cleardoc' ); } } }, '-', { label:lang.unlink, cmdName:'unlink' }, '-', { group:lang.paragraph, icon:'justifyjustify', subMenu:[ { label:me.getLang( "justifyleft" ), cmdName:'justify', value:'left' }, { label:me.getLang( "justifyright" ), cmdName:'justify', value:'right' }, { label:me.getLang( "justifyrenter" ), cmdName:'justify', value:'center' }, { label:me.getLang( "justify" ), cmdName:'justify', value:'justify' } ] }, '-', { label:lang.edittable, cmdName:'edittable', exec:function () { this.ui._dialogs['inserttableDialog'].open(); } }, { label:lang.edittd, cmdName:'edittd', exec:function () { //如果没有创建,创建一下先 if ( UE.ui['edittd'] ) { new UE.ui['edittd']( this ); } this.ui._dialogs['edittdDialog'].open(); } }, { group:lang.table, icon:'table', subMenu:[ { label:lang.deletetable, cmdName:'deletetable' }, { label:lang.insertparagraphbeforetable, cmdName:'insertparagraphbeforetable' }, '-', { label:lang.deleterow, cmdName:'deleterow' }, { label:lang.deletecol, cmdName:'deletecol' }, '-', { label:lang.insertrow, cmdName:'insertrow' }, { label:lang.insertcol, cmdName:'insertcol' }, '-', { label:lang.mergeright, cmdName:'mergeright' }, { label:lang.mergedown, cmdName:'mergedown' }, '-', { label:lang.splittorows, cmdName:'splittorows' }, { label:lang.splittocols, cmdName:'splittocols' }, { label:lang.mergecells, cmdName:'mergecells' }, { label:lang.splittocells, cmdName:'splittocells' } ] }, { label:lang['copy'], cmdName:'copy', exec:function () { alert( lang.copymsg ); }, query:function () { return 0; } }, { label:lang['paste'], cmdName:'paste', exec:function () { alert( lang.pastemsg ); }, query:function () { return 0; } } ]; if ( !items.length ) { return; } var uiUtils = UE.ui.uiUtils; me.addListener( 'contextmenu', function ( type, evt ) { var offset = uiUtils.getViewportOffsetByEvent( evt ); me.fireEvent( 'beforeselectionchange' ); if ( menu ) { menu.destroy(); } for ( var i = 0, ti, contextItems = []; ti = items[i]; i++ ) { var last; (function ( item ) { if ( item == '-' ) { if ( (last = contextItems[contextItems.length - 1 ] ) && last !== '-' ) { contextItems.push( '-' ); } } else if ( item.hasOwnProperty( "group" ) ) { for ( var j = 0, cj, subMenu = []; cj = item.subMenu[j]; j++ ) { (function ( subItem ) { if ( subItem == '-' ) { if ( (last = subMenu[subMenu.length - 1 ] ) && last !== '-' ) { subMenu.push( '-' ); } } else { if ( (me.commands[subItem.cmdName] || UE.commands[subItem.cmdName] || subItem.query) && (subItem.query ? subItem.query() : me.queryCommandState( subItem.cmdName )) > -1 ) { subMenu.push( { 'label':subItem.label || me.getLang( "contextMenu." + subItem.cmdName + (subItem.value || '') ), 'className':'edui-for-' + subItem.cmdName + (subItem.value || ''), onclick:subItem.exec ? function () { subItem.exec.call( me ); } : function () { me.execCommand( subItem.cmdName, subItem.value ); } } ); } } })( cj ); } if ( subMenu.length ) { contextItems.push( { //todo 修正成自动获取方式 'label':item.icon == "table" ? me.getLang( "contextMenu.table" ) : me.getLang( "contextMenu.paragraph" ), className:'edui-for-' + item.icon, 'subMenu':{ items:subMenu, editor:me } } ); } } else { //有可能commmand没有加载右键不能出来,或者没有command也想能展示出来添加query方法 if ( (me.commands[item.cmdName] || UE.commands[item.cmdName] || item.query) && (item.query ? item.query() : me.queryCommandState( item.cmdName )) > -1 ) { //highlight todo if ( item.cmdName == 'highlightcode' && me.queryCommandState( item.cmdName ) == 0 ) { return; } contextItems.push( { 'label':item.label || me.getLang( "contextMenu." + item.cmdName ), className:'edui-for-' + (item.icon ? item.icon : item.cmdName + (item.value || '')), onclick:item.exec ? function () { item.exec.call( me ); } : function () { me.execCommand( item.cmdName, item.value ); } } ); } } })( ti ); } if ( contextItems[contextItems.length - 1] == '-' ) { contextItems.pop(); } menu = new UE.ui.Menu( { items:contextItems, editor:me } ); menu.render(); menu.showAt( offset ); domUtils.preventDefault( evt ); if ( browser.ie ) { var ieRange; try { ieRange = me.selection.getNative().createRange(); } catch ( e ) { return; } if ( ieRange.item ) { var range = new dom.Range( me.document ); range.selectNode( ieRange.item( 0 ) ).select( true, true ); } } } ); }; ///import core ///commands 加粗,斜体,上标,下标 ///commandsName Bold,Italic,Subscript,Superscript ///commandsTitle 加粗,加斜,下标,上标 /** * b u i等基础功能实现 * @function * @name baidu.editor.execCommands * @param {String} cmdName bold加粗。italic斜体。subscript上标。superscript下标。 */ UE.plugins['basestyle'] = function(){ var basestyles = { 'bold':['strong','b'], 'italic':['em','i'], 'subscript':['sub'], 'superscript':['sup'] }, getObj = function(editor,tagNames){ //var start = editor.selection.getStart(); var path = editor.selection.getStartElementPath(); // return domUtils.findParentByTagName( start, tagNames, true ) return utils.findNode(path,tagNames); }, me = this; for ( var style in basestyles ) { (function( cmd, tagNames ) { me.commands[cmd] = { execCommand : function( cmdName ) { var range = new dom.Range(me.document),obj = ''; //table的处理 if(me.currentSelectedArr && me.currentSelectedArr.length > 0){ for(var i=0,ci;ci=me.currentSelectedArr[i++];){ if(ci.style.display != 'none'){ range.selectNodeContents(ci).select(); //trace:943 !obj && (obj = getObj(this,tagNames)); if(cmdName == 'superscript' || cmdName == 'subscript'){ if(!obj || obj.tagName.toLowerCase() != cmdName){ range.removeInlineStyle(['sub','sup']); } } obj ? range.removeInlineStyle( tagNames ) : range.applyInlineStyle( tagNames[0] ); } } range.selectNodeContents(me.currentSelectedArr[0]).select(); }else{ range = me.selection.getRange(); obj = getObj(this,tagNames); if ( range.collapsed ) { if ( obj ) { var tmpText = me.document.createTextNode(''); range.insertNode( tmpText ).removeInlineStyle( tagNames ); range.setStartBefore(tmpText); domUtils.remove(tmpText); } else { var tmpNode = range.document.createElement( tagNames[0] ); if(cmdName == 'superscript' || cmdName == 'subscript'){ tmpText = me.document.createTextNode(''); range.insertNode(tmpText) .removeInlineStyle(['sub','sup']) .setStartBefore(tmpText) .collapse(true); } range.insertNode( tmpNode ).setStart( tmpNode, 0 ); } range.collapse( true ); } else { if(cmdName == 'superscript' || cmdName == 'subscript'){ if(!obj || obj.tagName.toLowerCase() != cmdName){ range.removeInlineStyle(['sub','sup']); } } obj ? range.removeInlineStyle( tagNames ) : range.applyInlineStyle( tagNames[0] ); } range.select(); } return true; }, queryCommandState : function() { if(this.highlight){ return -1; } return getObj(this,tagNames) ? 1 : 0; } }; })( style, basestyles[style] ); } }; ///import core ///commands 选区路径 ///commandsName ElementPath,elementPathEnabled ///commandsTitle 选区路径 /** * 选区路径 * @function * @name baidu.editor.execCommand * @param {String} cmdName elementpath选区路径 */ UE.plugins['elementpath'] = function(){ var currentLevel, tagNames, me = this; me.setOpt('elementPathEnabled',true); if(!me.options.elementPathEnabled){ return; } me.commands['elementpath'] = { execCommand : function( cmdName, level ) { var start = tagNames[level], range = me.selection.getRange(); me.currentSelectedArr && domUtils.clearSelectedArr(me.currentSelectedArr); currentLevel = level*1; if(dtd.$tableContent[start.tagName]){ switch (start.tagName){ case 'TD':me.currentSelectedArr = [start]; start.className = me.options.selectedTdClass; break; case 'TR': var cells = start.cells; for(var i=0,ti;ti=cells[i++];){ me.currentSelectedArr.push(ti); ti.className = me.options.selectedTdClass; } break; case 'TABLE': case 'TBODY': var rows = start.rows; for(var i=0,ri;ri=rows[i++];){ cells = ri.cells; for(var j=0,tj;tj=cells[j++];){ me.currentSelectedArr.push(tj); tj.className = me.options.selectedTdClass; } } } start = me.currentSelectedArr[0]; if(domUtils.isEmptyNode(start)){ range.setStart(start,0).setCursor(); }else{ range.selectNodeContents(start).select(); } }else{ range.selectNode(start).select(); } }, queryCommandValue : function() { //产生一个副本,不能修改原来的startElementPath; var parents = [].concat(this.selection.getStartElementPath()).reverse(), names = []; tagNames = parents; for(var i=0,ci;ci=parents[i];i++){ if(ci.nodeType == 3) { continue; } var name = ci.tagName.toLowerCase(); if(name == 'img' && ci.getAttribute('anchorname')){ name = 'anchor'; } names[i] = name; if(currentLevel == i){ currentLevel = -1; break; } } return names; } }; }; ///import core ///import plugins\removeformat.js ///commands 格式刷 ///commandsName FormatMatch ///commandsTitle 格式刷 /** * 格式刷,只格式inline的 * @function * @name baidu.editor.execCommand * @param {String} cmdName formatmatch执行格式刷 */ UE.plugins['formatmatch'] = function(){ var me = this, list = [],img, flag = 0; me.addListener('reset',function(){ list = []; flag = 0; }); function addList(type,evt){ if(browser.webkit){ var target = evt.target.tagName == 'IMG' ? evt.target : null; } function addFormat(range){ if(text && (!me.currentSelectedArr || !me.currentSelectedArr.length)){ range.selectNode(text); } return range.applyInlineStyle(list[list.length-1].tagName,null,list); } me.undoManger && me.undoManger.save(); var range = me.selection.getRange(), imgT = target || range.getClosedNode(); if(img && imgT && imgT.tagName == 'IMG'){ //trace:964 imgT.style.cssText += ';float:' + (img.style.cssFloat || img.style.styleFloat ||'none') + ';display:' + (img.style.display||'inline'); img = null; }else{ if(!img){ var collapsed = range.collapsed; if(collapsed){ var text = me.document.createTextNode('match'); range.insertNode(text).select(); } me.__hasEnterExecCommand = true; //不能把block上的属性干掉 //trace:1553 var removeFormatAttributes = me.options.removeFormatAttributes; me.options.removeFormatAttributes = ''; me.execCommand('removeformat'); me.options.removeFormatAttributes = removeFormatAttributes; me.__hasEnterExecCommand = false; //trace:969 range = me.selection.getRange(); if(list.length == 0){ if(me.currentSelectedArr && me.currentSelectedArr.length > 0){ range.selectNodeContents(me.currentSelectedArr[0]).select(); } }else{ if(me.currentSelectedArr && me.currentSelectedArr.length > 0){ for(var i=0,ci;ci=me.currentSelectedArr[i++];){ range.selectNodeContents(ci); addFormat(range); } range.selectNodeContents(me.currentSelectedArr[0]).select(); }else{ addFormat(range); } } if(!me.currentSelectedArr || !me.currentSelectedArr.length){ if(text){ range.setStartBefore(text).collapse(true); } range.select(); } text && domUtils.remove(text); } } me.undoManger && me.undoManger.save(); me.removeListener('mouseup',addList); flag = 0; } me.commands['formatmatch'] = { execCommand : function( cmdName ) { if(flag){ flag = 0; list = []; me.removeListener('mouseup',addList); return; } var range = me.selection.getRange(); img = range.getClosedNode(); if(!img || img.tagName != 'IMG'){ range.collapse(true).shrinkBoundary(); var start = range.startContainer; list = domUtils.findParents(start,true,function(node){ return !domUtils.isBlockElm(node) && node.nodeType == 1; }); //a不能加入格式刷, 并且克隆节点 for(var i=0,ci;ci=list[i];i++){ if(ci.tagName == 'A'){ list.splice(i,1); break; } } } me.addListener('mouseup',addList); flag = 1; }, queryCommandState : function() { if(this.highlight){ return -1; } return flag; }, notNeedUndo : 1 }; }; ///import core ///commands 查找替换 ///commandsName SearchReplace ///commandsTitle 查询替换 ///commandsDialog dialogs\searchreplace\searchreplace.html /** * @description 查找替换 * @author zhanyi */ UE.plugins['searchreplace'] = function(){ var currentRange, first, me = this; me.addListener('reset',function(){ currentRange = null; first = null; }); me.commands['searchreplace'] = { execCommand : function(cmdName,opt){ var me = this, sel = me.selection, range, nativeRange, num = 0, opt = utils.extend(opt,{ all : false, casesensitive : false, dir : 1 },true); if(browser.ie){ while(1){ var tmpRange; nativeRange = me.document.selection.createRange(); tmpRange = nativeRange.duplicate(); tmpRange.moveToElementText(me.document.body); if(opt.all){ first = 0; opt.dir = 1; if(currentRange){ tmpRange.setEndPoint(opt.dir == -1 ? 'EndToStart' : 'StartToEnd',currentRange); } }else{ tmpRange.setEndPoint(opt.dir == -1 ? 'EndToStart' : 'StartToEnd',nativeRange); if(opt.hasOwnProperty("replaceStr")){ tmpRange.setEndPoint(opt.dir == -1 ? 'StartToEnd' : 'EndToStart',nativeRange); } } nativeRange = tmpRange.duplicate(); if(!tmpRange.findText(opt.searchStr,opt.dir,opt.casesensitive ? 4 : 0)){ currentRange = null; tmpRange = me.document.selection.createRange(); tmpRange.scrollIntoView(); return num; } tmpRange.select(); //替换 if(opt.hasOwnProperty("replaceStr")){ range = sel.getRange(); range.deleteContents().insertNode(range.document.createTextNode(opt.replaceStr)).select(); currentRange = sel.getNative().createRange(); } num++; if(!opt.all){ break; } } }else{ var w = me.window,nativeSel = sel.getNative(),tmpRange; while(1){ if(opt.all){ if(currentRange){ currentRange.collapse(false); nativeRange = currentRange; }else{ nativeRange = me.document.createRange(); nativeRange.setStart(me.document.body,0); } nativeSel.removeAllRanges(); nativeSel.addRange( nativeRange ); first = 0; opt.dir = 1; }else{ nativeRange = w.getSelection().getRangeAt(0); if(opt.hasOwnProperty("replaceStr")){ nativeRange.collapse(opt.dir == 1 ? true : false); } } //如果是第一次并且海选中了内容那就要清除,为find做准备 if(!first){ nativeRange.collapse( opt.dir <0 ? true : false); nativeSel.removeAllRanges(); nativeSel.addRange( nativeRange ); }else{ nativeSel.removeAllRanges(); } if(!w.find(opt.searchStr,opt.casesensitive,opt.dir < 0 ? true : false) ) { currentRange = null; nativeSel.removeAllRanges(); return num; } first = 0; range = w.getSelection().getRangeAt(0); if(!range.collapsed){ if(opt.hasOwnProperty("replaceStr")){ range.deleteContents(); var text = w.document.createTextNode(opt.replaceStr); range.insertNode(text); range.selectNode(text); nativeSel.addRange(range); currentRange = range.cloneRange(); } } num++; if(!opt.all){ break; } } } return true; } }; }; ///import core ///commands 自定义样式 ///commandsName CustomStyle ///commandsTitle 自定义样式 UE.plugins['customstyle'] = function() { var me = this; me.setOpt({ 'customstyle':[ {tag:'h1',name:'tc', style:'font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;'}, {tag:'h1',name:'tl', style:'font-size:32px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:left;margin:0 0 10px 0;'}, {tag:'span',name:'im', style:'font-size:16px;font-style:italic;font-weight:bold;color:#000;line-height:18px;'}, {tag:'span',name:'hi', style:'font-size:16px;font-style:italic;font-weight:bold;color:rgb(51, 153, 204);line-height:18px;'} ]}); me.commands['customstyle'] = { execCommand : function(cmdName, obj) { var me = this, tagName = obj.tag, node = domUtils.findParent(me.selection.getStart(), function(node) { return node.getAttribute('label'); }, true), range,bk,tmpObj = {}; for (var p in obj) { tmpObj[p] = obj[p]; } delete tmpObj.tag; if (node && node.getAttribute('label') == obj.label) { range = this.selection.getRange(); bk = range.createBookmark(); if (range.collapsed) { //trace:1732 删掉自定义标签,要有p来回填站位 if(dtd.$block[node.tagName]){ var fillNode = me.document.createElement('p'); domUtils.moveChild(node, fillNode); node.parentNode.insertBefore(fillNode, node); domUtils.remove(node); }else{ domUtils.remove(node,true); } } else { var common = domUtils.getCommonAncestor(bk.start, bk.end), nodes = domUtils.getElementsByTagName(common, tagName); if(new RegExp(tagName,'i').test(common.tagName)){ nodes.push(common); } for (var i = 0,ni; ni = nodes[i++];) { if (ni.getAttribute('label') == obj.label) { var ps = domUtils.getPosition(ni, bk.start),pe = domUtils.getPosition(ni, bk.end); if ((ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) && (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS) ) if (dtd.$block[tagName]) { var fillNode = me.document.createElement('p'); domUtils.moveChild(ni, fillNode); ni.parentNode.insertBefore(fillNode, ni); } domUtils.remove(ni, true); } } node = domUtils.findParent(common, function(node) { return node.getAttribute('label') == obj.label; }, true); if (node) { domUtils.remove(node, true); } } range.moveToBookmark(bk).select(); } else { if (dtd.$block[tagName]) { this.execCommand('paragraph', tagName, tmpObj,'customstyle'); range = me.selection.getRange(); if (!range.collapsed) { range.collapse(); node = domUtils.findParent(me.selection.getStart(), function(node) { return node.getAttribute('label') == obj.label; }, true); var pNode = me.document.createElement('p'); domUtils.insertAfter(node, pNode); domUtils.fillNode(me.document, pNode); range.setStart(pNode, 0).setCursor(); } } else { range = me.selection.getRange(); if (range.collapsed) { node = me.document.createElement(tagName); domUtils.setAttributes(node, tmpObj); range.insertNode(node).setStart(node, 0).setCursor(); return; } bk = range.createBookmark(); range.applyInlineStyle(tagName, tmpObj).moveToBookmark(bk).select(); } } }, queryCommandValue : function() { var parent = utils.findNode(this.selection.getStartElementPath(),null,function(node){return node.getAttribute('label')}); return parent ? parent.getAttribute('label') : ''; }, queryCommandState : function() { return this.highlight ? -1 : 0; } }; //当去掉customstyle是,如果是块元素,用p代替 me.addListener('keyup', function(type, evt) { var keyCode = evt.keyCode || evt.which; if (keyCode == 32 || keyCode == 13) { var range = me.selection.getRange(); if (range.collapsed) { var node = domUtils.findParent(me.selection.getStart(), function(node) { return node.getAttribute('label'); }, true); if (node && dtd.$block[node.tagName] && domUtils.isEmptyNode(node)) { var p = me.document.createElement('p'); domUtils.insertAfter(node, p); domUtils.fillNode(me.document, p); domUtils.remove(node); range.setStart(p, 0).setCursor(); } } } }); }; ///import core ///commandsName catchRemoteImage /** * 远程图片抓取,当开启本插件时所有不符合本地域名的图片都将被抓取成为本地服务器上的图片 * */ UE.plugins['catchremoteimage'] = function () { if (this.options.catchRemoteImageEnable===false){ return; } var me = this; this.setOpt({ localDomain:["127.0.0.1","localhost","img.baidu.com"], separater:'ue_separate_ue', catchFieldName:"upfile", catchRemoteImageEnable:true }); var ajax = UE.ajax, localDomain = me.options.localDomain , catcherUrl = me.options.catcherUrl, separater = me.options.separater; function catchremoteimage(imgs, callbacks) { var submitStr = imgs.join(separater); var tmpOption = { timeout:60000, //单位:毫秒,回调请求超时设置。目标用户如果网速不是很快的话此处建议设置一个较大的数值 onsuccess:callbacks["success"], onerror:callbacks["error"] }; tmpOption[me.options.catchFieldName] = submitStr; ajax.request(catcherUrl, tmpOption); } me.addListener("afterpaste", function () { me.fireEvent("catchRemoteImage"); }); me.addListener("catchRemoteImage", function () { var remoteImages = []; var imgs = domUtils.getElementsByTagName(me.document, "img"); var test = function (src,urls) { for (var j = 0, url; url = urls[j++];) { if (src.indexOf(url) !== -1) { return true; } } return false; }; for (var i = 0, ci; ci = imgs[i++];) { if (ci.getAttribute("word_img")){ continue; } var src = ci.getAttribute("data_ue_src") || ci.src || ""; if (/^(https?|ftp):/i.test(src) && !test(src,localDomain)) { remoteImages.push(src); } } if (remoteImages.length) { catchremoteimage(remoteImages, { //成功抓取 success:function (xhr) { try { var info = eval("(" + xhr.responseText + ")"); } catch (e) { return; } var srcUrls = info.srcUrl.split(separater), urls = info.url.split(separater); for (var i = 0, ci; ci = imgs[i++];) { var src = ci.getAttribute("data_ue_src") || ci.src || ""; for (var j = 0, cj; cj = srcUrls[j++];) { var url = urls[j - 1]; if (src == cj && url != "error") { //抓取失败时不做替换处理 //地址修正 var newSrc = me.options.catcherPath + url; domUtils.setAttributes(ci, { "src":newSrc, "data_ue_src":newSrc }); break; } } } }, //回调失败,本次请求超时 error:function () { me.fireEvent("catchremoteerror"); } }); } }); }; ///import core ///commandsName snapscreen ///commandsTitle 截屏 /** * 截屏插件 */ UE.commands['snapscreen'] = { execCommand: function(){ var me = this,lang = me.getLang("snapScreen_plugin"); me.setOpt({ snapscreenServerPort: 80 //屏幕截图的server端端口 ,snapscreenImgAlign: 'center' //截图的图片默认的排版方式 }); var editorOptions = me.options; if(!browser.ie){ alert(lang.browserMsg); return; } var onSuccess = function(rs){ try{ rs = eval("("+ rs +")"); }catch(e){ alert(lang.callBackErrorMsg); return; } if(rs.state != 'SUCCESS'){ alert(rs.state); return; } me.execCommand('insertimage', { src: editorOptions.snapscreenPath + rs.url, floatStyle: editorOptions.snapscreenImgAlign, data_ue_src:editorOptions.snapscreenPath + rs.url }); }; var onStartUpload = function(){ //开始截图上传 }; var onError = function(){ alert(lang.uploadErrorMsg); }; try{ var nativeObj = new ActiveXObject('Snapsie.CoSnapsie'); nativeObj.saveSnapshot(editorOptions.snapscreenHost, editorOptions.snapscreenServerUrl, editorOptions.snapscreenServerPort, onStartUpload,onSuccess,onError); }catch(e){ me.ui._dialogs['snapscreenDialog'].open(); } }, queryCommandState: function(){ return this.highlight || !browser.ie ? -1 :0; } }; ///import core ///commandsName attachment ///commandsTitle 附件上传 UE.commands["attachment"] = { queryCommandState:function(){ return this.highlight ? -1 :0; } }; /** * Created by JetBrains PhpStorm. * User: taoqili * Date: 12-5-7 * Time: 下午2:37 * To change this template use File | Settings | File Templates. */ UE.plugins['webapp'] = function () { var me = this; function createInsertStr( obj, toIframe, addParagraph ) { return !toIframe ? (addParagraph ? '

' : '') + '' + (addParagraph ? '

' : '') : ''; } function switchImgAndIframe( img2frame ) { var tmpdiv, nodes = domUtils.getElementsByTagName( me.document, !img2frame ? "iframe" : "img" ); for ( var i = 0, node; node = nodes[i++]; ) { if ( node.className != "edui-faked-webapp" ){ continue; } tmpdiv = me.document.createElement( "div" ); tmpdiv.innerHTML = createInsertStr( img2frame ? {url:node.getAttribute( "_url" ), width:node.width, height:node.height,title:node.title,logo:node.style.backgroundImage.replace("url(","").replace(")","")} : {url:node.getAttribute( "src", 2 ),title:node.title, width:node.width, height:node.height,logo:node.getAttribute("logo_url")}, img2frame ? true : false,false ); node.parentNode.replaceChild( tmpdiv.firstChild, node ); } } me.addListener( "beforegetcontent", function () { switchImgAndIframe( true ); } ); me.addListener( 'aftersetcontent', function () { switchImgAndIframe( false ); } ); me.addListener( 'aftergetcontent', function ( cmdName ) { if ( cmdName == 'aftergetcontent' && me.queryCommandState( 'source' ) ){ return; } switchImgAndIframe( false ); } ); UE.commands['webapp'] = { execCommand:function ( cmd, obj ) { me.execCommand( "inserthtml", createInsertStr( obj, false,true ) ); }, queryCommandState:function () { return me.highlight ? -1 : 0; } }; }; ///import core ///commands 模板 ///commandsName template ///commandsTitle 模板 ///commandsDialog dialogs\template\template.html (function() { UE.plugins['template'] = function(){ var me = this; UE.commands['template'] = { execCommand : function(cmd,obj) { obj.html&&me.execCommand("inserthtml",obj.html); }, queryCommandState : function(){ return this.highlight ? -1 : 0; } }; me.addListener("click",function(type,evt){ var el = evt.target || evt.srcElement, range = me.selection.getRange(); var tnode = domUtils.findParent(el,function(node){ if(node.className && domUtils.hasClass(node,"ue_t")){ return node; } },true); tnode&&range.selectNode(tnode).shrinkBoundary().select(); }); me.addListener("keydown",function(type, evt){ var range = me.selection.getRange(); if(!range.collapsed){ if(!evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey){ var tnode = domUtils.findParent(range.startContainer,function(node){ if(node.className && domUtils.hasClass(node,"ue_t")){ return node; } },true); if(tnode){ domUtils.removeClasses(tnode,["ue_t"]); } } } }); }; })(); var baidu = baidu || {}; baidu.editor = baidu.editor || {}; baidu.editor.ui = {}; (function (){ var browser = baidu.editor.browser, domUtils = baidu.editor.dom.domUtils; var magic = '$EDITORUI'; var root = window[magic] = {}; var uidMagic = 'ID' + magic; var uidCount = 0; var uiUtils = baidu.editor.ui.uiUtils = { uid: function (obj){ return (obj ? obj[uidMagic] || (obj[uidMagic] = ++ uidCount) : ++ uidCount); }, hook: function ( fn, callback ) { var dg; if (fn && fn._callbacks) { dg = fn; } else { dg = function (){ var q; if (fn) { q = fn.apply(this, arguments); } var callbacks = dg._callbacks; var k = callbacks.length; while (k --) { var r = callbacks[k].apply(this, arguments); if (q === undefined) { q = r; } } return q; }; dg._callbacks = []; } dg._callbacks.push(callback); return dg; }, createElementByHtml: function (html){ var el = document.createElement('div'); el.innerHTML = html; el = el.firstChild; el.parentNode.removeChild(el); return el; }, getViewportElement: function (){ return (browser.ie && browser.quirks) ? document.body : document.documentElement; }, getClientRect: function (element){ var bcr; //trace IE6下在控制编辑器显隐时可能会报错,catch一下 try{ bcr = element.getBoundingClientRect(); }catch(e){ bcr={left:0,top:0,height:0,width:0} } var rect = { left: Math.round(bcr.left), top: Math.round(bcr.top), height: Math.round(bcr.bottom - bcr.top), width: Math.round(bcr.right - bcr.left) }; var doc; while ((doc = element.ownerDocument) !== document && (element = domUtils.getWindow(doc).frameElement)) { bcr = element.getBoundingClientRect(); rect.left += bcr.left; rect.top += bcr.top; } rect.bottom = rect.top + rect.height; rect.right = rect.left + rect.width; return rect; }, getViewportRect: function (){ var viewportEl = uiUtils.getViewportElement(); var width = (window.innerWidth || viewportEl.clientWidth) | 0; var height = (window.innerHeight ||viewportEl.clientHeight) | 0; return { left: 0, top: 0, height: height, width: width, bottom: height, right: width }; }, setViewportOffset: function (element, offset){ var rect; var fixedLayer = uiUtils.getFixedLayer(); if (element.parentNode === fixedLayer) { element.style.left = offset.left + 'px'; element.style.top = offset.top + 'px'; } else { domUtils.setViewportOffset(element, offset); } }, getEventOffset: function (evt){ var el = evt.target || evt.srcElement; var rect = uiUtils.getClientRect(el); var offset = uiUtils.getViewportOffsetByEvent(evt); return { left: offset.left - rect.left, top: offset.top - rect.top }; }, getViewportOffsetByEvent: function (evt){ var el = evt.target || evt.srcElement; var frameEl = domUtils.getWindow(el).frameElement; var offset = { left: evt.clientX, top: evt.clientY }; if (frameEl && el.ownerDocument !== document) { var rect = uiUtils.getClientRect(frameEl); offset.left += rect.left; offset.top += rect.top; } return offset; }, setGlobal: function (id, obj){ root[id] = obj; return magic + '["' + id + '"]'; }, unsetGlobal: function (id){ delete root[id]; }, copyAttributes: function (tgt, src){ var attributes = src.attributes; var k = attributes.length; while (k --) { var attrNode = attributes[k]; if ( attrNode.nodeName != 'style' && attrNode.nodeName != 'class' && (!browser.ie || attrNode.specified) ) { tgt.setAttribute(attrNode.nodeName, attrNode.nodeValue); } } if (src.className) { tgt.className += ' ' + src.className; } if (src.style.cssText) { tgt.style.cssText += ';' + src.style.cssText; } }, removeStyle: function (el, styleName){ if (el.style.removeProperty) { el.style.removeProperty(styleName); } else if (el.style.removeAttribute) { el.style.removeAttribute(styleName); } else throw ''; }, contains: function (elA, elB){ return elA && elB && (elA === elB ? false : ( elA.contains ? elA.contains(elB) : elA.compareDocumentPosition(elB) & 16 )); }, startDrag: function (evt, callbacks,doc){ var doc = doc || document; var startX = evt.clientX; var startY = evt.clientY; function handleMouseMove(evt){ var x = evt.clientX - startX; var y = evt.clientY - startY; callbacks.ondragmove(x, y); if (evt.stopPropagation) { evt.stopPropagation(); } else { evt.cancelBubble = true; } } if (doc.addEventListener) { function handleMouseUp(evt){ doc.removeEventListener('mousemove', handleMouseMove, true); doc.removeEventListener('mouseup', handleMouseMove, true); window.removeEventListener('mouseup', handleMouseUp, true); callbacks.ondragstop(); } doc.addEventListener('mousemove', handleMouseMove, true); doc.addEventListener('mouseup', handleMouseUp, true); window.addEventListener('mouseup', handleMouseUp, true); evt.preventDefault(); } else { var elm = evt.srcElement; elm.setCapture(); function releaseCaptrue(){ elm.releaseCapture(); elm.detachEvent('onmousemove', handleMouseMove); elm.detachEvent('onmouseup', releaseCaptrue); elm.detachEvent('onlosecaptrue', releaseCaptrue); callbacks.ondragstop(); } elm.attachEvent('onmousemove', handleMouseMove); elm.attachEvent('onmouseup', releaseCaptrue); elm.attachEvent('onlosecaptrue', releaseCaptrue); evt.returnValue = false; } callbacks.ondragstart(); }, getFixedLayer: function (){ var layer = document.getElementById('edui_fixedlayer'); if (layer == null) { layer = document.createElement('div'); layer.id = 'edui_fixedlayer'; document.body.appendChild(layer); if (browser.ie && browser.version <= 8) { layer.style.position = 'absolute'; bindFixedLayer(); setTimeout(updateFixedOffset); } else { layer.style.position = 'fixed'; } layer.style.left = '0'; layer.style.top = '0'; layer.style.width = '0'; layer.style.height = '0'; } return layer; }, makeUnselectable: function (element){ if (browser.opera || (browser.ie && browser.version < 9)) { element.unselectable = 'on'; if (element.hasChildNodes()) { for (var i=0; i'; } }; utils.inherits(Separator, UIBase); })(); ///import core ///import uicore (function (){ var utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, uiUtils = baidu.editor.ui.uiUtils; var Mask = baidu.editor.ui.Mask = function (options){ this.initOptions(options); this.initUIBase(); }; Mask.prototype = { getHtmlTpl: function (){ return '
'; }, postRender: function (){ var me = this; domUtils.on(window, 'resize', function (){ setTimeout(function (){ if (!me.isHidden()) { me._fill(); } }); }); }, show: function (zIndex){ this._fill(); this.getDom().style.display = ''; this.getDom().style.zIndex = zIndex; }, hide: function (){ this.getDom().style.display = 'none'; this.getDom().style.zIndex = ''; }, isHidden: function (){ return this.getDom().style.display == 'none'; }, _onMouseDown: function (){ return false; }, _fill: function (){ var el = this.getDom(); var vpRect = uiUtils.getViewportRect(); el.style.width = vpRect.width + 'px'; el.style.height = vpRect.height + 'px'; } }; utils.inherits(Mask, UIBase); })(); ///import core ///import uicore (function () { var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, Popup = baidu.editor.ui.Popup = function (options){ this.initOptions(options); this.initPopup(); }; var allPopups = []; function closeAllPopup( el ){ var newAll = []; for ( var i = 0; i < allPopups.length; i++ ) { var pop = allPopups[i]; if (!pop.isHidden()) { if (pop.queryAutoHide(el) !== false) { pop.hide(); } } } } Popup.postHide = closeAllPopup; var ANCHOR_CLASSES = ['edui-anchor-topleft','edui-anchor-topright', 'edui-anchor-bottomleft','edui-anchor-bottomright']; Popup.prototype = { SHADOW_RADIUS: 5, content: null, _hidden: false, autoRender: true, canSideLeft: true, canSideUp: true, initPopup: function (){ this.initUIBase(); allPopups.push( this ); }, getHtmlTpl: function (){ return '
' + '
' + ' ' + '
' + '
' + this.getContentHtmlTpl() + '
' + '
' + '
'; }, getContentHtmlTpl: function (){ if(this.content){ if (typeof this.content == 'string') { return this.content; } return this.content.renderHtml(); }else{ return '' } }, _UIBase_postRender: UIBase.prototype.postRender, postRender: function (){ if (this.content instanceof UIBase) { this.content.postRender(); } this.fireEvent('postRenderAfter'); this.hide(true); this._UIBase_postRender(); }, _doAutoRender: function (){ if (!this.getDom() && this.autoRender) { this.render(); } }, mesureSize: function (){ var box = this.getDom('content'); return uiUtils.getClientRect(box); }, fitSize: function (){ var popBodyEl = this.getDom('body'); popBodyEl.style.width = ''; popBodyEl.style.height = ''; var size = this.mesureSize(); popBodyEl.style.width = size.width + 'px'; popBodyEl.style.height = size.height + 'px'; return size; }, showAnchor: function ( element, hoz ){ this.showAnchorRect( uiUtils.getClientRect( element ), hoz ); }, showAnchorRect: function ( rect, hoz, adj ){ this._doAutoRender(); var vpRect = uiUtils.getViewportRect(); this._show(); var popSize = this.fitSize(); var sideLeft, sideUp, left, top; if (hoz) { sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width); sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height); left = (sideLeft ? rect.left - popSize.width : rect.right); top = (sideUp ? rect.bottom - popSize.height : rect.top); } else { sideLeft = this.canSideLeft && (rect.right + popSize.width > vpRect.right && rect.left > popSize.width); sideUp = this.canSideUp && (rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height); left = (sideLeft ? rect.right - popSize.width : rect.left); top = (sideUp ? rect.top - popSize.height : rect.bottom); } var popEl = this.getDom(); uiUtils.setViewportOffset(popEl, { left: left, top: top }); domUtils.removeClasses(popEl, ANCHOR_CLASSES); popEl.className += ' ' + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)]; if(this.editor){ popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10; baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = popEl.style.zIndex - 1; } }, showAt: function (offset) { var left = offset.left; var top = offset.top; var rect = { left: left, top: top, right: left, bottom: top, height: 0, width: 0 }; this.showAnchorRect(rect, false, true); }, _show: function (){ if (this._hidden) { var box = this.getDom(); box.style.display = ''; this._hidden = false; // if (box.setActive) { // box.setActive(); // } this.fireEvent('show'); } }, isHidden: function (){ return this._hidden; }, show: function (){ this._doAutoRender(); this._show(); }, hide: function (notNofity){ if (!this._hidden && this.getDom()) { // this.getDom().style.visibility = 'hidden'; this.getDom().style.display = 'none'; this._hidden = true; if (!notNofity) { this.fireEvent('hide'); } } }, queryAutoHide: function (el){ return !el || !uiUtils.contains(this.getDom(), el); } }; utils.inherits(Popup, UIBase); domUtils.on( document, 'mousedown', function ( evt ) { var el = evt.target || evt.srcElement; closeAllPopup( el ); } ); domUtils.on( window, 'scroll', function () { closeAllPopup(); } ); // var lastVpRect = uiUtils.getViewportRect(); // domUtils.on( window, 'resize', function () { // var vpRect = uiUtils.getViewportRect(); // if (vpRect.width != lastVpRect.width || vpRect.height != lastVpRect.height) { // closeAllPopup(); // } // } ); })(); ///import core ///import uicore (function (){ var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, ColorPicker = baidu.editor.ui.ColorPicker = function (options){ this.initOptions(options); this.noColorText = this.noColorText || this.editor.getLang("clearColor"); this.initUIBase(); }; ColorPicker.prototype = { getHtmlTpl: function (){ return genColorPicker(this.noColorText,this.editor); }, _onTableClick: function (evt){ var tgt = evt.target || evt.srcElement; var color = tgt.getAttribute('data-color'); if (color) { this.fireEvent('pickcolor', color); } }, _onTableOver: function (evt){ var tgt = evt.target || evt.srcElement; var color = tgt.getAttribute('data-color'); if (color) { this.getDom('preview').style.backgroundColor = color; } }, _onTableOut: function (){ this.getDom('preview').style.backgroundColor = ''; }, _onPickNoColor: function (){ this.fireEvent('picknocolor'); } }; utils.inherits(ColorPicker, UIBase); var COLORS = ( 'ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646,' + 'f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada,' + 'd8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5,' + 'bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f,' + 'a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09,' + '7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806,' + 'c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,').split(','); function genColorPicker(noColorText,editor){ var html = '
' + '
' + '
' + '
'+ noColorText +'
' + '
' + '' + ''+ ''; for (var i=0; i':'')+''; } html += i<70 ? '':''; } html += '
'+editor.getLang("themeColor")+'
'+editor.getLang("standardColor")+'
'; return html; } })(); ///import core ///import uicore (function (){ var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase; var TablePicker = baidu.editor.ui.TablePicker = function (options){ this.initOptions(options); this.initTablePicker(); }; TablePicker.prototype = { defaultNumRows: 10, defaultNumCols: 10, maxNumRows: 20, maxNumCols: 20, numRows: 10, numCols: 10, lengthOfCellSide: 22, initTablePicker: function (){ this.initUIBase(); }, getHtmlTpl: function (){ var me = this; return '
' + '
' + '
' + '' + ''+me.editor.getLang("more")+'' + '
' + '
' + '
' + '
' + '
' + '
'; }, _UIBase_render: UIBase.prototype.render, render: function (holder){ this._UIBase_render(holder); this.getDom('label').innerHTML = '0'+this.editor.getLang("t_row")+' x 0'+this.editor.getLang("t_col"); }, _track: function (numCols, numRows){ var style = this.getDom('overlay').style; var sideLen = this.lengthOfCellSide; style.width = numCols * sideLen + 'px'; style.height = numRows * sideLen + 'px'; var label = this.getDom('label'); label.innerHTML = numCols +this.editor.getLang("t_col")+' x ' + numRows + this.editor.getLang("t_row"); this.numCols = numCols; this.numRows = numRows; }, _onMouseOver: function (evt, el){ var rel = evt.relatedTarget || evt.fromElement; if (!uiUtils.contains(el, rel) && el !== rel) { this.getDom('label').innerHTML = '0'+this.editor.getLang("t_col")+' x 0'+this.editor.getLang("t_row"); this.getDom('overlay').style.visibility = ''; } }, _onMouseOut: function (evt, el){ var rel = evt.relatedTarget || evt.toElement; if (!uiUtils.contains(el, rel) && el !== rel) { this.getDom('label').innerHTML = '0'+this.editor.getLang("t_col")+' x 0'+this.editor.getLang("t_row"); this.getDom('overlay').style.visibility = 'hidden'; } }, _onMouseMove: function (evt, el){ var style = this.getDom('overlay').style; var offset = uiUtils.getEventOffset(evt); var sideLen = this.lengthOfCellSide; var numCols = Math.ceil(offset.left / sideLen); var numRows = Math.ceil(offset.top / sideLen); this._track(numCols, numRows); }, _onClick: function (){ this.fireEvent('picktable', this.numCols, this.numRows); }, _onMore: function (){ this.fireEvent('more'); } }; utils.inherits(TablePicker, UIBase); })(); (function (){ var browser = baidu.editor.browser, domUtils = baidu.editor.dom.domUtils, uiUtils = baidu.editor.ui.uiUtils; var TPL_STATEFUL = 'onmousedown="$$.Stateful_onMouseDown(event, this);"' + ' onmouseup="$$.Stateful_onMouseUp(event, this);"' + ( browser.ie ? ( ' onmouseenter="$$.Stateful_onMouseEnter(event, this);"' + ' onmouseleave="$$.Stateful_onMouseLeave(event, this);"' ) : ( ' onmouseover="$$.Stateful_onMouseOver(event, this);"' + ' onmouseout="$$.Stateful_onMouseOut(event, this);"' )); baidu.editor.ui.Stateful = { alwalysHoverable: false, Stateful_init: function (){ this._Stateful_dGetHtmlTpl = this.getHtmlTpl; this.getHtmlTpl = this.Stateful_getHtmlTpl; }, Stateful_getHtmlTpl: function (){ var tpl = this._Stateful_dGetHtmlTpl(); // 使用function避免$转义 return tpl.replace(/stateful/g, function (){ return TPL_STATEFUL; }); }, Stateful_onMouseEnter: function (evt, el){ if (!this.isDisabled() || this.alwalysHoverable) { this.addState('hover'); this.fireEvent('over'); } }, Stateful_onMouseLeave: function (evt, el){ if (!this.isDisabled() || this.alwalysHoverable) { this.removeState('hover'); this.removeState('active'); this.fireEvent('out'); } }, Stateful_onMouseOver: function (evt, el){ var rel = evt.relatedTarget; if (!uiUtils.contains(el, rel) && el !== rel) { this.Stateful_onMouseEnter(evt, el); } }, Stateful_onMouseOut: function (evt, el){ var rel = evt.relatedTarget; if (!uiUtils.contains(el, rel) && el !== rel) { this.Stateful_onMouseLeave(evt, el); } }, Stateful_onMouseDown: function (evt, el){ if (!this.isDisabled()) { this.addState('active'); } }, Stateful_onMouseUp: function (evt, el){ if (!this.isDisabled()) { this.removeState('active'); } }, Stateful_postRender: function (){ if (this.disabled && !this.hasState('disabled')) { this.addState('disabled'); } }, hasState: function (state){ return domUtils.hasClass(this.getStateDom(), 'edui-state-' + state); }, addState: function (state){ if (!this.hasState(state)) { this.getStateDom().className += ' edui-state-' + state; } }, removeState: function (state){ if (this.hasState(state)) { domUtils.removeClasses(this.getStateDom(), ['edui-state-' + state]); } }, getStateDom: function (){ return this.getDom('state'); }, isChecked: function (){ return this.hasState('checked'); }, setChecked: function (checked){ if (!this.isDisabled() && checked) { this.addState('checked'); } else { this.removeState('checked'); } }, isDisabled: function (){ return this.hasState('disabled'); }, setDisabled: function (disabled){ if (disabled) { this.removeState('hover'); this.removeState('checked'); this.removeState('active'); this.addState('disabled'); } else { this.removeState('disabled'); } } }; })(); ///import core ///import uicore ///import ui/stateful.js (function (){ var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase, Stateful = baidu.editor.ui.Stateful, Button = baidu.editor.ui.Button = function (options){ this.initOptions(options); this.initButton(); }; Button.prototype = { uiName: 'button', label: '', title: '', showIcon: true, showText: true, initButton: function (){ this.initUIBase(); this.Stateful_init(); }, getHtmlTpl: function (){ return '
' + '
' + '
' + (this.showIcon ? '
' : '') + (this.showText ? '
' + this.label + '
' : '') + '
' + '
' + '
'; }, postRender: function (){ this.Stateful_postRender(); this.setDisabled(this.disabled) }, _onClick: function (){ if (!this.isDisabled()) { this.fireEvent('click'); } } }; utils.inherits(Button, UIBase); utils.extend(Button.prototype, Stateful); })(); ///import core ///import uicore ///import ui/stateful.js (function (){ var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, domUtils = baidu.editor.dom.domUtils, UIBase = baidu.editor.ui.UIBase, Stateful = baidu.editor.ui.Stateful, SplitButton = baidu.editor.ui.SplitButton = function (options){ this.initOptions(options); this.initSplitButton(); }; SplitButton.prototype = { popup: null, uiName: 'splitbutton', title: '', initSplitButton: function (){ this.initUIBase(); this.Stateful_init(); var me = this; if (this.popup != null) { var popup = this.popup; this.popup = null; this.setPopup(popup); } }, _UIBase_postRender: UIBase.prototype.postRender, postRender: function (){ this.Stateful_postRender(); this._UIBase_postRender(); }, setPopup: function (popup){ if (this.popup === popup) return; if (this.popup != null) { this.popup.dispose(); } popup.addListener('show', utils.bind(this._onPopupShow, this)); popup.addListener('hide', utils.bind(this._onPopupHide, this)); popup.addListener('postrender', utils.bind(function (){ popup.getDom('body').appendChild( uiUtils.createElementByHtml('
') ); popup.getDom().className += ' ' + this.className; }, this)); this.popup = popup; }, _onPopupShow: function (){ this.addState('opened'); }, _onPopupHide: function (){ this.removeState('opened'); }, getHtmlTpl: function (){ return '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
'; }, showPopup: function (){ // 当popup往上弹出的时候,做特殊处理 var rect = uiUtils.getClientRect(this.getDom()); rect.top -= this.popup.SHADOW_RADIUS; rect.height += this.popup.SHADOW_RADIUS; this.popup.showAnchorRect(rect); }, _onArrowClick: function (event, el){ if (!this.isDisabled()) { this.showPopup(); } }, _onButtonClick: function (){ if (!this.isDisabled()) { this.fireEvent('buttonclick'); } } }; utils.inherits(SplitButton, UIBase); utils.extend(SplitButton.prototype, Stateful, true); })(); ///import core ///import uicore ///import ui/colorpicker.js ///import ui/popup.js ///import ui/splitbutton.js (function (){ var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, ColorPicker = baidu.editor.ui.ColorPicker, Popup = baidu.editor.ui.Popup, SplitButton = baidu.editor.ui.SplitButton, ColorButton = baidu.editor.ui.ColorButton = function (options){ this.initOptions(options); this.initColorButton(); }; ColorButton.prototype = { initColorButton: function (){ var me = this; this.popup = new Popup({ content: new ColorPicker({ noColorText: me.editor.getLang("clearColor"), editor:me.editor, onpickcolor: function (t, color){ me._onPickColor(color); }, onpicknocolor: function (t, color){ me._onPickNoColor(color); } }), editor:me.editor }); this.initSplitButton(); }, _SplitButton_postRender: SplitButton.prototype.postRender, postRender: function (){ this._SplitButton_postRender(); this.getDom('button_body').appendChild( uiUtils.createElementByHtml('
') ); this.getDom().className += ' edui-colorbutton'; }, setColor: function (color){ this.getDom('colorlump').style.backgroundColor = color; this.color = color; }, _onPickColor: function (color){ if (this.fireEvent('pickcolor', color) !== false) { this.setColor(color); this.popup.hide(); } }, _onPickNoColor: function (color){ if (this.fireEvent('picknocolor') !== false) { this.popup.hide(); } } }; utils.inherits(ColorButton, SplitButton); })(); ///import core ///import uicore ///import ui/popup.js ///import ui/tablepicker.js ///import ui/splitbutton.js (function (){ var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, TablePicker = baidu.editor.ui.TablePicker, SplitButton = baidu.editor.ui.SplitButton, TableButton = baidu.editor.ui.TableButton = function (options){ this.initOptions(options); this.initTableButton(); }; TableButton.prototype = { initTableButton: function (){ var me = this; this.popup = new Popup({ content: new TablePicker({ editor:me.editor, onpicktable: function (t, numCols, numRows){ me._onPickTable(numCols, numRows); }, onmore: function (){ me.popup.hide(); me.fireEvent('more'); } }), 'editor':me.editor }); this.initSplitButton(); }, _onPickTable: function (numCols, numRows){ if (this.fireEvent('picktable', numCols, numRows) !== false) { this.popup.hide(); } } }; utils.inherits(TableButton, SplitButton); })(); ///import core ///import uicore (function (){ var utils = baidu.editor.utils, UIBase = baidu.editor.ui.UIBase; var AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker = function (options){ this.initOptions(options); this.initAutoTypeSetPicker(); }; AutoTypeSetPicker.prototype = { initAutoTypeSetPicker: function (){ this.initUIBase(); }, getHtmlTpl: function (){ var me = this.editor, opt = me.options.autotypeset, lang = me.getLang("autoTypeSet"); return '
' + '
' + '' + ''+ ''+ ''+ '' + ''+ ''+ ''+ ''+ ''+ '
'+lang.mergeLine+''+lang.delLine+'
'+lang.removeFormat+''+lang.indent+'
'+lang.alignment+''+me.getLang("justifyleft")+''+me.getLang("justifycenter")+''+me.getLang("justifyright")+'
'+lang.imageFloat+'' + '' + me.getLang("default")+ '' + me.getLang("justifyleft")+ '' + me.getLang("justifycenter") + ''+me.getLang("justifyright")+'
'+lang.removeFontsize+''+lang.removeFontFamily+'
'+lang.removeHtml+'
'+lang.pasteFilter+'
'+ '
' + '
'; }, _UIBase_render: UIBase.prototype.render }; utils.inherits(AutoTypeSetPicker, UIBase); })(); ///import core ///import uicore ///import ui/popup.js ///import ui/autotypesetpicker.js ///import ui/splitbutton.js (function (){ var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker, SplitButton = baidu.editor.ui.SplitButton, AutoTypeSetButton = baidu.editor.ui.AutoTypeSetButton = function (options){ this.initOptions(options); this.initAutoTypeSetButton(); }; function getPara(me){ var opt = me.editor.options.autotypeset, cont = me.getDom(), ipts = domUtils.getElementsByTagName(cont,"input"); for(var i=ipts.length-1,ipt;ipt=ipts[i--];){ if(ipt.getAttribute("type")=="checkbox"){ var attrName = ipt.getAttribute("name"); opt[attrName] && delete opt[attrName]; if(ipt.checked){ var attrValue = document.getElementById(attrName+"Value"); if(attrValue){ if(/input/ig.test(attrValue.tagName)){ opt[attrName] = attrValue.value; }else{ var iptChilds = attrValue.getElementsByTagName("input"); for(var j=iptChilds.length-1,iptchild;iptchild=iptChilds[j--];){ if(iptchild.checked){ opt[attrName] = iptchild.value; break; } } } }else{ opt[attrName] = true; } } } } var selects = domUtils.getElementsByTagName(cont,"select"); for(var i=0,si;si=selects[i++];){ var attr = si.getAttribute('name'); opt[attr] = opt[attr] ? si.value : ''; } me.editor.options.autotypeset = opt; } AutoTypeSetButton.prototype = { initAutoTypeSetButton: function (){ var me = this; this.popup = new Popup({ //传入配置参数 content: new AutoTypeSetPicker({editor:me.editor}), 'editor':me.editor, hide : function(){ if (!this._hidden && this.getDom()) { getPara(this); this.getDom().style.display = 'none'; this._hidden = true; this.fireEvent('hide'); } } }); var flag = 0; this.popup.addListener('postRenderAfter',function(){ var popupUI = this; if(flag)return; var cont = this.getDom(), btn = cont.getElementsByTagName('button')[0]; btn.onclick = function(){ getPara(popupUI); me.editor.execCommand('autotypeset') }; flag = 1; }); this.initSplitButton(); } }; utils.inherits(AutoTypeSetButton, SplitButton); })(); (function (){ var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase, Toolbar = baidu.editor.ui.Toolbar = function (options){ this.initOptions(options); this.initToolbar(); }; Toolbar.prototype = { items: null, initToolbar: function (){ this.items = this.items || []; this.initUIBase(); }, add: function (item){ this.items.push(item); }, getHtmlTpl: function (){ var buff = []; for (var i=0; i' + buff.join('') + '' }, postRender: function (){ var box = this.getDom(); for (var i=0; i
'; }, postRender: function (){}, queryAutoHide: function (){ return true; } }; Menu.prototype = { items: null, uiName: 'menu', initMenu: function (){ this.items = this.items || []; this.initPopup(); this.initItems(); }, initItems: function (){ for (var i=0; i' + buff.join('') + ''); }, _Popup_postRender: Popup.prototype.postRender, postRender: function (){ var me = this; for (var i=0; i' + '
' + this.renderLabelHtml() + '
' + ''; }, postRender: function (){ var me = this; this.addListener('over', function (){ me.ownerMenu.fireEvent('submenuover', me); if (me.subMenu) { me.delayShowSubMenu(); } }); if (this.subMenu) { this.getDom().className += ' edui-hassubmenu'; this.subMenu.render(); this.addListener('out', function (){ me.delayHideSubMenu(); }); this.subMenu.addListener('over', function (){ clearTimeout(me._closingTimer); me._closingTimer = null; me.addState('opened'); }); this.ownerMenu.addListener('hide', function (){ me.hideSubMenu(); }); this.ownerMenu.addListener('submenuover', function (t, subMenu){ if (subMenu !== me) { me.delayHideSubMenu(); } }); this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide; this.subMenu.queryAutoHide = function (el){ if (el && uiUtils.contains(me.getDom(), el)) { return false; } return this._bakQueryAutoHide(el); }; } this.getDom().style.tabIndex = '-1'; uiUtils.makeUnselectable(this.getDom()); this.Stateful_postRender(); }, delayShowSubMenu: function (){ var me = this; if (!me.isDisabled()) { me.addState('opened'); clearTimeout(me._showingTimer); clearTimeout(me._closingTimer); me._closingTimer = null; me._showingTimer = setTimeout(function (){ me.showSubMenu(); }, 250); } }, delayHideSubMenu: function (){ var me = this; if (!me.isDisabled()) { me.removeState('opened'); clearTimeout(me._showingTimer); if (!me._closingTimer) { me._closingTimer = setTimeout(function (){ if (!me.hasState('opened')) { me.hideSubMenu(); } me._closingTimer = null; }, 400); } } }, renderLabelHtml: function (){ return '
' + '
' + '
' + (this.label || '') + '
'; }, getStateDom: function (){ return this.getDom(); }, queryAutoHide: function (el){ if (this.subMenu && this.hasState('opened')) { return this.subMenu.queryAutoHide(el); } }, _onClick: function (event, this_){ if (this.hasState('disabled')) return; if (this.fireEvent('click', event, this_) !== false) { if (this.subMenu) { this.showSubMenu(); } else { Popup.postHide(); } } }, showSubMenu: function (){ var rect = uiUtils.getClientRect(this.getDom()); rect.right -= 5; rect.left += 2; rect.width -= 7; rect.top -= 4; rect.bottom += 4; rect.height += 8; this.subMenu.showAnchorRect(rect, true, true); }, hideSubMenu: function (){ this.subMenu.hide(); } }; utils.inherits(MenuItem, UIBase); utils.extend(MenuItem.prototype, Stateful, true); })(); ///import core ///import uicore ///import ui/menu.js ///import ui/splitbutton.js (function (){ // todo: menu和item提成通用list var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, Menu = baidu.editor.ui.Menu, SplitButton = baidu.editor.ui.SplitButton, Combox = baidu.editor.ui.Combox = function (options){ this.initOptions(options); this.initCombox(); }; Combox.prototype = { uiName: 'combox', initCombox: function (){ var me = this; this.items = this.items || []; for (var i=0; i vpRect.right) { left = vpRect.right - rect.width; } var top = offset.top; if (top + rect.height > vpRect.bottom) { top = vpRect.bottom - rect.height; } el.style.left = Math.max(left, 0) + 'px'; el.style.top = Math.max(top, 0) + 'px'; }, showAtCenter: function (){ this.getDom().style.display = ''; var vpRect = uiUtils.getViewportRect(); var popSize = this.fitSize(); var titleHeight = this.getDom('titlebar').offsetHeight | 0; var left = vpRect.width / 2 - popSize.width / 2; var top = vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight; var popEl = this.getDom(); this.safeSetOffset({ left: Math.max(left | 0, 0), top: Math.max(top | 0, 0) }); if (!domUtils.hasClass(popEl, 'edui-state-centered')) { popEl.className += ' edui-state-centered'; } this._show(); }, getContentHtml: function (){ var contentHtml = ''; if (typeof this.content == 'string') { contentHtml = this.content; } else if (this.iframeUrl) { contentHtml = ''; } return contentHtml; }, getHtmlTpl: function (){ var footHtml = ''; if (this.buttons) { var buff = []; for (var i=0; i' + buff.join('') + '' + ''; } return '
' + '
' + '
' + '
' + '' + (this.title || '') + '' + '
' + this.closeButton.renderHtml() + '
' + '
'+ ( this.autoReset ? '' : this.getContentHtml()) +'
' + footHtml + '
'; }, postRender: function (){ // todo: 保持居中/记住上次关闭位置选项 if (!this.modalMask.getDom()) { this.modalMask.render(); this.modalMask.hide(); } if (!this.dragMask.getDom()) { this.dragMask.render(); this.dragMask.hide(); } var me = this; this.addListener('show', function (){ me.modalMask.show(this.getDom().style.zIndex - 2); }); this.addListener('hide', function (){ me.modalMask.hide(); }); if (this.buttons) { for (var i=0; i' + (this.label || '') + ''; } } ); })( ci.label || langLabel, ci.val ) } var ui = new editorui.Combox( { editor:editor, items:items, onselect:function ( t, index ) { editor.execCommand( 'FontFamily', this.items[index].value ); }, onbuttonclick:function () { this.showPopup(); }, title:title, initValue:title, className:'edui-for-fontfamily', indexByValue:function ( value ) { if ( value ) { for ( var i = 0, ci; ci = this.items[i]; i++ ) { if ( ci.value.indexOf( value ) != -1 ) return i; } } return -1; } } ); editor.addListener( 'selectionchange', function ( type, causeByUi, uiReady ) { if ( !uiReady ) { var state = editor.queryCommandState( 'FontFamily' ); if ( state == -1 ) { ui.setDisabled( true ); } else { ui.setDisabled( false ); var value = editor.queryCommandValue( 'FontFamily' ); //trace:1871 ie下从源码模式切换回来时,字体会带单引号,而且会有逗号 value && (value = value.replace( /['"]/g, '' ).split( ',' )[0]); ui.setValue( value ); } } } ); return ui; }; editorui.fontsize = function ( editor, list, title ) { title = editor.options.labelMap['fontsize'] || editor.getLang( "labelMap.fontsize" ) || ''; list = list || editor.options['fontsize'] || []; var items = []; for ( var i = 0; i < list.length; i++ ) { var size = list[i] + 'px'; items.push( { label:size, value:size, renderLabelHtml:function () { return '
' + (this.label || '') + '
'; } } ); } var ui = new editorui.Combox( { editor:editor, items:items, title:title, initValue:title, onselect:function ( t, index ) { editor.execCommand( 'FontSize', this.items[index].value ); }, onbuttonclick:function () { this.showPopup(); }, className:'edui-for-fontsize' } ); editor.addListener( 'selectionchange', function ( type, causeByUi, uiReady ) { if ( !uiReady ) { var state = editor.queryCommandState( 'FontSize' ); if ( state == -1 ) { ui.setDisabled( true ); } else { ui.setDisabled( false ); ui.setValue( editor.queryCommandValue( 'FontSize' ) ); } } } ); return ui; }; editorui.paragraph = function ( editor, list, title ) { title = editor.options.labelMap['paragraph'] || editor.getLang( "labelMap.paragraph" ) || ''; list = editor.options['paragraph'] || []; var items = []; for ( var i in list ) { items.push( { value:i, label:list[i] || editor.getLang( "paragraph" )[i], renderLabelHtml:function () { return '
' + (this.label || '') + '
'; } } ) } var ui = new editorui.Combox( { editor:editor, items:items, title:title, initValue:title, className:'edui-for-paragraph', onselect:function ( t, index ) { editor.execCommand( 'Paragraph', this.items[index].value ); }, onbuttonclick:function () { this.showPopup(); } } ); editor.addListener( 'selectionchange', function ( type, causeByUi, uiReady ) { if ( !uiReady ) { var state = editor.queryCommandState( 'Paragraph' ); if ( state == -1 ) { ui.setDisabled( true ); } else { ui.setDisabled( false ); var value = editor.queryCommandValue( 'Paragraph' ); var index = ui.indexByValue( value ); if ( index != -1 ) { ui.setValue( value ); } else { ui.setValue( ui.initValue ); } } } } ); return ui; }; //自定义标题 editorui.customstyle = function ( editor ) { var list = editor.options['customstyle'] || [], title = editor.options.labelMap['customstyle'] || editor.getLang( "labelMap.customstyle" ) || ''; if ( !list )return; var langCs = editor.getLang( 'customstyle' ); for ( var i = 0, items = [], t; t = list[i++]; ) { (function ( t ){ var ck ={}; ck.label = t.label? t.label:langCs[t.name]; ck.style = t.style; ck.className = t.className; ck.tag = t.tag; items.push( { label:ck.label, value:ck, renderLabelHtml:function () { return '
' + '<' + ck.tag + ' ' + (ck.className ? ' class="' + ck.className + '"' : "") + (ck.style ? ' style="' + ck.style + '"' : "") + '>' + ck.label + "<\/" + ck.tag + ">" + '
'; } } ); })( t ); } var ui = new editorui.Combox( { editor:editor, items:items, title:title, initValue:title, className:'edui-for-customstyle', onselect:function ( t, index ) { editor.execCommand( 'customstyle', this.items[index].value ); }, onbuttonclick:function () { this.showPopup(); }, indexByValue:function ( value ) { for ( var i = 0, ti; ti = this.items[i++]; ) { if ( ti.label == value ) { return i - 1 } } return -1; } } ); editor.addListener( 'selectionchange', function ( type, causeByUi, uiReady ) { if ( !uiReady ) { var state = editor.queryCommandState( 'customstyle' ); if ( state == -1 ) { ui.setDisabled( true ); } else { ui.setDisabled( false ); var value = editor.queryCommandValue( 'customstyle' ); var index = ui.indexByValue( value ); if ( index != -1 ) { ui.setValue( value ); } else { ui.setValue( ui.initValue ); } } } } ); return ui; }; editorui.inserttable = function ( editor, iframeUrl, title ) { iframeUrl = iframeUrl || (editor.options.iframeUrlMap || {})['inserttable'] || iframeUrlMap['inserttable']; title = editor.options.labelMap['inserttable'] || editor.getLang( "labelMap.inserttable" ) || ''; if ( iframeUrl ) { var dialog = new editorui.Dialog( { iframeUrl:editor.ui.mapUrl( iframeUrl ), editor:editor, className:'edui-for-inserttable', title:title, buttons:[ { className:'edui-okbutton', label:editor.getLang( "ok" ), onclick:function () { dialog.close( true ); } }, { className:'edui-cancelbutton', label:editor.getLang( "cancel" ), onclick:function () { dialog.close( false ); } } ] } ); dialog.render(); editor.ui._dialogs['inserttableDialog'] = dialog; } var openDialog = function(){ if(dialog){ //打开后再关闭再打开是为了解决fieldset文字错位问题 if(browser.webkit){ dialog.open(); dialog.close(); } dialog.open(); } }; var ui = new editorui.TableButton( { editor:editor, title:title, className:'edui-for-inserttable', onpicktable:function ( t, numCols, numRows ) { editor.execCommand( 'InsertTable', {numRows:numRows, numCols:numCols, border:1} ); }, onmore:openDialog, onbuttonclick:openDialog } ); editor.addListener( 'selectionchange', function () { ui.setDisabled( editor.queryCommandState( 'inserttable' ) == -1 ); } ); return ui; }; editorui.lineheight = function ( editor ) { var val = editor.options.lineheight; for ( var i = 0, ci, items = []; ci = val[i++]; ) { items.push( { //todo:写死了 label:ci, value:ci, onclick:function () { editor.execCommand( "lineheight", this.value ); } } ) } var ui = new editorui.MenuButton( { editor:editor, className:'edui-for-lineheight', title:editor.options.labelMap['lineheight'] || editor.getLang( "labelMap.lineheight" ) || '', items:items, onbuttonclick:function () { var value = editor.queryCommandValue( 'LineHeight' ) || this.value; editor.execCommand( "LineHeight", value ); } } ); editor.addListener( 'selectionchange', function () { var state = editor.queryCommandState( 'LineHeight' ); if ( state == -1 ) { ui.setDisabled( true ); } else { ui.setDisabled( false ); var value = editor.queryCommandValue( 'LineHeight' ); value && ui.setValue( (value + '').replace( /cm/, '' ) ); ui.setChecked( state ) } } ); return ui; }; var rowspacings = ['top', 'bottom']; for ( var r = 0, ri; ri = rowspacings[r++]; ) { (function ( cmd ) { editorui['rowspacing' + cmd] = function ( editor ) { var val = editor.options['rowspacing' + cmd]; for ( var i = 0, ci, items = []; ci = val[i++]; ) { items.push( { label:ci, value:ci, onclick:function () { editor.execCommand( "rowspacing", this.value, cmd ); } } ) } var ui = new editorui.MenuButton( { editor:editor, className:'edui-for-rowspacing' + cmd, title:editor.options.labelMap['rowspacing' + cmd] || editor.getLang( "labelMap.rowspacing" + cmd ) || '', items:items, onbuttonclick:function () { var value = editor.queryCommandValue( 'rowspacing', cmd ) || this.value; editor.execCommand( "rowspacing", value, cmd ); } } ); editor.addListener( 'selectionchange', function () { var state = editor.queryCommandState( 'rowspacing', cmd ); if ( state == -1 ) { ui.setDisabled( true ); } else { ui.setDisabled( false ); var value = editor.queryCommandValue( 'rowspacing', cmd ); value && ui.setValue( (value + '').replace( /%/, '' ) ); ui.setChecked( state ) } } ); return ui; } })( ri ) } //有序,无序列表 var lists = ['insertorderedlist', 'insertunorderedlist']; for ( var l = 0, cl; cl = lists[l++]; ) { (function ( cmd ) { editorui[cmd] = function ( editor ) { var vals = editor.options[cmd], _onMenuClick = function () { editor.execCommand( cmd, this.value ); }, items = []; for ( var i in vals ) { items.push( { label:vals[i] || editor.getLang()[cmd][i] || "", value:i, onclick:_onMenuClick } ) } var ui = new editorui.MenuButton( { editor:editor, className:'edui-for-' + cmd, title:editor.getLang( "labelMap." + cmd ) || '', 'items':items, onbuttonclick:function () { var value = editor.queryCommandValue( cmd ) || this.value; editor.execCommand( cmd, value ); } } ); editor.addListener( 'selectionchange', function () { var state = editor.queryCommandState( cmd ); if ( state == -1 ) { ui.setDisabled( true ); } else { ui.setDisabled( false ); var value = editor.queryCommandValue( cmd ); ui.setValue( value ); ui.setChecked( state ) } } ); return ui; }; })( cl ) } editorui.fullscreen = function ( editor, title ) { title = editor.options.labelMap['fullscreen'] || editor.getLang( "labelMap.fullscreen" ) || ''; var ui = new editorui.Button( { className:'edui-for-fullscreen', title:title, onclick:function () { if ( editor.ui ) { editor.ui.setFullScreen( !editor.ui.isFullScreen() ); } this.setChecked( editor.ui.isFullScreen() ); } } ); editor.addListener( 'selectionchange', function () { var state = editor.queryCommandState( 'fullscreen' ); ui.setDisabled( state == -1 ); ui.setChecked( editor.ui.isFullScreen() ); } ); return ui; }; // 表情 editorui.emotion = function ( editor, iframeUrl ) { var ui = new editorui.MultiMenuPop( { title:editor.options.labelMap['emotion'] || editor.getLang( "labelMap.emotion" ) || '', editor:editor, className:'edui-for-emotion', iframeUrl:editor.ui.mapUrl( iframeUrl || (editor.options.iframeUrlMap || {})['emotion'] || iframeUrlMap['emotion'] ) } ); editor.addListener( 'selectionchange', function () { ui.setDisabled( editor.queryCommandState( 'emotion' ) == -1 ) } ); return ui; }; editorui.autotypeset = function ( editor ) { var ui = new editorui.AutoTypeSetButton( { editor:editor, title:editor.options.labelMap['autotypeset'] || editor.getLang( "labelMap.autotypeset" ) || '', className:'edui-for-autotypeset', onbuttonclick:function () { editor.execCommand( 'autotypeset' ) } } ); editor.addListener( 'selectionchange', function () { ui.setDisabled( editor.queryCommandState( 'autotypeset' ) == -1 ); } ); return ui; }; })(); ///import core ///commands 全屏 ///commandsName FullScreen ///commandsTitle 全屏 (function () { var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase, domUtils = baidu.editor.dom.domUtils; function EditorUI( options ) { this.initOptions( options ); this.initEditorUI(); } EditorUI.prototype = { uiName:'editor', initEditorUI:function () { this.editor.ui = this; this._dialogs = {}; this.initUIBase(); this._initToolbars(); var editor = this.editor, me = this; editor.addListener( 'ready', function () { //提供getDialog方法 editor.getDialog = function(name){ return editor.ui._dialogs[name+"Dialog"]; }; domUtils.on( editor.window, 'scroll', function () { baidu.editor.ui.Popup.postHide(); } ); //display bottom-bar label based on config if ( editor.options.elementPathEnabled ) { editor.ui.getDom( 'elementpath' ).innerHTML = '
'+editor.getLang("elementPathTip")+':
'; } if ( editor.options.wordCount ) { editor.ui.getDom( 'wordcount' ).innerHTML = editor.getLang("wordCountTip"); //为wordcount捕获中文输入法的空格 editor.addListener( 'keyup', function ( type, evt ) { var keyCode = evt.keyCode || evt.which; if ( keyCode == 32 ) { me._wordCount(); } } ); } if ( !editor.options.elementPathEnabled && !editor.options.wordCount ) { editor.ui.getDom( 'elementpath' ).style.display = "none"; editor.ui.getDom( 'wordcount' ).style.display = "none"; } if ( !editor.selection.isFocus() )return; editor.fireEvent( 'selectionchange', false, true ); } ); editor.addListener( 'mousedown', function ( t, evt ) { var el = evt.target || evt.srcElement; baidu.editor.ui.Popup.postHide( el ); } ); editor.addListener( 'contextmenu', function ( t, evt ) { baidu.editor.ui.Popup.postHide(); } ); editor.addListener( 'selectionchange', function () { //if(!editor.selection.isFocus())return; if ( editor.options.elementPathEnabled ) { me[(editor.queryCommandState( 'elementpath' ) == -1 ? 'dis' : 'en') + 'ableElementPath']() } if ( editor.options.wordCount ) { me[(editor.queryCommandState( 'wordcount' ) == -1 ? 'dis' : 'en') + 'ableWordCount']() } } ); var popup = new baidu.editor.ui.Popup( { editor:editor, content:'', className:'edui-bubble', _onEditButtonClick:function () { this.hide(); editor.ui._dialogs.linkDialog.open(); }, _onImgEditButtonClick:function ( name ) { this.hide(); editor.ui._dialogs[name] && editor.ui._dialogs[name].open(); }, _onImgSetFloat:function ( value ) { this.hide(); editor.execCommand( "imagefloat", value ); }, _setIframeAlign:function ( value ) { var frame = popup.anchorEl; var newFrame = frame.cloneNode( true ); switch ( value ) { case -2: newFrame.setAttribute( "align", "" ); break; case -1: newFrame.setAttribute( "align", "left" ); break; case 1: newFrame.setAttribute( "align", "right" ); break; case 2: newFrame.setAttribute( "align", "middle" ); break; } frame.parentNode.insertBefore( newFrame, frame ); domUtils.remove( frame ); popup.anchorEl = newFrame; popup.showAnchor( popup.anchorEl ); }, _updateIframe:function () { editor._iframe = popup.anchorEl; editor.ui._dialogs.insertframeDialog.open(); popup.hide(); }, _onRemoveButtonClick:function ( cmdName ) { editor.execCommand( cmdName ); this.hide(); }, queryAutoHide:function ( el ) { if ( el && el.ownerDocument == editor.document ) { if ( el.tagName.toLowerCase() == 'img' || domUtils.findParentByTagName( el, 'a', true ) ) { return el !== popup.anchorEl; } } return baidu.editor.ui.Popup.prototype.queryAutoHide.call( this, el ); } } ); popup.render(); if ( editor.options.imagePopup ) { editor.addListener( 'mouseover', function ( t, evt ) { evt = evt || window.event; var el = evt.target || evt.srcElement; if ( editor.ui._dialogs.insertframeDialog && /iframe/ig.test( el.tagName ) ) { var html = popup.formatHtml( ''+editor.getLang("property")+': '+editor.getLang("default")+'  '+editor.getLang("justifyleft")+'  '+editor.getLang("justifyright")+'  ' + ''+editor.getLang("justifycenter")+'' + ' '+editor.getLang("modify")+'' ); if ( html ) { popup.getDom( 'content' ).innerHTML = html; popup.anchorEl = el; popup.showAnchor( popup.anchorEl ); } else { popup.hide(); } } } ); editor.addListener( 'selectionchange', function ( t, causeByUi ) { if ( !causeByUi ) return; var html = '', img = editor.selection.getRange().getClosedNode(), dialogs = editor.ui._dialogs; if ( img && img.tagName == 'IMG' ) { var dialogName = 'insertimageDialog'; if ( img.className.indexOf( "edui-faked-video" ) != -1 ) { dialogName = "insertvideoDialog" } if ( img.className.indexOf( "edui-faked-webapp" ) != -1 ) { dialogName = "webappDialog" } if ( img.src.indexOf( "http://api.map.baidu.com" ) != -1 ) { dialogName = "mapDialog" } if ( img.src.indexOf( "http://maps.google.com/maps/api/staticmap" ) != -1 ) { dialogName = "gmapDialog" } if ( img.getAttribute( "anchorname" ) ) { dialogName = "anchorDialog"; html = popup.formatHtml( ''+editor.getLang("property")+': '+editor.getLang("modify")+'  ' + ''+editor.getLang("delete")+'' ); } if ( img.getAttribute( "word_img" ) ) { //todo 放到dialog去做查询 editor.word_img = [img.getAttribute( "word_img" )]; dialogName = "wordimageDialog" } if ( !dialogs[dialogName] ) { return; } !html && (html = popup.formatHtml( ''+editor.getLang("property")+': '+editor.getLang("default")+'  ' + ''+editor.getLang("justifyleft")+'  ' + ''+editor.getLang("justifyright")+'  ' + ''+editor.getLang("justifycenter")+'  ' + ''+editor.getLang("modify")+'' )) } if ( editor.ui._dialogs.linkDialog ) { var link = domUtils.findParentByTagName( editor.selection.getStart(), "a", true ); var url; if ( link && (url = (link.getAttribute( 'data_ue_src' ) || link.getAttribute( 'href', 2 ))) ) { var txt = url; if ( url.length > 30 ) { txt = url.substring( 0, 20 ) + "..."; } if ( html ) { html += '
' } html += popup.formatHtml( ''+editor.getLang("anthorMsg")+': ' + txt + '' + ' '+editor.getLang("modify")+'' + ' '+editor.getLang("clear")+'' ); popup.showAnchor( link ); } } if ( html ) { popup.getDom( 'content' ).innerHTML = html; popup.anchorEl = img || link; popup.showAnchor( popup.anchorEl ); } else { popup.hide(); } } ); } }, _initToolbars:function () { var editor = this.editor; var toolbars = this.toolbars || []; var toolbarUis = []; for ( var i = 0; i < toolbars.length; i++ ) { var toolbar = toolbars[i]; var toolbarUi = new baidu.editor.ui.Toolbar(); for ( var j = 0; j < toolbar.length; j++ ) { var toolbarItem = toolbar[j]; var toolbarItemUi = null; if ( typeof toolbarItem == 'string' ) { toolbarItem = toolbarItem.toLowerCase(); if ( toolbarItem == '|' ) { toolbarItem = 'Separator'; } if ( baidu.editor.ui[toolbarItem] ) { toolbarItemUi = new baidu.editor.ui[toolbarItem]( editor ); } //fullscreen这里单独处理一下,放到首行去 if ( toolbarItem == 'fullscreen' ) { if ( toolbarUis && toolbarUis[0] ) { toolbarUis[0].items.splice( 0, 0, toolbarItemUi ); } else { toolbarItemUi && toolbarUi.items.splice( 0, 0, toolbarItemUi ); } continue; } } else { toolbarItemUi = toolbarItem; } if ( toolbarItemUi ) { toolbarUi.add( toolbarItemUi ); } } toolbarUis[i] = toolbarUi; } this.toolbars = toolbarUis; }, getHtmlTpl:function () { return '
' + '
' + (this.toolbars.length ? '
' + this.renderToolbarBoxHtml() + '
' : '') + '' + '
' + '
' + //modify wdcount by matao '
' + '' + '' + '
' + '
'; }, showWordImageDialog:function () { this.editor.execCommand( "wordimage", "word_img" ); this._dialogs['wordimageDialog'].open(); }, renderToolbarBoxHtml:function () { var buff = []; for ( var i = 0; i < this.toolbars.length; i++ ) { buff.push( this.toolbars[i].renderHtml() ); } return buff.join( '' ); }, setFullScreen:function ( fullscreen ) { if ( this._fullscreen != fullscreen ) { this._fullscreen = fullscreen; this.editor.fireEvent( 'beforefullscreenchange', fullscreen ); var editor = this.editor; if ( baidu.editor.browser.gecko ) { var bk = editor.selection.getRange().createBookmark(); } if ( fullscreen ) { this._bakHtmlOverflow = document.documentElement.style.overflow; this._bakBodyOverflow = document.body.style.overflow; this._bakAutoHeight = this.editor.autoHeightEnabled; this._bakScrollTop = Math.max( document.documentElement.scrollTop, document.body.scrollTop ); if ( this._bakAutoHeight ) { //当全屏时不能执行自动长高 editor.autoHeightEnabled = false; this.editor.disableAutoHeight(); } document.documentElement.style.overflow = 'hidden'; document.body.style.overflow = 'hidden'; this._bakCssText = this.getDom().style.cssText; this._bakCssText1 = this.getDom( 'iframeholder' ).style.cssText; this._updateFullScreen(); } else { this.getDom().style.cssText = this._bakCssText; this.getDom( 'iframeholder' ).style.cssText = this._bakCssText1; if ( this._bakAutoHeight ) { editor.autoHeightEnabled = true; this.editor.enableAutoHeight(); } document.documentElement.style.overflow = this._bakHtmlOverflow; document.body.style.overflow = this._bakBodyOverflow; window.scrollTo( 0, this._bakScrollTop ); } if ( baidu.editor.browser.gecko ) { var input = document.createElement( 'input' ); document.body.appendChild( input ); editor.body.contentEditable = false; setTimeout( function () { input.focus(); setTimeout( function () { editor.body.contentEditable = true; editor.selection.getRange().moveToBookmark( bk ).select( true ); baidu.editor.dom.domUtils.remove( input ); fullscreen && window.scroll( 0, 0 ); } ) } ) } this.editor.fireEvent( 'fullscreenchanged', fullscreen ); this.triggerLayout(); } }, _wordCount:function () { var wdcount = this.getDom( 'wordcount' ); if ( !this.editor.options.wordCount ) { wdcount.style.display = "none"; return; } wdcount.innerHTML = this.editor.queryCommandValue( "wordcount" ); }, disableWordCount:function () { var w = this.getDom( 'wordcount' ); w.innerHTML = ''; w.style.display = 'none'; this.wordcount = false; }, enableWordCount:function () { var w = this.getDom( 'wordcount' ); w.style.display = ''; this.wordcount = true; this._wordCount(); }, _updateFullScreen:function () { if ( this._fullscreen ) { var vpRect = uiUtils.getViewportRect(); this.getDom().style.cssText = 'border:0;position:absolute;left:0;top:'+(this.editor.options.topOffset||0)+'px;width:' + vpRect.width + 'px;height:' + vpRect.height + 'px;z-index:' + (this.getDom().style.zIndex * 1 + 100); uiUtils.setViewportOffset( this.getDom(), { left:0, top:this.editor.options.topOffset||0 } ); this.editor.setHeight( vpRect.height - this.getDom( 'toolbarbox' ).offsetHeight - this.getDom( 'bottombar' ).offsetHeight - (this.editor.options.topOffset||0) ); } }, _updateElementPath:function () { var bottom = this.getDom( 'elementpath' ), list; if ( this.elementPathEnabled && (list = this.editor.queryCommandValue( 'elementpath' )) ) { var buff = []; for ( var i = 0, ci; ci = list[i]; i++ ) { buff[i] = this.formatHtml( '' + ci + '' ); } bottom.innerHTML = '
'+this.editor.getLang("elementPathTip")+': ' + buff.join( ' > ' ) + '
'; } else { bottom.style.display = 'none' } }, disableElementPath:function () { var bottom = this.getDom( 'elementpath' ); bottom.innerHTML = ''; bottom.style.display = 'none'; this.elementPathEnabled = false; }, enableElementPath:function () { var bottom = this.getDom( 'elementpath' ); bottom.style.display = ''; this.elementPathEnabled = true; this._updateElementPath(); }, isFullScreen:function () { return this._fullscreen; }, postRender:function () { UIBase.prototype.postRender.call( this ); for ( var i = 0; i < this.toolbars.length; i++ ) { this.toolbars[i].postRender(); } var me = this; var timerId, domUtils = baidu.editor.dom.domUtils, updateFullScreenTime = function () { clearTimeout( timerId ); timerId = setTimeout( function () { me._updateFullScreen(); } ); }; domUtils.on( window, 'resize', updateFullScreenTime ); me.addListener( 'destroy', function () { domUtils.un( window, 'resize', updateFullScreenTime ); clearTimeout( timerId ); } ) }, showToolbarMsg:function ( msg, flag ) { this.getDom( 'toolbarmsg_label' ).innerHTML = msg; this.getDom( 'toolbarmsg' ).style.display = ''; // if ( !flag ) { var w = this.getDom( 'upload_dialog' ); w.style.display = 'none'; } }, hideToolbarMsg:function () { this.getDom( 'toolbarmsg' ).style.display = 'none'; }, mapUrl:function ( url ) { return url ? url.replace( '~/', this.editor.options.UEDITOR_HOME_URL || '' ) : '' }, triggerLayout:function () { var dom = this.getDom(); if ( dom.style.zoom == '1' ) { dom.style.zoom = '100%'; } else { dom.style.zoom = '1'; } } }; utils.inherits( EditorUI, baidu.editor.ui.UIBase ); baidu.editor.ui.Editor = function ( options ) { var editor = new baidu.editor.Editor( options ); editor.options.editor = editor; var oldRender = editor.render; editor.render = function ( holder ) { utils.domReady( function () { editor.langIsReady ? renderUI() : editor.addListener( "langReady", renderUI ); function renderUI() { editor.setOpt({ labelMap:editor.options.labelMap||UE.I18N[editor.options.lang].labelMap }); new EditorUI( editor.options ); if ( holder ) { if ( holder.constructor === String ) { holder = document.getElementById( holder ); } holder && holder.getAttribute( 'name' ) && ( editor.options.textarea = holder.getAttribute( 'name' )); if ( holder && /script|textarea/ig.test( holder.tagName ) ) { var newDiv = document.createElement( 'div' ); holder.parentNode.insertBefore( newDiv, holder ); var cont = holder.value || holder.innerHTML; editor.options.initialContent = /^[\t\r\n ]*$/.test( cont ) ? editor.options.initialContent : cont.replace( />[\n\r\t]+([ ]{4})+/g, '>' ) .replace( /[\n\r\t]+([ ]{4})+[\n\r\t]+<' ); holder.id && (newDiv.id = holder.id); holder.className && (newDiv.className = holder.className); holder.style.cssText && (newDiv.style.cssText = holder.style.cssText); if ( /textarea/i.test( holder.tagName ) ) { editor.textarea = holder; editor.textarea.style.display = 'none' } else { holder.parentNode.removeChild( holder ) } holder = newDiv; holder.innerHTML = ''; } } editor.ui.render( holder ); var iframeholder = editor.ui.getDom( 'iframeholder' ); //给实例添加一个编辑器的容器引用 editor.container = editor.ui.getDom(); editor.container.style.zIndex = editor.options.zIndex; oldRender.call( editor, iframeholder ); } } ) }; return editor; }; })(); ///import core ///import uicore ///commands 表情 (function(){ var utils = baidu.editor.utils, Popup = baidu.editor.ui.Popup, SplitButton = baidu.editor.ui.SplitButton, MultiMenuPop = baidu.editor.ui.MultiMenuPop = function(options){ this.initOptions(options); this.initMultiMenu(); }; MultiMenuPop.prototype = { initMultiMenu: function (){ var me = this; this.popup = new Popup({ content: '', editor : me.editor, iframe_rendered: false, onshow: function (){ if (!this.iframe_rendered) { this.iframe_rendered = true; this.getDom('content').innerHTML = ''; me.editor.container.style.zIndex && (this.getDom().style.zIndex = me.editor.container.style.zIndex * 1 + 1); } } // canSideUp:false, // canSideLeft:false }); this.onbuttonclick = function(){ this.showPopup(); }; this.initSplitButton(); } }; utils.inherits(MultiMenuPop, SplitButton); })(); })();