[SalesForce] Call JavaScript function in VisualForce Page

I want to call a javascript function – makeRowInit() – that arranges some selectCheckBoxes. However, the selectCheckBoxes are not rendered until after an event fires on the page.

To call the javascript from the VF page, I've been trying to use <apex:actionFunction> and <apex:actionSupport>, but it appears those both only call Apex Functions. Am I right? My page code looks like so

<apex:outputPanel id="exportPanel">
    <apex:pageBlockSectionItem>
        <apex:outputLabel value="Fields:"/>
            <apex:selectCheckboxes value="{!selectedFields}" layout="pageDirection" styleClass="makeRows">
                 <apex:selectOptions value="{!columnChoices}" />
                 <apex:actionSupport oncomplete="makeRowInit();" reRender="exportPanel" />
            </apex:selectCheckboxes>
    </apex:pageBlockSectionItem>
</apex:outputPanel>

My javascript (totally borrowed from this post) is currently sitting in the VF page, as the last element in the page before the closing </apex:page> like so:

<script type="text/javascript">

function makeRowInit() {
   tables = document.getElementsByTagName('table');
   console.log(tables);
   for (i = 0; i < tables.length; i++) {
      table = tables[i];
      console.log('Table Classes: ' + table.className);
      if (table.className == 'makeRows') {
         makeRows(table, 7);
      } 
   } 
}

function makeRows(table, columnCount) {
   cells = table.rows[0].cells;
   cellCount = cells.length;
   rowCount = Math.ceil(cellCount / columnCount);

   for (i = 0; i < rowCount; i++) {
      table.insertRow(0);
   }

   for (i = 0; i < cellCount; i++) {
      row = Math.floor(i / columnCount);
      table.rows[row].appendChild(cells[i].cloneNode(true));
   }
   table.deleteRow(rowCount);
} 
</script>

How can I call my makeRowInit() javascript function when selectCheckBoxes table is rendered in the DOM?

Best Answer

There are quite a few ways you can call javascript function on your page, it all depends on what you are trying to achieve. Do you want the makeRowInit() js to be fired once the page is loaded or on every change of checkboxes' status (select/unselect)? If you'd like the js function to be fired only once, you could add this js snippet to at the bottom of your script:

if (window.addEventListener) {
  window.addEventListener('load', makeRowInit, false);
} else if (window.attachEvent) {
  window.attachEvent('onload', makeRowInit);
}



=== Edit #1 ===

As an extension to sfdcfox's approach, if you want the js to be fired only when the output panel is re-rendered, why simple not invoke javascript function from inline js at the bottom of the panel in question?

<apex:outputPanel id="exportPanel">
    <apex:pageBlockSectionItem>
        <apex:outputLabel value="Fields:"/>
            <apex:selectCheckboxes value="{!selectedFields}" layout="pageDirection" styleClass="makeRows">
                 <apex:selectOptions value="{!columnChoices}" />
                 <apex:actionSupport event="onchange" reRender="exportPanel" />
            </apex:selectCheckboxes>
    </apex:pageBlockSectionItem>
    <script type="text/javascript">
        // Any js placed here will be fired when output panel is rerendered
        (function(){
            makeRowInit();
        })();
    </script>
</apex:outputPanel>