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)?
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Apr 9, 2012 at 15:29
\$\endgroup\$
1
  • \$\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\$ Commented Apr 9, 2012 at 15:49

1 Answer 1

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()

answered Apr 9, 2012 at 17:48
\$\endgroup\$
1
  • \$\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\$ Commented Apr 9, 2012 at 18:26

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.