我目前正在编写一个JS库,以便在HTML中创建一个表单。这个图书馆需要:
所以,我现在所做的就是:
window.MyBasicLibrary = (function()
{
'use strict';
// Utilitarian function not to loose the scope
function bind(context, name){
return function(){
return context[name].apply(context, arguments);
};
}
// Utilitarian function to get DOM by class
function getElementsByClassName(node, classname)
{
var a = [];
var re = new RegExp('(^| )'+ classname +'( |$)');
var els = node.getElementsByTagName("*");
for (var i = 0, j = els.length; i < j; i++)
{
if (re.test(els[i].className))
a.push(els[i]);
}
return (a);
}
/*
** Utilitarian function to serialize a form
** See : https://code.google.com/archive/p/form-serialize/
*/
function serialize(form)
{
if (!form || form.nodeName !== "FORM") {
return;
}
var i, j, q = [];
for (i = form.elements.length - 1; i >= 0; i = i - 1) {
if (form.elements[i].name === "") {
continue;
}
switch (form.elements[i].nodeName) {
case 'INPUT':
switch (form.elements[i].type) {
case 'text':
case 'hidden':
case 'password':
case 'button':
case 'reset':
case 'submit':
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
break;
case 'checkbox':
case 'radio':
if (form.elements[i].checked) {
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
}
break;
case 'file':
break;
}
break;
case 'TEXTAREA':
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
break;
case 'SELECT':
switch (form.elements[i].type) {
case 'select-one':
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
break;
case 'select-multiple':
for (j = form.elements[i].options.length - 1; j >= 0; j = j - 1) {
if (form.elements[i].options[j].selected) {
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value));
}
}
break;
}
break;
case 'BUTTON':
switch (form.elements[i].type) {
case 'reset':
case 'submit':
case 'button':
q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
break;
}
break;
}
}
return q.join("&");
}
// Element should be the result of getElementByID.
var mb = function(element)
{
this.mainContainer = element;
};
mb.prototype.regional = {
mcta_1: "Form A <This One Works>",
mcta_2: "Form B",
mcta_3: "Form C",
submitFormA: "Submit"
};
mb.prototype.mainContainer = undefined;
mb.prototype.currentForm = undefined;
mb.prototype.APIEndpoint = 'https://www.example.com/api/';
mb.prototype.initialize = function()
{
this.createMainPageHTML();
};
mb.prototype.hideContainers = function()
{
var list = getElementsByClassName(this.mainContainer, "mbform_container");
for (var i = 0; i < list.length; i++)
{
list[i].style["display"] = "none";
}
}
mb.prototype.createMainPageHTML = function()
{
var element = document.getElementById('mbform_mainpage');
this.hideContainers();
if (typeof(element) != 'undefined' && element != null)
{
element.style["display"] = "block";
}
else
{
var mcta1 = '<div id="mbform_mcta1" class="button">'+ this.regional.mcta_1 +'</div>';
var mcta2 = '<div id="mbform_mcta2" class="button">'+ this.regional.mcta_2 +'</div>';
var mcta3 = '<div id="mbform_mcta3" class="button">'+ this.regional.mcta_3 +'</div>';
var mpHTML = '<div id="mbform_mainpage" class="mbform_container">'+mcta1 + mcta2 + mcta3 +'</div>';
// TODO Load CSS
// Add HTML to DOM
this.mainContainer.innerHTML = mpHTML; // takes an HTML string
// TODO Load JS Dependencies
// Add Event listener
document.getElementById('mbform_mcta1').addEventListener("click", bind(this, "createFormA"), false);
document.getElementById('mbform_mcta2').addEventListener("click", bind(this, "createFormB"), false);
document.getElementById('mbform_mcta3').addEventListener("click", bind(this, "createFormC"), false);
}
};
mb.prototype.createFormA = function()
{
var element = document.getElementById('mbform_FormAContainer');
this.hideContainers();
this.currentForm = "mbform_FormA";
if (typeof(element) != 'undefined' && element != null)
{
element.style["display"] = "block";
}
else
{
var iemail = '<input type="text" value="" name="email" id="mbform_iemail"/><br/>';
var ifirstname = '<input type="text" value="" name="firstname" id="mbform_ifirstname"/><br/>';
var ilastname = '<input type="text" value="" name="lastname" id="mbform_ilastname"/><br/>';
var formHTML = '<form id="mbform_FormA">'+iemail + ifirstname + ilastname + '</form>'
// TODO : Disable form default bahaviour (Submit when Enter Keypress + submit button), button is placed outside form for testing purpose.
var submitButton = '<button id="mbform_FormASubmit">'+ this.regional.submitFormA +'</button>';
var formContainerHTML = '<div id="mbform_FormAContainer" class="mbform_container">'+ formHTML + submitButton +'</div>';
this.mainContainer.innerHTML += formContainerHTML; // Append HTML to existing
document.getElementById('mbform_FormASubmit').addEventListener("click", bind(this, "saveForm"), false);
}
};
mb.prototype.createFormB = function()
{
console.log(this.mainContainer); // Is scope ok ?
};
mb.prototype.createFormC = function()
{
console.log(this.mainContainer); // Is scope ok ?
};
mb.prototype.getPostFromCurrentForm = function()
{
var data = serialize(document.getElementById(this.currentForm));
console.log(data);
return (data);
}
mb.prototype.saveForm = function()
{
var xhr = new XMLHttpRequest();
var params = this.getPostFromCurrentForm();
xhr.open('POST', this.APIEndpoint, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
console.log("Loading...");
};
// Current APIEndpoint is example.com, do not send the form.
//xhr.send(params);
}
return (mb);
})();下面是如何初始化库
(function() {
var dom = document.getElementById('myForm');
var mb = new MyBasicLibrary(dom);
mb.initialize();
})();我尽了最大的努力来尊重javascript最佳实践,但我不确定我是否做得很好。你对此有何看法?
此外,在变量中包含原始HTML似乎是一种糟糕的做法,但是为了性能目的,我需要最小化向服务器提出的请求的数量。这意味着我无法存储HTML服务器端并通过AJAX发送它。这是最好的解决办法吗?
我已经创建了一个JSFiddle,以防您想要修改它。
发布于 2017-02-11 08:49:55
答复:
开放/关闭:
元素-nodeName-类型的组合目前对于库的使用者来说很难扩展以允许它们处理更多。
表单-目前只能处理3,可以使处理0到多少硬件可以处理。
不要重复:
如果将问题的代码与这个答案进行比较,就可以看出。增加了一些局部变量和函数来减少冗余,还使用了本机文档方法。
window.MyBasicLibrary = (function()
{
'use strict';
// Utilitarian function not to loose the scope
function bind(context, name){
return function(){
return context[name].apply(context, arguments);
};
}
// Utilitarian function to get DOM by class
function getElementsByClassName(node, classname)
{
return node.getElementsByClassName(classname);// works IE9+
}
/*
** Utilitarian function to serialize a form
** See : https://code.google.com/archive/p/form-serialize/
*/
function serialize(form)
{
if (!form || form.nodeName !== "FORM") {
return;
}
var i, j, name, value, q = [];
var elements = form.elements;
var push = function()
{
q.push(name + "=" + encodeURIComponent(value));
};
for (i = elements.length - 1; i >= 0; i = i - 1) {
var element = elements[i];
name = element.name;
if (name === "") {
continue;
}
value = element.value;
switch (element.nodeName) {
case 'INPUT':
switch (element.type) {
case 'text':
case 'hidden':
case 'password':
case 'button':
case 'reset':
case 'submit':
push();
break;
case 'checkbox':
case 'radio':
if (element.checked) {
push();
}
break;
case 'file':
break;
}
break;
case 'TEXTAREA':
push();
break;
case 'SELECT':
switch (element.type) {
case 'select-one':
push();
break;
case 'select-multiple':
var options = element.options;
for (j = options.length - 1; j >= 0; j = j - 1) {
var option = options[j];
if (option.selected) {
value = option.value;
push();
}
}
break;
}
break;
case 'BUTTON':
switch (element.type) {
case 'reset':
case 'submit':
case 'button':
push();
break;
}
break;
}
}
return q.join("&");
}
// Element should be the result of getElementByID.
var mb = function(element)
{
this.mainContainer = element;
};
mb.prototype.regional = {
mcta_1: "Form A <This One Works>",
mcta_2: "Form B",
mcta_3: "Form C",
submitFormA: "Submit"
};
mb.prototype.mainContainer = undefined;
mb.prototype.currentForm = undefined;
mb.prototype.APIEndpoint = 'https://www.example.com/api/';
mb.prototype.initialize = function()
{
this.createMainPageHTML();
};
mb.prototype.hideContainers = function()
{
var list = getElementsByClassName(this.mainContainer, "mbform_container");
for (var i = 0; i < list.length; i++)
{
list[i].style["display"] = "none";
}
}
mb.prototype.createMainPageHTML = function()
{
var element = document.getElementById('mbform_mainpage');
this.hideContainers();
if (typeof(element) != 'undefined' && element != null)
{
element.style["display"] = "block";
}
else
{
var button = function (id, text)
{
return '<div id="mbform_mcta' + id + '" class="button">'+ text +'</div>';
};
var mcta1 = button(1, this.regional.mcta_1);
var mcta2 = button(2, this.regional.mcta_2);
var mcta3 = button(3, this.regional.mcta_3);
var mpHTML = '<div id="mbform_mainpage" class="mbform_container">'+mcta1 + mcta2 + mcta3 +'</div>';
// TODO Load CSS
// Add HTML to DOM
this.mainContainer.innerHTML = mpHTML; // takes an HTML string
// TODO Load JS Dependencies
// Add Event listener
var listener = function(id, letter)
{
document.getElementById('mbform_mcta' + id).addEventListener("click", bind(this, "createForm" + letter), false);
};
listener(1, "A");
listener(2, "B");
listener(3, "C");
}
};
mb.prototype.createFormA = function()
{
var element = document.getElementById('mbform_FormAContainer');
this.hideContainers();
this.currentForm = "mbform_FormA";
if (typeof(element) != 'undefined' && element != null)
{
element.style["display"] = "block";
}
else
{
var text = function(name)
{
return '<input type="text" value="" name="' + name + '" id="mbform_i' + name + '"/><br/>';
};
var iemail = text("email");
var ifirstname = text("firstname");
var ilastname = text("lastname");
var formHTML = '<form id="mbform_FormA">'+iemail + ifirstname + ilastname + '</form>'
// TODO : Disable form default bahaviour (Submit when Enter Keypress + submit button), button is placed outside form for testing purpose.
var submitButton = '<button id="mbform_FormASubmit">'+ this.regional.submitFormA +'</button>';
var formContainerHTML = '<div id="mbform_FormAContainer" class="mbform_container">'+ formHTML + submitButton +'</div>';
this.mainContainer.innerHTML += formContainerHTML; // Append HTML to existing
document.getElementById('mbform_FormASubmit').addEventListener("click", bind(this, "saveForm"), false);
}
};
mb.prototype.createFormB = function()
{
console.log(this.mainContainer); // Is scope ok ?
};
mb.prototype.createFormC = function()
{
console.log(this.mainContainer); // Is scope ok ?
};
mb.prototype.getPostFromCurrentForm = function()
{
var data = serialize(document.getElementById(this.currentForm));
console.log(data);
return (data);
};
mb.prototype.saveForm = function()
{
var xhr = new XMLHttpRequest();
var params = this.getPostFromCurrentForm();
xhr.open('POST', this.APIEndpoint, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
console.log("Loading...");
};
// Current APIEndpoint is example.com, do not send the form.
//xhr.send(params);
};
return (mb);
})();https://codereview.stackexchange.com/questions/154761
复制相似问题