javascript 解析dom字符串

知识要求:1:熟悉dom结构层次(如childNodes,nodeType,parent,children)等。

              2:熟悉jq对象转换js 对象,反之 毕竟不是专业js人。借助第3方框架。其实jq也是js封装的,所以请不要侮辱jq。

              3:递归的使用(http://www.iteye.com/job/topic/1126012) iteye  深圳7k难找写递归的人 不知道大侠你们是怎么认为的。

              4:学会调试js。工具 谷歌或者火狐 ie个人不习惯.

第1文本编辑器。http://www.cnblogs.com/rubylouvre/archive/2009/08/02/1537022.html(博客园司徒正美 听一个朋友说他是国内知名js高手具体也不清楚!)

最后我修改了下变成这个样子!

需求:

文本框输入文字,编辑 如果是颜色用\F,字体用\C,大小用\S, 举个例子:

|\F2,,\C1,,w||\F1,,博客园||  首先\F是字体的意思 ;\C是颜色 ;\S字体大小 里面的数字是具体属性。如颜色有红色,绿色 ;字体有12px ,14px ,20px (没有默认添加属性 这些都是自定义的),合起来的意思就是 "w"字体是宋体 颜色是红色 字体大小默认12px。同理博客园字体为宋体.

为了形象截下图。

 

还是直接上代码吧:

   <script type="text/javascript">
        var fontName = {
            ht: "黑体",
            kt: "楷体",
            yt: "幼圆",
            st: "宋体"
        };
        var colorOhterHtml = {
            red: "#ff0000",
            lanSe: "#0000ff",
            hs: "#ffff00",
            ls: "#008000",
            bs: "#ffffff",
            qs: "#6a5acd",
            Black: "black"
        };
        var colorIEHtml = {
            red: "red",
            green: "green",
            yellow: "yellow",
            blue: "blue",
            white: "white",
            Black: "#000000"
        };

        $(function () {
            var content = $("#content");

            new RichTextEditor({
                id: 'editor',
                textarea_id: 'textarea'
            });

            $("#btnValue").click(function () {
                var sEditValue = $("#RTE_iframe").contents().find("body").html().toLowerCase();
                if (sEditValue == "") {
                    alert("空");
                    return;
                }
                var txtDom = "<font><font><font color='black' face='宋体' size='1'>";
                txtDom += sEditValue;
                txtDom += "</font></font></font>"
                $("#Div1").html("").append(txtDom);
                $("#div2").html("").append(txtDom);
                var dom = $("#Div1").children();

                getTextNode($(dom)[0]); 
                var textValue = getChildDom($(dom), 0);
                alert(textValue);
            });
            //jquery结束
        });

        function fontCode(font) {
            var sCode = "";
            switch (font) {
                case fontName.st:
                    sCode += "\\F0,,";
                    break;
                case fontName.ht:
                    sCode += "\\F1,,";
                    break;
                case fontName.kt:
                    sCode += "\\F2,,";
                    break;
                case fontName.yt:
                    sCode += "\\F3,,";
                    break;
            }
            return sCode;
        }

        function colorCode(color) {
            var sCode = "";
            switch (color) {
                case colorOhterHtml.Black:
                case colorIEHtml.Black:
                    sCode += "\\C0,,";
                    break;
                case colorOhterHtml.red:
                case colorIEHtml.red:
                    sCode += "\\C1,,";
                    break;
                case colorOhterHtml.ls:
                case colorIEHtml.blue:
                    sCode += "\\C2,,";
                    break;
                case colorOhterHtml.hs:
                case colorIEHtml.yellow:
                    sCode += "\\C3,,";
                    break;
                case colorOhterHtml.qs:
                case colorIEHtml.blue:
                    sCode += "\\C6,,";
                    break;
                case colorOhterHtml.ls:
                case colorIEHtml.green:
                    sCode += "\\C4,,";
                    break;
                case colorOhterHtml.bs:
                case colorIEHtml.white:
                    sCode += "\\C7,,";
                    break;
            }
            return sCode;
        }

        function sizeCode(size) {
            var sCode = "";
            switch (size) {
                case "1":
                    sCode += "\\S0,,";
                    break;
                case "2":
                    sCode += "\\S1,,";
                    break;
                case "3":
                    sCode += "\\S2,,";
                    break;
                case "4":
                    sCode += "\\S3,,";
                    break;
                case "5":
                    sCode += "\\S4,,";
                    break;
                case "6":
                    sCode += "\\S5,,";
                    break;
                case "7":
                    sCode += "\\S6,,";
                    break;
                case "8":
                    sCode += "\\S7,,";
                    break;
            }
            return sCode;
        }

        function getChildDom(dom) {
            var lastCode = "";
            for (var i = 0; i < dom.length; i++) {
                if ($(dom[i]).children().length > 0) {
                    var baseDomObj = $(dom[i]);
                    var childText = getChildDom(baseDomObj.children());
                    if (!baseDomObj.is('font')) {
                        continue;
                    }
                    var baseText = baseDomObj.html();
                    baseDomObj.replaceWith("|?" + baseText + "|?");
                    lastCode += baseText;
                    baseText = "|?" + baseText + "|?";
                } else {
                    var childDomObj = $(dom[i]);
                    if (!childDomObj.is('font')) {
                        continue;
                    }
                    var childrenText = childDomObj.html();
                    childrenText = "|?" + childrenText + "|?";
                    childDomObj.replaceWith(childrenText);
                }
            }
            return lastCode;
        }

        function getColorVal(dom) {
            if ($(dom).parent('font')[0] != null && typeof ($(dom).parent('font')[0]) != 'undefined') {
                var color = $($(dom).parent('font')[0]).attr("color");
                if (typeof (color) == "undefined") {
                    var colVal = getColorVal($(dom).parent('font')[0]);
                    if (typeof (colVal) == "undefined") {
                        return colVal;
                    }
                } else {
                    return color;
                }
            }
        }

        function getFontVal(dom) {
            if ($(dom).parent('font')[0] != null && typeof ($(dom).parent('font')[0]) != 'undefined') {
                var font = $($(dom).parent('font')[0]).attr("face");
                if (typeof (font) == "undefined") {
                    var fontVal = getFontVal($(dom).parent('font')[0]);
                    if (typeof (fontVal) == "undefined") {
                        return fontVal;
                    }
                } else {
                    return font;
                }
            }
        }

        function getSizeVal(dom) {
            if ($(dom).parent('font')[0] != null && typeof ($(dom).parent('font')[0]) != 'undefined') {
                var size = $($(dom).parent('font')[0]).attr("size");
                if (typeof (size) == "undefined") {
                    var sizeVal = getSizeVal($(dom).parent('font')[0]);
                    if (typeof (sizeVal) == "undefined") {
                        return sizeVal;
                    }
                } else {
                    return size;
                }
            }
        }

        function getTextNode(dom) {
            var oElement = dom.childNodes;
            for (var i = 0; i < oElement.length; i++) {
                if (oElement[i].nodeType == 3 && typeof (oElement[i]) != "undefined") {
                    if (oElement[i].nodeType == 3) {
                        var color = getParentNodeColor(oElement[i]);
                        var size = getParentNodeSize(oElement[i]);
                        var face = getParentNodeFace(oElement[i]);
                        var colorCd = colorCode(color);
                        var sizeCd = sizeCode(size);
                        var faceCd = fontCode(face);
                        $(oElement[i]).replaceWith(colorCd + sizeCd + faceCd + oElement[i].nodeValue);
                    }
                } else {
                    getTextNode(oElement[i]);
                }
            }
        }

        function getParentNodeColor(txtNode) {
            if (typeof (txtNode.parentNode) != "undefined" && txtNode.parentNode.nodeType == 1) {
                var color = getColorVal(txtNode);
                if (color != '') {
                    return color;
                } else {
                    color = getParentNodeColor(txtNode.parentNode);
                }
            } else {
                color = getParentNodeColor(txtNode.parentNode);
            }
            return color;
        }

        function getParentNodeSize(txtNode) {
            if (typeof (txtNode.parentNode) != "undefined" && txtNode.parentNode.nodeType == 1) {
                var size = getSizeVal(txtNode);
                if (size != '') {
                    return size;
                } else {
                    size = getParentNodeSize(txtNode.parentNode);
                }
            } else {
                size = getParentNodeSize(txtNode.parentNode);
            }
            return size;
        }

        function getParentNodeFace(txtNode) {
            if (typeof (txtNode.parentNode) != "undefined" && txtNode.parentNode.nodeType == 1) {
                var face = getFontVal(txtNode);
                if (face != '') {
                    return face;
                } else {
                    face = getParentNodeFace(txtNode.parentNode);
                }
            } else {
                face = getParentNodeFace(txtNode.parentNode);
            }
            return face;
        }

        function delHtmlTag(str) {
            return str.replace(/<[^>]+>/g, "");
        }
    </script>

 

html:

<html>
<head>
    <script src="jquery-1.3.1.js" type="text/javascript"></script>
    <script src="textEdit.js" type="text/javascript"></script>
    <style type="text/css">
        #textarea
        {
            width: 378px;
            height: 97px;
            background: #F2F1D7;
        }
    </style>
    <title>富文本编辑器</title>
</head>
<body>
    <form action="#">
    <textarea id="textarea" wrap="on"></textarea>
    <br />
    <textarea id="tsp" wrap="on" style="width: 626px; height: 200px;"></textarea>
    <input type="button" id="btnValue" value="获取值" />
    <div id="content">
    </div>
    <div id="Div1">
    </div>
    <div id="div2">
    </div>
    </form>
</body>
</html>
textEdit.js代码:(注)修改博客园司徒的
      var addSheet = function () {
            var doc, cssCode;
            if (arguments.length == 1) {
                doc = document;
                cssCode = arguments[0];
            } else if (arguments.length == 2) {
                doc = arguments[0];
                cssCode = arguments[1];
            } else {
                alert("addSheet函数最多接受两个参数!");
            }
            var headElement = doc.getElementsByTagName("head")[0];
            var styleElements = headElement.getElementsByTagName("style");
            if (styleElements.length == 0) {/*如果不存在style元素则创建*/
                if (! +"\v1") {    //ie
                    doc.createStyleSheet();
                } else {
                    var tempStyleElement = doc.createElement('style'); //w3c
                    tempStyleElement.setAttribute("type", "text/css");
                    headElement.appendChild(tempStyleElement);
                }
            }
            var styleElement = styleElements[0];
            var media = styleElement.getAttribute("media");
            if (media != null && !/screen/.test(media.toLowerCase())) {
                styleElement.setAttribute("media", "screen");
            }
            if (! +"\v1") {    //ie
                styleElement.styleSheet.cssText += cssCode;
            } else if (/a/[-1] == 'a') {
                styleElement.innerHTML += cssCode; //火狐支持直接innerHTML添加样式表字串
            } else {
                styleElement.appendChild(doc.createTextNode(cssCode))
            }
        }
        var Class = {
            create: function () {
                return function () {
                    this.initialize.apply(this, arguments);
                }
            }
        }
        var extend = function (destination, source) {
            for (var property in source) {
                destination[property] = source[property];
            }
            return destination;
        }
        var RichTextEditor = Class.create(); //我们的富文本编辑器类
        RichTextEditor.prototype = {
            initialize: function (options) {
                this.setOptions(options);
                this.drawEditor(this.options.textarea_id);
            },
            setOptions: function (options) {
                this.options = { //这里集中设置默认属性
                    id: 'jeditor_' + new Date().getTime(),
                    textarea_id: null//用于textarea的ID,也就是我们的必选项
                }
                extend(this.options, options || {}); //这里是用来重写默认属性
            },
            ID: function (id) { return document.getElementById(id) }, //getElementById的快捷方式
            TN: function (tn) { return document.getElementsByTagName(tn) }, //getElementsByTagName的快捷方式
            CE: function (s) { return document.createElement(s) }, //createElement的快捷方式
            fontPickerHtml: function (type, array) {
                var builder = [];
                for (var i = 0, l = array.length; i < l; i++) {
                    builder.push('<a class="aFont" unselectable="on" style="');
                    if (type == 'fontname') {
                        builder.push('font-family');
                        builder.push(':');
                        builder.push(array[i]); /*呈现一行(一行就是一种字体)*/
                        builder.push(';" href="javascript:void(0)">');
                        builder.push(array[i]);
                    } else if (type == 'fontsize') {
                        /*呈现一行(一行就是一种字号)*/
                        builder.push('font-size');
                        //builder.push(':');
                        //builder.push(array[i][1]);如果加这个下面一句前面要加;builder.push(';" sizevalue="');
                        builder.push('" sizevalue="');
                        builder.push(array[i][0]);
                        builder.push('" href="javascript:void(0)">');
                        builder.push(array[i][2]);
                    }
                    builder.push("</a>");
                }
                return builder.join('');
            },
            fontClorHtml: function (type, array) {
                var builder = [];
                var sText;
                for (var i = 0, l = array.length; i < l; i++) {
                    builder.push('<a class="aFontColor" unselectable="on" style="');
                    if (type == 'forecolor') {
                        builder.push('color');
                        builder.push(':');
                        builder.push(array[i]);
                        builder.push(';" href="javascript:void(0)">');
                        builder.push(array[i]);
                    }
                    builder.push("</a>");
                }
                return builder.join('');
            },
            addEvent: function (el, type, fn) {
                if (! +"\v1") {
                    el['e' + type + fn] = fn;
                    el.attachEvent('on' + type, function () {
                        el['e' + type + fn]();
                    });
                } else {
                    el.addEventListener(type, fn, false);
                }
            },
            drawEditor: function (id) {
                var $ = this,
      textarea = this.ID(id),
      toolbar = this.CE('div'),
      br = this.CE('br'), //用于清除浮动
      iframe = this.CE('iframe');
                textarea.style.display = "none";
                textarea.parentNode.insertBefore(toolbar, textarea);
                textarea.parentNode.insertBefore(br, textarea);
                textarea.parentNode.insertBefore(iframe, textarea);
                br.style.cssText = "clear:both";
                toolbar.setAttribute("id", "RTE_toolbar");
                iframe.setAttribute("id", "RTE_iframe");
                iframe.frameBorder = 0;
                var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
                iframeDocument.designMode = "on";
                iframeDocument.open();
                iframeDocument.write('<html><head><style type="text/css">body{ font-family:arial; font-size:13px;background:#DDF3FF;border:0; }</style></head><body></body></html>');
                iframeDocument.close();
                var buttons = {//工具栏的按钮集合
                    'forecolor': '颜色',
                    'fontname': '字体',
                    'fontsize': '字码'
                };
                var fontFamilies = ['宋体', '黑体', '楷体', '幼圆', '扩展字体'];
                var fontColors = ["黑色", "红色", "绿色", "黄色", "蓝色", "品红", "青色", "白色", "斑点", "条纹"];
                var fontSizes = [[1, '8px', '8'],
                [2, '12px', '12'],
                [3, '16px', '16'],
                [4, '24px', '24'],
                [5, '32px', '32'],
                [6, '40px', '40'],
                [7, '48px', '48'],
                [8, '56px', '56']];
                var buttonClone = $.CE("a"),
      fragment = document.createDocumentFragment();
                buttonClone.className = 'button';
                for (var i in buttons) {/*添加命令按钮的名字,样式*/
                    var button = buttonClone.cloneNode("true");
                    if (i == 'backcolor') {/*特殊处理背景色按钮*/
                        if (! +"\v1") {
                            button.setAttribute("title", "background")
                        } else {
                            button.setAttribute("title", "hilitecolor")
                        }
                    }
                    button.setAttribute("title", i); /*把execCommand的命令参数放到title*/
                    button.innerHTML = buttons[i];
                    button.setAttribute("unselectable", "on"); /*防止焦点转移到点击的元素上,从而保证文本的选中状态*/
                    toolbar[i] = button;   /*★★★★把元素放进一个数组,用于下一个循环绑定事件!★★★★*/
                    fragment.appendChild(button);
                }
                toolbar.appendChild(fragment);
                $.addEvent(toolbar, 'click', function () {
                    var e = arguments[0] || window.event,
        target = e.srcElement ? e.srcElement : e.target,
        command = target.getAttribute("title");
                    switch (command) {
                        case 'fontname': //这六个特殊处理,不直接执行fontEdit命令!
                        case 'forecolor':
                        case 'fontsize':
                        default: //其他执行fontEdit(cmd, null)命令
                            _format(command, '');
                            break;
                    }
                });
                /******************************************************************/
                var fontPicker = $.CE('div');
                fontPicker.className = "fontpicker";
                toolbar.appendChild(fontPicker);
                $.addEvent(toolbar['fontname'], 'click', function () {
                    fontPicker.innerHTML = $.fontPickerHtml('fontname', fontFamilies);
                    fontPicker.style.width = "60px";
                    fontPicker.setAttribute("id", "fontPicker");
                    bind_select_event(this, fontPicker);
                });
                /******************************************************************/
                var fontPicker = $.CE('div');
                fontPicker.className = "fontpicker";
                toolbar.appendChild(fontPicker);
                $.addEvent(fontPicker, 'click', function () {
                    var e = arguments[0] || window.event,
        target = e.srcElement ? e.srcElement : e.target,
        command = this.getAttribute("title");
                    var nn = target.nodeName.toLowerCase();
                    if (nn == 'a') {
                        var value;
                        if ('fontsize' == command) {
                            value = target.getAttribute('sizevalue');
                        } else {
                            value = target.innerHTML;
                        }
                        _format(command, value);
                        e.cancelBubble = true;
                        fontPicker.style.display = 'none';
                    }
                });

                /******************************************************************/
                var fontColor = $.CE('div');
                fontColor.className = "fontColor";
                toolbar.appendChild(fontColor);
                $.addEvent(toolbar['forecolor'], 'click', function () {
                    fontColor.innerHTML = $.fontClorHtml('forecolor', fontColors);
                    fontColor.style.width = "60px";
                    fontColor.style.height = "80px";
                    fontColor.setAttribute("id", "fontColor");
                    bind_select_event(this, fontColor);
                });

                /******************************************************************/
                var fontColor = $.CE('div');
                fontColor.className = "fontColor";
                toolbar.appendChild(fontColor);
                $.addEvent(fontColor, 'click', function () {
                    var e = arguments[0] || window.event,
        target = e.srcElement ? e.srcElement : e.target,
        command = this.getAttribute("title");
                    var nn = target.nodeName.toLowerCase();
                    if (nn == 'a') {
                        var value;
                        if ('fontsize' == command) {
                            value = target.getAttribute('sizevalue');
                        } else {
                            value = target.innerHTML;
                            if (value === "黑色") {
                                value = "black";
                            } else if (value === "红色") {
                                value = "red";
                            }
                            else if (value === "绿色") {
                                value = "Green";
                            }
                            else if (value === "黄色") {
                                value = "Yellow";
                            }
                            else if (value === "蓝色") {
                                value = "Blue";
                            }
                            else if (value === "品红") {
                                value = "bule";
                            }
                            else if (value === "青色") {
                                value = "SlateBlue";
                            }
                            else if (value === "白色") {
                                value = "White";
                            }
                            else if (value === "斑点") {
                                value = "bule";
                            }
                            else if (value === "条纹") {
                                value = "bule";
                            }
                        }
                        _format(command, value);
                        e.cancelBubble = true;
                        fontColor.style.display = 'none';
                    }
                });
                /******************************************************************/
                $.addEvent(toolbar['fontsize'], 'click', function () {
                    fontPicker.innerHTML = $.fontPickerHtml('fontsize', fontSizes);
                    fontPicker.style.width = "80px";
                    bind_select_event(this, fontPicker);
                });
                /******************************************************************/
                var _insertHTML = function (html) {
                    iframe.contentWindow.focus();
                    if (! +"\v1") {
                        /****这里需要解决IE丢失光标位置的问题,详见核心代码四**************/
                        iframeDocument.selection.createRange().pasteHTML(html);
                    } else {
                        var selection = iframe.contentWindow.getSelection();
                        var range;
                        if (selection) {
                            range = selection.getRangeAt(0);
                        } else {
                            range = iframeDocument.createRange();
                        }
                        var oFragment = range.createContextualFragment(html),
                            oLastNode = oFragment.lastChild;
                        range.insertNode(oFragment);
                        range.setEndAfter(oLastNode);
                        range.setStartAfter(oLastNode);
                        selection.removeAllRanges(); //清除选择
                        selection.addRange(range);
                    }
                }

                /*******************核心代码之一******************************************/
                /********************处理富文本编辑器的格式化命令**************************/
                var _format = function (x, y) {
                    try {
                        iframeDocument.execCommand(x, false, y);
                        iframe.contentWindow.focus();
                    } catch (e) { }
                }
                /***********核心代码之二*************************************************/
                /***********隐藏与显示弹出层**********************************************/
                var bind_select_event = function (button, picker) {
                    button.style.position = 'relative';
                    var command = button.getAttribute("title");
                    picker.setAttribute("title", command); //转移命令
                    if (picker.style.display == 'none') {
                        picker.style.display = 'block';
                        picker.style.left = button.offsetLeft + 'px';
                        picker.style.top = (button.clientHeight + button.offsetTop) + 'px';
                    } else {
                        picker.style.display = 'none';
                    }
                }
                /*******************核心代码之三******************************************/
                /**********************获取iframe的内容************************************/
                $.addEvent(iframe.contentWindow, "blur", function () {
                    textarea.value = iframeDocument.body.innerHTML;
                });
                /*******************核心代码之四******************************************/
                /*当光标离开iframe再进入时默认放在body的第1个节点上了,所以要记录光标的位置***/
                if (! +"\v1") {
                    var bookmark;
                    //记录IE的编辑光标
                    $.addEvent(iframe, "beforedeactivate", function () {//在文档失去焦点之前
                        var range = iframeDocument.selection.createRange();
                        bookmark = range.getBookmark();
                    });
                    //恢复IE的编辑光标
                    $.addEvent(iframe, "activate", function () {
                        if (bookmark) {
                            var range = iframeDocument.body.createTextRange();
                            range.moveToBookmark(bookmark);
                            range.select();
                            bookmark = null;
                        }
                    });
                }
                /**********************************************************fontpicker******/
                addSheet('\
                     #RTE_iframe{width:600px;height:300px;}\
                     #RTE_toolbar{float:left;width:600px;background:#D5F3F4;}\
                     #RTE_toolbar .button{display:block;float:left;border:1px solid #CCC;margin-left:5px;\
                          color:#000;background:#D0E8FC;height:20px;text-align:center;padding:0 10px;white-space: nowrap;}\
                     #RTE_toolbar select{float:left;height:20px;width:60px;margin-right:5px;}\
                     #RTE_toolbar .button:hover{color:#fff;border-color:#fff #aaa #aaa #fff;}\
                     div.fontpicker{display:none;height:150px;overflow:auto;position:absolute;\
                     border:2px solid #c3c9cf;background:#F1FAFA;}\
                     div.fontpicker a{display:block;text-decoration:none;color:#000;background:#F1FAFA;padding:2px;}\
                     div.fontpicker a:hover{color:#999;background:#e3e6e9;}\
                     div.colorpicker {display:none;position:absolute;width:216px;border:2px solid #c3c9cf;background:#f8f8f8;}\
                     div.colorpicker table{border-collapse:collapse;margin:0;padding:0;}\
                     div.colorpicker .cell td{height:12px;width:12px;}\
                     div.fontColor{display:none;height:60px;overflow:auto;position:absolute;\
                     border:2px solid #c3c9cf;background:#F1FAFA;}\
                     div.fontColor a{display:block;text-decoration:none;color:#000;background:#F1FAFA;padding:2px;}\
                     div.fontColor a:hover{color:#999;background:#e3e6e9;}\
                     div.fontColor {display:none;position:absolute;width:60px;border:2px solid #c3c9cf;background:#f8f8f8;}\
                     div.fontColor table{border-collapse:collapse;margin:0;padding:0;}\
                     div.fontColor .cell td{height:12px;width:12px;}');
            }
        }
个人总结:dom是 如此的强大和优美,所以请不要随便说精通javascript.递归是一种思路和算法(这里用了8个递归 当然大部分思路一样!)。
关于递归借用我朋友的话 如果你项目里面有2个for 一般就可以尝试递归。

优点:把字符串转换成dom节点处理可以避免浏览器差役, 不要永远想着大规模去处理字符串 .当然这个功能的完成也求助了我的朋友!
吐槽一句 后台出身的人却喜欢前端技术。

最后感谢大家的阅读 希望能看的懂的朋友 如果觉得有意义帮忙推荐下 谢谢!

posted @ 2013-06-25 16:35  s_p  阅读(2839)  评论(6编辑  收藏  举报