PDA

View Full Version : [FNR] [1.2.3] Cell editor triggers do not fire in IE7 if browser scrolled



ts4jda
31 Mar 2009, 10:24 AM
In the gwt emulator and in IE7;

Given an editable grid with some triggering cell editor(s) e.g. datepicker, twintrigger, combobox;
[it may or may not be required that there is another panel above the editable grid]

If the browser client window area is small enough that it has enabled the vertical scrollbar AND the user has scrolled down;

Then when the user activates the cell with a triggering cell editor then clicks its button, the button does not fire, instead the cell editor blurs.

So for instance the date picker does not open.

The problem occurs in the gwt emulator and in IE7 but not in FF3.

The problem occurs in all types of triggering Field s when used as cell editors (combo, datepicker, trigger, twin trigger).

The problem does not occur when these Field types are used on a FormPanel, even if the browser client window area is similarly scrolled.

The following code can be used to see the problem and is composed almost entirely from example code copied from the gxt explorer. Be sure to *shrink the browser window vertically* and *scroll the browser vertically* using the scrollbar.

In other code (with too many dependencies to post) I have seen that the problem is that the Y coordinate in the event seen by the Field's onBlur event is too low, it is the Y offset in browser's client window at that moment, not the offset in the overall content, and so the check to see if the button was hit fails.



/*
* Based on the gxt EditableGridExample
* with extensions to illustrate bug(s) trigger in fields used as cell editors
* not suppressing Blur events (i.e. not firing) in IE7
* if the browser client window has been scrolled vertically
*
* note there may be unnecessary embellishments in this code
* left over from the effort to characterize the problem.
*
*
* to see the problem, display this class, shrink the browser window enough
* that it activates the vertical scroll bar, SCROLL IT DOWN BY MORE THAN
* ONE * ROW HEIGHT, then try to open the date picker in the second column
* in the lower grid.
*
* instead of opening the date picker, the cell editor blurs, because the
* coordinates in the event are relative to the browser client window but
* the coordinates in the widget are relative to this class's origin, so the
* hit test fails in the field's onblur method.
*
* problem does not occur in FF3
*
*/
//package whatever;
import java.util.ArrayList;
import java.util.List;
import com.extjs.gxt.samples.resources.client.TestData;
import com.extjs.gxt.samples.resources.client.model.Plant;
import com.extjs.gxt.samples.resources.client.model.Stock;
import com.extjs.gxt.ui.client.Events;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.ToolBarEvent;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.DateWrapper;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.NumberField;
import com.extjs.gxt.ui.client.widget.form.SimpleComboBox;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.form.TwinTriggerField;
import com.extjs.gxt.ui.client.widget.grid.CellEditor;
import com.extjs.gxt.ui.client.widget.grid.CheckColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
import com.extjs.gxt.ui.client.widget.toolbar.TextToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.table.NumberCellRenderer;
/**
*
* @author ...
*/
public class EditGridTriggerBlurBugSimplified extends LayoutContainer {
boolean useTwinTriggerCellEditor = true;
private ContentPanel panelOuter = null;

public EditGridTriggerBlurBugSimplified() {
panelOuter = new ContentPanel();
init0();
init();
add(panelOuter);
}
public void showClickBox() {
MessageBox mb = new MessageBox();
mb.setMessage("I was clicked");
mb.setType(MessageBox.MessageBoxType.ALERT);
mb.show();
}

private void init0() {
GridExample gex = new GridExample();
Grid g = gex.getGrid();
g.addListener(Events.RowClick, new Listener<GridEvent>() {
public void handleEvent(GridEvent ge) {
showClickBox();
}
});
ContentPanel cp = new ContentPanel();
cp.setHeading("Just a ContentPanel");
cp.setFrame(true);
cp.setLayout(new FitLayout());
cp.setSize(420, 340);
cp.add(gex);
panelOuter.add(cp);
}
void init() {
setLayout(new FlowLayout(10));
List<Stock> stocks = TestData.getStocks();
for (Stock s : stocks) {
DateWrapper w = new DateWrapper();
w = w.clearTime();
w = w.addDays((int) (Math.random() * 1000));
s.set("date", w.asDate());
}
List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
ColumnConfig column = new ColumnConfig();
column.setId("name");
column.setHeader("Common Name");
column.setWidth(220);
if (useTwinTriggerCellEditor) {
TwinTriggerField ttf = new TwinTriggerField();
ttf.setAllowBlank(false);
ttf.setAutoValidate(true);
Listener<ComponentEvent> lsn = new Listener<ComponentEvent>() {
public void handleEvent(ComponentEvent arg0) {
showClickBox();
}
};
//ttf.addListener(Events.TwinTriggerClick, lsn);
ttf.addListener(Events.TriggerClick, lsn);
ttf.enableEvents(true);
column.setEditor(new CellEditor(ttf));
} else {
TextField<String> text = new TextField<String>();
text.setAllowBlank(false);
text.setAutoValidate(true);
column.setEditor(new CellEditor(text));
}
configs.add(column);
DateField dateField = new DateField();
dateField.getPropertyEditor().setFormat(DateTimeFormat.getFormat("MM/dd/y"));
column = new ColumnConfig();
column.setId("available");
column.setHeader("Available");
column.setWidth(95);
column.setEditor(new CellEditor(dateField));
column.setDateTimeFormat(DateTimeFormat.getMediumDateFormat());
configs.add(column);
final SimpleComboBox<String> combo = new SimpleComboBox<String>();
combo.setTriggerAction(TriggerAction.ALL);
combo.add("Shade");
combo.add("Mostly Shady");
combo.add("Sun or Shade");
combo.add("Mostly Sunny");
combo.add("Sunny");
CellEditor editor = new CellEditor(combo) {
@Override
public Object preProcessValue(Object value) {
if (value == null) {
return value;
}
return combo.findModel(value.toString());
}
@Override
public Object postProcessValue(Object value) {
if (value == null) {
return value;
}
return ((ModelData) value).get("value");
}
};
column = new ColumnConfig();
column.setId("light");
column.setHeader("Light");
column.setWidth(130);
column.setEditor(editor);
configs.add(column);
column = new ColumnConfig();
column.setId("price");
column.setHeader("Price");
column.setAlignment(HorizontalAlignment.RIGHT);
column.setWidth(70);
column.setNumberFormat(NumberFormat.getCurrencyFormat());
column.setEditor(new CellEditor(new NumberField()));
configs.add(column);
CheckColumnConfig checkColumn = new CheckColumnConfig("indoor", "Indoor?", 55);
configs.add(checkColumn);
final ListStore<Plant> store = new ListStore<Plant>();
store.add(TestData.getPlants());
ColumnModel cm = new ColumnModel(configs);
ContentPanel cp = new ContentPanel();
cp.setHeading("Edit Plants");
cp.setFrame(true);
cp.setSize(600, 300);
cp.setLayout(new FitLayout());
final EditorGrid<Plant> grid = new EditorGrid<Plant>(store, cm);
grid.setAutoExpandColumn("name");
grid.setBorders(true);
grid.addPlugin(checkColumn);
enableEvents(true);
cp.add(grid);
ToolBar toolBar = new ToolBar();
TextToolItem add = new TextToolItem("Add Plant");
add.addSelectionListener(new SelectionListener<ToolBarEvent>() {
@Override
public void componentSelected(ToolBarEvent ce) {
Plant plant = new Plant();
plant.setName("New Plant 1");
plant.setLight("Mostly Shady");
plant.setPrice(0);
plant.setAvailable(new DateWrapper().clearTime().asDate());
plant.setIndoor(false);
grid.stopEditing();
store.insert(plant, 0);
grid.startEditing(0, 0);
}
});
toolBar.add(add);
cp.setTopComponent(toolBar);
cp.setButtonAlign(HorizontalAlignment.CENTER);
cp.addButton(new Button("Reset", new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
store.rejectChanges();
}
}));
cp.addButton(new Button("Save", new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
store.commitChanges();
}
}));
if (this.panelOuter == null)
add(cp);
else
panelOuter.add(cp);
}
// use another example class, with minor mods,
// to take up some space and help illustrate the break
public class GridExample extends LayoutContainer {
//Grid<Stock> grid = null;
EditorGrid<Stock> grid = null;
public GridExample() {
setLayout(new FlowLayout(10));
final NumberFormat currency = NumberFormat.getCurrencyFormat();
final NumberFormat number = NumberFormat.getFormat("0.00");
final NumberCellRenderer<Grid<Stock>> numberRenderer = new NumberCellRenderer<Grid<Stock>>(
currency);
GridCellRenderer<Stock> change = new GridCellRenderer<Stock>() {
public String render(Stock model, String property, ColumnData config, int rowIndex,
int colIndex, ListStore<Stock> store) {
double val = (Double) model.get(property);
String style = val < 0 ? "red" : "green";
return "<span style='color:" + style + "'>" + number.format(val) + "</span>";
}
};
GridCellRenderer<Stock> gridNumber = new GridCellRenderer<Stock>() {
public String render(Stock model, String property, ColumnData config, int rowIndex,
int colIndex, ListStore<Stock> store) {
return numberRenderer.render(null, property, model.get(property));
}
};
List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
ColumnConfig column = new ColumnConfig();
column.setId("name");
column.setHeader("Company");
column.setWidth(200);
configs.add(column);
column = new ColumnConfig();
column.setId("symbol");
column.setHeader("Symbol");
column.setWidth(100);
configs.add(column);
column = new ColumnConfig("date", "Last Updated", 100);
column.setAlignment(HorizontalAlignment.RIGHT);
column.setDateTimeFormat(DateTimeFormat.getShortDateFormat());
configs.add(column);
column = new ColumnConfig();
column.setId("last");
column.setHeader("Last");
column.setAlignment(HorizontalAlignment.RIGHT);
column.setWidth(75);
column.setRenderer(gridNumber);
configs.add(column);
column = new ColumnConfig("change", "Change", 100);
column.setAlignment(HorizontalAlignment.RIGHT);
column.setRenderer(change);
configs.add(column);
ListStore<Stock> store = new ListStore<Stock>();
List<Stock> allOfThem = TestData.getStocks();
List<Stock> aFewOfThem = new ArrayList();
for (int i = 0; i < 3; i++) aFewOfThem.add(allOfThem.get(i)); // no sublist in gwt
store.add(aFewOfThem);
ColumnModel cm = new ColumnModel(configs);
ContentPanel cp = new ContentPanel();
cp.setBodyBorder(false);
cp.setHeading("Basic Grid");
cp.setButtonAlign(HorizontalAlignment.CENTER);
cp.setLayout(new FitLayout());
cp.setSize(400, 300);
grid = new EditorGrid<Stock>(store, cm);
grid.setStyleAttribute("borderTop", "none");
//grid.setAutoExpandColumn("name");
grid.setBorders(true);
cp.add(grid);
add(cp);
}
private Grid getGrid() {
return grid;
}
}
}

Mjollnir26
14 Apr 2009, 12:09 AM
Hi, not sure if this is the exact same Problem as we are having, but it sounds very familiar.

We have a EditorGridPanel with a RowExpander and some basic Editors defined, (Checkbox, Combo, Textfield).
Editing rows that are not expanded seems to be always possible.

But trying to edit a expanded Row fails and the Page just "jumps" to the FormPanel included in the RowExpander when a vertical scrollbar is present. But, when i hit F11 and put my IE7 in fullscreen mode (eliminating the vertical scollbar) the editor on the expanded row works normally. This is a big issue for which i have been trying to find a solution all day long...

jaf
10 Jul 2009, 3:07 AM
Hi,

I'm experiencing exactly the same problem (GXT 1.2.4, IE7).

Does anybody know if this is fixed in version 2?

I'm evaluating GXT for use in our product and this would be a serious issue for us.

Thanks,
John.

sven
10 Jul 2009, 4:08 AM
This is fixed in SVN now. For TwinTriggerfield you ened to implement the bluringactions on your own. This was dicussed several timeson the forums already.

We changed the blurin of Triggerfields in GXT2. So there it was not an issue.