/* * Copyright 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.user.client.ui; import com.google.gwt.dom.client.AnchorElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.i18n.client.BidiUtils; import com.google.gwt.i18n.client.HasDirection; import com.google.gwt.i18n.shared.DirectionEstimator; import com.google.gwt.i18n.shared.HasDirectionEstimator; import com.google.gwt.safehtml.shared.SafeHtml; /** * A widget that represents a simple <a> element. * * <p> * If you want use this anchor only for changing history states, use * {@link Hyperlink} instead. * </p> * * <p> * <h3>Built-in Bidi Text Support</h3> * This widget is capable of automatically adjusting its direction according to * its content. This feature is controlled by {@link #setDirectionEstimator} or * passing a DirectionEstimator parameter to the constructor, and is off by * default. * </p> * * <h3>CSS Style Rules</h3> * <ul class='css'> * <li>.gwt-Anchor { }</li> * </ul> * * @see Hyperlink */ public class Anchor extends FocusWidget implements HasHorizontalAlignment, HasName, HasHTML, HasWordWrap, HasDirection, HasDirectionEstimator, HasDirectionalSafeHtml { public static final DirectionEstimator DEFAULT_DIRECTION_ESTIMATOR = DirectionalTextHelper.DEFAULT_DIRECTION_ESTIMATOR; /** * The default HREF is a no-op javascript statement. We need an href to ensure * that the browser renders the anchor with native styles, such as underline * and font color. */ private static final String DEFAULT_HREF = "javascript:;"; /** * Creates an Anchor widget that wraps an existing <a> element. * * This element must already be attached to the document. If the element is * removed from the document, you must call * {@link RootPanel#detachNow(Widget)}. * * @param element the element to be wrapped */ public static Anchor wrap(Element element) { // Assert that the element is attached. assert Document.get().getBody().isOrHasChild(element); Anchor anchor = new Anchor(element); // Mark it attached and remember it for cleanup. anchor.onAttach(); RootPanel.detachOnWindowClose(anchor); return anchor; } private final DirectionalTextHelper directionalTextHelper; private HorizontalAlignmentConstant horzAlign; /** * Creates an empty anchor. * * <p> * The anchor's href is <em>not</em> set, which means that the widget will not * not be styled with the browser's native link styles (such as underline and * font color). Use {@link #Anchor(boolean)} to add a default no-op href that * does not open a link but ensures the native link styles are applied. * </p> * * @see #Anchor(boolean) */ public Anchor() { this(false); } /** * Creates an anchor. * * The anchor's href is optionally set to <code>javascript:;</code>, based on * the expectation that listeners will be added to the anchor. * * @param useDefaultHref true to set the default href to * <code>javascript:;</code>, false to leave it blank */ public Anchor(boolean useDefaultHref) { setElement(Document.get().createAnchorElement()); setStyleName("gwt-Anchor"); directionalTextHelper = new DirectionalTextHelper(getAnchorElement(), /* is inline */true); if (useDefaultHref) { setHref(DEFAULT_HREF); } } /** * Creates an anchor for scripting. * * @param html the anchor's html */ public Anchor(SafeHtml html) { this(html.asString(), true); } /** * Creates an anchor for scripting. * * The anchor's href is set to <code>javascript : ;</code>, based on the * expectation that listeners will be added to the anchor. * * @param html the anchor's html * @param dir the html's direction */ public Anchor(SafeHtml html, Direction dir) { this(html.asString(), true, dir, DEFAULT_HREF); } /** * Creates an anchor for scripting. * * The anchor's href is set to <code>javascript : ;</code>, based on the * expectation that listeners will be added to the anchor. * * @param html the anchor's html * @param directionEstimator A DirectionEstimator object used for automatic * direction adjustment. For convenience, * {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used. */ public Anchor(SafeHtml html, DirectionEstimator directionEstimator) { this(html.asString(), true, directionEstimator, DEFAULT_HREF); } /** * Creates an anchor for scripting. * * The anchor's href is set to <code>javascript:;</code>, based on the * expectation that listeners will be added to the anchor. * * @param text the anchor's text */ public Anchor(String text) { this(text, DEFAULT_HREF); } /** * Creates an anchor for scripting. * * The anchor's href is set to <code>javascript : ;</code>, based on the * expectation that listeners will be added to the anchor. * * @param text the anchor's text * @param dir the text's direction */ public Anchor(String text, Direction dir) { this(text, dir, DEFAULT_HREF); } /** * Creates an anchor for scripting. * * The anchor's href is set to <code>javascript : ;</code>, based on the * expectation that listeners will be added to the anchor. * * @param text the anchor's text * @param directionEstimator A DirectionEstimator object used for automatic * direction adjustment. For convenience, * {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used. */ public Anchor(String text, DirectionEstimator directionEstimator) { this(text, directionEstimator, DEFAULT_HREF); } /** * Creates an anchor for scripting. * * The anchor's href is set to <code>javascript:;</code>, based on the * expectation that listeners will be added to the anchor. * * @param text the anchor's text * @param asHtml <code>true</code> to treat the specified text as html */ public Anchor(String text, boolean asHtml) { this(text, asHtml, DEFAULT_HREF); } /** * Creates an anchor with its html and href (target URL) specified. * * @param html the anchor's html * @param href the url to which it will link */ public Anchor(SafeHtml html, String href) { this(html.asString(), true, href); } /** * Creates an anchor with its html and href (target URL) specified. * * @param html the anchor's html * @param dir the html's direction * @param href the url to which it will link */ public Anchor(SafeHtml html, Direction dir, String href) { this(html.asString(), true, dir, href); } /** * Creates an anchor with its html and href (target URL) specified. * * @param html the anchor's html * @param directionEstimator A DirectionEstimator object used for automatic * direction adjustment. For convenience, * {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used. * @param href the url to which it will link */ public Anchor(SafeHtml html, DirectionEstimator directionEstimator, String href) { this(html.asString(), true, directionEstimator, href); } /** * Creates an anchor with its text and href (target URL) specified. * * @param text the anchor's text * @param href the url to which it will link */ public Anchor(String text, String href) { this(text, false, href); } /** * Creates an anchor with its text and href (target URL) specified. * * @param text the anchor's text * @param dir the text's direction * @param href the url to which it will link */ public Anchor(String text, Direction dir, String href) { this(text, false, dir, href); } /** * Creates an anchor with its text and href (target URL) specified. * * @param text the anchor's text * @param directionEstimator A DirectionEstimator object used for automatic * direction adjustment. For convenience, * {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used. * @param href the url to which it will link */ public Anchor(String text, DirectionEstimator directionEstimator, String href) { this(text, false, directionEstimator, href); } /** * Creates an anchor with its text and href (target URL) specified. * * @param text the anchor's text * @param asHTML <code>true</code> to treat the specified text as html * @param href the url to which it will link */ public Anchor(String text, boolean asHTML, String href) { this(); directionalTextHelper.setTextOrHtml(text, asHTML); setHref(href); } /** * Creates a source anchor (link to URI). * * That is, an anchor with an href attribute specifying the destination URI. * * @param html the anchor's html * @param href the url to which it will link * @param target the target frame (e.g. "_blank" to open the link in a new * window) */ public Anchor(SafeHtml html, String href, String target) { this(html.asString(), true, href, target); } /** * Creates a source anchor with a frame target. * * @param text the anchor's text * @param href the url to which it will link * @param target the target frame (e.g. "_blank" to open the link in a new * window) */ public Anchor(String text, String href, String target) { this(text, false, href, target); } /** * Creates a source anchor (link to URI). * * That is, an anchor with an href attribute specifying the destination URI. * * @param text the anchor's text * @param asHtml asHTML <code>true</code> to treat the specified text as html * @param href the url to which it will link * @param target the target frame (e.g. "_blank" to open the link in a new * window) */ public Anchor(String text, boolean asHtml, String href, String target) { this(text, asHtml, href); setTarget(target); } /** * This constructor may be used by subclasses to explicitly use an existing * element. This element must be an <a> element. * * @param element the element to be used */ protected Anchor(Element element) { AnchorElement.as(element); setElement(element); directionalTextHelper = new DirectionalTextHelper(getAnchorElement(), /* is inline */ true); } /** * Creates an anchor with its text, direction and href (target URL) specified. * * @param text the anchor's text * @param asHTML <code>true</code> to treat the specified text as html * @param dir the text's direction * @param href the url to which it will link */ private Anchor(String text, boolean asHTML, Direction dir, String href) { this(); directionalTextHelper.setTextOrHtml(text, dir, asHTML); setHref(href); } /** * Creates an anchor with its text, direction and href (target URL) specified. * * @param text the anchor's text * @param asHTML <code>true</code> to treat the specified text as html * @param directionEstimator A DirectionEstimator object used for automatic * direction adjustment. For convenience, * {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used. * @param href the url to which it will link */ private Anchor(String text, boolean asHTML, DirectionEstimator directionEstimator, String href) { this(); directionalTextHelper.setDirectionEstimator(directionEstimator); directionalTextHelper.setTextOrHtml(text, asHTML); setHref(href); } public Direction getDirection() { return BidiUtils.getDirectionOnElement(getElement()); } public DirectionEstimator getDirectionEstimator() { return directionalTextHelper.getDirectionEstimator(); } public HorizontalAlignmentConstant getHorizontalAlignment() { return horzAlign; } /** * Gets the anchor's href (the url to which it links). * * @return the anchor's href */ public String getHref() { return getAnchorElement().getHref(); } public String getHTML() { return getElement().getInnerHTML(); } public String getName() { return getAnchorElement().getName(); } @Override public int getTabIndex() { return getAnchorElement().getTabIndex(); } /** * Gets the anchor's target frame (the frame in which navigation will occur * when the link is selected). * * @return the target frame */ public String getTarget() { return getAnchorElement().getTarget(); } public String getText() { return directionalTextHelper.getTextOrHtml(false); } public Direction getTextDirection() { return directionalTextHelper.getTextDirection(); } public boolean getWordWrap() { return !getElement().getStyle().getProperty("whiteSpace").equals("nowrap"); } @Override public void setAccessKey(char key) { getAnchorElement().setAccessKey(Character.toString(key)); } /** * @deprecated Use {@link #setDirectionEstimator} and / or pass explicit * direction to {@link #setText}, {@link #setHTML} instead */ @Deprecated public void setDirection(Direction direction) { directionalTextHelper.setDirection(direction); } /** * {@inheritDoc} * <p> * See note at {@link #setDirectionEstimator(DirectionEstimator)}. */ public void setDirectionEstimator(boolean enabled) { directionalTextHelper.setDirectionEstimator(enabled); } /** * {@inheritDoc} * <p> * Note: DirectionEstimator should be set before the widget has any content; * it's highly recommended to set it using a constructor. Reason: if the * widget already has non-empty content, this will update its direction * according to the new estimator's result. This may cause flicker, and thus * should be avoided. */ public void setDirectionEstimator(DirectionEstimator directionEstimator) { directionalTextHelper.setDirectionEstimator(directionEstimator); } @Override public void setFocus(boolean focused) { if (focused) { getAnchorElement().focus(); } else { getAnchorElement().blur(); } } public void setHorizontalAlignment(HorizontalAlignmentConstant align) { horzAlign = align; getElement().getStyle().setProperty("textAlign", align.getTextAlignString()); } /** * Sets the anchor's href (the url to which it links). * * @param href the anchor's href */ public void setHref(String href) { getAnchorElement().setHref(href); } public void setHTML(SafeHtml html) { setHTML(html.asString()); } public void setHTML(String html) { directionalTextHelper.setTextOrHtml(html, true); } public void setHTML(SafeHtml html, Direction dir) { directionalTextHelper.setTextOrHtml(html.asString(), dir, true); } public void setName(String name) { getAnchorElement().setName(name); } @Override public void setTabIndex(int index) { getAnchorElement().setTabIndex(index); } /** * Sets the anchor's target frame (the frame in which navigation will occur * when the link is selected). * * @param target the target frame */ public void setTarget(String target) { getAnchorElement().setTarget(target); } public void setText(String text) { directionalTextHelper.setTextOrHtml(text, false); } public void setText(String text, Direction dir) { directionalTextHelper.setTextOrHtml(text, dir, false); } public void setWordWrap(boolean wrap) { getElement().getStyle().setProperty("whiteSpace", wrap ? "normal" : "nowrap"); } private AnchorElement getAnchorElement() { return AnchorElement.as(getElement()); } }