diff --git a/_src/core/htmlparser.js b/_src/core/htmlparser.js new file mode 100644 index 0000000000000000000000000000000000000000..026c078b4742975ce84875a68e862945629c4051 --- /dev/null +++ b/_src/core/htmlparser.js @@ -0,0 +1,105 @@ +//html字符串转换成uNode节点 +//by zhanyi +var htmlparser = UE.htmlparser = function(htmlstr){ + var reg = new RegExp( domUtils.fillChar, 'g' ); + //ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除 + htmlstr = htmlstr.replace( reg, '' ).replace( />[\t\r\n]*?<' ); + + var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g, + re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g; + + var uNode = UE.uNode, + needparentNode = { + 'td' : 'tr', + 'tr' : 'tbody', + 'tbody' : 'table', + 'th' : 'tr', + 'thead':'table', + 'tfoot':'table', + 'caption':'table', + 'li':['ul','ol'], + 'dt':'dl', + 'dd':'dl', + 'option':'select' + }; + + function text(parent,data){ + parent.children.push(new uNode({ + type : 'text', + data : data, + parentNode : parent + })); + } + + function element(parent,tagName,htmlattr){ + var needParentTag; + if(needParentTag = needparentNode[tagName]){ + if(tagName == parent.tagName){ + parent = parent.parentNode; + }else if(utils.isArray(needParentTag) ? utils.indexOf(needParentTag,parent.tagName) == -1 : needParentTag != parent.tagName){ + parent = element(parent,utils.isArray(needParentTag) ? needParentTag[0] : needParentTag) + } + } + var elm = new uNode({ + parentNode : parent, + type : 'element', + tagName : tagName, + //是自闭合的处理一下 + children : dtd.$empty[tagName] ? null : [] + }); + //如果属性存在,处理属性 + if(htmlattr){ + var attrs = {},match; + while(match = re_attr.exec(htmlattr)){ + attrs[match[1].toLowerCase()] = match[2] + } + elm.attrs = attrs; + } + + parent.children.push(elm); + //如果是自闭合节点返回父亲节点 + return dtd.$empty[tagName] ? parent : elm + } + + function comment(parent,data){ + parent.children.push(new uNode({ + type : 'comment', + data : data, + parentNode : parent + })); + } + + var match,currentIndex = 0,nextIndex = 0; + //设置根节点 + var root = new uNode({ + type : 'root', + children : [] + }); + var currentParent = root; + while(match = re_tag.exec(htmlstr)){ + currentIndex = match.index; + if(currentIndex > nextIndex){ + //text node + text(currentParent,htmlstr.slice(nextIndex,currentIndex)); + } + if(match[3]){ + //start tag + currentParent = element(currentParent,match[3],match[4]); + + }else if(match[1]){ + //end tag + currentParent = currentParent.parentNode; + }else if(match[2]){ + //comment + comment(currentParent,match[2]) + } + nextIndex = re_tag.lastIndex; + + } + //如果结束是文本,就有可能丢掉,所以这里手动判断一下 + //例如
  • sdfsdfsdf
  • sdfsdfsdfsdf + if(nextIndex < htmlstr.length){ + text(currentParent,htmlstr.slice(nextIndex)); + } + return root; +}; \ No newline at end of file diff --git a/_src/core/node.js b/_src/core/node.js new file mode 100644 index 0000000000000000000000000000000000000000..28bd0a4e325af91cdb0eaec5fb4d13404bce12a4 --- /dev/null +++ b/_src/core/node.js @@ -0,0 +1,356 @@ +///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', + needWrap = utils.extend(utils.extend({},dtd.$block),dtd.$cdata); + + 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' && needWrap[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 ? '="' + attrs[a] + '"' : '')) + } + attrhtml = attrhtml.join(' '); + } + arr.push('<' + node.tagName + + (attrhtml ? ' ' + attrhtml + ' ' : '') + + (dtd.$empty[node.tagName] ? '\/' : '' ) + '>' + ); + //插入新行 + if (formatter && needWrap[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' && needWrap[ci.tagName] && i>1) { + insertLine(arr, current); + insertIndent(arr, current) + } + nodeToHtml(ci, arr, formatter, current) + } + } + if (!dtd.$empty[node.tagName]) { + if (formatter && needWrap[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) + } + } + } + + 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) { + 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; + }, + replaceChild:function (target, source) { + if (this.children) { + 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 == 'element' && !dtd.$empty[this.tagName]) { + if (!this.children) { + this.children = [] + } + 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) { + for (var i = 0, ci; ci = this.children[i]; i++) { + if (ci === target) { + this.children.splice(i, 1); + i--; + } + if (ci === source) { + this.children.splice(i, 0, target); + target.parentNode = this; + i++; + } + } + return target; + } + }, + insertAfter:function (target, source) { + if (this.children) { + for (var i = 0, ci; ci = this.children[i]; i++) { + if (ci === target) { + this.children.splice(i, 1); + i--; + } + if (ci === source) { + this.children.splice(i + 1, 1, target); + target.parentNode = this; + i = i + 2; + + } + return target; + } + } + }, + removeChild:function (node) { + if (this.children) { + for (var i = 0, ci; ci = this.children[i]; i++) { + if (ci === node) { + this.children.splice(i, 1); + ci.parentNode = null; + return ci; + } + } + } + }, + getAttr:function (attrName) { + return this.attrs[attrName.toLowerCase()] + }, + setAttr:function (attrName, attrVal) { + if(!attrName){ + delete this.attrs; + return; + } + 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; + } + + } + }, + 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[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 + ':' + 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) + } + } +})(); diff --git a/_src/core/utils.js b/_src/core/utils.js index b147205ff63f9eaa0448065aa3cf1dfebe6a3b2e..9ccf0cce0a82225ea63f4f3dbd52686dbd8d2eed 100644 --- a/_src/core/utils.js +++ b/_src/core/utils.js @@ -572,7 +572,7 @@ var utils = UE.utils = { * @name isNumber * @grammar UE.utils.isNumber(obj) => true|false */ -utils.each(['String','Function','Array','Number','RegExp'],function(v){ +utils.each(['String','Function','Array','Number','RegExp','Object'],function(v){ UE.utils['is' + v] = function(obj){ return Object.prototype.toString.apply(obj) == '[object ' + v + ']'; }