Package org.apache.wicket.markup.html.link

Source Code of org.apache.wicket.markup.html.link.Link$AnchorChange

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.wicket.markup.html.link;

import org.apache.wicket.Component;
import org.apache.wicket.IPageMap;
import org.apache.wicket.Page;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.string.Strings;
import org.apache.wicket.version.undo.Change;

/**
* Implementation of a hyperlink component. A link can be used with an anchor
* (<a href...) element or any element that supports the onclick javascript
* event handler (such as buttons, td elements, etc). When used with an anchor,
* a href attribute will be generated. When used with any other element, an
* onclick javascript event handler attribute will be generated.
* <p>
* You can use a link like:
*
* <pre>
* add(new Link(&quot;myLink&quot;)
* {
*     public void onClick(RequestCycle cycle)
*     {
*         // do something here... 
*     }
* );
* </pre>
*
* and in your HTML file:
*
* <pre>
*  &lt;a href=&quot;#&quot; wicket:id=&quot;myLink&quot;&gt;click here&lt;/a&gt;
* </pre>
*
* or:
*
* <pre>
*  &lt;td wicket:id=&quot;myLink&quot;&gt;my clickable column&lt;/td&gt;
* </pre>
*
* </p>
* The following snippet shows how to pass a parameter from the Page creating
* the Page to the Page responded by the Link.
*
* <pre>
* add(new Link(&quot;link&quot;, listItem.getModel())
* {
*     public void onClick()
*     {
*         MyObject obj = (MyObject)getModelObject();
*         setResponsePage(new MyPage(obj.getId(), ... ));
*     }
* </pre>
*
* @author Jonathan Locke
* @author Eelco Hillenius
*/
public abstract class Link extends AbstractLink implements ILinkListener
{
  /** Change record for when an anchor is changed. */
  private final class AnchorChange extends Change
  {
    private static final long serialVersionUID = 1L;

    /** the old anchor. */
    private Component anchor;

    /**
     * Construct.
     *
     * @param anchor
     */
    public AnchorChange(Component anchor)
    {
      this.anchor = anchor;
    }

    public final void undo()
    {
      Link.this.anchor = anchor;
    }
  }

  private static final long serialVersionUID = 1L;

  /**
   * An anchor (form 'http://server/app/etc#someAnchor') will be appended to
   * the link so that after this link executes, it will jump to the provided
   * anchor component's position. The provided anchor must either have the
   * {@link Component#getOutputMarkupId()} flag true, or it must be attached
   * to a &lt;a tag with a href attribute of more than one character starting
   * with '#' ('&lt;a href="#someAnchor" ... ').
   */
  private Component anchor;

  /**
   * True if link should automatically enable/disable based on current page;
   * false by default.
   */
  private boolean autoEnable = false;

  /**
   * The popup specification. If not-null, a javascript on-click event handler
   * will be generated that opens a new window using the popup properties.
   */
  private PopupSettings popupSettings = null;

  /**
   * @see org.apache.wicket.Component#Component(String)
   */
  public Link(final String id)
  {
    super(id);
  }

  /**
   * @see org.apache.wicket.Component#Component(String, IModel)
   */
  public Link(final String id, IModel object)
  {
    super(id, object);
  }

  /**
   * Gets any anchor component.
   *
   * @return Any anchor component to jump to, might be null
   */
  public Component getAnchor()
  {
    return anchor;
  }

  /**
   * Gets whether link should automatically enable/disable based on current
   * page.
   *
   * @return Whether this link should automatically enable/disable based on
   *         current page.
   */
  public final boolean getAutoEnable()
  {
    return autoEnable;
  }

  /**
   * Gets the popup specification. If not-null, a javascript on-click event
   * handler will be generated that opens a new window using the popup
   * properties.
   *
   * @return the popup specification.
   */
  public PopupSettings getPopupSettings()
  {
    return popupSettings;
  }

  /**
   * @see org.apache.wicket.Component#isEnabled()
   */
  public boolean isEnabled()
  {
    // If we're auto-enabling
    if (getAutoEnable())
    {
      // the link is enabled if this link doesn't link to the current page
      return !linksTo(getPage());
    }
    return super.isEnabled();
  }

  protected boolean getStatelessHint()
  {
    return false;
  }

  /**
   * Called when a link is clicked.
   */
  public abstract void onClick();

  /**
   * THIS METHOD IS NOT PART OF THE WICKET API. DO NOT ATTEMPT TO OVERRIDE OR
   * CALL IT.
   *
   * Called when a link is clicked. The implementation of this method is
   * currently to simply call onClick(), but this may be augmented in the
   * future.
   *
   * @see ILinkListener
   */
  public final void onLinkClicked()
  {
    // if there are popupsettings and this link is clicked.
    // set the popup page map in the request parameters, so that pages that
    // are created in the onClick are made in the wanted pagemap
    if (popupSettings != null)
    {
      RequestCycle.get().getRequest().getRequestParameters().setPageMapName(
          popupSettings.getPageMap(this).getName());
    }
    // Invoke subclass handler
    onClick();
  }

  /**
   * Sets an anchor component. An anchor (form
   * 'http://server/app/etc#someAnchor') will be appended to the link so that
   * after this link executes, it will jump to the provided anchor component's
   * position. The provided anchor must either have the
   * {@link Component#getOutputMarkupId()} flag true, or it must be attached
   * to a &lt;a tag with a href attribute of more than one character starting
   * with '#' ('&lt;a href="#someAnchor" ... ').
   *
   * @param anchor
   *            The anchor
   * @return this
   */
  public Link setAnchor(Component anchor)
  {
    addStateChange(new AnchorChange(this.anchor));
    this.anchor = anchor;
    return this;
  }

  /**
   * Sets whether this link should automatically enable/disable based on
   * current page.
   *
   * @param autoEnable
   *            whether this link should automatically enable/disable based on
   *            current page.
   * @return This
   */
  public final Link setAutoEnable(final boolean autoEnable)
  {
    this.autoEnable = autoEnable;
    return this;
  }

  /**
   * Sets the popup specification. If not-null, a javascript on-click event
   * handler will be generated that opens a new window using the popup
   * properties.
   *
   * @param popupSettings
   *            the popup specification.
   * @return This
   */
  public final Link setPopupSettings(final PopupSettings popupSettings)
  {
    this.popupSettings = popupSettings;
    return this;
  }

  /**
   * Appends any anchor to the url if the url is not null and the url does not
   * already contain an anchor (url.indexOf('#') != -1). This implementation
   * looks whether an anchor component was set, and if so, it will append the
   * markup id of that component. That markup id is gotten by either calling
   * {@link Component#getMarkupId()} if {@link Component#getOutputMarkupId()}
   * returns true, or if the anchor component does not output it's id, this
   * method will try to retrieve the id from the markup directly. If neither
   * is found, an {@link WicketRuntimeException excpeption} is thrown. If no
   * anchor component was set, but the link component is attached to a &lt;a
   * element, this method will append what is in the href attribute <i>if</i>
   * there is one, starts with a '#' and has more than one character.
   * <p>
   * You can override this method, but it means that you have to take care of
   * whatever is done with any set anchor component yourself. You also have to
   * manually append the '#' at the right place.
   * </p>
   *
   * @param tag
   *            The component tag
   * @param url
   *            The url to start with
   * @return The url, possibly with an anchor appended
   */
  protected CharSequence appendAnchor(final ComponentTag tag, CharSequence url)
  {
    if (url != null)
    {
      Component anchor = getAnchor();
      if (anchor != null)
      {
        if (url.toString().indexOf('#') == -1)
        {
          String id;
          if (anchor.getOutputMarkupId())
          {
            id = anchor.getMarkupId();
          }
          else
          {
            id = anchor.getMarkupAttributes().getString("id");
          }

          if (id != null)
          {
            url = url + "#" + anchor.getMarkupId();
          }
          else
          {
            throw new WicketRuntimeException("an achor component was set on " + this
                + " but it neither has outputMarkupId set to true "
                + "nor has a id set explicitly");
          }
        }
      }
      else
      {
        if (tag.getName().equalsIgnoreCase("a"))
        {
          if (url.toString().indexOf('#') == -1)
          {
            String href = tag.getAttributes().getString("href");
            if (href != null && href.length() > 1 && href.charAt(0) == '#')
            {
              url = url + href;
            }
          }
        }
      }
    }
    return url;
  }

  /**
   * @param url
   *            The url for the link
   * @return Any onClick JavaScript that should be used
   */
  protected CharSequence getOnClickScript(final CharSequence url)
  {
    return getOnClickScript(url.toString());
  }

  /**
   * @param url
   *            The url for the link
   * @return Any onClick JavaScript that should be used
   * @deprecated this method will be removed by
   *             {@link #getOnClickScript(CharSequence)} shortly. Please
   *             override that method instead.
   */
  protected String getOnClickScript(final String url)
  {
    return null;
  }

  /**
   * Gets the url to use for this link.
   *
   * @return The URL that this link links to
   */
  protected CharSequence getURL()
  {
    return urlFor(ILinkListener.INTERFACE);
  }

  /**
   * Whether this link refers to the given page.
   *
   * @param page
   *            A page
   * @return True if this link goes to the given page
   */
  protected boolean linksTo(final Page page)
  {
    return false;
  }

  /**
   * Handles this link's tag.
   *
   * @param tag
   *            the component tag
   * @see org.apache.wicket.Component#onComponentTag(ComponentTag)
   */
  protected void onComponentTag(final ComponentTag tag)
  {
    // Default handling for tag
    super.onComponentTag(tag);

    // Set href to link to this link's linkClicked method
    CharSequence url = getURL();

    // append any anchor
    url = appendAnchor(tag, url);

    // If we're disabled
    if (!isLinkEnabled())
    {
      disableLink(tag);
    }
    else
    {
      // if the tag is an anchor proper
      if (tag.getName().equalsIgnoreCase("a") || tag.getName().equalsIgnoreCase("link")
          || tag.getName().equalsIgnoreCase("area"))
      {
        // generate the href attribute
        tag.put("href", Strings.replaceAll(url, "&", "&amp;"));

        // Add any popup script
        if (popupSettings != null)
        {
          // NOTE: don't encode to HTML as that is not valid
          // JavaScript
          tag.put("onclick", popupSettings.getPopupJavaScript());
        }
      }
      else if (tag.getName().equalsIgnoreCase("script")
          || tag.getName().equalsIgnoreCase("style"))
      {
        tag.put("src", Strings.replaceAll(url, "&", "&amp;"));
      }
      else
      {
        // generate a popup script by asking popup settings for one
        if (popupSettings != null)
        {
          popupSettings.setTarget("'" + url + "'");
          String popupScript = popupSettings.getPopupJavaScript();
          tag.put("onclick", popupScript);
        }
        else
        {
          // or generate an onclick JS handler directly
          tag.put("onclick", "window.location.href='" + url + "';return false;");
        }
      }
     
      // If the subclass specified javascript, use that
      final CharSequence onClickJavaScript = getOnClickScript(url);
      if (onClickJavaScript != null)
      {
        tag.put("onclick", onClickJavaScript);
      }

      if (popupSettings != null)
      {
        IPageMap popupPageMap = popupSettings.getPageMap(this);
        if (popupPageMap != null && popupPageMap.getName() != null)
        {
          tag.put("target", popupPageMap.getName());
        }
      }
    }

  }
}
TOP

Related Classes of org.apache.wicket.markup.html.link.Link$AnchorChange

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.