HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptMinor

Writting a JS library to create a HTML form

Submitted by: @import:stackexchange-codereview··
0
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 :

  • 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:

  • 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.