5
\$\begingroup\$

I had originally posted this question without posting the full algorithm. Here is the whole thing.

I have an HTML page like this:

<table id="inputTable"> 
    <tr>
       <td>Label1</td>
       <td><input type="text" value="" id="inputA1"></td>
       <td><span id="inputA1ErrMsg"/></span></td>
       <td><input type="text" value="" id="inputA1_"></td>
       <td><span id="inputA1ErrMsg_"/></span></td>
    </tr>
    <tr>
       <td>Label1</td>
       <td><input type="text" value="" id="inputA2"></td>
       <td><span id="inputA2ErrMsg"/></span></td>
       <td><input type="text" value="" id="inputA2_"></td>
       <td><span id="inputA2ErrMsg_"/></span></td>
    </tr>
    <tr>
       <td>Label1</td>
       <td><input type="text" value="" id="inputA3"></td>
       <td><span id="inputA3ErrMsg"/></span></td>
       <td><input type="text" value="" id="inputA3_"></td>
       <td><span id="inputA3ErrMsg_"/></span></td>
    </tr>
    // ... repeat all the way up to A15.
    <tr>
       <td>Label1</td>
       <td><input type="text" value="" id="inputB1"></td>
       <td><span id="inputB1ErrMsg"/></span></td>
       <td><input type="text" value="" id="inputB1_"></td>
       <td><span id="inputB1ErrMsg_"/></span></td>
    </tr>
    <tr>
       <td>Label1</td>
       <td><input type="text" value="" id="inputB2"></td>
       <td><span id="inputB2ErrMsg"/></span></td>
       <td><input type="text" value="" id="inputB2_"></td>
       <td><span id="inputB2ErrMsg"/></span></td>
    </tr>
    // ... so on up to E1. 
</table>

I want my JavaScript to do three things:

  • It takes input input*5 and sums up it up. If it is less than 20, show the next input.

    • inputA5 + inputB5 < 20 than show input for inputC*

      In the same way, do it for input*5_. If it is less than 5, show the next set of input.

    • inputA5_ + inputB5_ < 20 then show input for inputC*_ which is inputC1_, inputC2_, inputC3_... else we hide it.
  • Now if, let's say, they enter 20 for inputA5 and 20 for inputA5_, then it would not only hide the input but the entire row.

To make it easier I added class = "inputTrigger" to each of input*5 and inputTrigger_ to each of input*5_.

jQuery

$("inputTable").on("change", "inputTrigger", function() { 
     inputChange(this.id, indexArray.indexOf(this.id.replace("input", "").replace("5", "")); // so we can get if it is A, B, C, D
}); 

My functions:

var indexArray = { 'A', 'B', 'C', 'D', 'E'};
function getTotal(id, index) { 
   var total = 0;
   var len = indexArray.length;
   for (var i = 0; i != len;  ++i) {
        total += parseFloat($(input + indexArray[i] + "5").val());
   }
   return total;
}

function inputChange(id,currentIndex) {
        var nextIndex, total, isShow, MAX_INDEX;
        nextIndex = +currentIndex + 1;
        MAX_INDEX= '5';
        if (nextIndex < MAX_INDEX) {
            total = parseFloat(getTotal(id, currentIndex));
            if (nextIndex === 1) {
                nextIndex += 1;
            }
            isShow = (total < 20.0 &&  document.getElementById(id).value > 0.0);
            showOrHideInput(isShow, nextIndex, resetValue);
            inputChange(id, nextIndex);
        }
    }

    function    showOrHideInput(isShow, nextIndex) {
             var id1 = $("#input" + nextIndex + "1");
             var id2 = $("#input" + nextIndex + "2");
             var id10 = .....
             var id1Other = $("#input" + nextIndex + "1_");
             var id2Other = $("#input" + nextIndex + "2_");
             var id10Other = ....
             if (isShow) { 
                 if (id1.length) {
                    id1.show();
                 }
                 // ... so on up to id10
             }
             else {
                 if (id1.length) {
                    id1.hide();
                 }
                 // .. so on up to id10
             }
             showOrHideRows(isShow, id1, id1Other);
             showOrHideRows(isShow, id2, id2Other);
             showOrHideRows(isShow, id3, id3Other);
             // ... up to id10.
   }

   function showOrHideRows(isShow, id, idOther) {
         if (isShow) {
             id.closest("tr").show();
         } else {
            if (!idOther.is(":visible")) {
               id.closest("tr").hide();
            }
         }
   }

I know my function works but it seems really slow on IE 8 and 9, and sometimes causes a memory leak. I have analyzed the speed with dynaTrace and showOrHideInput takes over 800 ms.

  1. What is the fastest way to tell if a jQuery element is visible? It seems is(":visible") has performance hit.
  2. What is the best way to hide the first ancestor table row (in terms of performance)?
\$\endgroup\$

migrated from stackoverflow.com Apr 9 '12 at 15:59

This question came from our site for professional and enthusiast programmers.

  • \$\begingroup\$ Often a good way to speed up jQuery code is to use less jQuery. This means being comfortable with the native API, and using it directly. For example, if you know how the element is being hidden, then you don't need .is(':visible'). \$\endgroup\$ – user10711 Apr 9 '12 at 15:49
1
\$\begingroup\$

As a general advice - use less document-wide selectors. I meant that you always selected something from entire document context:

$(input + indexArray[i] + "5")
//.........
$("#input" + nextIndex + "1")

Try to narrow context - for example, assign a class to all '#inputWhatever and then

var myInputs = $(".assignedClass");
$("#input" + nextIndex + "1", myInputs);

The code in

if (id1.length) {
  id1.show();
}

looks strange: if element length is 0, it is hidden anyway, isn't it? I'm not sure in this for all kinds of browsers... If what I suppose is true, better do:

if(isShow) {
  $(".assignedClass").show();
} else {
  $(".assignedClass").hide();
}

Other things:

if (!idOther.is(":visible"))

looks better in style as

if (idOther.is(":hidden")) 

Btw, what if isShow is false and !idOther.is(":visible" is false too? What about id visibility? May it be a bug?

If you use a lot of "if something then show else hide" consider toggle()

\$\endgroup\$
  • \$\begingroup\$ id1.length is to check if element exists or not. If it exists than id1.show() will show the element. 2.) showOrHideRows deals with isShow = false.. if both are false, hide the entire row. (not just the inputs/table cell). \$\endgroup\$ – user578635 Apr 9 '12 at 18:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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