Javascript 创建或更新给定HTML的脚本
代码正在获取一个HTML文件和configObject,并且根据此config对象需要修改此htmlFile内容(代码正在工作) 这是输入: 请注意,在数组的第一个OBJ中(有一种情况是未提供next属性,该属性表示将新脚本放在底部),下一个表示将脚本标记放在ID为的脚本之后“ui启动” 这是主要功能: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
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还比较陌生),我可以用JSprototype
来改进它吗?
我只想在开始时执行一次解析,在结束时执行parseBack
(循环输入对象),但问题是在createNewScript
中,第二个fork不需要使用解析器
requireJS的模块内的代码
更新
更清楚地说,外部API有两个输入和一个输出
如果我能提供更多的数据让它更清楚,请让我知道是什么。也许可以看看那里众多的模板系统 或者,简化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放回网站的函数不应该在创建函数中
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>';