28 Sep 2015

Show an Image in a Popup Window

There is a very common use-case when we have a link with an image on a page and we need to show a full-size version of the image in a popup window by clicking on the link. In this post I am going to show a few implementations of this use-case in ADF application.

Inline Popup
The first and the most obvious solution is to use af:popup and af:showPopupBehavior tags. Something like this:

<af:link text="Inline Popup" id="l1" icon="/images/turtle.jpg"
         iconPosition="top" styleClass="ImageLink">
  <af:showPopupBehavior popupId="p1"/>

<af:popup animate="false" contentDelivery="lazyUncached"
          childCreation="deferred" id="p1">
  <af:panelWindow resize="on" stretchChildren="first" id="pw1" title="Turtle">
    <af:image id="dc_i1" source="/images/turtle.jpg"/>

In this case an inline popup is going to be shown whenever the link is clicked:

So, it is pretty easy to implement and it works quite fast and nice.
What if we don't want to use an inline popup and we prefer to show the image in a separate browser window?

Separate browser tab
Let's assume the requirement is to show the image in a separate browser tab.
Actually, it is very easy to implement. We're going to use destination and targetFrame attributes of af:link component:

<af:link text="Destination" id="l2" icon="/images/turtle.jpg"
         iconPosition="top" styleClass="ImageLink"
         destination="/images/turtle.jpg" targetFrame="_blank"/>

So, whenever the link is clicked a new tab should be opened with a full-size image inside it. Actually, the "_blank" targetFrame forces the browser to open a new tab.

Separate browser window
If we want to force a browser to show the image inside a new window, we're going to use either of the following techniques:

ADF dialog: action
This is a pure ADF technique and it is based on ability to show a page in a new browser window while navigating to it. There are two pages in our page flow:

The ImageView contains an image:
  <af:form id="f1">
    <af:image source="/images/turtle.jpg" id="i1"/>

And the MainView contains a link:
<af:link text="Dialog action" id="l3" icon="/images/turtle.jpg"
         useWindow="true" windowHeight="400" windowWidth="400"/>

Pay attention to the useWindow attribute and to the action name which starts with "dialog:" prefix. These two things force the browser to show ImageView page in a new window. The size of this new window is defined with windowHeight and windowWidth attributes.
This approach works fine, but I wouldn't say that this solution is the best one in terms of performance. Whenever the framework is processing such "dialog:" navigation it seams that a spaceship is starting  on Cape Canaveral. It may take a second or two to open this new tab.

Java Script Approach
This lightweight solution uses a java script to open a new browser window:

function showImage(event)
  var link = event.getSource();
  popupWindow = window.open(link.getProperty("imageSrc"),
                            'Turtle', 'height=400,width=400');

There is a corresponding clientListener defined for the link:
<af:link text="Java Script" id="l4" icon="/images/turtle.jpg"
         iconPosition="top" styleClass="ImageLink">
  <af:clientListener method="showImage" type="action"/>
  <af:clientAttribute value="#{ImageBean.endpointURL}/images/turtle.jpg"

In order to pass correct image URI to the Java Script function we are using a managed bean method getEndpointURL:

public String getEndpointURL()
  FacesContext facesContext = FacesContext.getCurrentInstance();
  HttpServletRequest request =
    (HttpServletRequest) facesContext.getExternalContext().getRequest();
  String url = request.getRequestURL().toString();
  StringBuffer newUrlBuffer = new StringBuffer();
  newUrlBuffer.append(url.substring(0, url.lastIndexOf("faces/")));
  return newUrlBuffer.toString();

Basically this method returns URL to the application endpoint.

The sample application for this post can be downloaded here. It requires JDeveloper 12.1.3.

That's it!

No comments:

Post a Comment

Post Comment