A Modal Dialog For Tapestry

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;
}

The example is chrome :

About these ads

Tagged: , , ,

10 thoughts on “A Modal Dialog For Tapestry

  1. Dragan Sahpaski July 2, 2011 at 3:09 AM Reply

    Why don’t you provide at least one screenshot in the posts.

    Just an idea.

    Cheers

  2. hongdengdao July 3, 2011 at 9:45 AM Reply

    great!!!,very useful

  3. hongdengdao July 5, 2011 at 6:14 AM Reply

    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!!

    • hongdengdao July 5, 2011 at 12:16 PM Reply

      ” params.options.onContentLoaded = function()” => ” params.options.afterload = function()”

      sorry

      • tawus July 8, 2011 at 12:10 PM

        Done!!

  4. Mihail Slobodyanuk July 8, 2011 at 10:35 AM Reply

    The same solution provide Window component of ChenilleKit

  5. mauro May 31, 2012 at 3:17 PM Reply

    Hi, I have a problem with the Modal Dialog.
    I’m using it like in the example you made and it works fine but the problem happens when i have a modal dialog in a form.

    For instance,
    i have a form to save a new user. I’ using the modal dialog box to enter a telephone number and in the dialog box there is a form with the field to input the thelephone number and a radio button to chose between Fax or Tel.
    The problem is that when i save the telephone, it appears on the page but because the onSubmitFromDialogBox returns the Zone and not the Zone.getBody(), all the data previously inserted in the form disappear!

    This happens because after the submit the whole page is refreshed while i would expect, because of the t:zone, only the small piece of page associated with the telephone numbers would do.

    Any suggestion?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 91 other followers

%d bloggers like this: