RunJavaScript ignored on first click but works on second and additional clicks

RunJavaScript ignored on first click but works on second and additional clicks

  

I'm having trouble getting a JavaScript function to run the first time I click a checkbox. The second and subsequent clicks work as expected. 

The Script contents from RunJavaScript

"Table_SelectAll('" + ChkSelectAll.Id + "', '" + RiskTable.Id + "', 'false');"
  1. I've tried putting the function call in the onclick of the checkbox and in a RunJavaScript server-action of a screen-action that I need to run just after the JavaScript runs. But the behavior is the same. 
  2. The function is included at the module level. I've tried putting it at the page level and the behavior is unchanged. 

When putting a breakpoint in the function using Chrome, my breakpoint is not reached on the first click, but it is every other time. 

This is the first time I include a JavaScript function that is triggered by a click. What am I doing wrong?

The following details are for more context, but all of this works:

The function is a select_all for a column of checkboxes, based on RichWidgets BulkSelect. The list contains items that are updated in bulk. The update is accomplished using a WebBlock to the right of the list. As items are checked and unchecked, the user sees the corresponding values if all the checked items have the same values and 'multiple values' if they don't.  

I changed BulkSelect so it doesn't disable any links or run the onchange events for each checkbox in the table. BulkSelect does work on the first click out of the box, but it executes the onchange for every checkbox which slows things down as there is a round-trip to the server for each line. The modifications I made allow me to make one round trip for the whole list. 

If you've read this far and have any tips on approach, etc., I'd be happy to read them.

function Table_SelectAll(chkboxId, TableRecordsWidget, RunOnClickFunctions) {
  $(function($) {
  
    //click on bulk select
    $('#' + chkboxId).click(function(){
        var bulkChecked = $('#' + chkboxId).attr('checked');
        $('#' + TableRecordsWidget).find("tbody tr td:first-child").find('input:checkbox').each(function() {
            var boxChecked = $(this).attr('checked');
            if (bulkChecked) {
                if(!boxChecked) {
                    if(typeof $(this)[0].onclick == "function" && RunOnClickFunctions == "true")
                        $(this)[0].click();
                    else
                        $(this).attr('checked',true);
                }
            }
            else {
                if(boxChecked) {
                    if(typeof $(this)[0].onclick == "function" && RunOnClickFunctions == "true")
                        $(this)[0].click();
                    else
                        $(this).attr('checked',false);
                }
            }
        });
$('#' + TableRecordsWidget + ' tbody ').find('tr:has(:checkbox:not(:checked))').removeClass('TableRecords_SelectedLine');
    $('#' + TableRecordsWidget + ' tbody ').find('tr:has(:checked)').addClass('TableRecords_SelectedLine');
});
    
   });
 }

Hi Marcos,

If you have a function, why you have "$(function($) {" within function? I do not think it's necessary.

Does the console show any errors?

Paulo Cação wrote:

Hi Marcos,

If you have a function, why you have "$(function($) {" within function? I do not think it's necessary.

Does the console show any errors?

Hi Paulo, I copied "$(function($) {" from the BulkSelect code and made as few changes as possible. It may not be needed in this case but since they had it in there and my JavaScript experience is limited...

No errors on the console.

Thanks, Marcos

Try to use console logs or alerts to "debug". Can you share link where you copied the code? 

It seems the function is not properly bound to the screen action until the second click. The screen action code is running because I can see it correctly counts the number items that should be selected, but the checkboxes for those items are not getting checked by the JavaScript function. 

I can't diagnose by debugging because my code is not called until the second time the checkbox is clicked. Once the code runs, everything works fine. So after the second click, I can set and use a breakpoint but I don't need it because the code works fine.

I will create a new solution to isolate the problem and share that link...


Here is a link that demonstrates the problem. I've also uploaded the OML. The first time you click the SelectAll checkbox it doesn't work.

https://riskbucket.outsystemscloud.com/SelectAllTest/Home.aspx

I've also tried putting the function in 1. an unescaped expression at the top of the page and 2. in a WebPatterns JavaScript container at the top 3. and then at the bottom of the page. I always get the same behavior. 


Solution

Hello Marcos,

It seems to me the problem is that the first time you call your function, you are binding the action to the click. So nothing happens. Only from the second time on the OnClick has the binding and will to what it is meant to do.

My suggestion is:

1) Put your Table_SelectAll at the start of the html file (JavaScript of the module is fine).

2) Call the function only ONCE, in the Web Block if you're using one, or after the check box if you are doing things "loosy", with an expression with Escape Content set to No.

That's it. The function will be called immediately after the Table and the check box (the one for the bulk select) are rendered, so they exist, and the onClick will bind the code to the click in the check box at the moment of the render.

You don't need to call it from anywhere else, as this is what the function is doing, binding a function that will be called everytime you click the check box. 

I think this will solve the problem.

Cheers.


Solution

Eduardo, Thank you so much for taking the time to answer. That worked! 

I'm embarrassed not to have tried that earlier.  I opted to call the function from a WebPatterns\JS block placed at the bottom of the WebBlock, which I understand is functionally the same as your suggestion. 

This has created several questions for me. I hope you'll indulge me with answers as I try to understand the functioning of the platform. 

  1. Is there some reason why the platform didn't bind the action to the click until after the first call. Consider I was calling this from a RunJavaScript screen action? 
  2. Is it always necessary to explicitly call onclick actions to bind them at page render? 
  3. Does this apply to other actions?
  4. Would you have used a different approach to do a SelectAll on a column of checkboxes while not running the onclick actions of each checkbox? 

Thanks again!

EDIT: Aha! You already answered questions 1-3. I read your reply more closely and I realize the code was binding each time the JS executed  $('#' + chkboxId).click(function(){ . This is why it only needed to run once at page render. It worked after the first time because it was bound to the checkbox, not because I called the JS again each time the Screen Action ran. 

Instead of binding the click at screen render, I can run the JS from a Screen Action if I remove the part of the code that does the binding. 

Question 4 remains a doubt.

5. Is there a benefit to binding the click vs. using RunJavaScript from a Screen Action?

Hi :)

4. Probably the same approach. But I am also no expert in JavaScript.
5. The advantage is that you don't need to go to the server just to select de-select hings. Doing client-side improve application performance.

Cheers!