How can I improve performance of my selecting code I have a page with a list of items. Items have several actions assigned to them. (see screenshot).

One may choose to directly click on an icon next to each row or check a checkbox on the left hand side and click action above the list.

The issue is that after clicking an item OR checking a checkbox of several items and then clicking an action there is a lag (a second or so). Imagine having 100 rows or more.

    

Script:

 $("a.action:not(.remove)").click(function (e) { // .remove =&gt; do not execute on download tasks page
            var selected = new Array(); // array to hold selections or clicks
            var obj = $(this), objData = obj.data();
            e.preventDefault();
            if (!obj.hasClass('disablelink')) {                
                if (objData.ajaxMachineid) {
                    selected.push(objData.ajaxMachineid);
                } else {
                    $("input.checkbox:checkbox:checked:not(.checkall)").each(function () {
                        var checkbox = $(this), machineId = checkbox.val(), packageId = objData.ajaxPackageid.removeSpecialChars().toUpperCase(), operation = objData.ajaxType;
                        var $row = $("#" + machineId + packageId.removeSpecialChars().toUpperCase());
                        if ($row.length) {
                            $row.has("a[data-ajax-type=" + operation + "]:not(.hide)").length ? selected.push(machineId) : $(this).attr('checked', false);
                        }
                    });
                }
                if (selected.length &gt; 0) {
                    // do something more here blah blah blah
                };
            }
            $("input.checkall").attr("checked", false);
        });


Sample HTML of one row:

&lt;tr id="1960AGISGIGAMEM22220204" class=""&gt;
&lt;td class="checkbox"&gt;&lt;input type="checkbox" value="1960" class="checkbox"&gt;&lt;/td&gt;
&lt;td class=""&gt;&lt;p&gt;&lt;a href="/Devices/View/1960"&gt;GD009000246&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td class="platform"&gt;PCGames&lt;/td&gt;
&lt;td class="cat"&gt;Up&lt;/td&gt;
&lt;td class="platform"&gt;&lt;div class="pbar"&gt;&lt;span class="progresslabel"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="date"&gt;10.48.1.236&lt;/td&gt;   
&lt;td class="options clearfix"&gt;   
   &lt;a title="View" class="iconMagnifier tip" href="/Packages/View/AGI-SGI-GAME-M222-2.0.2.0.4"&gt;View&lt;/a&gt;
&lt;a title="Install" href="/Packages/PackageActionInstallAsync" data-ajax-type="Install" data-ajax-packageid="AGI-SGI-GAME-M222-2.0.2.0.4" data-ajax-machineid="1960" class="iconDiskPlus action tip "&gt;Install&lt;/a&gt;
   &lt;a title="" href="/Packages/PackageActionAsyncDeletePackage" data-ajax-type="DeletePackage" data-ajax-packageid="AGI-SGI-GAME-M222-2.0.2.0.4" data-ajax-machineid="1960" class="iconDelete action tip"&gt;Remove&lt;/a&gt;                              
&lt;/td&gt;       
&lt;/tr&gt;
So pretty much everything will make a insignificant effect apart from the section where you are looping through each of the checkboxes. See my modifications and notes below.

$("a.action:not(.remove)").click(function (e) { // .remove =&gt; do not execute on download tasks page
     var selected = new Array(); // array to hold selections or clicks
     var obj = $(this),
         objData = obj.data(),

         // Moved these up here as they are not specific to the checkboxes
         packageId = objData.ajaxPackageid.removeSpecialChars().toUpperCase(),
         operation = objData.ajaxType;

     e.preventDefault();
     if (!obj.hasClass('disablelink')) {
         if (objData.ajaxMachineid) {
             selected.push(objData.ajaxMachineid);
         } else {

             // This seems a little convoluted to me, normally you would 
             // use [type=checkbox]
             $("input[type=checkbox]:checked:not(.checkall)").each(function () {

                 var checkbox = $(this),
                     machineId = checkbox.val();

                 // No need to call .removeSpecialChars().toUpperCase() on packageId
                 var $row = $("#" + machineId + packageId);

                 if ($row.length) {

                     // Not 100% whether you need .length here
                     // It could also be beneficial to add a class to the row instead
                     // of calling this complex selector
                     $row.has("a[data-ajax-type=" + operation + "]:not(.hide)").length 
                         ? selected.push(machineId) 
                         : $(this).attr('checked', false);

                 }
             });
         }
         if (selected.length &gt; 0) {
             // do something more here blah blah blah
         };
     }
     $("input.checkall").attr("checked", false);
 });


The obvious thing to do on top of my suggestions above is to cache the checkbox list, this means that every time it enters that section, the app will no longer need to go through every element in the DOM looking for all the checkboxes. Doing this will probably have the most meaningful impact on performance.

// in document ready
var checkboxes = $('input[type=checkbox]');

// When you need to find the checked check boxes
var checked = checkboxes.find(':checked:not(.checkall)');