Prevent toolbar menu from stealing focus?

Hi Guys,
I am writing an application using your Toolbar, and have a problem where sub-menu items are stealing focus.

To explain why this is an issue:

  • I am adding toolbar menu items for “Cut”, “Copy”, and “Paste” in a sub-menu under ‘Edit’.
  • If keyboard focus is in the text field before the user clicks on the toolbar, the user can click on the ‘Edit’ button on the toolbar and the text input still retains its focus while the sub-menu is displayed.
  • As soon as the user clicks on one of the sub-menu items, the input field loses focus immediately, prior to my onClick handler being called.
  • As a result, I can no longer perform the “Copy” or “Paste” action that the user chose, because the text input no longer has focus to perform it.

I have tested this out by placing the “Copy” and “Paste” items directly on the toolbar, and this problem does not occur. It appears that there is something different about the top-level items that won’t steal keyboard focus where the sub-menu items will.

Unfortunately, my toolbar is too crowded to warrant putting those extra buttons on the toolbar all the time, so they have to be hidden under an “Edit” menu.

I have tried looking through the javascript and css files for a while to see if I can spot an obvious difference or cause, but it has eluded me so far.

I know it is not in my handler code, because the focus has changed before my handler code even gets called.

Could you point me in the right direction so that I can get the same behaviour consistently across all elements of the toolbar - specifically, that they never have an impact on the keyboard focus.

Thanks,
Matt

Hi

Unfortunately toolbar get focus for some button types. Common solution is not easy - the best way is to update code and chaneg current behaviour but in case of back-compat we do not have such plans, so please open ticket in our Support System, I’ll check how it can be solved for your case.

For this application, I don’t need to be concerned at all about backwards compatibility or future upgrades, so I am happy to hack into the code as much as is necessary if you can give me a pointer for where to look.

It is really just that your standard sub-menu elements are grabbing focus where the top-level buttons are not (I would expect certain items like sliders or text fields to obviously take focus).

Unfortunately, I can’t open a support ticket. I tried to login but apparently my support has expired - man you guys provide a very short window for support by default :slight_smile:

Thanks,
Matt

well, then you can start from the following:

open dhtmlxtoolbar.js source code and find the following functions for button/buttonSelect

dhtmlXToolbarObject.prototype._buttonObject = function(that, id, data) {
this.obj.onclick = function(e) {
// add here
e = e||event;
e.cancelBubble = truel
if (e.preventDefault) e.preventDefault();
};
dhtmlXToolbarObject.prototype._buttonSelectObject …

this probably will help a bit. if not - step 2 - rewrite all onClick handlers to mousedown section, and step 3 - use

Unfortunately there is no common logic, and some tricks can help for some browsers and some not. That’s why you have 3 options above.

Thanks for the pointer, I have fixed the issue.

In case anyone else stumbles across this same issue later…

In my case, it was the sub-menu, so I needed to change the onclick handler to be an onmousedown handler for the

element inside the buttonSelect’s submenu, and add a second handler to suppress the onclick…
this.obj.tr.onclick = function(e) {
	e = e||event;
	e.cancelBubble = true;
        if (e.preventDefault) e.preventDefault();
        return false;
}
        
this.obj.tr[window.dhx4.isIPad?"ontouchend":"onmousedown"] = function(e) {
        e = e||event;
        e.cancelBubble = true;
        if (e.preventDefault) e.preventDefault();

        // ... normal code as before
}

I haven’t had need or cause to test the IsIPad/ontouchend portion of the code, so there may be a chance that I have broken that particular device functionality in the process.

Matt

Fine!