D.Rivera
D.Rivera

Reputation: 35

Javascript DRY Design Patterns - Functions vs Object

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;

}

Upvotes: 2

Views: 1855

Answers (3)

vsync
vsync

Reputation: 130155

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;
}

Upvotes: 0

Aadit M Shah
Aadit M Shah

Reputation: 74204

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.

Upvotes: 1

Dan D.
Dan D.

Reputation: 74645

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.

Upvotes: 1

Related Questions