2

Below is a code snippet of a function that creates and appends div HTML objects. The function is called from another function which appends additional elements to it.

I'm finding myself writing similar code as whats illustrated below. I know there has to be another more efficient way writing this code. What dry design pattern should I using? Is the object notation better for something like this? Examples would be great.

function create_element_container(){
  var newElement = document.createElement('div'); //create container element
      newElement.className = 'dropped'; //add classes to container element      

  var controllerContainer = document.createElement('div');
      controllerContainer.className = 'drop-element-controls';

      newElement.appendChild(controllerContainer);//Append controller container to main div

  var controller_left = document.createElement('div');
      controller_left.className = 'drop-move-controller';

      controllerContainer.appendChild(controller_left);

      var controller_left_move = document.createElement('div');
          controller_left_move.className = 'drop-move';

            controller_left.appendChild(controller_left_move);

            var controller_left_icon = document.createElement('span');
                controller_left_icon.className = 'fa fa-question fa-lg';

                controller_left_move.appendChild(controller_left_icon);

      controllerContainer.appendChild(controller_left); //Append controller Left


  var controller_middle = document.createElement('div')
      controller_middle.className = 'drop-sortable-controller';

      controllerContainer.appendChild(controller_middle);

      var controller_middle_sortable = document.createElement('div');
          controller_middle_sortable.className = 'drop-sortable';

          controller_middle.appendChild(controller_middle_sortable);

            var controller_middle_icon = document.createElement('span');
                controller_middle_icon.className = 'fa fa-arrows fa-lg';

                controller_middle_sortable.appendChild(controller_middle_icon);

      controllerContainer.appendChild(controller_middle); //Append controller Left


  var controller_right = document.createElement('div')
      controller_right.className = 'drop-remove-controller';

      controllerContainer.appendChild(controller_right);

      var controller_right_move = document.createElement('div');
          controller_right_move.className = 'drop-remove';

          controller_right.appendChild(controller_right_move);

            var controller_right_icon = document.createElement('span');
                controller_right_icon.className = 'fa fa-remove fa-lg';

                controller_right_move.appendChild(controller_right_icon);

  return newElement;

}
5
  • 1
    stop writing so many var, There are people with OCD here Commented Sep 21, 2014 at 9:25
  • 1
    @vsync: There's nothing wrong with the vars. What is odd is the seemingly arbitrary indentation, and the double calls to controllerContainer.appendChild(controller_*) Commented Sep 21, 2014 at 11:13
  • yes there is wrong with them. there is more than one of them. also the indentation is obviously off. Commented Sep 21, 2014 at 13:08
  • Hi guys thanks for your comments. I didn't think there was anything wrong with the vars, isn't it good practice to declare a new variable with var. Also what do you mean the double calls to to controllerContainer these calls are sequential to append to the elements. The person below did list another style that took out the redundancies. @vsync how would you write the function/object? Commented Sep 21, 2014 at 16:43
  • see my answer, with the cleanest solution. Commented Sep 21, 2014 at 16:56

3 Answers 3

1

First I would write a createElement function:

function createElement(tagName, className) {
    var element = document.createElement(tagName);
    element.className = className;
    return element;
}

Next I would rewrite your create_element_container function as follows:

function create_element_container() {
    var newElement = createElement("div", "dropped");

    var controllerContainer = newElement
        .appendChild(createElement("div", "drop-element-controls"));

    controllerContainer
        .appendChild(createElement("div", "drop-move-controller"))
        .appendChild(createElement("div", "drop-move"))
        .appendChild(createElement("span", "fa fa-question fa-lg"));

    controllerContainer
        .appendChild(createElement("div", "drop-sortable-controller"))
        .appendChild(createElement("div", "drop_sortable"))
        .appendChild(createElement("span", "fa fa-arrows fa-lg"));

    controllerContainer
        .appendChild(createElement("div", "drop-remove-controller"))
        .appendChild(createElement("div", "drop-remove"))
        .appendChild(createElement("div", "fa fa-remove fa-lg"));

    return newElement;
}

You can do this because parent.appendChild(child) returns the child element.

Sign up to request clarification or add additional context in comments.

Comments

1

Your code consists of this repeated:

var controllerContainer = document.createElement('div');
    controllerContainer.className = 'drop-element-controls';

    newElement.appendChild(controllerContainer);

You might want to consider put-selector. With put:

var controllerContainer = put(newElement, 'div.drop-element-controls');

Doing that cuts down that function by 2/3rd. Then even combine the calls:

put(controllerContainer, 'div.drop-move-controller div.drop-move span.fa.fa-question.fa-lg <<');

Replaces:

 var controller_left = document.createElement('div');
      controller_left.className = 'drop-move-controller';

      controllerContainer.appendChild(controller_left);

      var controller_left_move = document.createElement('div');
          controller_left_move.className = '';

            controller_left.appendChild(controller_left_move);

            var controller_left_icon = document.createElement('span');
                controller_left_icon.className = 'fa fa-question fa-lg';

                controller_left_move.appendChild(controller_left_icon);

      controllerContainer.appendChild(controller_left); //Append controller Left

That cuts it down by 15/16th.

Another option is to just create the first element:

var newElement = document.createElement('div'); //create container element
    newElement.className = 'dropped'; //add classes to container element 

And then do:

newElement.innerHTML = '<div class="drop-move-controller"><div class="drop-move"><span class="fa fa-question fa-lg"></span></div></div>...';

Note that the HTML above only includes the div with the class drop-move-controller.

1 Comment

I'm looking for a solution that doesn't involve another plug-in but thanks anyway.
0

It depends how many times it would run. if not many, then I would prepare a string of DOM and just use innerHTML to put everything in some container. this would be more readable and maintainable.

Basic example:

function create_element_container(){
    var elm, template;
    
    elm = document.createElement('div'); //create container element
    elm.className = 'dropped';
    
    template = '<div class="something another"> \
                    <span></span> \
                </div> \
                <span class="foo"></span>';
    
    // this makes our template text into a real DOM elements
    elm.innerHTML = template;
    
    return elm;
}

4 Comments

Great approach, very clean! I think a combination of this and @Aadit code will work perfectly.
there is no combination :) his and mine are totally different things. you either use this or that, but there is nothing more simpler than my approach, unless you're using jQuery...and still, not by much at all.
Your code is missing the controller element container. Also my code is a bit more involved I just posted a snippet of the function.
my code is only a sample, you can write anything you want as the "template"... thousands lines of HTML. it will be maintainable because it looks exactly like HTML..using actual templates is even better. see handlebarsjs.com

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.