package org.jboss.ballroom.client.widgets.window; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; import java.util.LinkedList; import java.util.List; /** * Used to trap focus in modal windows. * * @author Heiko Braun * @date 3/12/12 */ public class Focus { private static final String[] INPUT_TYPES = new String[]{"INPUT", "TEXTAREA"}; private static final String[] BUTTON_TYPES = new String[]{"BUTTON"}; private static final String[] SUPPORTED_TYPES = new String[]{"INPUT", "TEXTAREA", "SELECT", "CHECKBOX", "A", "BUTTON"}; private List<Element> focusable = new LinkedList<Element>(); private int currentFocus = 0; private boolean includeChildren = false; private Element rootElement; public Focus(Element root) { reset(root); } public void reset(Element root) { rootElement = root; reset(); } public void reset() { focusable = new LinkedList<Element>(); currentFocus = 0; includeChildren = false; findFocusable(rootElement, focusable, includeChildren); //System.out.println("num focusable: " + focusable.size()); } public void next() { if(focusable.isEmpty()) return; int next = currentFocus+1; if(next>focusable.size()-1) next = 0; setFocus(focusable.get(next)); currentFocus = next; } private void setFocus(Element element) { //System.out.println("on: "+element.getTagName()); element.focus(); } public void prev() { if(focusable.isEmpty()) return; int prev = currentFocus-1; if(prev<0) prev = focusable.size()-1; setFocus(focusable.get(prev)); currentFocus = prev; } /*public static void flagFocusable(Element element, boolean isFocusable) { element.setAttribute("focusable", String.valueOf(isFocusable)); } */ private void findFocusable(Element root, List<Element> focusable, boolean include) { NodeList<Node> children = root.getChildNodes(); for(int i=0; i<children.getLength(); i++) { Node child = children.getItem(i); if(Node.ELEMENT_NODE == child.getNodeType()) { Element childElement = (Element)child; //if(childElement.hasAttribute("focusable")) // includeChildren = childElement.getAttribute("focusable").equals("true"); if(childElement.getTabIndex()>=0) { String tagName = childElement.getTagName(); //System.out.println(tagName); for(String supported : SUPPORTED_TYPES) { if(tagName.equalsIgnoreCase(supported)) { focusable.add(childElement); break; } } } findFocusable(childElement, focusable, include); } } } public void onFirstInput() { currentFocus = focusOn(focusable, INPUT_TYPES); } public void onFirstButton() { currentFocus = focusOn(focusable, BUTTON_TYPES); } private static int focusOn(List<Element> focusable, String[] types) { int index = 0; for(int i=0; i<focusable.size(); i++) { Element element = focusable.get(i); String tagName = element.getTagName(); Element match = null; for(String type : types) { if(tagName.equalsIgnoreCase(type)) { match = element; break; } } if(match!=null) { match.focus(); index =i; break; } } return index; } public void onElement(Element target) { for(int i=0; i<focusable.size(); i++) { Element element = focusable.get(i); if(target.equals(element)) { // reset focus setFocus(element); currentFocus = i; break; } } } public static native Element getActiveElement() /*-{ if($wnd.document.activeElement) return $wnd.document.activeElement; else return null; }-*/; }