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節點處理可以避免瀏覽器差役, 不要永遠想着大規模去處理字符串 .當然這個功能的完成也求助了我的朋友!
吐槽一句 后台出身的人卻喜歡前端技術。

最后感謝大家的閱讀 希望能看的懂的朋友 如果覺得有意義幫忙推薦下 謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM