0
\$\begingroup\$

In these fiddles I am generating the number of textboxes and checkboxes depending on the input of user.

This first fiddle deals with the first problem generate number of textboxes onchange of the input textboxes from errand (sample).

The second one is from Guruprasad Rao that helped add an attribute value on the generated checkboxes (sample).

I want this to be optimized to run faster and better.

HTML

<input type="number" id="nostorey" name="" class=' InputBox' />

<table id="floor">
    <tr id="headtable">
        <td>
            <center>Floor Names</center>
        </td>
        <td>
            <center>Floor wise Area</center>
        </td>
    </tr>
    <tr>
        <td>
            <p>1st Floor</p>
        </td>
        <td>
            <input type='text' id="firstfloor" name='' maxlength="10" value="" class='floor InputBox' />
        </td>
    </tr>
    <tr>
        <td>
            <p>2nd Floor</p>
        </td>
        <td>
            <input type='text' id="secondfloor" name='' maxlength="10" value="" class='floor InputBox' />
        </td>
    </tr>
    <tr>
        <td>
            <p>3rd Floor</p>
        </td>
        <td>
            <input type='text' id="thirdfloor" name='' maxlength="10" value="" class='floor InputBox' />
        </td>
    </tr>
    <tr>
        <td>
            <p>4th Floor</p>
        </td>
        <td>
            <input type='text' id="fourthfloor" name='' maxlength="10" value="" class='floor InputBox' />
        </td>
    </tr>
    <tr>
        <td>
            <p>Total</p>
        </td>
        <td>
            <input type='text' id="total" readonly name='' maxlength="10" value="" class=' InputBoxD' />
        </td>
    </tr>
</table>
<table id="flooring">
    <tbody>
        <tr>
            <td><strong><p>Flooring</p></strong>

            </td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr id="headerfloor">
            <td>
                <hr>
            </td>
            <td> <span class="checkboxfloorspan">1st Floor</span>

            </td>
            <td> <span class="checkboxfloorspan">2nd Floor</span>

            </td>
            <td> <span class="checkboxfloorspan">3rd Floor</span>

            </td>
            <td> <span class="checkboxfloorspan">4th Floor</span>

            </td>
        </tr>
        <tr>
            <td><span>Reinforced Concrete</span>

            </td>
            <td>
                <input type="checkbox" value="1st Floor Reinforced Concrete" class="materialsfloor1st checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="2nd Floor Reinforced Concrete" class="materialsfloor2nd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="3rd Floor Reinforced Concrete" class="materialsfloor3rd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="4th Floor Reinforced Concrete" class="materialsfloor4th checkboxstrucmatfloor" name="flooring[]">
            </td>
        </tr>
        <tr>
            <td><span>Plain Cement</span>

            </td>
            <td>
                <input type="checkbox" value="1st Floor Plain Cement" class="materialsfloor1st checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="2nd Floor Plain Cement" class="materialsfloor2nd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="3rd Floor Plain Cement" class="materialsfloor3rd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="4th Floor Plain Cement" class="materialsfloor4th checkboxstrucmatfloor" name="flooring[]">
            </td>
        </tr>
        <tr>
            <td><span>Marble</span>

            </td>
            <td>
                <input type="checkbox" value="1st Floor Marble" class="materialsfloor1st checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="2nd Floor Marble" class="materialsfloor2nd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="3rd Floor Marble" class="materialsfloor3rd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="4th Floor Marble" class="materialsfloor4th checkboxstrucmatfloor" name="flooring[]">
            </td>
        </tr>
        <tr>
            <td><span>Wood</span>

            </td>
            <td>
                <input type="checkbox" value="1st Floor Wood" class="materialsfloor1st checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="2nd Floor Wood" class="materialsfloor2nd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="3rd Floor Wood" class="materialsfloor3rd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="4th Floor Wood" class="materialsfloor4th checkboxstrucmatfloor" name="flooring[]">
            </td>
        </tr>
        <tr>
            <td><span>Tiles</span>

            </td>
            <td>
                <input type="checkbox" value="1st Floor Tiles" class="materialsfloor1st checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="2nd Floor Tiles" class="materialsfloor2nd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="3rd Floor Tiles" class="materialsfloor3rd checkboxstrucmatfloor" name="flooring[]">
            </td>
            <td>
                <input type="checkbox" value="4th Floor Tiles" class="materialsfloor4th checkboxstrucmatfloor" name="flooring[]">
            </td>
        </tr>
    </tbody>
</table>

jQuery

function addFloors(actual, target){
    for(i = actual +1;i<=target;i++)
        {

            newItemHTML = '<tr><td ><p>' + i + 'th Floor</p></td><td><input type="text" name="" class="floor InputBox " id="floor' + i + '"></td></tr>';

            $("table#floor tr").last().before(newItemHTML);
        }
}

function removeFloors(target){
    if(target >= 4)
    {
        $('.floor').slice(target).parent().parent().remove();
    }
}
function addCheckbox(actual, target) {


    for (var i = actual + 1; i <= target; i++) {

        $("table#flooring tr:nth-child(2)").find('td:last-child').after('<td><span class="floorspan">' + i + 'th Floor</span></td>');
        $("table#flooring tr").slice(2).find('td:last-child').after('<td><input value="'+i+'" type="checkbox" class="checkboxfloor materialsfloor' + i + 'th" name="flooring[]"></td>');

    }
     var spans =
    $("table#flooring tr").slice(2).find('td:first-child').find('span');
    var textToAdd=[];
    $.each(spans,function(index,value){
        textToAdd.push($(value).text());
    });
    for(var i=0;i<spans.length;i++)
    {

        var checks=$("input[value="+(i+5)+"]");
        $.each(checks,function(index,value){

            $(value).attr('value',(i+5)+'th Floor '+textToAdd[index]);
        });

    }

}
function removeCheckbox(target) {
    if (target >= 4) {
        $("table#flooring tr").find('td:eq(' + target + ')').nextAll().remove();

    } else {
        $("table#flooring tr").find('td:nth-child(5)').nextAll().remove();

    }
}
$("#nostorey").bind('change', function() {
    curVal = $.trim($(this).val()).match(/^\d*$/);
    curFloors = $('.floor').length;
    var numberNotChecked = curVal;
    if(curVal > curFloors)
    {
        addFloors(curFloors, curVal);
    }else if(curVal < curFloors)
    {
        removeFloors(curVal);
    }
    if (numberNotChecked > curFloors) {
            addCheckbox(curFloors, numberNotChecked);
            //addMaterial(curFloors);
        } else if (numberNotChecked < curFloors) {
            //removeFloors(curVal);
            removeCheckbox(numberNotChecked);
        }

    $('.floor').each(function(index){
        if(index >= curVal)
        {
            $(this).prop('disabled', true);
        }else
        {
            $(this).prop('disabled', false);
        }
    });

});
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Welcome to Code Review! There are a lot of things we can focus on here, so let's start with your request for suggestions around optimization.

Native JavaScript will outperform JQuery Equivalents

jQuery makes it easy to write working code quickly, but this is often at the expense of code performance. Converting jQuery methods to their native JavaScript equivalents can increase perfomance.

  • when selecting a single element by its ID, document.getElementById("idvalue") will be much faster than $("#idvalue")
  • when selecting an array of elements by CSS selectors, document.querySelectorAll("tag .class[etc]") will be faster than $(tag .class[etc])
  • When selecting a single element by CSS selectors, document.querySelector("tag .class[etc]") will be speedy as well
  • you can chain query selectors together for better performance (although the actual benefits can vary between different browsers' implementations of JavaScript), e.g. document.getElementById("idvalue").querySelector("tag .class")
  • document.getElementsByTagName() and document.getElementsByClassName can also be used

Note that there are also native JavaScript equivalents for manipulating HTML within HTML elements (such as element.innerHTML and element.insertAdjacentHTML()). Table elements in particular have their own special properties and methods for manipulating their layout and presentation, as documented here.

Cache reused HTML elements and collections to limit DOM queries

If you have code that queries the DOM using any of the selector methods I mentioned in the above section, you can save the results to a variable that you can access at will. That way you don't need to re-query the DOM for those elements if you need them later in the code.

The exception to this is when the DOM may have changed and you want to get the latest version, in which case you generally need to re-query the DOM.

Avoid polluting the global namespace

You can avoid creating global variables by simply wrapping all your code in an immediately-invoked function expression (IIFE).

(function(){ /* your code here */ }();

This creates a function scope around your code (function scope is the only type of scope in JavaScript), limiting those variables to use within that scope.

Another related pitfall to watch out for is implicitly declaring variables by assigning them values without using the var keyword to explicitly define their scope. There are a few variable assignments in your code where variables are unnecesarily scoped to global namespace, though defined and used only within functions.

Textbox event choice

For user-friendliness, I recommend attaching your event listener to the "keyup" event instead of the "change" event; that way the floor textboxes will update immediately as the user types a number instead of waiting for the input textbox to lose focus.

Working example of some modifications

Here's an example of your first linked jsfiddle modified to use native JavaScript and the other recommendations I provided above:

(function() {
  var floorTable = document.getElementById("floor");

  function addFloors(actual, target) {
    for (i = actual + 1; i <= target; i++) {
      var row = floorTable.insertRow(floorTable.rows.length - 1);
      var cell1 = row.insertCell(0);
      var cell2 = row.insertCell(1);
      cell1.innerHTML = '<p>' + i + 'th Floor</p>';
      cell2.innerHTML = '<input type="text" name="" class="floor InputBox " id="floor' + i + '"/>';
    }
  }

  function removeFloors(target) {
    var floors = floorTable.querySelectorAll('.floor');
    var row;
    if (target >= 4) {
      row = floors[target].parentElement.parentElement;
      row.parentElement.removeChild(row);
    } else {
      for (var i = floors.length - 1; i >= 4; i--) {
        row = floors[i].parentElement.parentElement;
        row.parentElement.removeChild(row);
      }
    }
  }
  document.getElementById("nostorey").addEventListener('keyup', function() {
    var curVal = +this.value;
    var floors = floorTable.querySelectorAll('.floor');
    var curFloors = floors.length;
    if (curVal > curFloors) {
      addFloors(curFloors, curVal);
    } else if (curVal < curFloors) {
      removeFloors(curVal);
    }
    floors = floorTable.querySelectorAll('.floor');
    for (var i = 0, len = floors.length; i < len; i++) {
      if (i >= curVal) {
        floors[i].setAttribute("disabled", true);
      } else {
        floors[i].removeAttribute("disabled");
      }
    }
  });

})();
[disabled] {
  background-color: lightgray;
}
<input type="number" id="nostorey" name="" class=' InputBox' />

<table id="floor">
  <tr id="headtable">
    <td>
      <center>Floor Names</center>
    </td>
    <td>
      <center>Floor wise Area</center>
    </td>
  </tr>
  <tr>
    <td>
      <p>1st Floor</p>
    </td>
    <td>
      <input type='text' id="firstfloor" name='' maxlength="10" value="" class='floor InputBox' />
    </td>
  </tr>
  <tr>
    <td>
      <p>2nd Floor</p>
    </td>
    <td>
      <input type='text' id="secondfloor" name='' maxlength="10" value="" class='floor InputBox' />
    </td>
  </tr>
  <tr>
    <td>
      <p>3rd Floor</p>
    </td>
    <td>
      <input type='text' id="thirdfloor" name='' maxlength="10" value="" class='floor InputBox' />
    </td>
  </tr>
  <tr>
    <td>
      <p>4th Floor</p>
    </td>
    <td>
      <input type='text' id="fourthfloor" name='' maxlength="10" value="" class='floor InputBox' />
    </td>
  </tr>
  <tr>
    <td>
      <p>Total</p>
    </td>
    <td>
      <input type='text' id="total" readonly name='' maxlength="10" value="" class=' InputBoxD' />
    </td>
  </tr>
</table>

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.