///import editor.js ///import core/utils.js ///import core/dom/dom.js ///import core/dom/dtd.js ///import core/htmlparser.js //模拟的节点类 //by zhanyi (function () { var uNode = UE.uNode = function (obj) { this.type = obj.type; this.data = obj.data; this.tagName = obj.tagName; this.parentNode = obj.parentNode; this.attrs = obj.attrs || {}; this.children = obj.children; }; var indentChar = ' ', breakChar = '\n'; function insertLine(arr, current, begin) { arr.push(breakChar); return current + (begin ? 1 : -1); } function insertIndent(arr, current) { //插入缩进 for (var i = 0; i < current; i++) { arr.push(indentChar); } } //创建uNode的静态方法 //支持标签和html uNode.createElement = function (html) { if (/[<>]/.test(html)) { return UE.htmlparser(html).children[0] } else { return new uNode({ type:'element', children:[], tagName:html }) } }; uNode.createText = function (data) { return new UE.uNode({ type:'text', 'data':data || '' }) }; function nodeToHtml(node, arr, formatter, current) { switch (node.type) { case 'root': for (var i = 0, ci; ci = node.children[i++];) { //插入新行 if (formatter && ci.type == 'element' && !dtd.$inline[ci.tagName] && i > 1) { insertLine(arr, current, true); insertIndent(arr, current) } nodeToHtml(ci, arr, formatter, current) } break; case 'text': isText(node, arr); break; case 'element': isElement(node, arr, formatter, current); break; case 'comment': isComment(node, arr, formatter); } return arr; } function isText(node, arr) { arr.push(node.data) } function isElement(node, arr, formatter, current) { var attrhtml = ''; if (node.attrs) { attrhtml = []; var attrs = node.attrs; for (var a in attrs) { attrhtml.push(a + (attrs[a] !== undefined ? '="' + utils.unhtml(attrs[a]) + '"' : '')) } attrhtml = attrhtml.join(' '); } arr.push('<' + node.tagName + (attrhtml ? ' ' + attrhtml + ' ' : '') + (dtd.$empty[node.tagName] ? '\/' : '' ) + '>' ); //插入新行 if (formatter && !dtd.$inline[node.tagName]) { current = insertLine(arr, current, true); insertIndent(arr, current) } if (node.children && node.children.length) { for (var i = 0, ci; ci = node.children[i++];) { if (formatter && ci.type == 'element' && !dtd.$inline[ci.tagName] && i > 1) { insertLine(arr, current); insertIndent(arr, current) } nodeToHtml(ci, arr, formatter, current) } } if (!dtd.$empty[node.tagName]) { if (formatter && !dtd.$inline[node.tagName]) { current = insertLine(arr, current); insertIndent(arr, current) } arr.push('<\/' + node.tagName + '>'); } } function isComment(node, arr) { arr.push(''); } function getNodeById(root, id) { var node; if (root.type == 'element' && root.getAttr('id') == id) { return root; } if (root.children && root.children.length) { for (var i = 0, ci; ci = root.children[i++];) { if (node = getNodeById(ci, id)) { return node; } } } } function getNodesByTagName(node, tagName, arr) { if (node.type == 'element' && node.tagName == tagName) { arr.push(node); } if (node.children && node.children.length) { for (var i = 0, ci; ci = node.children[i++];) { getNodesByTagName(ci, tagName, arr) } } } function nodeTraversal(root,fn){ if(root.children && root.children.length){ for(var i= 0,ci;ci=root.children[i];){ nodeTraversal(ci,fn); //ci被替换的情况,这里就不再走 fn了 if(ci.parentNode ){ if(ci.children){ fn(ci) } if(ci.parentNode) i++ } } }else{ fn(root) } } uNode.prototype = { toHtml:function (formatter) { var arr = []; nodeToHtml(this, arr, formatter, 0); return arr.join('') }, innerHTML:function (htmlstr) { if (this.type != 'element' || dtd.$empty[this.tagName]) { return this; } if (htmlstr) { if(this.children){ for (var i = 0, ci; ci = this.children[i++];) { ci.parentNode = null; } } this.children = []; var tmpRoot = UE.htmlparser(htmlstr); for (var i = 0, ci; ci = tmpRoot.children[i++];) { this.children.push(ci); ci.parentNode = this; } return this; } else { var tmpRoot = new UE.uNode({ type:'root', children:this.children }); return tmpRoot.toHtml(); } }, innerText:function () { if (this.type != 'element' || dtd.$empty[this.tagName]) { return this; } var html = this.toHtml(); return html.replace(/<[^>]+>/g, ''); }, getData:function () { if (this.type == 'element') return ''; return this.data }, firstChild:function () { // if (this.type != 'element' || dtd.$empty[this.tagName]) { // return this; // } return this.children ? this.children[0] : null; }, lastChild:function () { // if (this.type != 'element' || dtd.$empty[this.tagName] ) { // return this; // } return this.children ? this.children[this.children.length - 1] : null; }, previousSibling : function(){ var parent = this.parentNode; for (var i = 0, ci; ci = parent.children[i]; i++) { if (ci === this) { return i == 0 ? null : parent.children[i-1]; } } }, nextSibling : function(){ var parent = this.parentNode; for (var i = 0, ci; ci = parent.children[i++];) { if (ci === this) { return parent.children[i]; } } }, replaceChild:function (target, source) { if (this.children) { if(target.parentNode){ target.parentNode.removeChild(target); } for (var i = 0, ci; ci = this.children[i]; i++) { if (ci === source) { this.children.splice(i, 1, target); source.parentNode = null; target.parentNode = this; return target; } } } }, appendChild:function (node) { if (this.type == 'root' || (this.type == 'element' && !dtd.$empty[this.tagName])) { if (!this.children) { this.children = [] } if(node.parentNode){ node.parentNode.removeChild(node); } for (var i = 0, ci; ci = this.children[i]; i++) { if (ci === node) { this.children.splice(i, 1); break; } } this.children.push(node); node.parentNode = this; return node; } }, insertBefore:function (target, source) { if (this.children) { if(target.parentNode){ target.parentNode.removeChild(target); } for (var i = 0, ci; ci = this.children[i]; i++) { if (ci === source) { this.children.splice(i, 0, target); target.parentNode = this; return target; } } } }, insertAfter:function (target, source) { if (this.children) { if(target.parentNode){ target.parentNode.removeChild(target); } for (var i = 0, ci; ci = this.children[i]; i++) { if (ci === source) { this.children.splice(i + 1, 0, target); target.parentNode = this; return target; } } } }, removeChild:function (node,keepChildren) { if (this.children) { for (var i = 0, ci; ci = this.children[i]; i++) { if (ci === node) { this.children.splice(i, 1); ci.parentNode = null; if(keepChildren && ci.children && ci.children.length){ for(var j= 0,cj;cj=ci.children[j];j++){ this.children.splice(i+j,0,cj); cj.parentNode = this; } } return ci; } } } }, getAttr:function (attrName) { return this.attrs && this.attrs[attrName.toLowerCase()] }, setAttr:function (attrName, attrVal) { if (!attrName) { delete this.attrs; return; } if(!this.attrs){ this.attrs = {}; } if (utils.isObject(attrName)) { for (var a in attrName) { if (!attrName[a]) { delete this.attrs[a] } else { this.attrs[a.toLowerCase()] = attrName[a]; } } } else { if (!attrVal) { delete this.attrs[attrName] } else { this.attrs[attrName.toLowerCase()] = attrVal; } } }, getIndex:function(){ var parent = this.parentNode; for(var i= 0,ci;ci=parent.children[i];i++){ if(ci === this){ return i; } } return -1; }, getNodeById:function (id) { var node; if (this.children && this.children.length) { for (var i = 0, ci; ci = this.children[i++];) { if (node = getNodeById(ci, id)) { return node; } } } }, getNodesByTagName:function (tagNames) { tagNames = utils.trim(tagNames).replace(/[ ]{2,}/g, ' ').split(' '); var arr = [], me = this; utils.each(tagNames, function (tagName) { if (me.children && me.children.length) { for (var i = 0, ci; ci = me.children[i++];) { getNodesByTagName(ci, tagName, arr) } } }); return arr; }, getStyle:function (name) { var cssStyle = this.getAttr('style'); if (!cssStyle) { return '' } var reg = new RegExp(name + ':([^;]+)'); var match = cssStyle.match(reg); if (match && match[0]) { return match[1] } return ''; }, setStyle:function (name, val) { function exec(name, val) { var reg = new RegExp(name + ':([^;]+);?', 'gi'); cssStyle = cssStyle.replace(reg, ''); if (val) { cssStyle = name + ':' + utils.unhtml(val) + ';' + cssStyle } } var cssStyle = this.getAttr('style'); if (!cssStyle) { cssStyle = ''; } if (utils.isObject(name)) { for (var a in name) { exec(a, name[a]) } } else { exec(name, val) } this.setAttr('style', cssStyle) }, traversal:function(fn){ if(this.children && this.children.length){ nodeTraversal(this,fn); }; return this; } } })();