Javascript 创建或更新给定HTML的脚本

Javascript 创建或更新给定HTML的脚本,javascript,jquery,html,dom,Javascript,Jquery,Html,Dom,代码正在获取一个HTML文件和configObject,并且根据此config对象需要修改此htmlFile内容(代码正在工作) 这是输入: 请注意,在数组的第一个OBJ中(有一种情况是未提供next属性,该属性表示将新脚本放在底部),下一个表示将脚本标记放在ID为的脚本之后“ui启动” 这是主要功能: getExtend: function(htmlContent, extendedHtmlObject) { var self = this; if (extendedHtmlO

代码正在获取一个HTML文件和configObject,并且根据此config对象需要修改此htmlFile内容(代码正在工作)

这是输入: 请注意,在数组的第一个OBJ中(有一种情况是未提供next属性,该属性表示将新脚本放在底部),下一个表示将脚本标记放在ID为的脚本之后“ui启动”

这是主要功能:

getExtend: function(htmlContent, extendedHtmlObject) {
    var self = this;
    if (extendedHtmlObject) {
        extendedHtmlObject.forEach(function(configs) {
            switch (configs.type) {
                case 'script':
                    htmlContent = self._handleScriptElement(htmlContent, configs);
                    break;
                case 'head':
                    break;
            }
        });
    }
    return htmlContent;
},
此方法确定是否需要根据输入对象创建新脚本或更新现有脚本属性

_handleScriptElement: function(htmlFilecontent, configEntry) {

    var oExtendedHTML = htmlFilecontent;
    switch (configEntry.action) {
        case 'new':
            oExtendedHTML = this._createNewScript(htmlFilecontent, configEntry);
            break;
        case 'upd':
            var sParsedHtml = this._htmlParser(oExtendedHTML);
            oExtendedHTML = this._updateScript(oExtendedHTML, configEntry, sParsedHtml);
            oExtendedHTML = this._convertHtmlBack(oExtendedHTML);
            break;
    }
    return oExtendedHTML;
},
这是使用两个选项创建新脚本的方法 1.第一个fork需要解析html 2.第二个不是

_createNewScript: function(htmlFilecontent, configEn) {
    var sScriptContent = this._createScript(configEntry.content);
    if (configEn.next != null) {
        var sParsedHtml = this._htmlParser(htmlFilecon);
        $(sScriptContent).insertAfter(sParsedHtml.find('#' + configEn.next));
        htmlFilecontent = this._convertHtmlBack(sParsedHtml);
    } else {
     //when the script is at the end of file
        var iHeadEndTagPos = htmlFilecon.search("(| )* )*head(|*>");
        htmlFilecon = htmlFilecon.substr(0, iHeadEndTagPos) + sNewScript + htmlFilecon.substr(iHeadEndTagPos);
    }
    return htmlFilecon;
},
这段代码是多余的,效率不高(我对JS还比较陌生),我可以用JS
prototype
来改进它吗? 我只想在开始时执行一次解析,在结束时执行
parseBack
(循环输入对象),但问题是在
createNewScript
中,第二个fork不需要使用解析器

requireJS的模块内的代码

更新 更清楚地说,外部API有两个输入和一个输出

  • HTML文件内容
  • 确定如何更新HTML的config对象,例如创建新脚本(作为数组中的第一个对象 extendedHtmlObject)或更新现有脚本内容,如 属性(值)
  • 输出应该是经过所有修改的扩展HTML
  • **更新2**
    如果我能提供更多的数据让它更清楚,请让我知道是什么。

    也许可以看看那里众多的模板系统

    或者,简化html创建。如果您使用innerHTML创建DOM节点,那么HTML文件内容应该是一个长字符串,其中包含完整的标记以及所有值/类名/等的占位符

    例如:
    ,然后用值替换所有占位符。然后,您可以使用这个字符串更新目标的innerHTML

    如果使用DOM节点创建,
    document.createElement()
    ,请提前创建所有这些模板节点(documentFragments在这里非常方便)。然后有一个函数可以检查“extendedHtmlObject”设置,并在更新时选择页面上已有的节点,或者选择预先制作的节点列表。将html结构作为节点后,将其交给另一个函数,该函数将使用“extendedHtmlObject”中的新值更新结构中的所有节点。然后可以将节点附加到其目标

    在这两种情况下,您都可以抛弃来回的html解析和分支

    伪代码:

    (function myModule() {
        var templates = {},
            createTemplates = function() {
                // Create all templates you'll use and save them.
                // If you create nodes, also include a mapping from each node to its respective value
                // eg: children[0] = 'label', children[1] = 'value'
            },
            updateTemplate = function( template, values ) {
                // INNERHTML: for each placeholder 'valueName' in string template, replace placeholder by values[valueName]
                // NODE CREATION: use the node mapping in the template to select each node in the template and replace its current value with values[valueName]
                return template;
            },
            getTemplate = function( type, reference ) {
                return (type === 'new') ? templates[reference] : $('#' + reference);
            },
            update = function( config ) {
                var html = getTemplate(config.action, (config.next || config.id)),
                    updated = updateTemplate(html, config);
                if (config.next) $('#' + config.next).insertAfter(html);
                else $('#' + config.id).innerHTML = html /* OR */ $('#' + config.id).appendChild(html);
            },
            init = function() {
                createTemplates();
            };
    }());
    
    TLDR:首先创建新的或获取现有的HTML,然后更新字符串或节点,然后确定它必须去哪里。使一切尽可能一般化

    • html创建函数应该能够创建任何html元素/更新任何模板,而不仅仅是脚本节点

    • update函数不应该关心其更新的html文件是以前存在的还是新生成的

    • 将html放回网站的函数不应该在创建函数中

    这样一来,您可能首先只会得到一个大的switch语句,该语句将使用不同的参数调用相同的函数,可以通过向“extendedthmlobject”添加另一个配置设置来轻松替换

    更新:

    我创建了一个可用结构的示例。它使用DOM方法(createElement等)创建一个包含更新输入字符串的新文档。您可以更改它以更好地匹配您的特定输入/输出。这更像是一个示例,说明了如何只需几个常规函数和大量配置设置即可创建所需的任何内容

    不过,这并不使用我之前提到的模板,因为这样做需要更长的时间。如果您想要模板化,只需查看handlebar.js或mustache.js

    但它更符合你自己的结构,所以我希望你更容易选择你喜欢的部件

    var originalHTML = '<script id="ui-boot" src="path/to/script/scriptname.js"></script>',
    
        imports = {},
    
    // IMPORTANT NOTE:
    // Using a string as the body of a script element might use eval(), which should be avoided at all costs.
    // Better would be to replace the 'content' config setting by a 'src' attribute and ahve the content in a seperate file you can link to.
        configAry = [
            { // script-new
                type: 'script',
                action: 'new',
                content: 'console.log(‘hello world’);',
                next: "ui-boot"
            }, 
            { // script-upd
                type: 'script',
                id: "ui-boot",
                action: 'upd',
                innerElem: [
                    {
                        type: 'attr',
                        id: 'data--ui-comersion',
                        content: '1.17'
                    }, 
                    {
                        type: 'attr',
                        id: 'src',
                        content: '/test/test2/-co.js'
                    }
                ]
            }
        ],
    
    // Extra helpers to make the code smaller. Replace by JQuery functions if needed.
        DOM = {
            'create' : function create( name ) {
                return document.createElement(name);
            },
            // Create a new document and use the string as the body of this new document.
            // This can be replaced by other functions of document.implementation if the string contains more than just the content of the document body.
            'createDoc' : function createDoc( str ) {
                var doc = document.implementation.createHTMLDocument('myTitle');
                doc.body.innerHTML = str;
                return doc;
            },          
            'insertAfter' : function insertAfter(node, target, content ) {
                target = content.querySelector(target);
                if (target.nextSibling) target.nextSibling.insertBefore(node);
                else target.parentNode.appendChild(node);
                return content;
            },
            'replace' : function replace( node, target, content ) {
                target = content.querySelector(target);
                target.parentNode.replaceChild(node, target);
                return content;
            },
            'update' : function update( node, textContent, attributes ) {
                if (textContent) node.textContent = textContent;
                return (attributes) ? 
                    Object.keys(attributes).reduce(function( node, attr ) {
                        node.setAttribute(attr, attributes[attr]);
                        return node;
                    }, node) :
                    node;
            }
        },
    
    // The actual module
        moduleHTMLExtender = (function( imports ) {
            var createExtension = function createExtension( extension, content ) {
                    switch (extension.action) {
                        case 'new' :
                            return {
                                'method' : 'insertAfter',
                                'node' : DOM.update(DOM.create(extension.type), extension.content),
                                'target' : '#' + extension.next
                            };
                        break;
                        case 'upd' :
                            return {
                                'method' : 'replace',
                                'node' : DOM.update(content.querySelector('#' + extension.id).cloneNode(), null, extension.innerElem.reduce(function( map, config ) {
                                    if (config.type === 'attr') map[config.id] = config.content;
                                    return map;
                                }, {})),
                                'target' : '#' + extension.id
                            }
                        break;
                        default:
                            return false;
                        break;
                    }
                },
                addExtensions = function addExtensions( content, extensions ) {
                    return extensions.reduce(function( content, extension ) {
                        return DOM[extension.method](extension.node, extension.target, content);
                    }, content);
                },
                // Returns new document as an [object Document]
                extendContent = function extendContent( content, extensions ) {
                    var doc = DOM.createDoc(content),
                        toExtend = (extensions) ? 
                            extensions.map(function( extension ) {
                                return createExtension(extension, doc);
                            }) :
                            null;
                    var res = null;
                    if (toExtend) return addExtensions(doc, toExtend);
                    else return doc;
                };
            // Export public interface. Replace this by your require.js code or similar.
            return {
                'extendContent' : extendContent
            };
        }( imports )),
    
        extendedHTMLDoc = moduleHTMLExtender.extendContent(originalHTML, configAry);
    
    console.log(extendedHTMLDoc.documentElement.outerHTML);
    // output = '<html><head><title>myTitle</title></head><body><script id="ui-boot" src="/test/test2/-co.js" data--ui-comersion="1.17"></script><script>console.log(hello world);</script></body></html>'; 
    
    var originalHTML='',
    导入={},
    //重要提示:
    //使用字符串作为脚本元素的主体可能会使用eval(),这应该不惜一切代价避免。
    //最好用“src”属性替换“content”配置设置,并将内容保存在一个单独的文件中,您可以链接到该文件。
    配置=[
    {//脚本新建
    键入:“脚本”,
    行动:"新",,
    内容:“console.log('hello world');”,
    下一步:“ui启动”
    }, 
    {//scriptupd
    键入:“脚本”,
    id:“ui启动”,
    行动:‘upd’,
    内部元素:[
    {
    类型:“attr”,
    id:'数据--ui访问',
    内容:“1.17”
    }, 
    {
    类型:“attr”,
    id:'src',
    内容:'/test/test2/-co.js'
    }
    ]
    }
    ],
    //额外的助手使代码更小。如果需要,替换为JQuery函数。
    DOM={
    “创建”:函数创建(名称){
    返回单据.createElement(名称);
    },
    //创建一个新文档,并将该字符串用作此新文档的正文。
    //如果字符串不仅仅包含文档正文的内容,则可以用document.implementation的其他函数替换。
    “createDoc”:函数createDoc(str){
    var doc=document.implementation.createHTMLDocument('myTitle');
    doc.body.innerHTML=str;
    退货单;
    },
    
    var originalHTML = '<script id="ui-boot" src="path/to/script/scriptname.js"></script>',
    
        imports = {},
    
    // IMPORTANT NOTE:
    // Using a string as the body of a script element might use eval(), which should be avoided at all costs.
    // Better would be to replace the 'content' config setting by a 'src' attribute and ahve the content in a seperate file you can link to.
        configAry = [
            { // script-new
                type: 'script',
                action: 'new',
                content: 'console.log(‘hello world’);',
                next: "ui-boot"
            }, 
            { // script-upd
                type: 'script',
                id: "ui-boot",
                action: 'upd',
                innerElem: [
                    {
                        type: 'attr',
                        id: 'data--ui-comersion',
                        content: '1.17'
                    }, 
                    {
                        type: 'attr',
                        id: 'src',
                        content: '/test/test2/-co.js'
                    }
                ]
            }
        ],
    
    // Extra helpers to make the code smaller. Replace by JQuery functions if needed.
        DOM = {
            'create' : function create( name ) {
                return document.createElement(name);
            },
            // Create a new document and use the string as the body of this new document.
            // This can be replaced by other functions of document.implementation if the string contains more than just the content of the document body.
            'createDoc' : function createDoc( str ) {
                var doc = document.implementation.createHTMLDocument('myTitle');
                doc.body.innerHTML = str;
                return doc;
            },          
            'insertAfter' : function insertAfter(node, target, content ) {
                target = content.querySelector(target);
                if (target.nextSibling) target.nextSibling.insertBefore(node);
                else target.parentNode.appendChild(node);
                return content;
            },
            'replace' : function replace( node, target, content ) {
                target = content.querySelector(target);
                target.parentNode.replaceChild(node, target);
                return content;
            },
            'update' : function update( node, textContent, attributes ) {
                if (textContent) node.textContent = textContent;
                return (attributes) ? 
                    Object.keys(attributes).reduce(function( node, attr ) {
                        node.setAttribute(attr, attributes[attr]);
                        return node;
                    }, node) :
                    node;
            }
        },
    
    // The actual module
        moduleHTMLExtender = (function( imports ) {
            var createExtension = function createExtension( extension, content ) {
                    switch (extension.action) {
                        case 'new' :
                            return {
                                'method' : 'insertAfter',
                                'node' : DOM.update(DOM.create(extension.type), extension.content),
                                'target' : '#' + extension.next
                            };
                        break;
                        case 'upd' :
                            return {
                                'method' : 'replace',
                                'node' : DOM.update(content.querySelector('#' + extension.id).cloneNode(), null, extension.innerElem.reduce(function( map, config ) {
                                    if (config.type === 'attr') map[config.id] = config.content;
                                    return map;
                                }, {})),
                                'target' : '#' + extension.id
                            }
                        break;
                        default:
                            return false;
                        break;
                    }
                },
                addExtensions = function addExtensions( content, extensions ) {
                    return extensions.reduce(function( content, extension ) {
                        return DOM[extension.method](extension.node, extension.target, content);
                    }, content);
                },
                // Returns new document as an [object Document]
                extendContent = function extendContent( content, extensions ) {
                    var doc = DOM.createDoc(content),
                        toExtend = (extensions) ? 
                            extensions.map(function( extension ) {
                                return createExtension(extension, doc);
                            }) :
                            null;
                    var res = null;
                    if (toExtend) return addExtensions(doc, toExtend);
                    else return doc;
                };
            // Export public interface. Replace this by your require.js code or similar.
            return {
                'extendContent' : extendContent
            };
        }( imports )),
    
        extendedHTMLDoc = moduleHTMLExtender.extendContent(originalHTML, configAry);
    
    console.log(extendedHTMLDoc.documentElement.outerHTML);
    // output = '<html><head><title>myTitle</title></head><body><script id="ui-boot" src="/test/test2/-co.js" data--ui-comersion="1.17"></script><script>console.log(hello world);</script></body></html>';