Generate form and append to the body 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_label.innerHTML   = 'Bug priority:';
  reporter_details_label.innerHTML    = 'Bug details: &lt;small&gt;(Please include any specific steps to replicate)&lt;/small&gt;';
  reporter_user_label.innerHTML       = 'Your name:'

  // Poulate submit button
  reporter_submit.innerHTML           = 'Submit Bug';

  // Populate select with options
  var select_options = ['Low', 'Medium', 'Hard'];
  for(var i = 0; i &lt; select_options.length; i ++) {
    var option = document.createElement('option');
    option.value = select_options[i];
    option.innerHTML = select_options[i];
    reporter_bug_priority.appendChild(option);
  }

  // Create DOM tree
  for(var i = 1; i &lt; elements.length; i ++) {
    reporter_wrapper.appendChild(elements[i]);
  }

  // Add event listeners
  reporter_close.addEventListener('click', this.close);
  reporter_submit.addEventListener('click', this.submit);

  // Append DOM tree
  document.body.appendChild(reporter_wrapper);
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]);
}