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

Generate form and append to the body

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thebodyappendgenerateandform

Problem

I'm writing a plugin and want it to have no dependencies. I create a form and append it to the page, but the code is really long. Does anyone have any suggestions to clean it up, perhaps shortening it? I feel like there must be a better way!

```
// Create elements
var elements = [
reporter_wrapper = document.createElement('div'),
reporter_close = document.createElement('button'),
reporter_title = document.createElement('h1'),
reporter_title_label = document.createElement('label'),
reporter_bug_title = document.createElement('input'),
reporter_priority_label = document.createElement('label'),
reporter_bug_priority = document.createElement('select'),
reporter_details_label = document.createElement('label'),
reporter_bug_details = document.createElement('textarea'),
reporter_user_label = document.createElement('label'),
reporter_user = document.createElement('input'),
reporter_submit = document.createElement('button')];

// // Add class names
reporter_wrapper.className = 'buggr__reporter';
reporter_close.className = 'buggr__reporter-close';
reporter_title.className = 'buggr__reporter-title';
reporter_bug_title.className = 'buggr__reporter-input';
reporter_bug_priority.className = 'buggr__reporter-select';
reporter_bug_details.className = 'buggr__reporter-textarea';
reporter_user.className = 'buggr__reporter-input';
reporter_submit.className = 'buggr__reporter-submit';

// Input types
reporter_user.type = 'text';
reporter_bug_title.type = 'text';

// Populate title
reporter_title.innerHTML = 'Report a bug';

// Populate label text
reporter_title_label.innerHTML = 'Bug title:';
reporter_priority_la

Solution

var elements = [
      reporter_wrapper                = document.createElement('div'),
      reporter_close                  = document.createElement('button'),
      reporter_title                  = document.createElement('h1'),
      reporter_title_label            = document.createElement('label'),
      reporter_bug_title              = document.createElement('input'),
      reporter_priority_label         = document.createElement('label'),
      reporter_bug_priority           = document.createElement('select'),
      reporter_details_label          = document.createElement('label'),
      reporter_bug_details            = document.createElement('textarea'),
      reporter_user_label             = document.createElement('label'),
      reporter_user                   = document.createElement('input'),
      reporter_submit                 = document.createElement('button')];


Hmm. An array that has variables that each are assigned a value. Hmm. Oh wait; that sounds like an object!

Instead of reinventing the wheel and creating this array thing that's values are assigned to variables too, you should just create an object.

Here is what that would look like:

var reporter = {
    wrapper: document.createElement("div"),
    ...
};


I removed the part reporter_ from the key names because, now that they are in an object, you need not to worry about conflicting with other variable names.

There is practically no difference.

Let's take the last tip to the next level.

This time, let's create a map of names of the keys of the object, and then the type of HTML element to instantiate.

Here is what I mean:

var namesAndElements = {
    "wrapper": "div",
    "close": "button",
    ...
}


Excuse the poor variable name.

See the pattern? The keys are simply the part after reporter_ in the original array, and the values are the parameter passed into document.createElement.

Now, to create the object/map of elements, we simply need to create a loop that stores these keys and values into a new object/map.

Here is what I came up with:

var reporter = {};
for(var name in namesAndElements) {
    elements[name] = document.createElement(namesAndElements[name]);
}


Now, in order to access something from this object, you could write:

elements.details_label


As an example.

And you will get the element assigned to it.

reporter_wrapper.className          = 'buggr__reporter';
reporter_close.className            = 'buggr__reporter-close';
reporter_title.className            = 'buggr__reporter-title';
reporter_bug_title.className        = 'buggr__reporter-input';
reporter_bug_priority.className     = 'buggr__reporter-select';
reporter_bug_details.className      = 'buggr__reporter-textarea';
reporter_user.className             = 'buggr__reporter-input';
reporter_submit.className           = 'buggr__reporter-submit';


See something similar in the value that these classes are being assigned? If not, they are start with this:

"buggr__reporter"


Therefore, we can simplify this by creating a map (like above) of the elements whose classes need to be changed, and the value to change it to.

Here is what I came up with:

var newClasses = {
    "wrapper": "",
    "close", "-close",
    "title", "-title",
    "bug_title", "input",
    ...
}


Excuse the poor variable name.

Notice anything familiar about this object? The keys are keys of the first map we created, and the values are the extra part of the string that is not in the pattern I mentioned.

Now all we have to do is create a loop for setting these class names:

for(var element in newClasses) {
    reporter[element] = ("buggr__reporter" + newClasses[element]);
}

Code Snippets

var elements = [
      reporter_wrapper                = document.createElement('div'),
      reporter_close                  = document.createElement('button'),
      reporter_title                  = document.createElement('h1'),
      reporter_title_label            = document.createElement('label'),
      reporter_bug_title              = document.createElement('input'),
      reporter_priority_label         = document.createElement('label'),
      reporter_bug_priority           = document.createElement('select'),
      reporter_details_label          = document.createElement('label'),
      reporter_bug_details            = document.createElement('textarea'),
      reporter_user_label             = document.createElement('label'),
      reporter_user                   = document.createElement('input'),
      reporter_submit                 = document.createElement('button')];
var reporter = {
    wrapper: document.createElement("div"),
    ...
};
var namesAndElements = {
    "wrapper": "div",
    "close": "button",
    ...
}
var reporter = {};
for(var name in namesAndElements) {
    elements[name] = document.createElement(namesAndElements[name]);
}
elements.details_label

Context

StackExchange Code Review Q#96134, answer score: 5

Revisions (0)

No revisions yet.