Я пытаюсь реализовать функцию Excel, в которой ячейка может иметь комментарий, поэтому при наведении курсора я хочу, чтобы всплывающее окно отображалось с нужным текстом. Все хорошо, пока не появится всплывающее окно. Проблема, с которой я сталкиваюсь, заключается в том, что при появлении всплывающих окон все фоновые события отключены. При зависании в любой другой части сетки ничего не происходит, если всплывающее окно отображается (например, заголовок недоступен). Хотя я конкретно dialog.setGlassEnabled(false);
, Как я видел в chrome dev tools, glass div
который действует как фон, действительно отсутствует. Так почему же это странное поведение? Есть что-то еще? Ниже приведен весь тестовый пример (чтобы легко воспроизвести), а на отдельных частях - код, который, по моему мнению, имеет значение. Я использую GWT 2.6 и GXT 3.1, но компонент, который я использую, является родным компонентом DialogBox GWT, поэтому я считаю, что GXT здесь неактуальен.
mainGrid.addHandler(new GridHoverPopUpHandler()
{
@Override
public void onHover(Element element)
{
dialog.hide();
if(element == null) return;
Element cell = mainGrid.getView().findCell(element);
if(cell != null && cell.hasClassName("comment-indicator"))
{
Label label = new Label("mpazingka " + (String)cell.getInnerText());
dialog.setText("Title of comment");
dialog.setWidget(label);
dialog.setPopupPosition(absoluteX, absoluteY);
dialog.show();
}
}
}, MouseMoveEvent.getType());
abstract class GridHoverPopUpHandler implements MouseOutHandler, MouseMoveHandler
{
protected int absoluteX;
protected int absoluteY;
private Element lastHoveredElement = null;
protected DialogBox dialog;
public abstract void onHover(Element element);
GridHoverPopUpHandler()
{
dialog = new DialogBox();
dialog.setGlassEnabled(false);
}
@Override
public void onMouseMove(MouseMoveEvent event)
{
Element curHoveredElement = null;
NativeEvent natev = event.getNativeEvent();
if (Element.is(natev.getEventTarget()))
{
curHoveredElement = Element.as(natev.getEventTarget());
}
if(lastHoveredElement == curHoveredElement)
{
return;
}
absoluteX = event.getClientX();
absoluteY = event.getClientY();
lastHoveredElement = curHoveredElement;
onHover(curHoveredElement);
}
@Override
public void onMouseOut(MouseOutEvent event)
{
//TODO: Pendig implementation
}
}
package com.test.client;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.widget.core.client.ContentPanel;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
import com.sencha.gxt.widget.core.client.grid.GridView;
import com.sencha.gxt.widget.core.client.grid.GridViewConfig;
import com.sencha.gxt.widget.core.client.grid.GroupSummaryView;
import com.sencha.gxt.widget.core.client.grid.SummaryColumnConfig;
public class GridHoverExample implements IsWidget, EntryPoint {
private static final StockProperties props = GWT.create(StockProperties.class);
private ContentPanel root;
private ArrayList<String> comments;
private void rootInit() {
root = new ContentPanel();
root.setHeadingText("Locked Grid Sample");
root.setPixelSize(400, 300);
comments = new ArrayList();
comments.add("Stack_2");
}
@Override
public Widget asWidget() {
if (root == null) {
rootInit();
ColumnConfig<Stock, String> nameCol = new SummaryColumnConfig<Stock, String>(props.name(), 100, SafeHtmlUtils.fromTrustedString("<b>Company</b>"));
ColumnConfig<Stock, String> symbolCol = new SummaryColumnConfig<Stock, String>(props.symbol(), 100, "Symbol");
ColumnConfig<Stock, Double> changeCol = new SummaryColumnConfig<Stock, Double>(props.change(), 100, "Change");
ColumnConfig<Stock, String> industryCol = new SummaryColumnConfig<Stock, String>(props.industry(), 100, "Industry");
ColumnConfig<Stock, Date> dateCol = new SummaryColumnConfig<Stock, Date>(props.date(), 100, "Date");
dateCol.setCell(new DateCell(DateTimeFormat.getFormat("MM/dd/yyyy")));
List<ColumnConfig<Stock, ?>> ccFree = new ArrayList<ColumnConfig<Stock, ?>>();
ccFree.add(nameCol);
ccFree.add(symbolCol);
ccFree.add(changeCol);
ccFree.add(dateCol);
ccFree.add(industryCol);
ColumnModel<Stock> cm = new ColumnModel<Stock>(ccFree);
ListStore<Stock> store = new ListStore<Stock>(props.key());
for (int i = 1; i <= 100; i++)
store.add(new Stock("Stack_"+i, "S_"+i, 2, 2, new Date()));
final Grid<Stock> mainGrid = new Grid<Stock>(store, cm);
mainGrid.addHandler(new GridHoverPopUpHandler()
{
@Override
public void onHover(Element element)
{
dialog.hide();
if(element == null) return;
Element cell = mainGrid.getView().findCell(element);
if(cell != null && cell.hasClassName("comment-indicator"))
{
Label label = new Label("mpazingka " + (String)cell.getInnerText());
dialog.setText("Title of comment");
dialog.setWidget(label);
dialog.setPopupPosition(absoluteX, absoluteY);
dialog.show();
}
}
}, MouseMoveEvent.getType());
mainGrid.setView(createGridView());
root.setWidget(mainGrid);
}
return root;
}
@Override
public void onModuleLoad() {
RootPanel.get("nameFieldContainer").add(asWidget());
}
private GridView<Stock> createGridView()
{
final GroupSummaryView<Stock> view = new GroupSummaryView<Stock>();
view.setShowGroupedColumn(false);
view.setStripeRows(true);
view.setColumnLines(true);
view.setSortingEnabled(false);
view.setShowDirtyCells(false);
view.setViewConfig(new GridViewConfig<Stock>()
{
@Override
public String getRowStyle(Stock model, int rowIndex)
{
return "";
}
@Override
public String getColStyle(Stock model, ValueProvider<? super Stock, ?> valueProvider, int rowIndex, int colIndex)
{
String style = "";
if(model.getName().equals(comments.get(0)) && colIndex == 0)
{
style += "comment-indicator ";
}
style += "columnWidth";
return style;
}
});
return view;
}
}
abstract class GridHoverPopUpHandler implements MouseOutHandler, MouseMoveHandler
{
protected int absoluteX;
protected int absoluteY;
private Element lastHoveredElement = null;
protected DialogBox dialog;
public abstract void onHover(Element element);
GridHoverPopUpHandler()
{
dialog = new DialogBox();
dialog.setGlassEnabled(false);
}
@Override
public void onMouseMove(MouseMoveEvent event)
{
Element curHoveredElement = null;
NativeEvent natev = event.getNativeEvent();
if (Element.is(natev.getEventTarget()))
{
curHoveredElement = Element.as(natev.getEventTarget());
}
if(lastHoveredElement == curHoveredElement)
{
return;
}
absoluteX = event.getClientX();
absoluteY = event.getClientY();
lastHoveredElement = curHoveredElement;
onHover(curHoveredElement);
}
@Override
public void onMouseOut(MouseOutEvent event)
{
//TODO: Pendig implementation
}
}
Обновить
Хорошо, я нашел его. Этот виджет, чтобы манипулировать DOM для перетаскивания компонента, захватывает некоторые события (события мыши). Я не следил из-за ограничений по времени, поэтому я использовал DecoratedPopupPanel
который является родительским классом DialogBox
и не фиксирует все те события, которые мне нужны. Я буду ждать один или два дня, чтобы получить ответ о том, что делает это событие, и как я могу его отключить. Если этого не предусмотрено, я отправляю это как ответ, чтобы закрыть тему.
Я думаю, что вы, возможно, сделали это излишним, используя диалог, чтобы выполнить функциональность подсказки инструмента. IMHO, то, что вы должны сделать, это добавить подсказку в ячейку, в которой вы хотите иметь функцию "excel comment". Поэтому всякий раз, когда пользователь наводится на эту ячейку, он покажет всплывающую подсказку, загруженную данными из вашего комментария. Взгляните на пример базовой сетки: http://www.sencha.com/examples/#ExamplePlace:basicgrid. Попробуйте навести указатель мыши на ячейку "Изменить", и вы увидите подсказку. Ключевым моментом было создание собственной реализации ячеек сетки, например:
ColumnConfig<Stock, Double> changeCol = new ColumnConfig<Stock, Double>(props.change(), 100, "Change");
changeCol.setCell(new AbstractCell<Double>() {
@Override
public void render(Context context, Double value, SafeHtmlBuilder sb) {
String style = "style='color: " + (value < 0 ? "red" : "green") + "'";
String v = number.format(value);
sb.appendHtmlConstant("<span " + style + " qtitle='Change' qtip='" + v + "'>" + v + "</span>");
}
});
Если вам нужно использовать всплывающую подсказку другого типа, посмотрите пример всплывающих подсказок здесь: http://www.sencha.com/examples/#ExamplePlace:tooltips
Надеюсь, это может вам помочь.