Opened 10 years ago

Closed 7 years ago

#10485 closed defect (patchwelcome)

Incorrect blur event management on Internet Explorer

Reported by: Eric Pasquier Owned by: Evan
Priority: high Milestone: future
Component: DojoX Grid Version: 1.4.0b
Keywords: blur event internet explorer Cc:
Blocked By: Blocking:

Description

I discovered the problem by using the OnBlur? event of a Datagrid, but it can occured for any widget. On Internet Explorer, the OnBlur? event trigger each time you click in a cell of a Datagrid, and not only when you leave the table. The problem does not happend on Firefox, as the treatment is different (see below).

The blur event is managed in 'dijit/_base/focus.js' file. On Internet Explorer, the code simulate it by using the 'onactivate' event, may be for historical reason :

if(dojo.isIE){
  var activateListener = function(evt){
    // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
    // Should consider those more like a mouse-click than a focus....
    if(evt.srcElement.tagName.toLowerCase() != "#document" &&
      dijit.isTabNavigable(evt.srcElement)){
      dijit._onFocusNode(effectiveNode || evt.srcElement);
    }else{
(***This line***)  dijit._onTouchNode(effectiveNode || evt.srcElement);
    }
  };
  doc.attachEvent('onactivate', activateListener);
- - -

As the comment says, there is a special case for the <body> element. When you click in a cell of a Datagrid, this case trigger, and call the _onTouchNode function (same file):

_onTouchNode: function(/*DomNode*/ node, /*String*/ by){
  // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)

  in this case :
      node : DispHTMLBody
      nodeName: "BODY"

This code build the current active widgets stack. As the event comes from the <body> element, the stack is empty. Then we have a call to _setStack (same file):

_setStack: function(/*String[]*/ newStack, /*String*/ by){
  // compare old stack to new stack to see how many elements they have in common
  // for all elements that have gone out of focus, send blur event
  Call widget._onBlur(by);

This code compare the current active widget stack to the new one. I attached an image showing the 2 stacks in my case: 0 elements for the new one, and 6 elements on the actual one (oldStack):

http://rd.bepconcept.com/_setstack.png

The code is thinking that we clicked "outside", so it sends OnBlur? events to all the active widgets ! In my case, this leads to a disaster in my code.

I tried various options, but the simplest one was to put into comment the (*this line*) line. This solved the problem and make the onBlur event worked normally for me. I am quite new on Dojo, and I don't know what could be the side effects of not treating the "body onactivate" event.

I hope this help ;-). Please give me a feedback.

Eric.

Attachments (2)

testblur.htm (7.2 KB) - added by Eric Pasquier 10 years ago.
Complete functional test
testMenuBug.html (2.7 KB) - added by chrisbay 10 years ago.
test for improper blur event on a menu

Download all attachments as: .zip

Change History (22)

comment:1 Changed 10 years ago by bill

Hi Eric, thanks for the detailed description. Does this reproduce with the standard grid test files? Actually, can you attach a test case?

You are saying that clicking on a grid cell causing an onactivate event where evt.srcElement is the document? I'm not sure why that would be, that event usually reports the actual element, even if the clicked element isn't focusable. For example, clicking the up/down arrows on a NumberSpinner widget.

Changed 10 years ago by Eric Pasquier

Attachment: testblur.htm added

Complete functional test

comment:2 in reply to:  1 Changed 10 years ago by Eric Pasquier

Hi Bill, Please find a complete test. I put a grid inside a few containers and attached a console message to each blur event. Play with the grid by clicking/double-clicking on different rows and outside the grid. Try with Firefox and Internet Explorer. With FF, the blur event is triggered only when you click outside the grid (it is connected directly and working well). On IE, you can see a "nested fire" of events when you click in different rows and outside the grid. Note that my patch, commenting the (*line*) do not solve completly the problem, but at least invert the "isEditing" state when you click outside the grid, which solved my problems. It seems that you have better knowledge than me to understand why it has been implemented this way and what should be done to correct it. I hope this help. Eric.

comment:3 Changed 10 years ago by bill

Component: DijitDojoX Grid
Owner: set to Nathan Toone

Hi Eric, thanks for the test case. I'm seeing the problem when you double click to edit a cell, but not on single clicking. Is that what you are seeing?

Probably it's a problem where Grid blurs the focused cell before focusing the new cell (the <input> for editing).

comment:4 in reply to:  3 Changed 10 years ago by Eric Pasquier

No, you are right. The problems occurs only with double-click with the original code.

It happends on single click only with the modification I have done, confirming that the case is not so easy to solve.

<<Probably it's a problem where Grid blurs the focused cell before focusing the new cell (the <input> for editing).>> It seems that it blurs the current cell, as you can see "IsEditing?=true"; but it shouldn't do this as it *enters* in Edit mode, and anyway, shouldn't blur all the stack. I did not make any further investigation, but I wonder if this is happening with any other widget ? Or is it possible for the grid to break the stack ? is there any call to _setstack or indirect event generated from the grid ? Should not be too difficult to trace, but its true that the stack calls is quite long.

Eric.

comment:5 in reply to:  3 Changed 10 years ago by Eric Pasquier

I focused on the 'dijit/_base/focus.js', but I wonder now if the problem is not in the grid. Please check the calls stack:

dojox.grid.cells._base:
(function(){
	var focusSelectNode = function(inNode){
		try{
	  ------->      dojox.grid.util.fire(inNode, "focus");
			dojox.grid.util.fire(inNode, "select");
		}catch(e){// IE sux bad
		}
	};

dojox.grid.util:
	dgu.fire = function(ob, ev, args){
		var fn = ob && ev && ob[ev];
      -------->  return fn && (args ? fn.apply(ob, args) : ob[ev]());
	};

These last lines (dgu.fire) are quite obscur for me, and generate the 'onactivate body' event.

comment:6 Changed 10 years ago by bill

I also think the problem is in grid...

I mistyped my previous comment, I said "cell" but actually meant node (ie, DOMNode). Specifically, the focus is originally on a <td> (the readonly version of the cell), but when the user double-clicks, that (original) <td> is orphaned (not sure why), an <input> is created (and apparently, a new <td> to contain it), and focus is moved to the <input>.

Probably the <td> has focus when it's orphaned. When a node with focus is orphaned (or hidden), where does focus go? I think on IE it goes to <body>. So I suspect focus is momentarily moving to <body> and then being moved to the <input>.

I might be able to work around this in the dijit focus code but from what we've seen in dijit many times (especially with InlineEditBox), bad things happen when the focused node is hidden, so it would be better to redesign Grid to not do that.

The code you quoted above is obscure for me too :-) but I don't think they are the problem per se... I'm sticking with my theory above.

comment:7 in reply to:  6 ; Changed 10 years ago by Eric Pasquier

<<it would be better to redesign Grid to not do that. >> If you make some change, what about using a State transition Table to eliminate all these "settimeout" ? Eric.

comment:8 in reply to:  7 Changed 10 years ago by Eric Pasquier

Can I help doing something ?

comment:9 Changed 10 years ago by bill

Patches are always welcome (if you've signed the CLA), I don't know the grid editing code at all so I can't say more than that.

Not sure what a state transition table has to do with anything.

comment:10 Changed 10 years ago by chrisbay

I have seen this issue in another setting: when a popup is closed and it's wrapper is hidden. I have a test case (which I will attach) that shows the problem with a dijit.form.DropDownButton? containing a menu with a popup menu item. It seems to be only an IE issue. Apparently, when the popup menu closes the wrapper has the focus, which is then transferred to the body and the same behavior that Eric describes occurs. The widget stack containing the button, menu, menu item, etc. is cleared and the drop down closes.

Changed 10 years ago by chrisbay

Attachment: testMenuBug.html added

test for improper blur event on a menu

comment:11 Changed 10 years ago by bill

Thanks for the test case; I think the Menu problem is a different problem, a race condition regarding mousing off of the PopupMenuItem before the submenu has had a chance to display etc. I filed a separate ticket #10546 to track it.

We'll leave this ticket for the Grid problem.

comment:12 in reply to:  11 Changed 10 years ago by eric P

Any news for this ticket ? I have to patch the source code on each release to have my code work. Eric.

comment:13 Changed 9 years ago by Nathan Toone

Owner: Nathan Toone deleted

Unassigning my tickets.

comment:14 Changed 9 years ago by Eric Pasquier

The main default, ie the isEditing status of the grid, is corrected, may be due to an upgrade of IE (because the bug is not present anylonger even with previous 1.4.x versions) The grid is still raising Blur events when you enter into the Edit mode, but it is not so important as the isEditing status is now correct.

This ticket may be closed.

Thanks, Eric.

comment:15 Changed 8 years ago by evan

Milestone: tbdfuture
Owner: set to evan

comment:16 Changed 8 years ago by Evan

Owner: changed from evan to Evan

comment:17 in reply to:  14 Changed 8 years ago by dimamizou

Replying to Eric P:

The main default, ie the isEditing status of the grid, is corrected, may be due to an upgrade of IE (because the bug is not present anylonger even with previous 1.4.x versions) The grid is still raising Blur events when you enter into the Edit mode, but it is not so important as the isEditing status is now correct.

This ticket may be closed.

Nope, the bug is stil there in 1.4.3, 1.5.0 and 1.6.0. Every time user starts editing in a cell, IE fires onBlur event, which makes it impossible to submit changes in the last edited cell after focus actually leaves the grid.

comment:18 Changed 8 years ago by viliam.pucik

I ran into similar issue with Firefox. The following workaround should even work when the grid is loaded inside dojox.layout.ContentPane?:

<table dojoType="dojox.grid.EnhancedGrid" ...>
...
<script type="dojo/method" event="onMouseDownRow">
    // workaround for "onRowContextMenu" to make it work even with Ajax requests
    // and Grid bugs:
    // [http://bugs.dojotoolkit.org/ticket/10044]
    // [http://bugs.dojotoolkit.org/ticket/10485]
    this.onMouseDownRow = function(){}; // "disconnect" everything for the event
    dojo.connect( this, "onRowContextMenu", function( e ) {
        this.selection.select( e.rowIndex );
    } );
</script>
</table>

comment:19 Changed 7 years ago by bill

DojoX Grid and EnhancedGrid are deprecated in favor of dgrid and gridx.

You should upgrade your code to use one of those two grids.

We will consider patches to the old DojoX Grid code though.

comment:20 Changed 7 years ago by bill

Resolution: patchwelcome
Status: newclosed
Note: See TracTickets for help on using tickets.