J2EE developer with over 7 years of experience in designing and implementing enterprise j2ee solutions based on open source technologies like Tapestry, Hibernate, Spring. Current interests include Tapestry, Plastic, Spock, Scala. Taha is a DZone MVB and is not an employee of DZone and has posted 40 posts at DZone. You can read more from them at their website. View Full User Profile

A Modal Dialog For Tapestry

07.02.2011
| 4233 views |
  • submit to reddit

As Tapestry does not provide a Dialog Box, let us see how difficult(or easy) it is to create one on our own. We will use ModalBox as it has an MIT license and it is written in prototype (Soon this won’t be a criteria for choosing a script as Tapestry is going to be prototype independent). The ModalBox script is very easy to use. There is a ModalBox.show() method which displays a dialog box. It takes a dom element and configuration options as parameters. If you want to create a wizard just keep on using the same method inside the dialog box. There is also a ModalBox.hide() method to hide the dialog.

Our script is more than just a call to ModalBox.show(). It needs to call the event handler using a event URL and use the response to create an element which it will display in the dialog box. It also provides an option to update a zone after closure of the dialog box.

Tapestry.Initializer.setupModalDialog = function(params)
{
   // Setup zone
   var element = $(params.id);
   $T(element).zoneId = params.zone;

   var showModalbox = function()
   {
         var loadContentWithScripts = function(transport)
         {
            var node = new Element('div').update(transport.responseJSON.content);
            params.options.onContentLoaded = function()
            {
               Tapestry.loadScriptsInReply(transport.responseJSON, function() {});
            };

            params.options.afterHide = function()
            {
               if(params.zone)
               {
                  var zoneManager = Tapestry.findZoneManager(element);
                  zoneManager.updateFromURL(params.closeLink);
               }
            };

            Modalbox.show(node, params.options);
         };

         Tapestry.ajaxRequest(params.openLink, {
            method : 'get',
            onSuccess : loadContentWithScripts
         });
   };

   Event.observe($(params.id), params.event, showModalbox);

};

The script function takes the following parameters

  • id : id of the element
  • event: client event on the element which will trigger the event
  • openLink: link to be called to create the dialog
  • closeLink: link called after the dialog is closed
  • zone: zone to be updated after dialog is closed
  • options: other options to be passed to ModalBox.show() e.g. width, height, title

The script links client event of the element to a method which makes an ajax based request to get the dialog box contents from the server and then calls the Tapestry.loadScriptsInReply() function to load any inline scripts.

The parameters are passed to the script by our ModalDialog component class.

@SupportsInformalParameters
@Import(library = {
      "modalbox/builder.js",
      "modalbox/effects.js",
      "modalbox/modalbox.js",
      "modalbox/modalboxinit.js"
      } , 

      stylesheet = "modalbox/modalbox.css"
)
@Events({TawusAddonsEventConstants.SHOW_DIALOG})
public class ModalDialog implements ClientElement
{
   /**
    * Javascript id, if not supplied is auto-generated
    */
   @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL, allowNull = false)
   private String clientId;

   /**
    * Client event that will trigger the modal dialog
    */
   @Parameter(value = "click", defaultPrefix = BindingConstants.LITERAL, allowNull = false)
   private String clientEvent;

   /**
    * Zone to update when dialog is closed
    */
   @Parameter(defaultPrefix = BindingConstants.LITERAL)
   private String zone;

   /**
    * Context to be passed to the page
    */
   @Parameter
   private Object[] context;

   @Environmental
   private JavaScriptSupport javaScriptSupport;

   @Inject
   private ComponentResources resources;

   private String assignedClientId;

   public ModalDialog()
   {

   }

   ModalDialog(JavaScriptSupport javaScriptSupport,
         ComponentResources resources)
   {
      this.javaScriptSupport = javaScriptSupport;
      this.resources = resources;
   }

   void setupRender()
   {
      assignedClientId = javaScriptSupport.allocateClientId(clientId);
   }

   void beginRender(MarkupWriter writer)
   {
      writer.element("a", "href", "#", "id", getClientId());
   }

   void afterRender(MarkupWriter writer)
   {
      writer.end();
   }

   @AfterRender
   void addJavaScript()
   {
      JSONObject params = new JSONObject();

      params.put("id", getClientId());
      params.put("event", clientEvent);
      params.put("openLink", getPageLink());
      params.put("closeLink", getCloseLink());
      params.put("zone", zone);
      params.put("options", getInformalParametersAsJSON());

      javaScriptSupport.addInitializerCall("setupModalDialog", params);
   }

   private JSONObject getInformalParametersAsJSON()
   {
      JSONObject modalboxOptions = new JSONObject();
      for(String parameter : resources.getInformalParameterNames())
      {
         modalboxOptions.put(parameter,
           resources.getInformalParameter(parameter, String.class));
      }
      return modalboxOptions;
   }

   private Object getPageLink()
   {
      Link link = resources.createEventLink(TawusAddonsEventConstants.SHOW_DIALOG, context);
      return link.toAbsoluteURI();
   }

   private String getCloseLink()
   {
      return resources.createEventLink(
         TawusAddonsEventConstants.CLOSE_DIALOG).toAbsoluteURI();
   }

   public String getClientId()
   {
      return assignedClientId;
   }
}

public class TawusAddonsEventConstants
{
   public static final String SHOW_DIALOG = "showDialog";

   public static final String CLOSE_DIALOG = "closeDialog";
}

The component creates an anchor tag and calls the javascript function with proper parameters. The informal parameters are used to supply ModalBox with other configuration options.

Usage

<a t:type='tawus/modaldialog' t:zone='closeZone'>Open Dialog</a>
<div t:type='zone' t:id='closeZone'>Call this zone on closure</div>

<t:block t:id='modaldialogContents'>
Some content
</t:block>
@Inject
private Block modalDialogContents;

public Block onShowDialog()
{
   return modalDialogContents;
}

public Zone onCloseDialog()
{
   return closeZone;
}

From http://tawus.wordpress.com/2011/07/02/a-modal-dialog-for-tapestry/

Published at DZone with permission of Taha Siddiqi, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Sirikant Noori replied on Sun, 2012/01/15 - 11:54am

thanks for you sharing ,and i find out i download the newest version of modalbox , the modalbox onContentLoaded event had changed to afterload event ,so
” params.options.onContentLoaded = function()” => ” params.options.afterwork = function()”
and tapestry js ok!!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.