UiDOM
浏览器提供了一个界面,可以使用 DOM(文档对象模型)来检查和操作屏幕上的元素。传统上,JavaScript 程序员使用 DOM 来编程其逻辑的用户界面部分,并且传统上,他们必须考虑 DOM 在不同浏览器上的实现中的许多差异。
为了让你不必担心(通常)在实现用户界面时跨浏览器支持,GWT 提供了一组 小部件 和 面板 类来封装此功能。但有时你可能需要访问 DOM。例如,如果你想要
- 在你的用户界面中提供 GWT 不支持的功能
- 编写新的 Widget 类
- 访问主机页面中直接定义的 HTML 元素
- 在低级别处理浏览器事件
- 对加载到浏览器中的 HTML 文档执行一些过滤或其他处理
GWT 为你提供 DOM 包中的类,用于直接与 DOM 交互。这些类为与 DOM 对象交互提供了静态类型接口,以及一定程度的跨浏览器抽象。
使用 DOM 操作小部件
每个小部件和面板都拥有一个底层的 DOM 元素,你可以使用 getElement() 方法访问。你可以使用 getElement() 方法从 DOM 获取底层元素。
以下示例展示了如何设置样式属性来更改小部件的背景颜色。
private HTML htmlWidget;
// Other code to instantiate the widget...
// Change the description background color.
htmlWidget.getElement().getStyle().setBackgroundColor("#ffee80");
这里,从 Widget
超类派生的 getElement() 方法返回一个 DOM Element 对象,该对象代表 DOM 树结构中的一个节点,并向它添加了一个样式属性。
这是一个使用 DOM 不是绝对必要的示例。一种替代方法是使用 样式表,并将不同的样式类与小部件关联,使用 setStylePrimaryName() 或 setStyleName() 方法。
在 DOM 中查找元素
以下示例展示了如何将 JSNI 方法与 Java 代码结合起来操作 DOM。首先,我们有一个 JSNI 例程,它将检索所有作为锚点标记的子元素。元素对象被分配了唯一的 ID,以便从 Java 方便访问
/**
* Find all child elements that are anchor tags,
* assign a unique id to them, and return a list of
* the unique ids to the caller.
*/
private native void putElementLinkIDsInList(Element elt, ArrayList<String> list) /*-{
var links = elt.getElementsByTagName("a");
for (var i = 0; i < links.length; i++ ) {
var link = links.item(i);
link.id = ("uid-a-" + i);
[email protected]::add(Ljava/lang/Object;) (link.id);
}
}-*/;
一旦你找到一个 DOM 元素,你还能用它做什么呢?这段代码遍历上面方法返回的所有锚点标记,然后重写它们的指向位置
/**
* Find all anchor tags and if any point outside the site,
* redirect them to a "blocked" page.
*/
private void rewriteLinksIterative() {
ArrayList<String> links = new ArrayList<String>();
putElementLinkIDsInList(this.getElement(), links);
for (int i = 0; i < links.size(); i++) {
Element elt = Document.get().getElementById(links.get(i));
rewriteLink(elt, "www.example.com");
}
}
/**
* Block all accesses out of the website that don't match 'sitename'
* @param element An anchor link element
* @param sitename name of the website to check. e.g. "www.example.com"
*/
private void rewriteLink(Element element, sitename) {
String href = element.getPropertyString("href");
if (null == href) {
return;
}
// We want to re-write absolute URLs that go outside of this site
if (href.startsWith("http://") &&
!href.startsWith("http://"+sitename+"/") {
element.setPropertyString("href", "http://"+sitename+"/Blocked.html");
}
}
JSNI 方法在每个元素上设置了一个 ID,我们随后将它用作 Document.getElementById(id) 的参数来获取 Java 中的 Element
。
使用 DOM 捕获浏览器事件
GWT 包含一个 Event 类,作为对原生 DOM 事件的类型化接口。
此示例展示了如何使用 DOM 方法捕获特定元素的键盘事件,并在 事件 分发之前处理它们
private ArrayList<Element> keyboardEventReceivers = new ArrayList<Element>();
/**
* Widgets can register their DOM element object if they would like to be a
* trigger to intercept keyboard events
*/
public void registerForKeyboardEvents(Element e) {
this.keyboardEventReceivers.add(e);
}
/**
* Returns true if this is one of the keys we are interested in
*/
public boolean isInterestingKeycode(int keycode) {
// ...
return false;
}
/**
* Setup the event preview class when the module is loaded.
*/
private void setupKeyboardShortcuts() {
// Define an inner class to handle the event
Event.addNativePreviewHandler(new NativePreviewHandler() {
public void onPreviewNativeEvent(NativePreviewEvent preview) {
NativeEvent event = preview.getNativeEvent();
Element elt = event.getEventTarget().cast();
int keycode = event.getKeyCode();
boolean ctrl = event.getCtrlKey();
boolean shift = event.getShiftKey();
boolean alt = event.getAltKey();
boolean meta = event.getMetaKey();
if (event.getType().equalsIgnoreCase("keypress") || ctrl || shift
|| alt || meta || keyboardEventReceivers.contains(elt)
|| !isInterestingKeycode(keycode)) {
// Tell the event handler to continue processing this event.
return;
}
GWT.log("Processing Keycode" + keycode, null);
handleKeycode(keycode);
// Tell the event handler that this event has been consumed
preview.consume();
}
});
}
/**
* Perform the keycode specific processing
*/
private void handleKeycode(int keycode) {
switch (keycode) {
// ...
}
}