snippetjavascriptMinor
Writting a JS library to create a HTML form
Viewed 0 times
createwrittinglibraryformhtml
Problem
I'm currently writting a JS Library in order to create a form in HTML.
This library need to be :
So, here is what I've done for now :
```
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 = 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
This library need to be :
- Cross-browser, with compatibility with at least IE10 (earlier version can be considered as bonus)
- Multi language : you should be able to change the form language
- Able to load external javascript dependencies*
- Communicate with my API
- Fast
- As simple to use as possible
So, here is what I've done for now :
```
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 = 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
Solution
Library violates Single Responsibility Principle, Open/Closed Principal, and Don't Repeat Yourself.
Responsibilies:
Open/Closed:
element-nodeName-type combination would currently be difficult for consumer of the library to extend to allow them to handle more.
Forms - Currently can only handle 3, could be made to handle zero to how many the hardware can handle.
Don't Repeat Yourself:
Which can be seen if the question's code is compared with this answers. Added some local variables and functions to reduce redundancy, also used native document method.
```
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 ",
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 '+ text +'';
};
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 = ''+mcta1 + mcta2 + mcta3 +'';
// 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_
Responsibilies:
- Posting Data
- Serializing Data
- Creating Markup
- Maintaining State
- UI effects
- Logging
Open/Closed:
element-nodeName-type combination would currently be difficult for consumer of the library to extend to allow them to handle more.
Forms - Currently can only handle 3, could be made to handle zero to how many the hardware can handle.
Don't Repeat Yourself:
Which can be seen if the question's code is compared with this answers. Added some local variables and functions to reduce redundancy, also used native document method.
```
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 ",
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 '+ text +'';
};
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 = ''+mcta1 + mcta2 + mcta3 +'';
// 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_
Code Snippets
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",Context
StackExchange Code Review Q#154761, answer score: 2
Revisions (0)
No revisions yet.