UEDITOR_CONFIG = window.UEDITOR_CONFIG || {}; var baidu = baidu || {}; /** * @namespace baidu.editor */ baidu.editor = baidu.editor || {}; /** * @class baidu.editor.commands */ baidu.editor.commands = {}; /** * @class baidu.editor.plugins */ baidu.editor.plugins = {}; baidu.editor.version = "1.1.8.4"; ///import editor.js /** * @class baidu.editor.browser 判断浏览器 */ baidu.editor.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 ), /** * 检测是否为Adobe AIR * @name baidu.editor.browser.air * @property 检测是否为Adobe AIR * @grammar baidu.editor.browser.air * @return {Boolean} 返回是否为Adobe AIR */ air : ( agent.indexOf( ' adobeair/' ) > -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] ); /** * 检测浏览器是否为 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; }(); ///import editor.js ///import core/utils.js /** * @class baidu.editor.utils 工具类 */ (function() { baidu.editor.utils = {}; var noop = new Function(); var utils = baidu.editor.utils = /**@lends baidu.editor.utils.prototype*/ { /** * 以obj为原型创建实例 * @public * @function * @param {Object} obj * @return {Object} 返回新的对象 */ makeInstance: function(obj) { 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; }, // /** // * 遍历元素执行迭代器 // * @public // * @function // * @param {Array|Object} eachable 要迭代的对象 // * @param {Function} iterator 迭代函数 // * @param {Object} this_ 传入对象 // */ // each: function(eachable, iterator, this_) { // if (utils.isArray(eachable)) { // for (var i = 0; i < eachable.length; i++) { // iterator.call(this_, eachable[i], i, eachable); // } // } else { // for (var k in eachable) { // iterator.call(this_, eachable[k], k, eachable); // } // } // }, /** * subClass继承superClass * @public * @function * @param {Object} subClass 子类 * @param {Object} superClass 超类 * @return {Object} 扩展后的新对象 */ inherits: function(subClass, superClass) { var oldP = subClass.prototype; var 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) { at = at || 0; while (at < array.length) { if (array[at] === item) { return at; } at++; } return - 1; }, /** * 移除数组中的元素 * @public * @function * @param {Array} array 要删除元素的数组 * @param {*} item 要删除的元素 */ removeItem: function(array, item) { var k = array.length; if (k) while (k--) { if (array[k] === item) { array.splice(k, 1); break; } } }, /** * 删除字符串首尾空格 * @public * @function * @param {String} str 字符串 * @return {String} str 删除空格后的字符串 */ trim: function() { // "non-breaking spaces" 就是 不能被捕获,所以不用\s var trimRegex = /(^[ \t\n\r]+)|([ \t\n\r]+$)/g; return function(str) { return str.replace(trimRegex, ''); }; }(), /** * 将字符串转换成hashmap * @public * @function * @param {String} list 字符串,以‘,’隔开 * @returns {Object} 转成hashmap的对象 */ listToMap: function(list) { if (!list) { return {}; } var array = list.split(/,/g), k = array.length, map = {}; if (k) while (k--) { map[array[k]] = 1; } return map; }, /** * 将str中的html符号转义 * @public * @function * @param {String} str 需要转义的字符串 * @returns {String} 转义后的字符串 */ unhtml: function() { var map = { '<': '<', '&': '&', '"': '"', '>': '>' }; function rep(m) { return map[m]; } return function(str) { return str ? str.replace(/[&<">]/g, rep) : ''; }; }(), /** * 将css样式转换为驼峰的形式。如font-size -> fontSize * @public * @function * @param {String} cssName 需要转换的样式 * @returns {String} 转换后的样式 */ cssStyleToDomStyle: function() { var test = document.createElement('div').style, cssFloat = test.cssFloat != undefined ? 'cssFloat': test.styleFloat != undefined ? 'styleFloat': 'float', cache = { 'float': cssFloat }; function replacer(match) { return match.charAt(1).toUpperCase(); } return function(cssName) { return cache[cssName] || (cache[cssName] = cssName.toLowerCase().replace(/-./g, replacer)); }; }(), /** * 加载css文件,执行回调函数 * @public * @function * @param {document} doc document对象 * @param {String} path 文件路径 * @param {Function} fun 回调函数 * @param {String} id 元素id */ loadFile : function(doc,obj,fun){ 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 || this.readyState == 'loaded' || this.readyState == 'complete') { if (fun) fun(); element.onload = element.onreadystatechange = null; } }; doc.getElementsByTagName("head")[0].appendChild(element); }, isEmptyObject : function(obj){ for ( var p in obj ) { return false; } return true; }, 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; } } })(); ///import editor.js ///import core/utils.js (function () { baidu.editor.EventBase = EventBase; var utils = baidu.editor.utils; /** * 事件基础类 * @public * @class * @name baidu.editor.EventBase */ function EventBase() { } EventBase.prototype = /**@lends baidu.editor.EventBase.prototype*/{ /** * 注册事件监听器 * @public * @function * @param {String} type 事件名 * @param {Function} listener 监听器数组 */ addListener : function ( type, listener ) { getListener( this, type, true ).push( listener ); }, /** * 移除事件监听器 * @public * @function * @param {String} type 事件名 * @param {Function} listener 监听器数组 */ removeListener : function ( type, listener ) { var listeners = getListener( this, type ); listeners && utils.removeItem( listeners, listener ); }, /** * 触发事件 * @public * @function * @param {String} type 事件名 * */ fireEvent : function ( type ) { var listeners = getListener( this, type ), 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' + type.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 //注册命名空间 /** * @class baidu.editor.dom */ baidu.editor.dom = baidu.editor.dom || {}; ///import editor.js ///import core/dom/dom.js /** * dtd html语义化的体现类 * @constructor * @namespace dtd */ baidu.editor.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; i -1) return node; node = node.parentNode; } } return null; }, /** * 查找祖先节点集合 * @param {Node} node 节点 * @param {Function} tester 函数 * @param {Boolean} includeSelf 是否从自身开始找 * @param {Boolean} closerFirst * @returns {Array} 祖先节点集合 */ findParents: function (node, includeSelf, tester, closerFirst) { var parents = includeSelf && ( tester && tester(node) || !tester ) ? [node] : []; while (node = domUtils.findParent(node, tester)) { parents.push(node); } if (!closerFirst) { parents.reverse(); } return parents; }, /** * 往后插入节点 * @function * @param {Node} node 基准节点 * @param {Node} nodeToInsert 要插入的节点 * @return {Node} 返回node */ insertAfter : function (node, nodeToInsert) { return node.parentNode.insertBefore(nodeToInsert, node.nextSibling); }, /** * 删除该节点 * @function * @param {Node} node 要删除的节点 * @param {Boolean} keepChildren 是否保留子节点不删除 * @return {Node} 返回要删除的节点 */ remove : function (node, keepChildren) { var parent = node.parentNode, child; if (parent) { if (keepChildren && node.hasChildNodes()) { while (child = node.firstChild) { parent.insertBefore(child, node); } } // if ( browser.ie ) { // if ( orphanDiv == null ) { // orphanDiv = node.ownerDocument.createElement( 'div' ); // } // orphanDiv.appendChild( node ); // orphanDiv.innerHTML = ''; // } else { // parent.removeChild( node ); // } parent.removeChild(node); } return node; }, /** * 取得node节点在dom树上的下一个节点 * @function * @param {Node} node 节点 * @param {Boolean} startFromChild 为true从子节点开始找 * @param {Function} fn fn为真的节点 * @return {Node} 返回下一个节点 */ getNextDomNode : function(node, startFromChild, filter, guard) { return getDomNode(node, 'firstChild', 'nextSibling', startFromChild, filter, guard); }, /** * 是bookmark节点 * @param {Node} node 判断是否为书签节点 * @return {Boolean} 返回是否为书签节点 */ isBookmarkNode : function(node) { return node.nodeType == 1 && node.id && /^_baidu_bookmark_/i.test(node.id); }, /** * 获取节点所在window对象 * @param {Node} node 节点 * @return {window} 返回window对象 */ getWindow : function (node) { var doc = node.ownerDocument || node; return doc.defaultView || doc.parentWindow; }, /** * 得到公共的祖先节点 * @param {Node} nodeA 节点A * @param {Node} nodeB 节点B * @return {Node} nodeA和nodeB的公共节点 */ getCommonAncestor : function(nodeA, nodeB) { if (nodeA === nodeB) return nodeA; var parentsA = [nodeA] ,parentsB = [nodeB], parent = nodeA, i = -1; while (parent = parent.parentNode) { if (parent === nodeB) return parent; parentsA.push(parent) } parent = nodeB; while (parent = parent.parentNode) { if (parent === nodeA) return parent; parentsB.push(parent) } parentsA.reverse(); parentsB.reverse(); while (i++,parentsA[i] === parentsB[i]); return i == 0 ? null : parentsA[i - 1]; }, /** * 清除该节点左右空的inline节点 * @function * @param {Node} node * @param {Boolean} ingoreNext 默认为false清除右边为空的inline节点。true为不清除右边为空的inline节点 * @param {Boolean} ingorePre 默认为false清除左边为空的inline节点。true为不清除左边为空的inline节点 * @exmaple xxxxbb --> xxxxbb */ clearEmptySibling : function(node, ingoreNext, ingorePre) { function clear(next, dir) { var tmpNode; if (next && (!domUtils.isBookmarkNode(next) && domUtils.isEmptyInlineElement(next) || domUtils.isWhitespace(next) )) { tmpNode = next[dir]; domUtils.remove(next); tmpNode && clear(tmpNode, dir); } } !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) { var reg = new RegExp('[^ \t\n\r' + domUtils.fillChar + ']'); return !reg.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 = type instanceof Array ? type : [type], k = types.length; if (k) while (k --) { eventListIndex++; 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 = type instanceof Array ? 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)return 0; if(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; }, /** * 判断是否为多余的span标签,该span没有显式定义的属性 * @param {Node} node 节点 * @return {boolean} 是否为多余的span标签 * @example * 如<span>hello</span>,这个span就是多余的 */ isRedundantSpan : function(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; ixxxxxxxxxx ==>
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 : browser.gecko ? function(node) { node.style.MozUserSelect = 'none'; } : browser.webkit ? function(node) { node.style.KhtmlUserSelect = 'none'; } : 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"); } } }, //todo yuxiang /** * 删除元素上的属性,可以删除多个 * @function * @param {Element} element 元素 * @param {Array} attrNames 要删除的属性数组 */ removeAttributes : function (element, attrNames) { var k = attrNames.length; if (k) while (k --) { var attr = attrNames[k]; attr = attrFix[attr] || attr; //for ie className if(attr == 'className'){ element[attr] = ''; } element.removeAttribute(attr); } }, /** * 给节点添加属性 * @function * @param {Node} node 节点 * @param {Object} attrNames 要添加的属性名称,采用json对象存放 */ setAttributes : function(node, attrs) { for (var name in attrs) { switch (name.toLowerCase()) { case 'class' : node.className = attrs[name]; break; case 'style' : node.style.cssText = attrs[name]; break; default: node.setAttribute(name.toLowerCase(), attrs[name]); } } 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) { element.className = (' ' + element.className + ' ').replace( new RegExp('(?:\\s+(?:' + classNames.join('|') + '))+\\s+', 'g'), ' '); }, /** * 删除元素的样式 * @param {Element} element元素 * @param {String} name 删除的样式名称 */ removeStyle : function(node, name) { node.style[utils.cssStyleToDomStyle(name)] = ''; if (node.style.removeAttribute) node.style.removeAttribute(utils.cssStyleToDomStyle(name)); if (!node.style.cssText) node.removeAttribute('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; }, /** * 清除冗余的inline标签 * @param node node下的冗余子孙节点 * @param tags 清除的节点的tagname * @example
==>
*/ clearReduent : function(node, tags) { var nodes, reg = new RegExp(domUtils.fillChar, 'g'), _parent; for (var t = 0,ti; ti = tags[t++];) { nodes = node.getElementsByTagName(ti); for (var i = 0,ci; ci = nodes[i++];) { if (ci.parentNode && ci[browser.ie ? 'innerText' : 'textContent'].replace(reg, '').length == 0 && ci.children.length == 0) { _parent = ci.parentNode; domUtils.remove(ci); while (_parent.childNodes.length == 0 && new RegExp(tags.join('|'), 'i').test(_parent.tagName)) { ci = _parent; _parent = _parent.parentNode; domUtils.remove(ci) } } } } }, /** * 判断是否为空节点 * @function * @param {Node} node 节点 * @return {Boolean} 是否为空节点 */ isEmptyNode : function(node) { var first = node.firstChild; return !first || 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']); } }, /** * 将显示区域滚动到显示节点的位置 * @funciton * @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){ var reg = new RegExp( domUtils.fillChar ); return node.nodeType == 3 && !node.nodeValue.replace(reg,'').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){ node.appendChild(browser.ie ? doc.createTextNode(domUtils.fillChar) : doc.createElement('br')); }, moveChild : function(src,tag,dir){ while(src.firstChild){ if(dir && tag.firstChild){ tag.insertBefore(src.lastChild,tag.firstChild); }else{ tag.appendChild(src.firstChild) } } } }; })(); ///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类 */ baidu.editor.dom.Range = baidu.editor.dom.Range || {}; /** * @description Range类实现 * @author zhanyi */ (function() { var editor = baidu.editor, browser = editor.browser, domUtils = editor.dom.domUtils, dtd = editor.dom.dtd, utils = editor.utils, guid = 0, fillChar = domUtils.fillChar; /** * 更新range的collapse状态 * @param {Range} range range对象 */ var updateCollapse = function( range ) { range.collapsed = range.startContainer && range.endContainer && range.startContainer === range.endContainer && range.startOffset == range.endOffset; }, setEndPoint = function( 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; }, execContentsAction = function( 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 = baidu.editor.dom.Range = function( document ) { var me = this; me.startContainer = me.startOffset = me.endContainer = me.endOffset = null; me.document = document; me.collapsed = true; }; /** * 删除内容为空的祖先节点 * @function * @param {Node} node 节点 */ function removeFillDataWithEmptyParentNode(node){ var parent = node.parentNode, tmpNode; domUtils.remove( node ); while(parent && dtd.$removeEmpty[parent.tagName] && parent.childNodes.length == 0){ tmpNode = parent; domUtils.remove(parent); parent = tmpNode.parentNode; } } 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() { if ( !this.collapsed ) execContentsAction( this, 1 ); if(browser.webkit){ var 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前 * @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 ? false : true ).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 fillData = editor.fillData, tmpText, tmp = this.document.createElement( 'span' ); try { if ( fillData && fillData.parentNode && !fillData.nodeValue.replace( new RegExp( domUtils.fillChar, 'g' ), '' ).length) { removeFillDataWithEmptyParentNode(fillData) } } catch( e ) { } tmpText = editor.fillData = this.document.createTextNode( fillChar ); tmp.appendChild( this.document.createTextNode( fillChar) ); start.parentNode.insertBefore( tmp, start ); start.parentNode.insertBefore( tmpText, start ); nativeRange.moveStart( 'character', -1 ); nativeRange.collapse( true ); } } this.moveToBookmark( bookmark ); tmp && domUtils.remove( tmp ); nativeRange.select(); return this; } : function( notInsertFillData ) { var win = domUtils.getWindow( this.document ), sel = win.getSelection(), txtNode; browser.gecko ? this.document.body.focus() : win.focus(); function mergSibling(node){ if(node && node.nodeType == 3 && !node.nodeValue.replace( new RegExp( domUtils.fillChar, 'g' ), '' ).length){ domUtils.remove(node); } } 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 && !notInsertFillData ){ var fillData = editor.fillData; txtNode = this.document.createTextNode( fillChar ); editor.fillData = txtNode; //跟着前边走 this.insertNode( txtNode ); //todo fillData有时会失效,不能关联到上一次的文本节点 if ( fillData && fillData.parentNode ) { if(!fillData.nodeValue.replace( new RegExp( domUtils.fillChar, 'g' ), '' ).length) removeFillDataWithEmptyParentNode(fillData); else fillData.nodeValue = fillData.nodeValue.replace( new RegExp( domUtils.fillChar, 'g' ), '' ) } mergSibling(txtNode.previousSibling); mergSibling(txtNode.nextSibling); 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类 */ baidu.editor.dom.Selection = baidu.editor.dom.Selection || {}; (function () { baidu.editor.dom.Selection = Selection; var domUtils = baidu.editor.dom.domUtils, dtd = baidu.editor.dom.dtd, ie = baidu.editor.browser.ie; 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 )}; // return dtd.$empty[child.tagName.toLowerCase()] ? // {container:parent,offset:getIndex( child )} : // {container:child,offset:0} } } 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; } function Selection( 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 () { if(!this.document){ return null; } if ( ie ) { return this.document.selection; } else { return domUtils.getWindow( this.document ).getSelection(); } }, /** * 获得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(); }, /** * 清空缓存 * @public * @function * @name baidu.editor.dom.Selection.clear */ clear : function () { this._cachedRange = this._cachedStartElement = null; }, /** * 获取选区对应的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 { optimze(range) } } return 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 = this.getNative(), nativeRange; if(nativeSel) nativeRange = baidu.editor.browser.ie ? nativeSel.createRange() : nativeSel.getRangeAt(0); else return ''; return nativeRange.text || nativeRange.toString(); } }; })(); ///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 () { baidu.editor.Editor = Editor; var editor = baidu.editor, utils = editor.utils, EventBase = editor.EventBase, domUtils = editor.dom.domUtils, Selection = editor.dom.Selection, ie = editor.browser.ie, uid = 0, browser = editor.browser, dtd = editor.dom.dtd, _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')) } } } /** * 编辑器类 * @public * @class * @extends baidu.editor.EventBase * @name baidu.editor.Editor * @param {Object} options */ function Editor( options ) { var me = this; me.uid = uid ++; EventBase.call( me ); me.commands = {}; me.options = utils.extend( options || {}, UEDITOR_CONFIG, true ); me.initPlugins(); } Editor.prototype = /**@lends baidu.editor.Editor.prototype*/{ destroy : function(){ this.fireEvent('destroy'); this.container.innerHTML = ''; domUtils.remove(this.container); }, /** * 渲染编辑器的DOM到指定容器,必须且只能调用一次 * @public * @function * @param {Element|String} container */ render : function ( container ) { if (container.constructor === String) { container = document.getElementById(container); } if(container){ container.innerHTML = ''; container.style.overflow = 'hidden'; this._setup( container.firstChild.contentWindow.document ); } }, _setup: function ( doc ) { var options = this.options, me = this; //防止在chrome下连接后边带# 会跳动的问题 !browser.webkit && doc.open(); var useBodyAsViewport = ie && browser.version < 9; doc.write( ( ie && browser.version < 9 ? '' : '') + '' + ( options.iframeCssUrl ? '' : '' ) + '' ); !browser.webkit && doc.close(); if ( ie ) { doc.body.disabled = true; doc.body.contentEditable = true; doc.body.disabled = false; } else { doc.body.contentEditable = true; doc.body.spellcheck = false; } this.document = doc; this.window = doc.defaultView || doc.parentWindow; this.iframe = this.window.frameElement; this.body = doc.body; if (this.options.minFrameHeight) { this.setHeight(this.options.minFrameHeight); this.body.style.height = this.options.minFrameHeight; } this.selection = new Selection( doc ); this._initEvents(); if(me.options.initialContent){ if(me.options.autoClearinitialContent){ var oldExecCommand = me.execCommand; me.execCommand = function(){ me.fireEvent('firstBeforeExecCommand'); oldExecCommand.apply(me,arguments) }; this.setDefaultContent(this.options.initialContent); }else this.setContent(this.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(){ var textarea = document.getElementById('ueditor_textarea_' + me.options.textarea); if(!textarea){ textarea = document.createElement('textarea'); textarea.setAttribute('name',me.options.textarea); textarea.id = 'ueditor_textarea_' + me.options.textarea; textarea.style.display = 'none'; this.appendChild(textarea); } textarea.value = me.getContent(); }); break; } } //编辑器不能为空内容 if(domUtils.isEmptyNode(me.body)){ this.body.innerHTML = '

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

'; } //如果要求focus, 就把光标定位到内容开始 if(me.options.focus){ setTimeout(function(){ me.selection.getRange().setStartBefore(me.body.firstChild).setCursor(false,true); //如果自动清除开着,就不需要做selectionchange; !me.options.autoClearinitialContent && me._selectionChange() }); } if(!this.container){ this.container = this.iframe.parentNode; } this.fireEvent( 'ready' ); //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) } }, /** * 创建textarea,同步编辑的内容到textarea,为后台获取内容做准备 * @param formId 制定在那个form下添加 * @public * @function */ sync : function(formId){ var me = this, form; function setValue(form){ var textarea = document.getElementById('ueditor_textarea_' + me.options.textarea); if(!textarea){ textarea = document.createElement('textarea'); textarea.setAttribute('name',me.options.textarea); textarea.id = 'ueditor_textarea_' + me.options.textarea; textarea.style.display = 'none'; form.appendChild(textarea); } textarea.value = me.getContent(); } if(formId){ form = document.getElementById(formId); form && setValue(form); }else{ for(form = me.iframe.parentNode;!domUtils.isBody(form);form = form.parentNode){ if(form.tagName == 'FORM'){ setValue(form); break; } } } }, /** * 设置编辑器高度 * @public * @function * @param {Number} height 高度 */ setHeight: function (height){ if (height !== parseInt(this.iframe.parentNode.style.height)){ this.iframe.parentNode.style.height = height + 'px'; } //ie9下body 高度100%失效,改为手动设置 if(browser.ie && browser.version == 9){ this.document.body.style.height = height - 20 + 'px' } }, /** * 获取编辑器内容 * @public * @function * @returns {String} */ getContent : function (cmd) { this.fireEvent( 'beforegetcontent',cmd ); var reg = new RegExp( domUtils.fillChar, 'g' ), html = this.document.body.innerHTML.replace(reg,''); this.fireEvent( 'aftergetcontent',cmd ); if (this.serialize) { var node = this.serialize.parseHTML(html); node = this.serialize.transformOutput(node); html = this.serialize.toHTML(node); } return html; }, /** * 获取编辑器中的文本内容 * @public * @function * @returns {String} */ getContentTxt : function(){ var reg = new RegExp( domUtils.fillChar,'g' ); return this.body[browser.ie ? 'innerText':'textContent'].replace(reg,'') }, /** * 设置编辑器内容 * @public * @function * @param {String} html */ setContent : function ( html,notFireSelectionchange) { var me = this; 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.document.body.innerHTML = html.replace(new RegExp('[\r' + domUtils.fillChar + ']*','g'),''); //处理ie6下innerHTML自动将相对路径转化成绝对路径的问题 if(browser.ie && browser.version < 7 && me.options.relativePath){ replaceSrc(this.document.body); } //给文本或者inline节点套p标签 if(me.options.enterTag == 'p'){ var child = this.body.firstChild, p = me.document.createElement('p'), tmpNode; if(!child || child.nodeType == 1 && dtd.$cdata[child.tagName]){ this.body.innerHTML = '

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

' + this.body.innerHTML; }else{ while(child){ if(child.nodeType ==3 || child.nodeType == 1 && dtd.p[child.tagName]){ tmpNode = child.nextSibling; p.appendChild(child); child = tmpNode; if(!child){ me.body.appendChild(p); } }else{ if(p.firstChild){ me.body.insertBefore(p,child); p = me.document.createElement('p') } child = child.nextSibling } } } } me.adjustTable && me.adjustTable(me.body); me.fireEvent( 'aftersetcontent' ); !notFireSelectionchange && me._selectionChange(); }, /** * 让编辑器获得焦点 * @public * @function */ focus : function () { browser.gecko ? this.body.focus() : domUtils.getWindow(this.document).focus(); }, /** * 加载插件 * @private * @function * @param {Array} plugins */ initPlugins : function ( plugins ) { var fn,originals = baidu.editor.plugins; if ( plugins ) { for ( var i = 0,pi; pi = plugins[i++]; ) { if ( utils.indexOf( this.options.plugins, pi ) == -1 && (fn = baidu.editor.plugins[pi]) ) { this.options.plugins.push( pi ); fn.call( this ) } } } else { plugins = this.options.plugins; if ( plugins ) { for ( i = 0; pi = originals[plugins[i++]]; ) { pi.call( this ) } } else { this.options.plugins = []; for ( pi in originals ) { this.options.plugins.push( pi ); originals[pi].call( this ) } } } }, /** * 初始化事件,绑定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; 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; cmdFn = ( cmd = this.commands[cmdName] ) && cmd[fnName] || ( cmd = baidu.editor.commands[cmdName]) && cmd[fnName]; if ( cmd && !cmdFn && fnName == 'queryCommandState' ) { return false; } 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] || baidu.editor.commands[cmdName]; if ( !cmd || !cmd.execCommand ) { return; } if ( !cmd.notNeedUndo && !me.__hasEnterExecCommand ) { me.__hasEnterExecCommand = true; 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 } return false; }, /** * 从新设置 * @public * @function */ reset : function(){ this.fireEvent('reset'); }, /** * 设置默认内容 * @function * @param {String} cont 要存入的内容 */ setDefaultContent : function(){ function clear(){ var me = this; if(me.document.getElementById('initContent')){ me.document.body.innerHTML = '

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

'; var range = me.selection.getRange(); me.removeListener('firstBeforeExecCommand',clear); me.removeListener('mousedown',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 && me.options.relativePath){ replaceSrc(me.document.body); } me.addListener('firstBeforeExecCommand',clear); me.addListener('mousedown',clear); } }() }; utils.inherits( Editor, EventBase ); })(); ///import core /** * @description 插入内容 * @name baidu.editor.execCommand * @param {String} cmdName inserthtml插入内容的命令 * @param {String} html 要插入的内容 * @author zhanyi */ (function(){ var domUtils = baidu.editor.dom.domUtils, dtd = baidu.editor.dom.dtd, utils = baidu.editor.utils, browser = baidu.editor.browser; baidu.editor.commands['inserthtml'] = { execCommand: function (command,html){ var editor = this, range,deletedElms, i,ci, div, tds = editor.currentSelectedArr; range = editor.selection.getRange(); div = range.document.createElement( 'div' ); div.style.display = 'inline'; div.innerHTML = utils.trim( html ); try{ editor.adjustTable && editor.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); editor.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); } hadBreak = 1; } } var next = child.nextSibling; if(!div.firstChild && next && domUtils.isBlockElm(next)){ range.setStart(next,0).collapse(true); break; } range.setEndAfter( child ).collapse(); } // if(!range.startContainer.childNodes[range.startOffset] && domUtils.isBlockElm(range.startContainer)){ // next = editor.document.createElement('br'); // range.insertNode(next); // range.collapse(true); // } //block为空无法定位光标 child = range.startContainer; //用chrome可能有空白展位符 if(domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)){ child.innerHTML = baidu.editor.browser.ie ? '' : '
' } //加上true因为在删除表情等时会删两次,第一次是删的fillData range.select(true); setTimeout(function(){ range = editor.selection.getRange(); range.scrollToView(editor.autoHeightEnabled,editor.autoHeightEnabled ? domUtils.getXY(editor.iframe).y:0); },200) } }; }()); ///import core ///import commands\inserthtml.js ///commands 插入图片,操作图片的对齐方式 ///commandsName InsertImage,ImageNone,ImageLeft,ImageRight,ImageCenter ///commandsTitle 图片,默认,居左,居右,居中 ///commandsDialog dialogs\image\image.html /** * Created by . * User: zhanyi * for image */ (function (){ var domUtils = baidu.editor.dom.domUtils, utils = baidu.editor.utils, defaultValue = { left : 1, right : 1, center : 1 }, dtd = baidu.editor.dom.dtd; baidu.editor.commands['imagefloat'] = { execCommand : function (cmd, align){ var range = this.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(this.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 = this.document.createElement('div'); pN.appendChild(tmpNode); domUtils.setStyle(tmpNode,'float',''); this.execCommand('insertHtml','

'+pN.innerHTML+'

'); tmpNode = this.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 defaultValue[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; } }; baidu.editor.commands['insertimage'] = { execCommand : function (cmd, opt){ opt = utils.isArray(opt) ? opt : [opt]; var range = this.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); this.execCommand('imagefloat',floatStyle); if(opt.length > 0){ range.setStartAfter(img).setCursor(false,true); this.execCommand('insertimage',opt); } }else{ var html = [],str = '',ci; ci = opt[0]; if(opt.length == 1){ str = ''; if(ci['floatStyle'] == 'center'){ str = '

'+str+'

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

'; // if(ci['floatStyle'] == 'center'){ // str = '

'+str+'

' // } html.push(str) } } this.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 domUtils = baidu.editor.dom.domUtils, dtd = baidu.editor.dom.dtd, block = domUtils.isBlockElm, defaultValue = { left : 1, right : 1, center : 1, justify : 1 }, utils = baidu.editor.utils, 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) }; baidu.editor.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); 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(){ if(this.highlight){ return -1; } return this.queryCommandState('highlightcode') == 1 ? -1 : 0; } } })(); ///import core ///import commands\removeformat.js ///commands 字体颜色,背景色,字号,字体,下划线,删除线 ///commandsName ForeColor,BackColor,FontSize,FontFamily,Underline,StrikeThrough ///commandsTitle 字体颜色,背景色,字号,字体,下划线,删除线 /** * @description 字体 * @name baidu.editor.execCommand * @param {String} cmdName 执行的功能名称 * @param {String} value 传入的值 */ (function() { var domUtils = baidu.editor.dom.domUtils, fonts = { 'forecolor':'color', 'backcolor':'background-color', 'fontsize':'font-size', 'fontfamily':'font-family', 'underline':'text-decoration', 'strikethrough':'text-decoration' }, reg = new RegExp(domUtils.fillChar,'g'), browser = baidu.editor.browser, flag = 0; for ( var p in fonts ) { (function( cmd, style ) { baidu.editor.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; //执行了上述代码可能产生冗余的html代码,所以要注册 beforecontent去掉这些冗余的代码 if(!flag){ me.addListener('beforegetcontent',function(){ domUtils.clearReduent(me.document,['span']) }); flag = 1; } 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(reg,'').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 = 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'){ span.style.cssText = spanParent.style.cssText + span.style.cssText; } spanParent = spanParent.parentNode; } } 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() { var dom = baidu.editor.dom, domUtils = dom.domUtils, browser = baidu.editor.browser; 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 ) } } baidu.editor.commands['unlink'] = { execCommand : function() { var as, range = new baidu.editor.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(){ if(this.highlight){ return -1; } return 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.innerHTML = opt.href; } } range.removeInlineStyle( 'a' ); if ( range.collapsed ) { var a = range.document.createElement( 'a' ); domUtils.setAttributes( a, opt ); a.innerHTML = opt.href; range.insertNode( a ).selectNode( a ); } else { range.applyInlineStyle( 'a', opt ) } } baidu.editor.commands['link'] = { queryCommandState : function(){ return this.highlight ? -1 :0; }, execCommand : function( cmdName, opt ) { var range = new baidu.editor.dom.Range(this.document), tds = this.currentSelectedArr; if(tds && tds.length){ for(var i=0,ti;ti=tds[i++];){ if(domUtils.isEmptyNode(ti)){ ti.innerHTML = opt.href } doLink(range.selectNodeContents(ti),opt) } range.selectNodeContents(tds[0]).select() }else{ doLink(range=this.selection.getRange(),opt); range.collapse().select(browser.gecko ? true : false); } }, queryCommandValue : function() { var range = new baidu.editor.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 commands\inserthtml.js ///commands 地图 ///commandsName Map,GMap ///commandsTitle Baidu地图,Google地图 ///commandsDialog dialogs\map\map.html,dialogs\gmap\gmap.html (function() { baidu.editor.commands['gmap'] = baidu.editor.commands['map'] = { execCommand : function(){ }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; })(); ///import core ///import commands\inserthtml.js ///commands 插入框架 ///commandsName InsertFrame ///commandsTitle 插入Iframe ///commandsDialog dialogs\insertframe\insertframe.html (function() { baidu.editor.commands['insertframe'] = { execCommand : function(){ }, queryCommandState : function(){ return this.highlight ? -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 */ (function() { var domUtils = baidu.editor.dom.domUtils, dtd = baidu.editor.dom.dtd; baidu.editor.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 baidu.editor.dom.Range( this.document ), bookmark,node,parent, filter = function( node ) { return node.nodeType == 1; }; function doRemove( range ) { var bookmark1 = range.createBookmark(); if ( range.collapsed ) { range.enlarge( true ); } //不能把a标签切了 if(!notIncludeA){ var aNode = domUtils.findParentByTagName(range.startContainer,'a',true); if(aNode){ range.setStartBefore(aNode) } aNode = domUtils.findParentByTagName(range.endContainer,'a',true); if(aNode){ range.setEndAfter(aNode) } } bookmark = range.createBookmark(); node = bookmark.start; //切开始 while ( (parent = node.parentNode) && !domUtils.isBlockElm( parent ) ) { domUtils.breakParent( node, parent ); domUtils.clearEmptySibling( node ); } if ( bookmark.end ) { //切结束 node = bookmark.end; while ( (parent = node.parentNode) && !domUtils.isBlockElm( parent ) ) { domUtils.breakParent( node, parent ); domUtils.clearEmptySibling( node ); } //开始去除样式 var current = domUtils.getNextDomNode( bookmark.start, false, filter ), next; while ( current ) { if ( current == bookmark.end ) { break; } next = domUtils.getNextDomNode( current, true, filter ); if ( !dtd.$empty[current.tagName.toLowerCase()] && !domUtils.isBookmarkNode( current ) ) { if ( tagReg.test( current.tagName ) ) { if ( style ) { domUtils.removeStyle( current, style ); if ( domUtils.isRedundantSpan( current ) && style != 'text-decoration') domUtils.remove( current, true ); } else { domUtils.remove( current, true ) } } else { //trace:939 不能把list上的样式去掉 if(!dtd.$tableContent[current.tagName] && !dtd.$list[current.tagName]){ domUtils.removeAttributes( current, removeFormatAttributes ); if ( domUtils.isRedundantSpan( current ) ) domUtils.remove( current, true ); } } } current = next; } } //trace:1035 //trace:1096 不能把td上的样式去掉,比如边框 var pN = bookmark.start.parentNode; if(domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]){ domUtils.removeAttributes( pN,removeFormatAttributes ); } pN = bookmark.end.parentNode; if(bookmark.end && domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName]&& !dtd.$list[pN.tagName]){ domUtils.removeAttributes( pN,removeFormatAttributes ); } range.moveToBookmark( bookmark ).moveToBookmark(bookmark1); //清除冗余的代码 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; } } // baidu.editor.contextMenuItems.push({ // label : '清除样式', // cmdName : 'removeformat' // }) })(); ///import core ///commands 引用 ///commandsName BlockQuote ///commandsTitle 引用 /** * * 引用模块实现 * @function * @name baidu.editor.execCommand * @param {String} cmdName blockquote引用 */ (function() { var domUtils = baidu.editor.dom.domUtils, dtd = baidu.editor.dom.dtd, getObj = function(editor){ var startNode = editor.selection.getStart(); return domUtils.findParentByTagName( startNode, 'blockquote', true ) }; baidu.editor.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; } }; // baidu.editor.contextMenuItems.push({ // label : '引用', // cmdName : 'blockquote' // }) })(); ///import core ///import commands\paragraph.js ///commands 首行缩进 ///commandsName Outdent,Indent ///commandsTitle 取消缩进,首行缩进 /** * 首行缩进 * @function * @name baidu.editor.execCommand * @param {String} cmdName outdent取消缩进,indent缩进 */ (function (){ var domUtils = baidu.editor.dom.domUtils; baidu.editor.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 start = this.selection.getStart(), pN = domUtils.findParentByTagName(start,['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],true), indent = pN && pN.style.textIndent ? parseInt(pN.style.textIndent) : ''; return indent ? 1 : 0; } }; })(); ///import core ///commands 打印 ///commandsName Print ///commandsTitle 打印 /** * @description 打印 * @name baidu.editor.execCommand * @param {String} cmdName print打印编辑器内容 * @author zhanyi */ (function() { baidu.editor.commands['print'] = { execCommand : function(){ this.window.print(); }, notNeedUndo : 1 }; })(); ///import core ///commands 预览 ///commandsName Preview ///commandsTitle 预览 /** * 预览 * @function * @name baidu.editor.execCommand * @param {String} cmdName preview预览编辑器内容 */ baidu.editor.commands['preview'] = { execCommand : function(){ var me = this, w = window.open('', '_blank', ""), d = w.document, utils = baidu.editor.utils, css = me.document.getElementById("syntaxhighlighter_css"), js = document.getElementById("syntaxhighlighter_js"), style = "", cont = me.getContent(); if(baidu.editor.browser.ie){ cont = cont.replace(/<\s*br\s*\/?\s*>/gi,'

') } d.open(); d.write(''+style+''+ (css ? '' : '') + (css ? ' ':'') +'' + cont + (css ? '':'') + ''); d.close(); }, notNeedUndo : 1 }; ///import core ///import commands\inserthtml.js ///commands 特殊字符 ///commandsName Spechars ///commandsTitle 特殊字符 ///commandsDialog dialogs\spechars\spechars.html (function() { baidu.editor.commands['spechars'] = { execCommand : function(){ }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; })(); ///import core ///import commands\image.js ///commands 插入表情 ///commandsName Emotion ///commandsTitle 表情 ///commandsDialog dialogs\emotion\emotion.html (function() { baidu.editor.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 */ (function() { var browser = baidu.editor.browser; baidu.editor.commands['selectall'] = { execCommand : function(){ this.document.execCommand('selectAll',false,null); //trace 1081 !browser.ie && this.focus(); }, notNeedUndo : 1 }; })(); ///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 */ (function() { var domUtils = baidu.editor.dom.domUtils, block = domUtils.isBlockElm, notExchange = ['TD','LI','PRE'], utils = baidu.editor.utils, browser = baidu.editor.browser, doParagraph = function(range,style,attrs){ 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); // for(var pro in attrs){ // para.style[utils.cssStyleToDomStyle(pro)] = attrs[pro]; // } } 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 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); if(attrs && /h\d/i.test(parent.tagName)){ // for(var pro in attrs){ // parent.style[utils.cssStyleToDomStyle(pro)] = attrs[pro]; // } domUtils.setAttributes(parent,attrs); 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 ); }; baidu.editor.commands['paragraph'] = { execCommand : function( cmdName, style,attrs ) { var range = new baidu.editor.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); 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); 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 startNode = this.selection.getStart(), parent = domUtils.findParentByTagName( startNode, ['p','h1','h2','h3','h4','h5','h6'], true ); return parent && parent.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 domUtils = baidu.editor.dom.domUtils, 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; } } } }, 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 ); }; baidu.editor.commands['directionality'] = { execCommand : function( cmdName,forward ) { var range = new baidu.editor.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 commands\inserthtml.js ///commands 分割线 ///commandsName Horizontal ///commandsTitle 分隔线 /** * 分割线 * @function * @name baidu.editor.execCommand * @param {String} cmdName horizontal插入分割线 */ (function (){ var domUtils = baidu.editor.dom.domUtils; baidu.editor.commands['horizontal'] = { execCommand : function( cmdName ) { if(this.queryCommandState(cmdName)!==-1){ this.execCommand('insertHtml','
'); var range = this.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(this.options.enterTag == 'p'){ tmp = this.document.createElement('p'); range.insertNode(tmp); range.setStart(tmp,0).setCursor(); }else{ tmp = this.document.createElement('br'); range.insertNode(tmp); range.setStartBefore(tmp).setCursor(); } } } } return true; } }, //边界在table里不能加分隔线 queryCommandState : function() { if(this.highlight){ return -1; } var range = this.selection.getRange(); return domUtils.findParentByTagName(range.startContainer,'table') || domUtils.findParentByTagName(range.endContainer,'table') ? -1 : 0; } }; })(); ///import core ///import commands\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 */ baidu.editor.commands['time'] = { execCommand : function() { var date = new Date, min = date.getMinutes(), sec = date.getSeconds(), arr = [date.getHours(),min<10 ? "0"+min : min,sec<10 ? "0"+sec : sec]; this.execCommand('insertHtml',arr.join(":")); return true; }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; baidu.editor.commands['date'] = { execCommand : function() { var date = new Date, month = date.getMonth()+1, day = date.getDate(), arr = [date.getFullYear(),month<10 ? "0"+month : month,day<10?"0"+day:day]; this.execCommand('insertHtml',arr.join("-")); return true; }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; ///import core ///import commands\paragraph.js ///commands 段间距 ///commandsName RowSpacing ///commandsTitle 段间距 /** * @description 设置行距 * @name baidu.editor.execCommand * @param {String} cmdName rowspacing设置行间距 * @param {String} value 值,以px为单位 * @author zhanyi */ (function(){ var domUtils = baidu.editor.dom.domUtils; baidu.editor.commands['rowspacing'] = { execCommand : function( cmdName,value ) { this.execCommand('paragraph','p',{style:'padding:'+value + 'px 0'}); return true; }, queryCommandValue : function() { var startNode = this.selection.getStart(), pN = domUtils.findParent(startNode,function(node){return domUtils.isBlockElm(node)},true), value; //trace:1026 if(pN){ value = domUtils.getComputedStyle(pN,'padding-top').replace(/[^\d]/g,''); return value*1 <= 10 ? 0 : value; } return 0; }, queryCommandState : function(){ return this.highlight ? -1 :0; } } })(); ///import core ///import commands\paragraph.js ///commands 行间距 ///commandsName LineHeight ///commandsTitle 行间距 /** * @description 设置行内间距 * @name baidu.editor.execCommand * @param {String} cmdName lineheight设置行内间距 * @param {String} value 值 * @author zhuwenxuan */ (function(){ var domUtils = baidu.editor.dom.domUtils; baidu.editor.commands['lineheight'] = { execCommand : function( cmdName,value ) { this.execCommand('paragraph','p',{style:'line-height:'+value + '%' }); return true; }, queryCommandValue : function() { var startNode = this.selection.getStart(), pN = domUtils.findParent(startNode,function(node){return domUtils.isBlockElm(node)},true), value; if(pN){ value = domUtils.getComputedStyle(pN,'line-height').replace(/[^\d]*/ig,""); return (value == "normal" || value<100) ? 100 : value+"%"; } return 100; }, queryCommandState : function(){ return this.highlight ? -1 :0; } } })(); ///import core ///commands 清空文档 ///commandsName ClearDoc ///commandsTitle 清空文档 /** * * 清空文档 * @function * @name baidu.editor.execCommand * @param {String} cmdName cleardoc清空文档 */ (function(){ function setRange(range,node){ range.setStart(node,0).setCursor(); } baidu.editor.commands['cleardoc'] = { execCommand : function( cmdName) { var me = this, enterTag = me.options.enterTag, browser = baidu.editor.browser, range = this.selection.getRange(); if(enterTag == "br"){ this.body.innerHTML = "
"; setRange(range,this.body); }else{ //不用 也能定位,所以去掉,chrom也可以不要br,ff不行再想定位回去不行了,需要br this.body.innerHTML = "

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

"; me.focus(); setRange(range,me.body.firstChild); } } }; })(); ///import core ///commands 锚点 ///commandsName Anchor ///commandsTitle 锚点 ///commandsDialog dialogs\anchor\anchor.html /** * 锚点 * @function * @name baidu.editor.execCommands * @param {String} cmdName cmdName="anchor"插入锚点 */ (function (){ var domUtils = baidu.editor.dom.domUtils; baidu.editor.commands['anchor'] = { execCommand : function (cmd, name){ var range = this.selection.getRange(); var 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); anchor.setAttribute('anchorname',name); anchor.className = 'anchorclass'; range.insertNode(anchor).setStartAfter(anchor).collapse(true).select(true); //baidu.editor.browser.gecko && anchor.parentNode.insertBefore(this.document.createElement('br'),anchor.nextSibling) } } }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; })(); ///import core ///commands 删除 ///commandsName Delete ///commandsTitle 删除 /** * 删除 * @function * @name baidu.editor.execCommand * @param {String} cmdName delete删除 */ (function (){ var domUtils = baidu.editor.dom.domUtils, browser = baidu.editor.browser, dtd = baidu.editor.dom.dtd; baidu.editor.commands['delete'] = { execCommand : function (){ var range = this.selection.getRange(), mStart = 0, mEnd = 0, me = this; 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) while(!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.selection.getRange().collapsed ? -1 : 0; } }; })(); ///import core ///commands 字数统计 ///commandsName WordCount ///commandsTitle 字数统计 /** * Created by JetBrains WebStorm. * User: taoqili * Date: 11-9-7 * Time: 下午8:18 * To change this template use File | Settings | File Templates. */ baidu.editor.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; } var open = this.options.wordCount, max= this.options.maximumWords, msg = this.options.messages.wordCountMsg, errMsg=this.options.messages.wordOverFlowMsg; if(!open) return ""; reg = new RegExp("[\r\t\n]","g"); contentText = this.getContentTxt().replace(reg,""); length = contentText.length; if(max-length<0){ return ""+errMsg+" " } msg = msg.replace("{#leave}",max-length >= 0 ? max-length:0); msg = msg.replace("{#count}",length); return msg; } }; ///import core ///commands 添加分页功能 ///commandsName PageBreak ///commandsTitle 分页 /** * @description 添加分页功能 * @author zhanyi */ (function() { var editor = baidu.editor, domUtils = editor.dom.domUtils, notBreakTags = ['td']; baidu.editor.plugins['pagebreak'] = function() { var me = this; //重写了Editor.hasContents var hasContentsOrg = me.hasContents; me.hasContents = function(tags){ for(var i=0,di,divs = me.document.getElementsByTagName('div');di=divs[i++];){ if(domUtils.hasClass(di,'pagebreak')){ return true; } } return hasContentsOrg.call(me,tags); }; me.commands['pagebreak'] = { execCommand:function(){ var range = me.selection.getRange(); var div = me.document.createElement('div'); div.className = 'pagebreak'; domUtils.unselectable(div); //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'); table.parentNode.insertBefore(div,table); parents = domUtils.findParents(div,true); }else{ pN.parentNode.insertBefore(div,pN); parents = domUtils.findParents(div); } pN = parents[1]; if(div!==pN){ domUtils.breakParent(div,pN); } domUtils.clearSelectedArr(me.currentSelectedArr); } }else{ if(!range.collapsed){ range.deleteContents(); var start = range.startContainer; while(domUtils.isBlockElm(start) && domUtils.isEmptyNode(start)){ range.setStartBefore(start).collapse(true); domUtils.remove(start); start = range.startContainer; } } parents = domUtils.findParents(range.startContainer,true); pN = parents[1]; range.insertNode(div); pN && domUtils.breakParent(div,pN); range.setEndAfter(div).setCursor(true,true) } }, queryCommandState : function(){ return this.highlight ? -1 :0; } } } })(); ///import core ///commands 本地图片引导上传 ///commandsName CheckImage ///commandsTitle 本地图片引导上传 baidu.editor.plugins["checkimage"] = function(){ var checkedImgs=[],me = this; me.commands['checkimage'] = { execCommand : function( cmdName,checkType) { if(checkedImgs.length){ this[checkType] = checkedImgs; } }, queryCommandState: function(cmdName,checkType){ checkedImgs=[]; var images = this.document.getElementsByTagName("img"); for(var i=0,ci;ci =images[i++];){ if(ci.getAttribute(checkType)){ checkedImgs.push(ci.getAttribute(checkType)); } } return checkedImgs.length ? 1:-1; } }; }; ///import core ///commands 撤销和重做 ///commandsName Undo,Redo ///commandsTitle 撤销,重做 /** * @description 回退 * @author zhanyi */ (function() { var domUtils = baidu.editor.dom.domUtils, fillchar = new RegExp(baidu.editor.dom.domUtils.fillChar + '|<\/hr>','gi'),// ie会产生多余的 browser = baidu.editor.browser; baidu.editor.plugins['undo'] = function() { var me = this, maxUndoCount = me.options.maxUndoCount, maxInputCount = me.options.maxInputCount, //在比较时,需要过滤掉这些属性 specialAttr = /\b(?:href|src|name)="[^"]*?"/gi; function UndoManager() { this.list = []; this.index = 0; this.hasUndo = false; this.hasRedo = false; this.undo = function() { if ( this.hasUndo ) { var currentScene = this.getScene(), lastScene = this.list[this.index]; if ( lastScene.content.replace(specialAttr,'') != currentScene.content.replace(specialAttr,'') ) { this.save(); } if(!this.list[this.index - 1] && this.list.length == 1){ this.reset(); return; } while ( this.list[this.index].content == this.list[this.index - 1].content ) { this.index--; if ( this.index == 0 ) { return this.restore( 0 ) } } this.restore( --this.index ); } }; this.redo = function() { if ( this.hasRedo ) { while ( this.list[this.index].content == this.list[this.index + 1].content ) { this.index++; if ( this.index == this.list.length - 1 ) { return this.restore( this.index ) } } this.restore( ++this.index ); } }; this.restore = function() { var scene = this.list[this.index]; //trace:873 //去掉展位符 me.document.body.innerHTML = scene.bookcontent.replace(fillchar,''); var range = new baidu.editor.dom.Range( me.document ); range.moveToBookmark( { start : '_baidu_bookmark_start_', end : '_baidu_bookmark_end_', id : true //去掉true 是为了|,回退后还能在b里 //todo safari里输入中文时,会因为改变了dom而导致丢字 } ); //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); setTimeout(function(){ range.scrollToView(me.autoHeightEnabled,me.autoHeightEnabled ? domUtils.getXY(me.iframe).y:0); },200); 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,''); baidu.editor.browser.ie && (cont = cont.replace(/> <').replace(/\s*\s*/g,'>')); var bookmark = range.createBookmark( true, true ), bookCont = me.body.innerHTML.replace(fillchar,''); 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 && 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.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(); 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 ) { setTimeout( function() { me.undoManger.save(); }, 0 ); } } } ) }; })(); ///import core ///import commands/inserthtml.js ///import plugins/undo/undo.js ///import plugins/serialize/serialize.js ///commands 粘贴 ///commandsName PastePlain ///commandsTitle 纯文本粘贴模式 /* ** @description 粘贴 * @author zhanyi */ (function() { var domUtils = baidu.editor.dom.domUtils, browser = baidu.editor.browser; 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 ); } baidu.editor.plugins['paste'] = function() { var me = this; var word_img_flag = {flag:""}; var pasteplain = me.options.pasteplain; 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.innerHMTL = '


'; 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); } } 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); } } 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 ? 'keydown' : 'paste',function(e){ if(browser.ie && (!e.ctrlKey || e.keyCode != '86')) return; getClipboardData.call( me, function( div ) { filter(div); function hideMsg(){ me.ui.hideToolbarMsg(); me.removeListener("selectionchange",hideMsg); } if ( modify_num.flag && me.ui){ me.ui.showToolbarMsg( me.options.messages.pasteMsg, word_img_flag.flag ); modify_num.flag = ""; //trance:为了解决fireevent (selectionchange)事件的延时 setTimeout(function(){ me.addListener("selectionchange",hideMsg); },100); } if ( word_img_flag.flag && !me.queryCommandState("pasteplain") && me.ui){ me.ui.showToolbarMsg( me.options.messages.pasteWordImgMsg,true); word_img_flag.flag = ''; //trance:为了解决fireevent (selectionchange)事件的延时 setTimeout(function(){ me.addListener("selectionchange",hideMsg); },100); } } ); }) }); } })(); ///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 */ (function() { var domUtils = baidu.editor.dom.domUtils, dtd = baidu.editor.dom.dtd, notExchange = { 'TD':1, 'PRE':1, 'BLOCKQUOTE':1 }; 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); } } baidu.editor.plugins['list'] = function(){ var me = this; 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 = domUtils.isBlockElm(li.firstChild) ? li.firstChild : li; 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; } // if (domUtils.isEmptyNode(first)) { // var list = li.parentNode; // if (li.nextSibling) { // list = li.parentNode; // domUtils.breakParent(li, list); // list = li.previousSibling; // } // var p = me.document.createElement('p'); // p.innerHTML = browser.ie ? '' : '
'; // domUtils.remove(li); // list.parentNode.insertBefore(p, list.nextSibling); // range.setStart(p, 0).setCursor(); // // } else { 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)) { 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(); var 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); } else { var start = domUtils.findParentByTagName(range.startContainer, 'p', true); if(start && start !== first){ return; } span = me.document.createElement('span'); range.insertNode(span); // if (domUtils.isBlockElm(pre.firstChild)) { // // pre.firstChild.appendChild(span); // while (first.firstChild) { // pre.firstChild.appendChild(first.firstChild); // } // // } else { // while (first.firstChild) { // pre.appendChild(first.firstChild); // } // } 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; if (!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 ) { if(this.highlight){ return -1; } var startNode = this.selection.getStart(); return domUtils.findParentByTagName( startNode, command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul', true ) ? 1 : 0; }, queryCommandValue : function( command ) { var startNode = this.selection.getStart(), node = domUtils.findParentByTagName( startNode, command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul', true ); return node ? domUtils.getComputedStyle( node, 'list-style-type' ) : null; } } } })(); ///import core ///import plugins/serialize/serialize.js ///import plugins/undo/undo.js ///commands 查看源码 ///commandsName Source ///commandsTitle 查看源码 (function (){ var browser = baidu.editor.browser, domUtils = baidu.editor.dom.domUtils, dtd = baidu.editor.dom.dtd; 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 ) : ''; }; }(); 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 = baidu.editor.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 (!dtd.$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 (!dtd.$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, ' '); } 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 (baidu.editor.browser.ie && baidu.editor.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 (baidu.editor.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; } }; } }; baidu.editor.plugins['source'] = function (){ var me = this,utils = baidu.editor.utils; me.initPlugins(['serialize']); var opt = this.options; var formatter = new SourceFormater(opt.source); var sourceMode = false; var sourceEditor; function createSourceEditor(holder){ var useCodeMirror = opt.sourceEditor == 'codemirror' && window.CodeMirror; return sourceEditors[useCodeMirror ? '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; me.setContent(sourceEditor.getContent().replace(new RegExp(formatter.breakChar + '?(' + formatter.indentChar + '){0,}<','g'),'<') || '

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

'); 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 || baidu.editor.dom.dtd.$empty[first.tagName]){ range.setStartBefore(first) }else{ range.setStart(first,0); } if(baidu.editor.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); baidu.editor.dom.domUtils.remove(input) }) }) }else{ range.setCursor(false,true); } }) } this.fireEvent('sourcemodechanged', sourceMode); }, queryCommandState: function (){ return sourceMode|0; } }; 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) } }; me.addListener("ready",function(){ if(opt.sourceEditor == "codemirror"){ utils.loadFile(document,{ src : opt.UEDITOR_HOME_URL+"third-party/codemirror2.15/codemirror.js", tag : "script", type : "text/javascript", defer : "defer" }); utils.loadFile(document,{ tag : "link", rel : "stylesheet", type : "text/css", href : opt.UEDITOR_HOME_URL+"third-party/codemirror2.15/codemirror.css" }); } }); }; })(); ///import core ///commands 快捷键 ///commandsName ShortCutKeys ///commandsTitle 快捷键 //配置快捷键 baidu.editor.plugins['shortcutkeys'] = function(){ var editor = this, shortcutkeys = baidu.editor.utils.extend({ "ctrl+66" : "Bold" //^B ,"ctrl+90" : "Undo" //undo ,"ctrl+89" : "Redo" //redo ,"ctrl+73" : "Italic" //^I ,"ctrl+85" : "Underline:Underline" //^U ,"ctrl+shift+67" : "removeformat" //清除格式 ,"ctrl+shift+76" : "justify:left" //居左 ,"ctrl+shift+82" : "justify:right" //居右 ,"ctrl+65" : "selectAll" // ,"9" : "indent" //tab },editor.options.shortcutkeys); editor.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) : 0) && (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1) && keyCode == RegExp.$3 ) || keyCode == RegExp.$1 ){ value = shortcutkeys[i].split(':'); editor.execCommand( value[0],value[1]); e.preventDefault ? e.preventDefault() : (e.returnValue = false); } } } }); }; ///import core ///import plugins/undo/undo.js ///commands 设置回车标签p或br ///commandsName EnterKey ///commandsTitle 设置回车标签p或br /** * @description 处理回车 * @author zhanyi */ (function() { var browser = baidu.editor.browser, domUtils = baidu.editor.dom.domUtils, hTag; baidu.editor.plugins['enterkey'] = function() { var 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() } } } range = me.selection.getRange(); setTimeout(function() { range.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); if (!start) { 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 (baidu.editor.dom.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(); } } } }); } })(); /* * 处理特殊键的兼容性问题 */ (function() { var domUtils = baidu.editor.dom.domUtils, browser = baidu.editor.browser, dtd = baidu.editor.dom.dtd, utils = baidu.editor.utils, 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'] }; baidu.editor.plugins['keystrokes'] = function() { var me = this; me.addListener('keydown', function(type, evt) { var keyCode = evt.keyCode || evt.which; //处理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); } 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; } if (browser.webkit && range.collapsed && start) { tmpRange = range.cloneRange().txtToElmBoundary(); start = tmpRange.startContainer; if (domUtils.isBlockElm(start) && start.nodeType == 1 && !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 = ''; i < me.options.tabSize; i++) { txt += me.options.tabNode; } var span = me.document.createElement('span'); span.innerHTML = txt; if (range.collapsed) { 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 baidu.editor.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 可以改大小 baidu.editor.plugins['fiximgclick'] = function() { var me = this, browser = baidu.editor.browser; if ( browser.webkit ) { me.addListener( 'click', function( type, e ) { if ( e.target.tagName == 'IMG' ) { var range = new baidu.editor.dom.Range( me.document ); range.selectNode( e.target ).select(); } } ) } }; ///import core ///commands 为非ie浏览器自动添加a标签 ///commandsName AutoLink ///commandsTitle 自动增加链接 /** * @description 为非ie浏览器自动添加a标签 * @author zhanyi */ (function() { var editor = baidu.editor, browser = editor.browser, domUtils = editor.dom.domUtils; baidu.editor.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(/^(\s*)(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) { var a = me.document.createElement('a'),text = me.document.createTextNode(' '),href; //去掉开头的空格 if (RegExp.$1.length) { range.setStart(range.startContainer, range.startOffset + RegExp.$1.length); } a.appendChild(range.extractContents()); a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g,''); href = a.getAttribute("href").replace(new RegExp(domUtils.fillChar,'g'),''); a.href = /^(?:https?:\/\/)/ig.test(href) ? href : "http://"+href; range.insertNode(a); a.parentNode.insertBefore(text, a.nextSibling); range.setStart(text, 0); range.collapse(true); sel.removeAllRanges(); sel.addRange(range) } } }) } })(); ///import core ///commands 当输入内容超过编辑器高度时,编辑器自动增高 ///commandsName AutoHeight ///commandsTitle 自动增高 /** * @description 自动伸展 * @author zhanyi */ (function() { var domUtils = baidu.editor.dom.domUtils; baidu.editor.plugins['autoheight'] = function() { var me = this; //提供开关,就算加载也可以关闭 me.autoHeightEnabled = me.options.autoHeightEnabled; if(!me.autoHeightEnabled)return; var timer; var bakScroll; var bakOverflow, div,tmpNode; me.enableAutoHeight = function (){ var iframe = me.iframe, doc = me.document; me.autoHeightEnabled = true; bakScroll = iframe.scrolling; iframe.scrolling = 'no'; bakOverflow = doc.body.style.overflowY; doc.body.style.overflowY = 'hidden'; var lastHeight = 0,currentHeight; timer = setInterval(function(){ if (me.queryCommandState('source') != 1) { if(!div){ div = me.document.createElement('div'); div.style.cssText = 'height:0;overflow:hidden;margin:0;padding:0;border:0;clear:both;'; div.innerHTML ='.'; } tmpNode = div.cloneNode(true); me.body.appendChild(tmpNode); currentHeight = Math.max(domUtils.getXY(tmpNode).y + tmpNode.offsetHeight,me.options.minFrameHeight); if(!baidu.editor.browser.gecko || currentHeight - lastHeight != tmpNode.offsetHeight){ me.setHeight(currentHeight); lastHeight = currentHeight; } domUtils.remove(tmpNode) } },50); me.addListener('destroy',function(){ clearInterval(timer) }); me.fireEvent('autoheightchanged', me.autoHeightEnabled); }; me.disableAutoHeight = function (){ var iframe = me.iframe, doc = me.document; iframe.scrolling = bakScroll; doc.body.style.overflowY = bakOverflow; clearInterval(timer); me.autoHeightEnabled = false; me.fireEvent('autoheightchanged', me.autoHeightEnabled); }; me.addListener( 'ready', function() { me.enableAutoHeight(); }); } })(); ///import core ///commands 悬浮工具栏 ///commandsName AutoFloat ///commandsTitle 悬浮工具栏 /* * modified by chengchao01 * * 注意: 引入此功能后,在IE6下会将body的背景图片覆盖掉! */ (function(){ var browser = baidu.editor.browser, domUtils = baidu.editor.dom.domUtils, uiUtils, utils = baidu.editor.utils, LteIE6 = browser.ie && browser.version <= 6; baidu.editor.plugins['autofloat'] = function() { var optsAutoFloatEnabled = this.options.autoFloatEnabled; //如果不固定toolbar的位置,则直接退出 if(!optsAutoFloatEnabled){ return; } var editor = this, floating = false, MIN_HEIGHT = 0, bakCssText, placeHolder = document.createElement('div'); function setFloating(delta){ var toolbarBox = editor.ui.getDom('toolbarbox'), toobarBoxPos = domUtils.getXY(toolbarBox), origalFloat = window.getComputedStyle? document.defaultView.getComputedStyle(toolbarBox, null).position : toolbarBox.currentStyle.position, origalLeft = window.getComputedStyle? document.defaultView.getComputedStyle(toolbarBox, null).left : toolbarBox.currentStyle.left; placeHolder.style.height = toolbarBox.offsetHeight + 'px'; bakCssText = toolbarBox.style.cssText; if (browser.ie7Compat) { var left = (toolbarBox.getBoundingClientRect().left - document.documentElement.getBoundingClientRect().left) + 'px'; } toolbarBox.style.width = toolbarBox.offsetWidth + 'px'; toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox); if (LteIE6) { toolbarBox.style.position = 'absolute'; toolbarBox.style.setExpression('top', 'eval("((document.documentElement||document.body).scrollTop-'+ delta +')+\'px\'")'); toolbarBox.style.zIndex = '1'; } else { toolbarBox.style.position = 'fixed'; toolbarBox.style.zIndex = '1'; toolbarBox.style.top = '0'; if (browser.ie7Compat) { toolbarBox.style.left = left; } ((origalFloat == 'absolute' || origalFloat == 'relative') && parseFloat(origalLeft)) && (toolbarBox.style.left = toobarBoxPos.x + 'px'); } floating = true; } function unsetFloating(){ var toolbarBox = editor.ui.getDom('toolbarbox'); placeHolder.parentNode.removeChild(placeHolder); if (LteIE6) { toolbarBox.style.removeExpression('top'); } toolbarBox.style.cssText = bakCssText; floating = false; } var updateFloating = utils.defer(function(){ var rect = uiUtils.getClientRect( editor.ui.getDom('toolbarbox')); var rect2 = uiUtils.getClientRect( editor.ui.getDom('iframeholder')); if (!floating) { if (rect.top < 0 && rect2.bottom > rect.height + MIN_HEIGHT) { var delta = (document.documentElement.scrollTop || document.body.scrollTop) + rect.top; setFloating(delta); } } else { var rect1 = uiUtils.getClientRect(placeHolder); if (rect.top < rect1.top || rect.bottom + MIN_HEIGHT > rect2.bottom) { unsetFloating(); } } },100,true); editor.addListener('destroy',function(){ domUtils.un(window, ['scroll','resize'], updateFloating); editor.removeListener('keydown', updateFloating); }); editor.addListener('ready', function(){ if(checkHasUI()){ if(LteIE6){ fixIE6FixedPos(); } editor.addListener('autoheightchanged', function (t, enabled){ if (enabled) { domUtils.on(window, ['scroll','resize'], updateFloating); editor.addListener('keydown', updateFloating); } else { domUtils.un(window, ['scroll','resize'], updateFloating); editor.removeListener('keydown', updateFloating); } }); editor.addListener('beforefullscreenchange', function (t, enabled){ if (enabled) { if (floating) { unsetFloating(); } } }); editor.addListener('fullscreenchanged', function (t, enabled){ if (!enabled) { updateFloating(); } }); editor.addListener('sourcemodechanged', function (t, enabled){ setTimeout(function (){ updateFloating(); }); }); } }) }; function checkHasUI(){ try{ uiUtils = baidu.editor.ui.uiUtils; }catch( ex ){ alert('autofloat插件功能依赖于UEditor UI\nautofloat定义位置: _src/plugins/autofloat/autofloat.js'); throw({ name: '未包含UI文件', message: 'autofloat功能依赖于UEditor UI。autofloat定义位置: _src/plugins/autofloat/autofloat.js' }); } return 1; } function fixIE6FixedPos(){ var docStyle = document.body.style; docStyle.backgroundImage = 'url("about:blank")'; docStyle.backgroundAttachment = 'fixed'; } })(); ///import core ///import commands/inserthtml.js ///commands 插入代码 ///commandsName HighlightCode ///commandsTitle 插入代码 ///commandsDialog dialogs\code\code.html baidu.editor.plugins['highlight'] = function() { var me = this,domUtils = baidu.editor.dom.domUtils,utils = baidu.editor.utils,browser = baidu.editor.browser; 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)); 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 = baidu.editor.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',function(){ me.highlight = me.queryCommandState('highlightcode') == 1 ? 1 : 0; }); me.addListener('afterselectionchange',function(){ me.highlight = 0; }); me.addListener("ready",function(){ //避免重复加载高亮文件 if(typeof XRegExp == "undefined"){ var obj = { id : "syntaxhighlighter_js", src : me.options.highlightJsUrl, tag : "script", type : "text/javascript", defer : "defer" }; utils.loadFile(document,obj,function(){ changePre(); }); } if(!me.document.getElementById("syntaxhighlighter_css")){ var obj = { id : "syntaxhighlighter_css", tag : "link", rel : "stylesheet", type : "text/css", href : me.options.highlightCssUrl }; utils.loadFile(me.document,obj); } }); me.addListener("beforegetcontent",function(type,cmd){ 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",function(type,cmd){ changePre(); }); function adjustHeight(){ 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]; 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("aftersetcontent",function(){ changePre(); }) }; ///import core ///commands 定制过滤规则 ///commandsName Serialize ///commandsTitle 定制过滤规则 baidu.editor.plugins['serialize'] = function () { var dtd = baidu.editor.dom.dtd, utils = baidu.editor.utils, domUtils = baidu.editor.dom.domUtils, browser = baidu.editor.browser, ie = browser.ie, version = browser.version; var me = this, EMPTY_TAG = baidu.editor.dom.dtd.$empty, parseHTML = function () { var RE_PART = /<(?:(?:\/([^>]+)>[ \t\r\n]*)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>[ \t\r\n]*))/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 ( tagEnd( currentNode ) ) continue; currentNode = currentNode.parent; } // TODO: 注意这里会去掉空白节点 if ( /[^ \t\r\n]/.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.parent.children.pop(); } currentNode = node.parent; } else { // 如果没有找到开始标签, 则创建新标签 // eg. =>
if ( !(dtd.$removeEmpty[tag] || dtd.$removeEmptyBlock[tag]) ) { 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 if ( /pt/.test(value) ) { value = value.replace( /([\d.]+)pt/g, function( str ) { return Math.round(parseInt(str, 10) * 96 / 72) + "px"; } ) } //color rgb ==> hex if(/rgba?\s*\([^)]*\)/.test(value)){ value = value.replace( /rgba?\s*\(([^)]*)\)/g, function( str ) { return utils.fixColor('color',str); } ) } attrs[k] = value.replace(/windowtext/g,'#000'); } buff.push( k + '="' + unhtml1( attrs[k] ) + '"' ); } return buff.join( ' ' ).replace(/\;+/g,';') } 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 ) { 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 //p标签在ie下为空,将不占位这里占位符不起作用,用  if(browser.ie && tag == 'p' && !node.children.length){ html += ' '; } 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 str = str.replace( /^(\r\n|\n|\r)|(\r\n|\n|\r)$/ig, "" ); //remove   entities at the start of contents str = str.replace( /^\s*( )+/ig, "" ); //remove   entities at the end of contents str = str.replace( /( |]*>)+\s*$/ig, "" ); // Word comments like conditional comments etc str = str.replace( //ig, "" ); //转换img str = str.replace( /v:imagedata/g, 'img' ).replace( /<\/img>/g, '' ); //去掉多余的属性 str = str.replace( /v:\w+=["']?[^'"]+["']?/g, '' ); // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, MS Office namespaced tags, and a few other tags str = str.replace( /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi, "" ); //convert word headers to strong str = str.replace( /

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

$1

" ); //remove lang attribute str = str.replace( /(lang)\s*=\s*([\'\"]?)[\w-]+\2/ig, "" ); //清除多余的font不能匹配 有可能是空格 str = str.replace( /]*>\s*<\/font>/gi, '' ); //清除多余的class str = str.replace( /class\s*=\s*["']?(?:(?:MsoTableGrid)|(?:MsoNormal(Table)?))\s*["']?/gi, '' ); // Examine all styles: delete junk, transform some, and keep the rest //修复了原有的问题, 比如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": case "mso-table-layout-alt": case "mso-height": case "mso-width": case "mso-vertical-align-alt": n[i++] = name.replace( /^mso-|-alt$/g, "" ) + ":" + ensureUnits( value ); continue; case "horiz-align": n[i++] = "text-align:" + value; continue; case "vert-align": n[i++] = "vertical-align:" + value; continue; case "font-color": case "mso-foreground": n[i++] = "color:" + value; continue; case "mso-background": case "mso-highlight": n[i++] = "background:" + value; continue; case "mso-default-height": n[i++] = "min-height:" + ensureUnits( value ); continue; case "mso-default-width": n[i++] = "min-width:" + ensureUnits( value ); continue; case "mso-padding-between-alt": n[i++] = "border-collapse:separate;border-spacing:" + ensureUnits( value ); continue; case "text-line-through": if ( (value == "single") || (value == "double") ) { n[i++] = "text-decoration:line-through"; } continue; //word里边的字体统一干掉 case 'font-family': case 'border-width': case 'border-style': continue; //word进来的默认都是1px solid #000 // case 'border-color': // case 'border': // n[i++] = 'border:1px solid #000'; // continue; case "mso-zero-height": if ( value == "yes" ) { n[i++] = "display:none"; } continue; case 'margin': if ( !/[1-9]/.test( parts[1] ) ) { continue; } } if ( /^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?:decor|trans)|top-bar|version|vnd|word-break)/.test( name ) ) { if ( !/mso\-list/.test( name ) ) continue; } //pt 转换成为px // if ( /pt$/.test( parts[1] ) ) { // parts[1] = parts[1].replace( /([\d.]+)pt/g, function( str ) { // return Math.round(parseInt(str, 10) * 96 / 72) + "px"; // } ) // // } n[i] = name + ":" + parts[1]; // Lower-case name, but keep value case } } // If style attribute contained any valid styles the re-write it; otherwise delete style attribute. if ( i > 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 ) { //dtd.$removeEmptyBlock[node.tag] if ( node.type == 'element' && !node.children.length && (dtd.$removeEmpty[node.tag]) && node.tag != 'a' ) {// 锚点保留 return { type : 'fragment', children:[] } } var sizeMap = [0, 10, 12, 16, 18, 24, 32, 48], attr, indexOf = utils.indexOf; switch ( node.tag ) { 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/localimage.jpg'; node.attributes.style = 'width:395px;height:173px;'; word_img_flag && (word_img_flag.flag = 1); } if(browser.ie && browser.version < 7 && me.options.relativePath) 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] ) { node.children = [ { type: 'element', tag: 'p', attributes: {}, children: child ? node.children : [ { type : 'element', tag : 'br', attributes:{}, closed: true, children: [] } ], parent : node } ]; } 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 ) { //trace:1493 //ff3.6出来的是background: none repeat scroll %0 %0 颜色 style = style.match( /(?:\b(?:color|font-size|background(-color)?|font-family|text-decoration)\b\s*:\s*(&[^;]+;|[^;])+(?=;)?)/gi ); if ( style ) { node.attributes.style = style.join( ';' ); if ( !node.attributes.style ) { 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 ) ) { 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,';'); // var border = node.attributes.style.match( /border[^:]*:([^;]*)/i ); // if ( border ) { // border = border[1]; // if ( border ) { // node.attributes.style = node.attributes.style.replace( /border[^;]*?(;|$)/ig, '' ).replace( /^\s*|\s*$/, '' ); // //// if ( !/^\s*#\w+\s*$/.test( border ) ) { //// node.attributes.style = (/;$/.test( node.attributes.style ) || node.attributes.style.length == 0 ? '' : ';') + 'border:' + border; //// } // // } // } node.attributes.style = node.attributes.style.replace( /^\s*|\s*$/, '' ) } } function transOutNode( node ) { if ( node.type == 'text' ) { //trace:1269 先注释了,引起ie预览会折行的问题 //node.data = node.data.replace(/ /g,' ') } switch ( node.tag ) { case 'table': !node.attributes.style && delete node.attributes.style; if ( ie && node.attributes.style ) { optStyle( node ); } 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 ); } 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 ( node.type == 'text' && node.data.replace( /\s/g, '' ) == me.options.pageBreakTag ) { node.type = 'element'; node.name = node.tag = 'div'; delete node.data; node.attributes = { 'class' : 'pagebreak', '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 == 'div' && 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 ); baidu.editor.serialize = new Serialize( {} ); }; ///import core ///import commands/inserthtml.js ///commands 视频 ///commandsName InsertVideo ///commandsTitle 插入视频 ///commandsDialog dialogs\video\video.html (function (){ baidu.editor.plugins['video'] = function (){ var me = this; var fakedMap = {}; var fakedPairs = []; var lastFakedId = 0; function fake(url, width, height,style){ var fakedId = 'edui_faked_video_' + (lastFakedId ++); var fakedHtml = ''; fakedMap[fakedId] = ''; return fakedHtml; } me.commands['insertvideo'] = { execCommand: function (cmd, options){ var url = options.url; var width = options.width || 320; var height = options.height || 240; var style = options.style ? options.style : ""; me.execCommand('inserthtml', fake(url, width, height,style)); }, queryCommandState : function(){ return this.highlight ? -1 :0; } }; //获得style里的某个样式对应的值 function getPars(str,par){ var reg = new RegExp(par+":\\s*((\\w)*)","ig"); var arr = reg.exec(str); return arr ? arr[1] : ""; } me.addListener('beforegetcontent', function (){ var tempDiv = me.document.createElement('div'); var newFakedMap = {}; for (var fakedId in fakedMap) { var fakedImg; while ((fakedImg = me.document.getElementById(fakedId))) { tempDiv.innerHTML = fakedMap[fakedId]; var temp = tempDiv.firstChild; temp.width = fakedImg.width; temp.height = fakedImg.height; var strcss = fakedImg.style.cssText; if(/float/ig.test(strcss)){ if(!!window.ActiveXObject){ temp.style.styleFloat = getPars(strcss,"float"); }else{ temp.style.cssFloat = getPars(strcss,"float"); } }else if(/display/ig.test(strcss)){ temp.style.display = getPars(strcss,"display"); } fakedImg.parentNode.replaceChild(temp, fakedImg); fakedPairs.push([fakedImg, temp]); newFakedMap[fakedId] = fakedMap[fakedId]; } } fakedMap = newFakedMap; }); me.addListener('aftersetcontent', function (){ var tempDiv = me.document.createElement('div'); fakedMap = {}; var embedNodeList = me.document.getElementsByTagName('embed'); var embeds = []; var k = embedNodeList.length; while (k --) { embeds[k] = embedNodeList[k]; } k = embeds.length; while (k --) { var url = embeds[k].getAttribute('src'); var width = embeds[k].width || 320; var height = embeds[k].height || 240; var strcss = embeds[k].style.cssText; var style = getPars(strcss,"display") ? "display:"+getPars(strcss,"display") : "float:"+getPars(strcss,"float"); tempDiv.innerHTML = fake(url, width, height,style); embeds[k].parentNode.replaceChild(tempDiv.firstChild, embeds[k]); } }); me.addListener('aftergetcontent', function (){ for (var i=0; i 0 ? -1 : 0; }, execCommand: function (cmdName, tableobj) { tableOpt = tableobj; var arr = []; arr.push('cellpadding="' + (tableobj.cellpadding || 0) + '"'); if(tableobj.cellspacing > 0){ arr.push('cellspacing="'+tableobj.cellspacing+'" style="border-collapse:separate;"') }else{ arr.push('cellspacing="' + (tableobj.cellspacing || 0) + '"'); } tableobj.width ? arr.push('width="' + tableobj.width + '"') : arr.push('width="500"'); arr.push('borderColor="' + (tableobj.bordercolor || '#000000') + '"'); arr.push('border="' + (tableobj.border || 1) + '"'); var html,rows = [],j = tableobj.numRows; if (j) while (j --) { var cols = []; var k = tableobj.numCols; while (k --) { var cssStyle = 'style="'; if(tableobj.cellpadding){ cssStyle += 'padding:'+ tableobj.cellpadding + 'px; ' } if(tableobj.border || tableobj.bordercolor){ cssStyle += 'border:' + (tableobj.border||1) +'px solid '+ (tableobj.bordercolor||'#000000') + ';'; } cssStyle += '" '; cols[k] = '
'; } rows.push('' + cols.join('') + ''); } html = '
' + //trace: IE6下占位符 (browser.ie ? domUtils.fillChar : '
') + '
' + rows.join('') + '
'; html += tableobj.tablealign ? "

" : ""; this.execCommand('insertHtml', html); reset(); } }; function insertClearNode(node) { var clearnode = node.nextSibling,p; if (!(clearnode && clearnode.nodeType == 1 && domUtils.hasClass(clearnode, "tableclear"))) { p = me.document.createElement("p"); p.className = "tableclear"; domUtils.insertAfter(node, p); } } me.commands['edittable'] = { queryCommandState: function () { var range = this.selection.getRange(); if(this.highlight || this.queryCommandState('highlightcode')){ return -1; } return domUtils.findParentByTagName(range.startContainer, 'table', true) || me.currentSelectedArr.length > 0 ? 0 : -1; }, execCommand: function (cmdName, tableobj) { var start = this.selection.getStart(); var table = domUtils.findParentByTagName(start, 'table', true); if (table) { var tmp = table.getAttribute("cellPadding"); if(tmp != tableobj.cellpadding){ table.setAttribute("cellPadding", tableobj.cellpadding||0); var tds = table.getElementsByTagName("td"); for(var i=0,ci;ci=tds[i++];){ ci.style.padding = (tableobj.cellpadding||0) + "px"; } } tmp = table.getAttribute("cellSpacing"); if(tmp != tableobj.cellspacing){ tableobj.cellspacing == 0 ? table.style.borderCollapse = "collapse": table.style.borderCollapse = "separate"; table.setAttribute("cellSpacing", tableobj.cellspacing||0); }else{ tableobj.cellspacing ==0 ? table.style.borderCollapse = "collapse":""; } table.setAttribute("width", tableobj.width||0); table.setAttribute("height", tableobj.height||0); table.setAttribute("border", tableobj.border||0); table.style.border = (tableobj.border||0)+"px solid #ffffff"; table.setAttribute("borderColor", tableobj.bordercolor); table.style.borderColor = tableobj.bordercolor; var tdss = table.getElementsByTagName("td"); for(var ii=0,tii;tii = tdss[ii++];){ tii.style.border = (tableobj.border||0)+"px solid #ffffff"; tii.style.borderColor = tableobj.bordercolor; } table.setAttribute("align", tableobj.tablealign); //fixed 1368 table.setAttribute("bgColor", tableobj.backgroundcolor); if(me.currentSelectedArr.length > 0){ for(var t=0,ti;ti=me.currentSelectedArr[t++];){ domUtils.setStyle(ti,'text-align',tableobj.align); } }else{ var td = domUtils.findParentByTagName(start,'td',true); if(td){ domUtils.setStyle(td,'text-align',tableobj.align); } } if (tableobj.tablealign) { insertClearNode(table); } } } }; /** * 删除表格 */ me.commands['deletetable'] = { queryCommandState:function() { if(this.highlight || this.queryCommandState('highlightcode')){ 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); var p = table.ownerDocument.createElement('p'),clearnode; p.innerHTML = browser.ie ? ' ' : '
'; table.parentNode.insertBefore(p, table); clearnode = domUtils.getNextDomNode(table); if (clearnode && domUtils.hasClass(clearnode, "tableclear")) { domUtils.remove(clearnode); } domUtils.remove(table); range.setStart(p, 0).setCursor(); reset(); } }; /** * 添加表格标题 */ me.commands['addcaption'] = { queryCommandState:function() { if(this.highlight || this.queryCommandState('highlightcode')){ 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(cmdName, opt) { var range = this.selection.getRange(), table = domUtils.findParentByTagName(me.currentSelectedArr.length > 0 ? me.currentSelectedArr[0] : range.startContainer, 'table', true); if (opt == "on") { var c = table.createCaption(); c.innerHTML = "请在此输入表格标题"; } else { table.removeChild(table.caption); } } }; /** * 向右合并单元格 */ me.commands['mergeright'] = { queryCommandState : function() { if(this.highlight || this.queryCommandState('highlightcode')){ 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 || this.queryCommandState('highlightcode')){ 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 || this.queryCommandState('highlightcode')){ 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; }, 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) { var p = table.ownerDocument.createElement('p'); p.innerHTML = browser.ie ? ' ' : '
'; table.parentNode.insertBefore(p, table); domUtils.remove(table); range.setStart(p, 0).setCursor(); 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 || this.queryCommandState('highlightcode')){ 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; }, 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) { var p = table.ownerDocument.createElement('p'); p.innerHTML = browser.ie ? ' ' : '
'; table.parentNode.insertBefore(p, table); domUtils.remove(table); range.setStart(p, 0).setCursor(); 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 || this.queryCommandState('highlightcode')){ 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 || this.queryCommandState('highlightcode')){ 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 || this.queryCommandState('highlightcode')){ 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 || this.queryCommandState('highlightcode')){ 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 || this.queryCommandState('highlightcode')){ 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); 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); 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 || this.queryCommandState('highlightcode')){ 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); 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); 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 || this.queryCommandState('highlightcode')){ 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) { if (anchorTd && tmpTd.tagName == "TD") { 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 = me.options.selectedTdClass; 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); } } } } } me.adjustTable = function(cont) { var table = cont.getElementsByTagName('table'); for (var i = 0,ti; ti = table[i++];) { if (ti.getAttribute('align')) { insertClearNode(ti) } if (!ti.getAttribute('border')) { ti.setAttribute('border', 1); } if (domUtils.getComputedStyle(ti, 'border-color') == '#ffffff') { ti.setAttribute('borderColor', '#000000'); } 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) } } } } } } } }; })(); ///import core ///commands 右键菜单 ///commandsName ContextMenu ///commandsTitle 右键菜单 /** * 右键菜单 * @function * @name baidu.editor.plugins.contextmenu * @author zhanyi */ (function () { baidu.editor.plugins['contextmenu'] = function () { var me = this, menu, items = me.options.contextMenu; if(!items || items.length==0) return; var editor = baidu.editor, domUtils = editor.dom.domUtils, browser = editor.browser; var uiUtils = baidu.editor.ui.uiUtils; me.addListener('contextmenu',function(type,evt){ var offset = uiUtils.getViewportOffsetByEvent(evt); 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.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.queryCommandState(subItem.cmdName) != -1) { subMenu.push({ 'label':subItem.label, 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({ 'label' : item.group, className: 'edui-for-' + item.icon, 'subMenu' : { items: subMenu, editor:me } }) } } else { if (me.queryCommandState(item.cmdName) != -1) { //highlight todo if(item.cmdName == 'highlightcode' && me.queryCommandState(item.cmdName) == 0) return; contextItems.push({ 'label':item.label, 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 baidu.editor.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 editor.dom.Range(me.document); range.selectNode(ieRange.item(0)).select(true,true); } } }) }; })(); ///import core ///commands 添加分页功能 ///commandsName PageBreak ///commandsTitle 分页 /** * @description 添加分页功能 * @author zhanyi */ (function() { var editor = baidu.editor, domUtils = editor.dom.domUtils, notBreakTags = ['td']; baidu.editor.plugins['pagebreak'] = function() { var me = this; //重写了Editor.hasContents var hasContentsOrg = me.hasContents; me.hasContents = function(tags){ for(var i=0,di,divs = me.document.getElementsByTagName('div');di=divs[i++];){ if(domUtils.hasClass(di,'pagebreak')){ return true; } } return hasContentsOrg.call(me,tags); }; me.commands['pagebreak'] = { execCommand:function(){ var range = me.selection.getRange(); var div = me.document.createElement('div'); div.className = 'pagebreak'; domUtils.unselectable(div); //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'); table.parentNode.insertBefore(div,table); parents = domUtils.findParents(div,true); }else{ pN.parentNode.insertBefore(div,pN); parents = domUtils.findParents(div); } pN = parents[1]; if(div!==pN){ domUtils.breakParent(div,pN); } domUtils.clearSelectedArr(me.currentSelectedArr); } }else{ if(!range.collapsed){ range.deleteContents(); var start = range.startContainer; while(domUtils.isBlockElm(start) && domUtils.isEmptyNode(start)){ range.setStartBefore(start).collapse(true); domUtils.remove(start); start = range.startContainer; } } parents = domUtils.findParents(range.startContainer,true); pN = parents[1]; range.insertNode(div); pN && domUtils.breakParent(div,pN); range.setEndAfter(div).setCursor(true,true) } }, queryCommandState : function(){ return this.highlight ? -1 :0; } } } })(); ///import core ///commands 加粗,斜体,上标,下标 ///commandsName Bold,Italic,Subscript,Superscript ///commandsTitle 加粗,加斜,下标,上标 /** * b u i等基础功能实现 * @function * @name baidu.editor.execCommands * @param {String} cmdName bold加粗。italic斜体。subscript上标。superscript下标。 */ baidu.editor.plugins['basestyle'] = function(){ var basestyles = { 'bold':['strong','b'], 'italic':['em','i'], //'underline':['u'], //'strikethrough':['strike'], 'subscript':['sub'], 'superscript':['sup'] }, domUtils = baidu.editor.dom.domUtils, getObj = function(editor,tagNames){ var start = editor.selection.getStart(); return domUtils.findParentByTagName( start, tagNames, true ) }, flag = 0, me = this; for ( var style in basestyles ) { (function( cmd, tagNames ) { me.commands[cmd] = { execCommand : function( cmdName ) { var range = new baidu.editor.dom.Range(this.document),obj = '',me = this; //执行了上述代码可能产生冗余的html代码,所以要注册 beforecontent去掉这些冗余的代码 if(!flag){ this.addListener('beforegetcontent',function(){ domUtils.clearReduent(me.document,['strong','u','em','sup','sub','strike']) }); flag = 1; } //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 ///commandsTitle 选区路径 /** * 选区路径 * @function * @name baidu.editor.execCommand * @param {String} cmdName elementpath选区路径 */ baidu.editor.plugins['elementpath'] = function(){ var domUtils = baidu.editor.dom.domUtils, currentLevel, tagNames, dtd = baidu.editor.dom.dtd, me = this; me.commands['elementpath'] = { execCommand : function( cmdName, level ) { var me = this, 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() { var start = this.selection.getStart(), parents = domUtils.findParents(start, true), 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 commands\removeformat.js ///commands 格式刷 ///commandsName FormatMatch ///commandsTitle 格式刷 /** * 格式刷,只格式inline的 * @function * @name baidu.editor.execCommand * @param {String} cmdName formatmatch执行格式刷 */ baidu.editor.plugins['formatmatch'] = function(){ var me = this, domUtils = baidu.editor.dom.domUtils, list = [],img, flag = 0, browser = baidu.editor.browser; this.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 */ baidu.editor.plugins['searchreplace'] = function(){ var currentRange, first, me = this; this.addListener('reset',function(){ currentRange = null; first = null; }); me.commands['searchreplace'] = { execCommand : function(cmdName,opt){ var editor = this, sel = editor.selection, range, nativeRange, num = 0, opt = baidu.editor.utils.extend(opt,{ all : false, casesensitive : false, dir : 1 },true); if(baidu.editor.browser.ie){ while(1){ var tmpRange; nativeRange = editor.document.selection.createRange(); tmpRange = nativeRange.duplicate(); tmpRange.moveToElementText(editor.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 = editor.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 = editor.window,nativeSel = sel.getNative(),tmpRange; while(1){ if(opt.all){ if(currentRange){ currentRange.collapse(false); nativeRange = currentRange; }else{ nativeRange = editor.document.createRange(); nativeRange.setStart(editor.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 自定义样式 (function() { var domUtils = baidu.editor.dom.domUtils, dtd = baidu.editor.dom.dtd; baidu.editor.plugins['customstyle'] = function() { var me = this; 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') == obj.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) { domUtils.remove(node, true); } else { var common = domUtils.getCommonAncestor(bk.start, bk.end), nodes = domUtils.getElementsByTagName(common, tagName); 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); 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 startNode = this.selection.getStart(), parent = domUtils.findParent(startNode, function(node) { return node.getAttribute('label') }, true); return parent ? parent.getAttribute('label') : ''; }, queryCommandState : function() { return this.highlight ? -1 : 0; } }; 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) { if (baidu.editor.dom.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(); } } } } }) } })(); 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 = element.getBoundingClientRect(); 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){ var 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); callbacks.ondragstop(); } doc.addEventListener('mousemove', handleMouseMove, true); doc.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 (typeof this.content == 'string') { return this.content; } return this.content.renderHtml(); }, _UIBase_postRender: UIBase.prototype.postRender, postRender: function (){ if (this.content instanceof UIBase) { this.content.postRender(); } 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.initUIBase(); }; ColorPicker.prototype = { getHtmlTpl: function (){ return genColorPicker( this.noColorText ); }, _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){ var html = '
' + '
' + '
' + '
'+ noColorText +'
' + '
' + '' + ''+ ''; for (var i=0; i':'')+''; } html += i<70 ? '':''; } html += '
主题颜色
标准颜色
'; 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 (){ return '
' + '
' + '
' + '' + '更多' + '
' + '
' + '
' + '
' + '
' + '
'; }, _UIBase_render: UIBase.prototype.render, render: function (holder){ this._UIBase_render(holder); this.getDom('label').innerHTML = '0列 x 0行'; }, _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 + '列 x ' + numRows + '行'; 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列 x 0行'; 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列 x 0行'; 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(); }, _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: '清除颜色', 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({ 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); })(); (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; i2?[].slice.call(arguments,2):null;return function(){var e=baidu.lang.isString(b)?a[b]:b,d=(c)?c.concat([].slice.call(arguments,0)):arguments;return e.apply(a||e,d)}};baidu.lang.Class.prototype.addEventListeners=function(c,d){if(typeof d=="undefined"){for(var b in c){this.addEventListener(b,c[b])}}else{c=c.split(",");var b=0,a=c.length,e;for(;b#{content}',disabled:false,statable:true,_getString:function(){var a=this;return baidu.format(a.tplBody,{id:a.getId(),statable:a._getStateHandlerString(),"class":a.getClass(),content:a.content})},render:function(c){var b=this,a;b.addState("click","click");baidu.dom.insertHTML(b.renderMain(c),"beforeEnd",b._getString());a=baidu.g(c).lastChild;if(b.title){a.title=b.title}b.disabled&&b.setState("disabled");b.dispatchEvent("onload")},isDisabled:function(){var a=this,b=a.getId();return a.getState()["disabled"]},dispose:function(){var b=this,a=b.getBody();b.dispatchEvent("dispose");baidu.each(b._allEventsName,function(d,c){a["on"+d]=null});baidu.dom.remove(a);b.dispatchEvent("ondispose");baidu.lang.Class.prototype.dispose.call(b)},disable:function(){var b=this,a=b.getBody();b.dispatchEvent("ondisable",{element:a})},enable:function(){var a=this;body=a.getBody();a.dispatchEvent("onenable",{element:body})},fire:function(a,c){var b=this,a=a.toLowerCase();if(b.getState()["disabled"]){return}b._fireEvent(a,null,null,c)},update:function(a){var b=this;baidu.extend(b,a);a.content&&(b.getBody().innerHTML=a.content);b.dispatchEvent("onupdate")}});baidu.lang.isBoolean=function(a){return typeof a==="boolean"};baidu.ui.Button.register(function(a){if(!a.poll){return}baidu.lang.isBoolean(a.poll)&&(a.poll={});a.addEventListener("mousedown",function(b){var d=0,c=a.poll.interval||100,e=a.poll.time||0;(function(){if(a.getState()["press"]){d++>e&&a.onmousedown&&a.onmousedown();a.poll.timeOut=setTimeout(arguments.callee,c)}})()});a.addEventListener("dispose",function(){if(a.poll.timeOut){a.disable();window.clearTimeout(a.poll.timeOut)}})});baidu.date=baidu.date||{};baidu.number=baidu.number||{};baidu.number.pad=function(d,c){var e="",b=(d<0),a=String(Math.abs(d));if(a.length#{content}',tplTable:'#{head}#{body}
',tplDateCell:'#{content}',tplTitle:'
#{text}
',_initialize:function(){var a=this;function b(d){var c=[];baidu.array.each(d,function(e){c.push(baidu.lang.isDate(e)?a._toLocalDate(e):{start:a._toLocalDate(e.start),end:a._toLocalDate(e.end)})});return c}a._highlightDates=b(a.highlightDates||[]);a._disableDates=b(a.disableDates||[]);a._initDate=a._toLocalDate(a.initDate||new Date());a._currDate=new Date(a._initDate.getTime());a.weekStart=a.weekStart.toLowerCase()},_getDateJson:function(b){var f=this,a=baidu.lang.guid(),h=f._currDate,d=[],e;function g(j,i){return j.getDate()==i.getDate()&&Math.abs(j.getTime()-i.getTime())<24*60*60*1000}function c(k,i){var j=i.getTime();return baidu.array.some(k,function(l){if(baidu.lang.isDate(l)){return g(l,i)}else{return g(l.start,i)||j>l.start.getTime()&&j<=l.end.getTime()}})}b.getMonth()!=h.getMonth()&&d.push(f.getClass("date-other"));c(f._highlightDates,b)&&d.push(f.getClass("date-highlight"));if(g(f._initDate,b)){d.push(f.getClass("date-current"));f._currElementId=f.getId(a)}g(f._toLocalDate(new Date()),b)&&d.push(f.getClass("date-today"));e=c(f._disableDates,b)&&(d=[]);return{id:f.getId(a),"class":d.join("\x20"),handler:f._getStateHandlerString("",a),date:b,disabled:e}},_getMonthCount:function(c,e){var a=baidu.i18n.date.getDaysInMonth,b=[31,28,31,30,31,30,31,31,30,31,30,31],d;a&&(d=a(c,e));if(!baidu.lang.isNumber(d)){d=1==e&&(c%4)&&(c%100!=0||c%400==0)?29:b[e]}return d},_getDateTableString:function(){var o=this,f=baidu.i18n.cultures[o.language].calendar,a=["sun","mon","tue","wed","thu","fri","sat"],s=o._currDate,p=s.getFullYear(),n=s.getMonth(),q=new Date(p,n,1).getDay(),g=0,e=[],m=[],h=[],r=o._disabledIds=[],d=0,c=0,l=a.length,k,b;for(;d0?e:h).push("",f.dayNames[a[d]],"")}e=e.concat(h);e.unshift("");e.push("");q=(q");for(c=0;c")}return baidu.string.format(o.tplTable,{"class":o.getClass("table"),headClass:o.getClass("week"),bodyClass:o.getClass("date"),head:e.join(""),body:m.join("")})},getString:function(){var a=this;return baidu.string.format(a.tplDOM,{id:a.getId(),"class":a.getClass(),content:baidu.string.format(a.tplDOM,{id:a.getId("content"),"class":a.getClass("content")})})},_toLocalDate:function(a){return a?baidu.i18n.date.toLocaleDate(a,null,this.language):a},_renderDate:function(){var a=this;baidu.dom.g(a.getId("content")).innerHTML=a._getDateTableString();baidu.array.each(a._disabledIds,function(b){a.setState("disabled",b)})},_basicFlipMonth:function(e){var b=this,d=b._currDate,c=d.getMonth()+(e=="prev"?-1:1),a=d.getFullYear()+(c<0?-1:(c>11?1:0));c=c<0?12:(c>11?0:c);d.setYear(a);b.gotoMonth(c);b.dispatchEvent(e+"month",{date:new Date(d.getTime())})},renderTitle:function(){var e=this,d,c,h=e._currDate,g=baidu.i18n.cultures[e.language].calendar,f=baidu.dom.g(e.getId("label")),a=baidu.string.format(g.titleNames,{yyyy:h.getFullYear(),MM:g.monthNames[h.getMonth()],dd:h.getDate()});if(f){f.innerHTML=a;return}baidu.dom.insertHTML(e.getBody(),"afterBegin",baidu.string.format(e.tplTitle,{id:e.getId("title"),"class":e.getClass("title"),labelId:e.getId("label"),labelClass:e.getClass("label"),text:a,prevId:e.getId("prev"),prevClass:e.getClass("prev"),nextId:e.getId("next"),nextClass:e.getClass("next")}));function b(i){return{classPrefix:e.classPrefix+"-"+i+"btn",skin:e.skin?e.skin+"-"+i:"",content:e.flipContent[i],poll:{time:4},element:e.getId(i),autoRender:true,onmousedown:function(){e._basicFlipMonth(i)}}}d=new baidu.ui.Button(b("prev"));c=new baidu.ui.Button(b("next"));e.addEventListener("ondispose",function(){d.dispose();c.dispose()})},render:function(c){var a=this,b=a.skin;if(!c||a.getMain()){return}baidu.dom.insertHTML(a.renderMain(c),"beforeEnd",a.getString());a._initialize();a.renderTitle();a._renderDate();baidu.dom.g(a.getId("content")).style.height=(a.getBody().clientHeight||a.getBody().offsetHeight)-baidu.dom.g(a.getId("title")).offsetHeight+"px";a.dispatchEvent("onload")},update:function(a){var b=this;baidu.object.extend(b,a||{});b._initialize();b.renderTitle();b._renderDate();b.dispatchEvent("onupdate")},gotoDate:function(a){var b=this;b._currDate=b._toLocalDate(a);b._initDate=b._toLocalDate(a);b.renderTitle();b._renderDate();b.dispatchEvent("ongotodate")},gotoYear:function(b){var d=this,f=d._currDate,e=f.getMonth(),a=f.getDate(),c;if(1==e){c=d._getMonthCount(b,e);a>c&&f.setDate(c)}f.setFullYear(b);d.renderTitle();d._renderDate();d.dispatchEvent("ongotoyear")},gotoMonth:function(e){var c=this,d=c._currDate,e=Math.min(Math.max(e,0),11),a=d.getDate(),b=c._getMonthCount(d.getFullYear(),e);a>b&&d.setDate(b);d.setMonth(e);c.renderTitle();c._renderDate();c.dispatchEvent("ongotomonth")},getToday:function(){return me._toLocalDate(new Date())},getDate:function(){return new Date(this._initDate.getTime())},setDate:function(a){if(baidu.lang.isDate(a)){var b=this;b._initDate=a;b._currDate=a}},prevMonth:function(){this._basicFlipMonth("prev")},nextMonth:function(){this._basicFlipMonth("next")},dispose:function(){var a=this;a.dispatchEvent("dispose");baidu.dom.remove(a.getMain());baidu.lang.Class.prototype.dispose.call(a)}}); TCalendar = baidu.ui.Calendar; Tformat = baidu.date.format; })(); var DatePickerPopup = function (options){ this.initOptions(options); this.initPopup(); var me = this; this._calendar = new TCalendar({ onclickdate: function (evt){ me.fireEvent('pickdate', evt.date); } }); }; DatePickerPopup.prototype = { content: '', _Popup_postRender: Popup.prototype.postRender, postRender: function (){ this._calendar.render(this.getDom('content')); this._Popup_postRender(); } }; utils.inherits(DatePickerPopup, Popup); var DateButton = baidu.editor.ui.DateButton = function (options){ this.initOptions(options); this.initDateButton(); }; DateButton.prototype = { initDateButton: function (){ var me = this; this.popup = new DatePickerPopup({ onpickdate: function (t, date){ if (me.fireEvent('pickdate', Tformat(date, 'yyyy-MM-dd')) !== false) { me.popup.hide(); } }, editor:me.editor }); this.initSplitButton(); } }; utils.inherits(DateButton, SplitButton); })(); (function (){ var utils = baidu.editor.utils; var editorui = baidu.editor.ui; var _Dialog = editorui.Dialog; editorui.Dialog = function (options){ var dialog = new _Dialog(options); dialog.addListener('hide', function (){ if (dialog.editor) { var editor = dialog.editor; try { if(baidu.editor.browser.ie){ editor.selection._bakIERange.select(); } else { editor.focus() } } catch(ex){} } }); return dialog; }; var k, cmd; var btnCmds = ['Undo', 'Redo','FormatMatch', 'Bold', 'Italic', 'Underline', 'StrikeThrough', 'Subscript', 'Superscript','Source','Indent','Outdent', 'BlockQuote','PastePlain','PageBreak', 'SelectAll', 'Print', 'Preview', 'Horizontal', 'RemoveFormat','Time','Date','Unlink', 'InsertParagraphBeforeTable','InsertRow','InsertCol','MergeRight','MergeDown','DeleteRow', 'DeleteCol','SplittoRows','SplittoCols','SplittoCells','MergeCells','DeleteTable']; k = btnCmds.length; while (k --) { cmd = btnCmds[k]; editorui[cmd] = function (cmd){ return function (editor, title){ title = title || editor.options.labelMap[cmd.toLowerCase()] || ''; var ui = new editorui.Button({ className: 'edui-for-' + cmd.toLowerCase(), title: title, onclick: function (){ editor.execCommand(cmd); }, showText: false }); editor.addListener('selectionchange', function (type, causeByUi, uiReady){ var state = editor.queryCommandState(cmd.toLowerCase()); if (state == -1) { ui.setDisabled(true); ui.setChecked(false); } else { if(!uiReady){ ui.setDisabled(false); ui.setChecked(state); } } }); return ui; }; }(cmd); } editorui.ClearDoc = function(editor, title){ var cmd = "ClearDoc"; title = title || editor.options.labelMap[cmd.toLowerCase()] || ''; var ui = new editorui.Button({ className: 'edui-for-' + cmd.toLowerCase(), title: title, onclick: function (){ if(confirm('确定清空文档吗?')){ editor.execCommand('cleardoc'); } } }); editor.addListener('selectionchange',function(){ var state = editor.queryCommandState('cleardoc'); ui.setDisabled(state == -1); }); return ui; }; editorui.Justify = function (editor, side, title){ side = (side || 'left').toLowerCase(); title = title || editor.options.labelMap['justify'+side.toLowerCase()] || ''; var ui = new editorui.Button({ className: 'edui-for-justify' + side.toLowerCase(), title: title, onclick: function (){ editor.execCommand('Justify', side); } }); editor.addListener('selectionchange', function (type, causeByUi, uiReady){ var state = editor.queryCommandState('Justify'); ui.setDisabled(state == -1); var value = editor.queryCommandValue('Justify'); ui.setChecked(value == side && !uiReady); }); return ui; }; editorui.JustifyLeft = function (editor, title){ return editorui.Justify(editor, 'left', title); }; editorui.JustifyCenter = function (editor, title){ return editorui.Justify(editor, 'center', title); }; editorui.JustifyRight = function (editor, title){ return editorui.Justify(editor, 'right', title); }; editorui.JustifyJustify = function (editor, title){ return editorui.Justify(editor, 'justify', title); }; editorui.ImageFloat = function(editor,side,title){ side = (side || 'none').toLowerCase(); title = title || editor.options.labelMap['image'+side.toLowerCase()] || ''; var ui = new editorui.Button({ className: 'edui-for-image' + side.toLowerCase(), title: title, onclick: function (){ editor.execCommand('imagefloat', side); } }); editor.addListener('selectionchange', function (type){ var state = editor.queryCommandState('imagefloat'); ui.setDisabled(state == -1); var state = editor.queryCommandValue('imagefloat'); ui.setChecked(state == side); }); return ui; }; editorui.ImageNone = function(editor,title){ return editorui.ImageFloat(editor, title); }; editorui.ImageLeft = function(editor,title){ return editorui.ImageFloat(editor,"left", title); }; editorui.ImageRight = function(editor,title){ return editorui.ImageFloat(editor,"right", title); }; editorui.ImageCenter = function(editor,title){ return editorui.ImageFloat(editor,"center", title); }; editorui.Directionality = function (editor, side, title){ side = (side || 'left').toLowerCase(); title = title || editor.options.labelMap['directionality'+side.toLowerCase()] || ''; var ui = new editorui.Button({ className: 'edui-for-directionality' + side.toLowerCase(), title: title, onclick: function (){ editor.execCommand('directionality', side); }, type : side }); editor.addListener('selectionchange', function (type, causeByUi, uiReady){ var state = editor.queryCommandState('directionality'); ui.setDisabled(state == -1); var value = editor.queryCommandValue('directionality'); ui.setChecked(value == ui.type && !uiReady); }); return ui; }; editorui.DirectionalityLtr = function (editor, title){ return new editorui.Directionality(editor, 'ltr', title); }; editorui.DirectionalityRtl = function (editor, title){ return new editorui.Directionality(editor, 'rtl', title); }; var colorCmds = ['BackColor', 'ForeColor']; k = colorCmds.length; while (k --) { cmd = colorCmds[k]; editorui[cmd] = function (cmd){ return function (editor, title){ title = title || editor.options.labelMap[cmd.toLowerCase()] || ''; var ui = new editorui.ColorButton({ className: 'edui-for-' + cmd.toLowerCase(), color: 'default', title: title, editor:editor, onpickcolor: function (t, color){ editor.execCommand(cmd, color); }, onpicknocolor: function (){ editor.execCommand(cmd, 'default'); this.setColor('transparent'); this.color = 'default'; }, onbuttonclick: function (){ editor.execCommand(cmd, this.color); } }); editor.addListener('selectionchange', function (){ var state = editor.queryCommandState(cmd); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); } }); return ui; }; }(cmd); } //不需要确定取消按钮的dialog var dialogNoButton = ['SearchReplace','Help','Spechars']; k = dialogNoButton.length; while(k --){ cmd = dialogNoButton[k]; editorui[cmd] = function (cmd){ cmd = cmd.toLowerCase(); return function (editor, iframeUrl, title){ iframeUrl = iframeUrl || editor.options.iframeUrlMap[cmd.toLowerCase()] || 'about:blank'; iframeUrl = editor.ui.mapUrl(iframeUrl); title = title || editor.options.labelMap[cmd.toLowerCase()] || ''; var dialog = new editorui.Dialog({ iframeUrl: iframeUrl, autoReset: true, draggable: true, editor: editor, className: 'edui-for-' + cmd, title: title, onok: function (){}, oncancel: function (){}, onclose: function (t, ok){ if (ok) { return this.onok(); } else { return this.oncancel(); } } }); dialog.render(); var ui = new editorui.Button({ className: 'edui-for-' + cmd, title: title, onclick: function (){ dialog.open(); } }); editor.addListener('selectionchange', function (){ var state = editor.queryCommandState(cmd); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); } }); return ui; }; }(cmd); } var dialogCmds = ['Anchor','Link', 'InsertImage', 'Map', 'GMap', 'InsertVideo','TableSuper','HighlightCode','InsertFrame']; k = dialogCmds.length; while (k --) { cmd = dialogCmds[k]; editorui[cmd] = function (cmd){ cmd = cmd.toLowerCase(); return function (editor, iframeUrl, title){ iframeUrl = iframeUrl || editor.options.iframeUrlMap[cmd.toLowerCase()] || 'about:blank'; iframeUrl = editor.ui.mapUrl(iframeUrl); title = title || editor.options.labelMap[cmd.toLowerCase()] || ''; var dialog = new editorui.Dialog({ iframeUrl: iframeUrl, autoReset: true, draggable: true, editor: editor, className: 'edui-for-' + cmd, title: title, buttons: [{ className: 'edui-okbutton', label: '确认', onclick: function (){ dialog.close(true); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function (){ dialog.close(false); } }], onok: function (){}, oncancel: function (){}, onclose: function (t, ok){ if (ok) { return this.onok(); } else { return this.oncancel(); } } }); dialog.render(); var ui = new editorui.Button({ className: 'edui-for-' + cmd, title: title, onclick: function (){ dialog.open(); } }); editor.addListener('selectionchange', function (){ var state = editor.queryCommandState(cmd); if (state == -1) { ui.setDisabled(true); } else { ui.setChecked(state); ui.setDisabled(false); } }); return ui; }; }(cmd); } editorui.CheckImage = function(editor){ var ui = new editorui.Button({ className: 'edui-for-checkimage', title: "图片转存", onclick: function (){ editor.execCommand("checkimage","_localImages"); editor.ui._dialogs['wordImageDialog'].open(); } }); editor.addListener('selectionchange', function (){ var state = editor.queryCommandState("checkimage","word_img"); //if(console)console.log(state); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); ui.setChecked(state); } }); return ui; }; editorui.FontFamily = function (editor, list, title){ list = list || editor.options.listMap['fontfamily'] || []; title = title || editor.options.labelMap['fontfamily'] || ''; var items = []; for (var i=0; i' + (this.label || '') + ''; } }); } 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: editor.options.ComboxInitial.FONT_FAMILY, className: 'edui-for-fontfamily', indexByValue: function (value){ value = '|' + value.replace(/,/g, '|').replace(/"/g, '') + '|'; value.replace(/\s*|\s*/g, '|'); for (var i=0; i' + (this.label || '') + ''; } }); } var ui = new editorui.Combox({ editor:editor, items: items, title: title, initValue: editor.options.ComboxInitial.FONT_SIZE, 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.RowSpacing = function (editor, list, title){ list = list || editor.options.listMap['rowspacing'] || []; title = title || editor.options.labelMap['rowspacing'] || ''; var items = []; for (var i=0; i' + (this.label || '') + ''; } }); } var ui = new editorui.Combox({ editor:editor, items: items, title: title, initValue: editor.options.ComboxInitial.ROW_SPACING, onselect: function (t,index){ editor.execCommand('RowSpacing', this.items[index].value); }, onbuttonclick: function (){ this.showPopup(); }, className: 'edui-for-rowspacing' }); editor.addListener('selectionchange', function (type, causeByUi, uiReady){ if(!uiReady){ var state = editor.queryCommandState('RowSpacing'); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); ui.setValue(editor.queryCommandValue('RowSpacing')); } } }); return ui; }; editorui.Paragraph = function (editor, list, title){ list = list || editor.options.listMap['paragraph'] || []; title = title || editor.options.labelMap['paragraph'] || ''; var items = []; for (var i=0; i' + (this.label || '') + ''; } }); } var ui = new editorui.Combox({ editor:editor, items: items, title: title, initValue: editor.options.ComboxInitial.PARAGRAPH, 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.LineHeight = function(editor,list,title){ list = list || editor.options.listMap['lineheight'] || []; title = title || editor.options.labelMap['lineheight'] || ''; var items = []; for (var i=0; i' + (this.label || '') + ''; } }); } var ui = new editorui.Combox({ editor:editor, items: items, title: title, initValue: editor.options.ComboxInitial.LINE_HEIGHT, className: 'edui-for-lineheight', onselect: function (t,index){ editor.execCommand('lineheight', this.items[index].value); }, onbuttonclick: function (){ this.showPopup(); } }); editor.addListener('selectionchange', function (type, causeByUi, uiReady){ if(!uiReady){ var state = editor.queryCommandState('lineheight'); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); ui.setValue(editor.queryCommandValue('lineheight')); } } }); return ui; }; //自定义标题 editorui.CustomStyle = function(editor,list,title){ list = list || editor.options.listMap['customstyle'] || []; title = title || editor.options.labelMap['customstyle'] || ''; for(var i=0,items = [],t;t=list[i++];){ (function(ti){ items.push({ label: ti.label, value: ti, renderLabelHtml: function (){ return '
' +'<'+ ti.tag +' ' + (ti.className?' class="'+ti.className+'"':"") + (ti.style ? ' style="' + ti.style+'"':"") + '>' + ti.label+"<\/"+ti.tag+">" + '
'; } }); })(t) } var ui = new editorui.Combox({ editor:editor, items: items, title: title, initValue:editor.options.ComboxInitial.CUSTOMSTYLE, 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'] || 'about:blank'; iframeUrl = editor.ui.mapUrl(iframeUrl); title = title || editor.options.labelMap['inserttable'] || ''; var dialog = new editorui.Dialog({ iframeUrl: iframeUrl, autoReset: true, draggable: true, editor: editor, className: 'edui-for-inserttable', title: title, buttons: [{ className: 'edui-okbutton', label: '确认', onclick: function (){ dialog.close(true); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function (){ dialog.close(false); } }], onok: function (){}, oncancel: function (){}, onclose: function (t,ok){ if (ok) { return this.onok(); } else { return this.oncancel(); } } }); dialog.render(); editor.tableDialog = dialog; 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}); }, onmore: function (){ dialog.open(); }, onbuttonclick: function (){ dialog.open(); } }); editor.addListener('selectionchange', function (){ var state = editor.queryCommandState('inserttable'); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); } }); return ui; }; editorui.InsertOrderedList = function (editor, title){ title = title || editor.options.labelMap['insertorderedlist'] || ''; var _onMenuClick = function(){ editor.execCommand("InsertOrderedList", this.value); }; var ui = new editorui.MenuButton({ editor:editor, className : 'edui-for-insertorderedlist', title : title, items : [{ label: '1,2,3...', value: 'decimal', onclick : _onMenuClick },{ label: 'a,b,c ...', value: 'lower-alpha', onclick : _onMenuClick },{ label: 'i,ii,iii...', value: 'lower-roman', onclick : _onMenuClick },{ label: 'A,B,C', value: 'upper-alpha', onclick : _onMenuClick },{ label: 'I,II,III...', value: 'upper-roman', onclick : _onMenuClick }], onbuttonclick: function (){ var value = editor.queryCommandValue('InsertOrderedList') || this.value; editor.execCommand("InsertOrderedList", value); } }); editor.addListener('selectionchange', function (){ var state = editor.queryCommandState('InsertOrderedList'); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); var value = editor.queryCommandValue('InsertOrderedList'); ui.setValue(value); ui.setChecked(state) } }); return ui; }; editorui.InsertUnorderedList = function (editor, title){ title = title || editor.options.labelMap['insertunorderedlist'] || ''; var _onMenuClick = function(){ editor.execCommand("InsertUnorderedList", this.value); }; var ui = new editorui.MenuButton({ editor:editor, className : 'edui-for-insertunorderedlist', title: title, items: [{ label: '○ 小圆圈', value: 'circle', onclick : _onMenuClick },{ label: '● 小圆点', value: 'disc', onclick : _onMenuClick },{ label: '■ 小方块', value: 'square', onclick : _onMenuClick }], onbuttonclick: function (){ var value = editor.queryCommandValue('InsertUnorderedList') || this.value; editor.execCommand("InsertUnorderedList", value); } }); editor.addListener('selectionchange', function (){ var state = editor.queryCommandState('InsertUnorderedList'); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); var value = editor.queryCommandValue('InsertUnorderedList'); ui.setValue(value); ui.setChecked(state) } }); return ui; }; editorui.FullScreen = function (editor, title){ title = title || editor.options.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, title){ title = title || editor.options.labelMap['emotion'] || ''; iframeUrl = iframeUrl || editor.options.iframeUrlMap['emotion'] || 'about:blank'; iframeUrl = editor.ui.mapUrl(iframeUrl); var ui = new editorui.MultiMenuPop({ title: title, editor: editor, className: 'edui-for-emotion', iframeUrl: iframeUrl }); editor.addListener('selectionchange', function (){ var state = editor.queryCommandState('emotion'); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); } }); return ui; }; // 覆盖了之前的Date. editorui.Date = function (editor){ var ui = new editorui.DateButton({ editor:editor, onpickdate: function (t, date){ editor.execCommand('inserthtml', date); }, onbuttonclick: function (){ editor.execCommand('date'); }, className: 'edui-for-date' }); editor.addListener('selectionchange', function (){ var state = editor.queryCommandState('inserthtml'); if (state == -1) { ui.setDisabled(true); } else { ui.setDisabled(false); } }); return ui; }; })(); ///import core ///commands 全屏 ///commandsName FullScreen ///commandsTitle 全屏 (function () { var utils = baidu.editor.utils, uiUtils = baidu.editor.ui.uiUtils, UIBase = baidu.editor.ui.UIBase; 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; editor.addListener( 'ready', function () { baidu.editor.dom.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 = '
path:
'; } if ( editor.options.wordCount ) { editor.ui.getDom( 'wordcount' ).innerHTML = '字数统计'; } if ( editor.selection.getNative() ) 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(); } ); var me = this; editor.addListener( 'selectionchange', function () { me._updateElementPath(); //字数统计 me._wordCount(); } ); editor.addListener( 'sourcemodechanged', function ( t, mode ) { if ( editor.options.elementPathEnabled ) { if ( mode ) { me.disableElementPath(); } else { me.enableElementPath(); } } if ( editor.options.wordCount ) { if ( mode ) { me.disableWordCount(); } else { me.enableWordCount(); } } } ); // 超链接的编辑器浮层 var linkDialog = new baidu.editor.ui.Dialog( { iframeUrl: editor.ui.mapUrl( me.editor.options.iframeUrlMap.link ), autoReset: true, draggable: true, editor: editor, className: 'edui-for-link', title: '超链接', buttons: [ { className: 'edui-okbutton', label: '确认', onclick: function () { linkDialog.close( true ); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function () { linkDialog.close( false ); } } ], onok: function () { }, oncancel: function () { }, onclose: function ( t, ok ) { if ( ok ) { return this.onok(); } else { return this.oncancel(); } } } ); linkDialog.render(); // 图片的编辑器浮层 var imgDialog = new baidu.editor.ui.Dialog( { iframeUrl: editor.ui.mapUrl( me.editor.options.iframeUrlMap.insertimage ), autoReset: true, draggable: true, editor: editor, className: 'edui-for-insertimage', title: '图片', buttons: [ { className: 'edui-okbutton', label: '确认', onclick: function () { imgDialog.close( true ); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function () { imgDialog.close( false ); } } ], onok: function () { }, oncancel: function () { }, onclose: function ( t, ok ) { if ( ok ) { return this.onok(); } else { return this.oncancel(); } } } ); imgDialog.render(); //锚点 var anchorDialog = new baidu.editor.ui.Dialog( { iframeUrl: editor.ui.mapUrl( me.editor.options.iframeUrlMap.anchor ), autoReset: true, draggable: true, editor: editor, className: 'edui-for-anchor', title: '锚点', buttons: [ { className: 'edui-okbutton', label: '确认', onclick: function () { anchorDialog.close( true ); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function () { anchorDialog.close( false ); } } ], onok: function () { }, oncancel: function () { }, onclose: function ( t, ok ) { if ( ok ) { return this.onok(); } else { return this.oncancel(); } } } ); anchorDialog.render(); // video var videoDialog = new baidu.editor.ui.Dialog( { iframeUrl: editor.ui.mapUrl( me.editor.options.iframeUrlMap.insertvideo ), autoReset: true, draggable: true, editor: editor, className: 'edui-for-insertvideo', title: '视频', buttons: [ { className: 'edui-okbutton', label: '确认', onclick: function () { videoDialog.close( true ); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function () { videoDialog.close( false ); } } ], onok: function () { }, oncancel: function () { }, onclose: function ( t, ok ) { if ( ok ) { return this.onok(); } else { return this.oncancel(); } } } ); videoDialog.render(); //本地word图片上传 var wordImageDialog = new baidu.editor.ui.Dialog( { iframeUrl: editor.ui.mapUrl( me.editor.options.iframeUrlMap.wordimage ), autoReset: true, draggable: true, editor: editor, className: 'edui-for-wordimage', title: '图片转存', buttons: [ { className: 'edui-okbutton', label: '确认', onclick: function () { wordImageDialog.close( true ); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function () { wordImageDialog.close( false ); } } ], onok: function () { }, oncancel: function () { }, onclose: function ( t, ok ) { if ( ok ) { return this.onok(); } else { return this.oncancel(); } } } ); wordImageDialog.render(); //挂载dialog框到ui实例 me._dialogs['wordImageDialog'] = wordImageDialog; // map var mapDialog = new baidu.editor.ui.Dialog( { iframeUrl: editor.ui.mapUrl( me.editor.options.iframeUrlMap.map ), autoReset: true, draggable: true, editor: editor, className: 'edui-for-map', title: '地图', buttons: [ { className: 'edui-okbutton', label: '确认', onclick: function () { mapDialog.close( true ); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function () { mapDialog.close( false ); } } ], onok: function () { }, oncancel: function () { }, onclose: function ( t, ok ) { if ( ok ) { return this.onok(); } else { return this.oncancel(); } } } ); mapDialog.render(); // map var gmapDialog = new baidu.editor.ui.Dialog( { iframeUrl: editor.ui.mapUrl( me.editor.options.iframeUrlMap.gmap ), autoReset: true, draggable: true, editor: editor, className: 'edui-for-gmap', title: 'Google地图', buttons: [ { className: 'edui-okbutton', label: '确认', onclick: function () { gmapDialog.close( true ); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function () { gmapDialog.close( false ); } } ], onok: function () { }, oncancel: function () { }, onclose: function ( t, ok ) { if ( ok ) { return this.onok(); } else { return this.oncancel(); } } } ); gmapDialog.render(); var popup = new baidu.editor.ui.Popup( { editor:editor, content: '', className: 'edui-bubble', _onEditButtonClick: function () { this.hide(); linkDialog.open(); }, _onImgEditButtonClick: function () { this.hide(); var nodeStart = editor.selection.getRange().getClosedNode(); var img = baidu.editor.dom.domUtils.findParentByTagName( nodeStart, "img", true ); if ( img && img.className.indexOf( "edui-faked-video" ) != -1 ) { videoDialog.open(); } else if ( img && img.src.indexOf( "http://api.map.baidu.com" ) != -1 ) { mapDialog.open(); } else if ( img && img.src.indexOf( "http://maps.google.com/maps/api/staticmap" ) != -1 ) { gmapDialog.open(); } else if ( img && img.getAttribute( "anchorname" ) ) { anchorDialog.open(); } else { imgDialog.open(); } }, _getImg: function () { var img = editor.selection.getRange().getClosedNode(); if ( img && (img.nodeName == 'img' || img.nodeName == 'IMG') ) { return img; } return null; }, _onImgSetFloat: function( value ) { if ( this._getImg() ) { editor.execCommand( "imagefloat", value ); var img = this._getImg(); if ( img ) { this.showAnchor( img ); } } }, _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 ); baidu.editor.dom.domUtils.remove( frame ); popup.anchorEl = newFrame; popup.showAnchor( popup.anchorEl ); }, _updateIframe: function() { editor._iframe = popup.anchorEl; insertframe.open(); popup.hide(); }, _onRemoveButtonClick: function () { var nodeStart = editor.selection.getRange().getClosedNode(); var img = baidu.editor.dom.domUtils.findParentByTagName( nodeStart, "img", true ); if ( img && img.getAttribute( "anchorname" ) ) { editor.execCommand( "anchor" ); } else { editor.execCommand( 'unlink' ); } this.hide(); }, queryAutoHide: function ( el ) { if ( el && el.ownerDocument == editor.document ) { if ( el.tagName.toLowerCase() == 'img' || baidu.editor.dom.domUtils.findParentByTagName( el, 'a', true ) ) { return el !== popup.anchorEl; } } return baidu.editor.ui.Popup.prototype.queryAutoHide.call( this, el ); } } ); popup.render(); //iframe var insertframe = new baidu.editor.ui.Dialog( { iframeUrl: editor.ui.mapUrl( me.editor.options.iframeUrlMap.insertframe ), autoReset: true, draggable: true, editor: editor, className: 'edui-for-insertframe', title: '插入iframe', buttons: [ { className: 'edui-okbutton', label: '确认', onclick: function () { insertframe.close( true ); } }, { className: 'edui-cancelbutton', label: '取消', onclick: function () { insertframe.close( false ); } } ], onok: function () { }, oncancel: function () { }, onclose: function ( t, ok ) { if ( ok ) { return this.onok(); } else { return this.oncancel(); } } } ); insertframe.render(); editor.addListener( 'mouseover', function( t, evt ) { evt = evt || window.event; var el = evt.target || evt.srcElement; if ( /iframe/ig.test( el.tagName ) && editor.options.imagePopup ) { var html = popup.formatHtml( '属性: 默认  左对齐  右对齐  ' + '居中' + ' 修改' ); 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 = ''; var img = editor.selection.getRange().getClosedNode(); if ( img != null && img.tagName.toLowerCase() == 'img' ) { if ( img.getAttribute( 'anchorname' ) ) { //锚点处理 html += popup.formatHtml( '属性: 修改  删除' ); } else if ( editor.options.imagePopup ) { html += popup.formatHtml( '属性: 默认  居左  居右  ' + '居中' + ' 修改' ); } } var link; if ( editor.selection.getRange().collapsed ) { link = editor.queryCommandValue( "link" ); } else { link = editor.selection.getStart(); } link = baidu.editor.dom.domUtils.findParentByTagName( link, "a", true ); var url; if ( link != null && (url = (link.getAttribute( 'data_ue_src' ) || link.getAttribute( 'href', 2 ))) != null ) { var txt = url; if ( url.length > 30 ) { txt = url.substring( 0, 20 ) + "..."; } if ( html ) { html += '
' } html += popup.formatHtml( '链接: ' + txt + '' + ' 修改' + ' 清除' ); 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' ) { if ( toolbarItem == '|' ) { toolbarItem = 'Separator'; } if ( baidu.editor.ui[toolbarItem] ) { toolbarItemUi = new baidu.editor.ui[toolbarItem]( editor ); } //todo fullscreen这里单独处理一下,放到首行去 if ( toolbarItem == 'FullScreen' ) { if ( toolbarUis && toolbarUis[0] ) { toolbarUis[0].items.splice( 0, 0, toolbarItemUi ); } else { 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.renderToolbarBoxHtml() + '
' + '' + '
' + '
' + //modify wdcount by matao '
' + '' + '' + '
' + '
'; }, showWordImageDialog:function() { this.editor.execCommand( "checkimage", "_localImages" ); 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 ) { function fixGecko( editor ) { editor.body.contentEditable = false; setTimeout( function() { editor.body.contentEditable = true; }, 200 ) } 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 ) { 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 ) { 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:0;width:' + vpRect.width + 'px;height:' + vpRect.height + 'px;z-index:' + (this.getDom().style.zIndex * 1 + 100); uiUtils.setViewportOffset( this.getDom(), { left: 0, top: 0 } ); this.editor.setHeight( vpRect.height - this.getDom( 'toolbarbox' ).offsetHeight - this.getDom( 'bottombar' ).offsetHeight ); } }, _updateElementPath: function () { var bottom = this.getDom( 'elementpath' ); if ( this.elementPathEnabled ) { var list = this.editor.queryCommandValue( 'elementpath' ); var buff = []; for ( var i = 0,ci; ci = list[i]; i++ ) { buff[i] = this.formatHtml( '' + ci + '' ); } bottom.innerHTML = '
path: ' + 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.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; new EditorUI( editor.options ); var oldRender = editor.render; editor.render = function ( holder ) { 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 ); editor.options.initialContent = holder.value || holder.innerHTML; holder.id && (newDiv.id = holder.id); holder.className && (newDiv.className = holder.className); holder.style.cssText && (newDiv.style.cssText = holder.style.cssText); 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); })();