Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#11613 closed defect (fixed)

Grid header misinterprets change-sort-dir clicks as resize requests

Reported by: Stefan Bird Owned by: Bryan Forbes
Priority: high Milestone: 1.6
Component: DojoX Grid Version: 1.5
Keywords: Cc:
Blocked By: Blocking:

Description

If you have a grid and tell it to sort on anything other than the sort column, subsequent clicks on that column's header (except on the sort arrow) will be misinterpreted as resize requests.

This can be seen on the first example on http://docs.dojocampus.org/dojox/grid/DataGrid (Firefox 3.6):

Click on the second column's header. (the grid will now be sorted by that column). Move the mouse over centre of the header cell, it will change into a resize cursor (which also shouldn't happen) Click, or click and drag and the grid will resize the column instead of reversing the order.

The first column doesn't exhibit this behaviour, ie the column is only resized when you click on the cell edge.

I don't recall seeing this in 1.4

Change History (6)

comment:1 in reply to:  description Changed 9 years ago by Stefan Bird

...sort on anything other than the sort column,

Should be first column, not sort column

comment:2 Changed 9 years ago by Yousuf Haider

We've run into this issue with the Grid header where after the first sort on a Grid header, any subsequent attempts to sort by that column result in the grid header interpreting it as a column resize . This will not happen on the first column of a grid. Also note that it only happens on Firefox.

After some investigation it turns out the problem lies in the getCellX() method of the dojox.grid._HeaderBuilder class. To understand what is going on here is a brief overview:

Consider a grid with 3 columns each of which has a width of 10 pixels :

Column0 | Column1 | Column2

When you hover over either of the columns various header events are raised. Such as mousemove etc. For each of the mousemove events this is the flow the DataGrid? goes through:

  1. Dojo event normalization takes place. (Note that for Firefox there is no event normalization for mousemove events as far as I could figure out)
  1. dojox.grid._HeaderBuilder.decorateEvent() method is called that decorates the event with Grid related information like cellNode etc.

3.During this event decoration an attribute on the event called cellX is set by calling the getCellX() method. The cellX is supposed to be the x-coordinate of the mouse when the mousemove event was raised relative to the cell. So if the mousemove event had been raised for Column1 in the above example and the mouse had been at exactly the middle of the column then the value of cellX should be 5.

  1. The domousemove() method is called to handle the event during which there are 2 conditions checked. One is whether the mouse was over the left resize area (the left border where we should show the resize cursor) or over the right resize area (the right border where we should show the resize cursor).

5.If either of these are true we add the 'dojoxGridColResize' class to the header.

6.Based on the Grid theme this would change the cursor to a resize cursor and enable the resizing.

Now whats going wrong in Firefox is that the check for the overLeftResizeArea() is returning true once you've sorted the column at least one time. The root cause for that is that the getCellX() method call is returning a negative and wrong value for cellX while decorating the event.

The reason why this is happening follows:

  1. For other browsers like IE dojo normalizes the event object and creates a layerX property on the event object and sets it to offsetX. This value is the X coordinate of the mouse position relative to that column. So in our example above in all browsers other than Firefox this value will be 5.
  1. Firefox by itself supports the layerX property and so dojo doesn't change that and relies on that value being correct. But the value of layerX in Firefox is relative to the whole header and not the column. The getCellX() method has special code for Firefox to handle that case.
  1. This layerX value is used to calculate the event.cellX value in the getCellX() method.
  1. Once you've sorted by a column, the DOM for that column changes to include a nested div with the class 'dojoxGridColCaption'.
  1. Now when that happens the layerX property in Firefox suddenly starts to give the value relative to the particular column instead of the whole header. As a result the special handling for Firefox (which in this case would not be necessary) messes up the calculation and returns the wrong value.
  1. As a result the overLeftResizeArea() method returns true and the grid thinks that the user is hovering over the resize area.

There are 2 possible fixes for this issue:

  1. Calculate the cellX value by getting the location of the column relative to the page (we would have to iterate over all the offsetParents) and then subtract the clientX (or pageX) values of the event.
  1. Don't do the Firefox special case if the event.target has the 'dojoxGridColCaption' class.

The first solution might be too expensive for the mousemove event. As a result I've implemented the second approach as a temporary fix for our code and also submitted the patch here:

Change the getCellX() method to check for the class before applying the subtraction,

if (!dojo.hasClass(e.target, "dojoxGridColCaption")) {

x -= (n && n.offsetLeft)
0;

}

comment:3 Changed 9 years ago by bill

Owner: changed from bryanforbes to Bryan Forbes

comment:4 Changed 9 years ago by evan

Resolution: fixed
Status: newclosed

(In [23791]) Fix #11613, FF needs "position:absolute" to get expected e.layerX

comment:5 Changed 9 years ago by evan

Milestone: tbd1.6

comment:6 Changed 9 years ago by evan

(In [23795]) Patch from Gino Andres Caverzan(IBM, CCLA), overLeftResizeArea() should only be effective when e.layerX > 0, refs #11613

Note: See TracTickets for help on using tickets.