Problem/Motivation

In file toolbar.menu.js line 137 you find:

    // Bind event handlers.
    $(document)
      .on('click.toolbar', '.toolbar-handle', toggleClickHandler);

Currently this binding is executed once only and so there is no problem. With multiple toolbars however the handler toggleClickHandler is registered multiple and on click executed multiple.

How to reproduce

  1. Install Drupal from the latest code from the 8.0.x branch
  2. Log in as admin
  3. Add a toolbar (see code below, thanks to @tohesi)
  4. Click the button to change the toolbar to vertical orientation
  5. Run the following jQuery command: jQuery('.some-wrapper').drupalToolbarMenu();
  6. Now it's not possible to collapse/uncollapse menu items in the admin toolbar
<div class="some-wrapper">
  <ul class="toolbar-menu">
    <li><a href="node/1">Menu item 1</a>
      <ul class="toolbar-menu">
        <li><a href="node/1">Sub menu item 1</a></li>
        <li><a href="node/2">Sub menu item 2</a></li>
      </ul>
    </li>
    <li><a href="node/2">Menu item 2</a></li>
    <li><a href="node/1">Menu item 3</a>
      <ul class="toolbar-menu">
        <li><a href="node/1">Sub menu</a></li>
        <li><a href="node/2">Another sub menu</a></li>
      </ul>
    </li>
  </ul>
</div>

Proposed resolution

Proposed code:

    // Bind event handlers.
    $(this)
      .on('click.toolbar', '.toolbar-handle', toggleClickHandler);

With this little change my attempts work fine. Maybe it causes another problem I do not see.

Remaining tasks

Done

Contributor tasks needed
Task Novice task? Contributor instructions Complete?
Create a patch Instructions Done
Update the issue summary Instructions Done
Update the issue summary noting if allowed during the beta Instructions
Manually test the patch Novice Instructions Done
Add steps to reproduce the issue Novice Instructions Done
Review patch to ensure that it fixes the issue, stays within scope, is properly documented, and follows coding standards Instructions Done

User interface changes

None.

API changes

None.

Data model changes

None.

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Bug because our jQuery plugin is not reusable
Issue priority Normal because there is no API change
Unfrozen changes Unfrozen because it only changes JS and make code reusable

Comments

nod_’s picture

Status: Active » Postponed (maintainer needs more info)
Issue tags: +Novice

I don't understand what you mean by multiple toolbars. There should be only one anyway, no?

gendoas’s picture

Hi nod_, I no longer expected a reaction.

I'm creating some more toolbars like the admin toolbar in my web-app using drupal's toolbar, I do not want to explain why. For each of this toolbars $.fn.drupalToolbarMenu is called. Because of '$(document).on('click.toolbar', '.toolbar-handle', ...' (toolbar.menu.js, line 137) the handler is registered and so executed multiple. On my installation I changed it to '$(this).on('click.toolbar', '.toolbar-handle', ...'. This solves my problems and I don't see any problem with this change, maybe you do.

For me it is ok to hack toolbar on my installation, but maybe I will publish my app sometimes, and then it would be better, if there were no need to hack. For now I'm far away from publishing the app because it is far away from being worth to publish it.

nod_’s picture

Category: Feature request » Bug report
Issue summary: View changes
Status: Postponed (maintainer needs more info) » Needs review
StatusFileSize
new436 bytes

My comment was eaten so I'll give the summary.

I agree, this is even a bug because our code is not reusable and our jquery plugin assumes it's only used once on a page.

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

This is a bug so according to the beta evaluation we should allow this change.

I tested this is on a local install and it doesn't break the current functionality.

droplet’s picture

umm.. put it inside initItems() is a better place I think.

Above change will work on case like:

$('.first-toolbar-menu').drupalToolbarMenu()
$('.second-toolbar-menu').drupalToolbarMenu()

but won't work in following case perfectly I think

$(object-contains-multiple-instances).drupalToolbarMenu()

Or simply calling `$('.first-toolbar-menu').drupalToolbarMenu()` twice it won't work anymore

droplet’s picture

Status: Reviewed & tested by the community » Needs work
tohesi’s picture

I'll start working with this in DrupalCon Barcelona, mentored by DuaelFr. Following the workflow as guided in https://www.drupal.org/contributor-tasks/create-patch.

tohesi’s picture

Status: Needs work » Needs review
StatusFileSize
new870 bytes
new866 bytes

Moved the event handler binding inside the jQuery.each method. Didn't put it in initItems() because the context didn't quite feel right.

tohesi’s picture

StatusFileSize
new866 bytes

Fixing the interdiff file name.

Status: Needs review » Needs work

The last submitted patch, 8: interdiff-2341267-3-8.patch, failed testing.

duaelfr’s picture

Issue tags: +Barcelona2015

I'm mentoring this issue at DrupalCon Barcelona :)

The last submitted patch, 8: interdiff-2341267-3-8.patch, failed testing.

tohesi’s picture

Issue tags: +Needs manual testing
bartvig’s picture

I'm working on this now at DrupalCon Barcelona, trying to reproduce the issue.

bartvig’s picture

Issue summary: View changes
Status: Needs work » Needs review

I updated the issue summary, added the step to reproduce, and added the table of remaining tasks.

gaas’s picture

I'm reviewing the proposed patch (#8) at DrupalCon Barcelona. Following the guidelines in https://www.drupal.org/contributor-tasks/review.

gaas’s picture

Status: Needs review » Reviewed & tested by the community

I've reproduced the failure using the steps in the summary without the patch and seen that the patch makes the admin menu still functional after the second toolbar is intialized. I've inspected the patch and agree that it works because it registers handlers separately for each menu. Alternative approach could be to keep a single handler at the document level, but protect the initialization with once() to make sure it's not registered multiple times.

gaas’s picture

Issue summary: View changes
duaelfr’s picture

Issue tags: -Needs manual testing

Everything looks good here now.
Removing the Needs manual testing tag as it has been done.
Thank you all for your work!

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed e8b5f46 and pushed to 8.0.x. Thanks!

  • alexpott committed e8b5f46 on 8.0.x
    Issue #2341267 by tohesi, nod_, gaas, gendoas, droplet, DuaelFr, bartvig...
nod_’s picture

Status: Fixed » Reviewed & tested by the community
StatusFileSize
new518 bytes

Nitpick. That's why we prefix jquery stuff with $, so we don't need extra jquery nesting.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

@nod_ good to know. Committed ede4d4a and pushed to 8.0.x. Thanks!

  • alexpott committed ede4d4a on 8.0.x
    Issue #2341267 followup by nod_: Bind event handlers for future multiple...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.