Make WordPress Core

Opened 8 years ago

Last modified 4 years ago

#39762 new defect (bug)

Change in DOM Element Properties as seen in Javascript Event Handlers Between 4.6.2 and 4.7+

Reported by: reldev's profile reldev Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.7
Component: Administration Keywords: reporter-feedback
Focuses: javascript, administration Cc:

Description (last modified by SergeyBiryukov)

I'm seeing a problem that appears to be related to the change introduced by ticket #37973 in 4.7. I don't see this issue in 4.6.2. I filed ticket #39739 earlier this week that documented another problem related to this change as well.

This problem is also related to a "select all" checkbox but has to do with the state of child checkboxes within javascript event handlers being different between 4.6.2 and 4.7. In short, I have an event handler for "click" for the "manage-column check-column" checkbox (simplified HTML shown below). This event handler looks for child checkboxes in the table ("nslb_import_rows") and triggers their "click" event accordingly. The "click" events are triggered so that additional HTML can be displayed on the page if certain conditions are met when the individual rows are selected / unselected or en masse via this "select all".

<table class="form-table">
  <tbody class="nslb-dynamic-content">
    <tr>
      <td>
        <table class="wp-list-table fixed widefat striped">
          <thead>
            <tr>
              <th scope="col" class="manage-column check-column">
                <label><input type="checkbox" class="check-all"></label>
              </th>
              <th scope="col">
                Name
              </th>
            </tr>
          </thead>
          <tbody id="the-list">
            <tr>
              <th scope="row" class=" check-column">
                <input type="checkbox" id="cb-select-1" name="nslb_import_rows" class="nslb-input" value="1">
              </th>
              <td>
                Steven<input type="hidden" name="s_1_1" class="nslb-input" value="Steven">
              </td>
            </tr>
            <tr>
              <th scope="row" class=" check-column">
                <input type="checkbox" id="cb-select-2" name="nslb_import_rows" class="nslb-input" value="2">
              </th>
              <td>
                David<input type="hidden" name="s_2_1" class="nslb-input" value="David">
              </td>
            </tr>
          </tbody>
        </table>
      </td>
    </tr>
  </tbody>
</table>

Please note the first <tbody> element with the class "nslb-dynamic-content". As the name implies, this content is created dynamically and added to the page via javascript as certain other options on the page are chosen. Because the inner HTML is added dynamically, when this code in common.js at line 459 at the 4.6.2 level executes:

$('thead, tfoot').find('.check-column :checkbox').on( 'click.wp-toggle-checkboxes', function( event ) { 
...

it doesn't find any elements that match the search criteria as they are not present on the page yet, therefore no event handlers are registered here. The HTML at this point would look only like this:

<table class="form-table">
  <tbody class="nslb-dynamic-content">
  </tbody>
</table>

Conversely, the code in common.js at 4.7+ on line 452 that replaced this line

$body.on( 'click.wp-toggle-checkboxes', 'thead .check-column :checkbox, tfoot .check-column :checkbox', function( event ) {
...

fires when the "manage-column check-column" checkbox is clicked even though it's in HTML that is added dynamically. This is because the line in 4.7+ handles click events in the body and then evaluates whether or not a "check-column" checkbox was clicked in a <thead> or <tfoot> as part of click event processing itself thereby finding my "manage-column check-column" checkbox" in the DOM at that point.

The net of effect of all this is a change in the value of the "clicked" property of these child checkboxes when my own click event handler executes. For example, in 4.6.2, if no checkboxes are selected on the page and I click my "manage-column check-column" checkbox, the "clicked" properties for the child checkboxes are "false" because the event handler on line 459 in common.js doesn't execute. However, in 4.7+ given the same scenario, the "clicked" properties for the child checkboxes are already "true" because the event handler on line 452 in common.js does execute each time.

You could actually argue the behavior in 4.6.2 is defective since the handler does not get registered for "check-column" checkboxes added dynamically. FYI, if I hard code this exact HTML statically, then the 4.6.2 event handler does get registered and the "clicked" property for child checkboxes is consistent between 4.6.2 and 4.7+.

Additionally, the code in common.js at the 4.7+ level could potentially trigger the "click" event for any child checkboxes it finds as opposed to just modifying their "checked" property, although I'm not sure of the ramifications of that type change.

Change History (3)

#1 @SergeyBiryukov
8 years ago

  • Description modified (diff)

This ticket was mentioned in Slack in #core by lukecarbis. View the logs.


4 years ago

#3 @kirasong
4 years ago

  • Keywords reporter-feedback added

Hi @reldev!

Thanks so much for the report, and my apologies that it's taken so long for a reply.

Folks looked at this ticket during triage today.

I looked into some other tickets, and saw that it looks like there were some follow-up changes that might have fixed this issue (#40056 is one of the ones I found that seems related). Are you still experiencing it?

If you're still having the problem, could you please add some example code or plugin so that it can be reproduced a little more easily?

Thanks again!

Last edited 4 years ago by kirasong (previous) (diff)
Note: See TracTickets for help on using tickets.