Ajax « Intelligrape Groovy & Grails Blogs

Posts Tagged ‘ Ajax ’

Accessing remote data through cross-domain ajax call in jquery

Posted by on September 24th, 2012

While developing a mobile app using phonegap ( or otherwise also :) ), we can access remotely hosted mysql database using jquery ajax calls. But this interaction between jquery and mysql database cannot happen directly. We will need to specify a server side script(in PHP terminology) or a controller action(in Grails Terminology) that will fetch data from the mysql database and serve it to the jquery call. Jquery will simply make a cross-domain ajax request to the server side script and the script will send requested data as response.

For a successful cross-domain communication, we need to use dataType “jsonp” in jquery ajax call.
JSONP or “JSON with padding” is a complement to the base JSON data format which provides a method to request data from a server in a different domain, something prohibited by typical web browsers.

When we specify dataType as jsonp, a “callback” parameter is appended to the request url and jquery creates a function whose name is the value of callback parameter. On server side, the script receives the “callback” parameter value(which is name of the function) and sends the data as argument to that function. Alternatively, that data is also available in the success function of jquery.

Jquery Code :

	    function crossDomainCall(url,data,fnSuccess,fnError){
            $.ajax({
                type:'POST',
                url:url,
                contentType:"application/json",
                dataType:'jsonp',
                crossDomain:true,
                data:data,
                success:fnSuccess,
                error: fnError
            });
        }
	
        function authenticateUser(username, password) {
            var url = 'http://www.example.com/user/authenticate';
            var data={username:username, password:password};
            var fnSuccess=function (dataReceived) {
		    if(dataReceived) {
			    alert("Welcome "+dataReceived.name);
		    }else{
			    alert("Authentication failed")
		    }
            };

            var fnError=function (e) {
                alert(e);
            };
            crossDomainCall(url,data,fnSuccess,fnError);
        }

Server side code :

 
	def authenticate(String username, String password){
        	User user=User.findByNameAndPassword(username,password)
		    if (user) {
		        render "${params.callback}(${user as JSON})"
		    }else{
		        render "${params.callback}(null)"
		    }
    	}

Here, the function name is received from params.callback and data is sent in json form as an argument to the function.

Hope it helps.
Have Fun :)

Implement Ajax call in Grails web-flow

Posted by on September 16th, 2012

In one of my recent project, i want to use grails web-flow with ajax call. It’s very easy to implement the web-flow with ajax call. Grails web-flow always track the actions on the basis of eventId & flow execution key. So, to implement ajax call in web-flow, we have to pass the event id & flow execution key.

1. Let us assume, we have the following web- flow code in grails.

def stepFlow ={
first{
action{
code.....
}on ("success"){code...}.to("second")
}
second{
on("third"){
}.to("fourth")
}
fourth();
}

In this case, step is web flow name, for each call we have to pass step as request uri . First, second and third are events, events are always tracked through flow execution key

2. We want to call the event third through ajax call. For this we have to write the following code in ajax.

function callAjaxFunctionInWebFlow(eventType,flowExecutionKey){

$.ajax({
url:"project-name/step",
type:'POST',
data:'_eventId=' + eventType + '&execution=' + flowExecutionKey,
success:function (result) {

},
error:function (jqXHR, textStatus, errorThrown) {
}
})
}

3. To call this function from GSP we have to write the following code.

<a href='javascript:void(0)' onclick="callAjaxFunctionInWebFlow('third','${request.flowExecutionKey}')">Click</a>

In this function callAjaxFunctionInWebFlow(‘third’,'${request.flowExecutionKey}’) third is eventId that we want to call, request.flowExecutionKey gives the current execution key that need to pass through each ajax call.

Hope it will help.

Thanks & Regards,

Mohit Garg

mohit@intelligrape.com

@gargmohit143Thanks & Regards,
Mohit Garg
mohit@intelligrape.com
@gargmohit143

Posted in Grails, Groovy

JQGrid Expanding SubGrid on page load

Posted by on February 13th, 2011

Hi,
 
Recently guys, i faced problem while expanding the JQGrid SubGrid onLoad of the page.
 
Initially, i used the following code on gridComplete Event of JQGrid, Using the code given below, i am only able to expand grid but without data populated in subgrid.

gridComplete: function() {
                var rowIds = $("#testTable").getDataIDs();
                $.each(rowIds, function (index, rowId) {
                        $("#testTable").expandSubGridRow(rowId);                   
                });
            }

After trying different ways, and many efforts i came up with this solution and it worked for me.
Solution to above problem given below :

gridComplete: function() {
                var timeOut = 50;
                var rowIds = $("#testTable").getDataIDs();
                $.each(rowIds, function (index, rowId) {
                    setTimeout(function() {
                        $("#testTable").expandSubGridRow(rowId);
                    }, timeOut);
                    timeOut = timeOut + 200;
                });
            }

It worked for me. Hope it help you too.

Thanks & regards,
Tarun Pareek
LinkedIn

Asynchronous behavior of AJAX

Posted by on September 14th, 2010

Ajax (shorthand for Asynchronous JavaScript and XML) is used to retrieve data from the server asynchronously without interfering with the display and behavior of the existing page. Forgetting this asynchronous behavior will produce incorrect result if it depends on the response from Ajax call.

Lets take an example(I am using JQuery to illustrate the example). Here is a JavaScript function to perform server side check of the form. Depending on the response of Ajax call the function either submits the form or does nothing.

function submitForm(){
	var isFormValid=false;
	var dataToBeSent=$('form').serialize();
	$.get(url, dataToBeSent, function(result){
		isFormValid=result;
	})
	if(isFormValid){
		$('form').submit();
	}
}

The statement $('form').submit() will never be called irrespective of the result (AJAX call response). After executing $.get statement it will execute the next statement  if(isFormValid) without waiting for the statement isFormValid=result inside the callback function to be executed.

There exist a dirty solution for the problem : using JavaScript sleep API. But how long you are going to halt the execution of JavaScript code. You are back to the same problem of getting the incorrect behavior.

One good solution is to make the $.get call synchronous by making changes to the global AJAX configuration like :

$.ajaxSettings.async=false;

or using calls like :

$.ajax({type: "GET", url: url, data: dataToBeSent, success: function(){
		isFormValid=result;
	}
});

Now the if(isFormValid) statement will be executed only after the $.ajax statement has completed its execution. However this approach has its own drawback. Obvious one is the execution of JavaScript halts until it receives the response.

However the better solution  is to execute $('form').submit() inside the callback function like :

$('submitButton').click(function(){
	var isFormValid=false;
	var dataToBeSent=$('form').serialize();
	$.get(url, dataToBeSent, function(result){
		isFormValid=result;
	if(isFormValid){
		$('form').submit();
	}
	})
return false;  // Needless if the button is not a submit button
})

return false statement at the end of the function prevents the form from being submitted. Now the form submission code will be executed only after the response to $.get statement is true.

There exist JQuery plugins (e.g. JQuery validation plugin) for doing form validation in a better way where you get support for server side validation also. But the case discussed above was to make you understand the asynchronous behavior of AJAX calls.

Hope this helps you while using Ajax.  :)

Cheers,
~~Bhagwat Kumar~~
bhagwat(at)intelligrape(dot)com

http://www.intelligrape.com

Cheers!
~~Bhagwat Kumar~~
bhagwat(at)intelligrape(dot)com
http://twitter.com/bhagwatkumar
http://in.linkedin.com/in/bhagwatkumar

JQuery: Send JSON Objects with an ajax request

Posted by on June 11th, 2010

Hi Friends,

Lets discuss today about sending JSON objects with ajax request using JQuery. We have number of functions in jQuery to kick-off an ajax request. But for sending JSON objects along with the request, I chose jQuer.ajax(). It takes various parameters url, type, data, dataType, beforeSend etc. Its API can be found here.

Lets look at example given below:

jQuery.ajax({
          url: <Url of the action>,
          type: "POST",
          data: {name: "amit", id:1 },
          dataType: "json",
          beforeSend: function(x) {
            if (x && x.overrideMimeType) {
              x.overrideMimeType("application/j-son;charset=UTF-8");
            }
          },
          success: function(result) {
 	     //Write your code here
          }
});

The above example works for simple JSON object. Now lets see how we can send JSON objects list as given below:

var jsonObjects = [{id:1, name:"amit"}, {id:2, name:"ankit"},{id:3, name:"atin"},{id:1, name:"puneet"}];
 
jQuery.ajax({
          url: <Url of the action>,
          type: "POST",
          data: {students: JSON.stringify(jsonObjects) },
          dataType: "json",
          beforeSend: function(x) {
            if (x && x.overrideMimeType) {
              x.overrideMimeType("application/j-son;charset=UTF-8");
            }
          },
          success: function(result) {
 	     //Write your code here
          }
});

If you notice, for sending my json objects it has not been written directly as data: jsonObjects. As it expects the JSON object passed to it written as key value pair. So we made students the key. And since we have json objects stored in a variable, we need to expand the json objects list using stringify(), otherwise it would be sent as a java script object.

Now on the server we can parse the JSON object, and use it as the list of objects of type map. For example

//this code is written in grails 
import grails.converters.JSON;
List<JSON> students = JSON.parse(params.students) //students in request params is parsed to json objects and stored in the List
println "Student id: " + students[0].studentId    //first element of the students list is accessed as a map holding a key studentId

Hope this helpled!

~~Amit Jain~~
amit@intelligrape.com

http://www.IntelliGrape.com

Tags: , ,

Monitoring ajax call response

Posted by on March 4th, 2010

Recently I have faced a problem of monitoring all the ajax calls. Based on the response from server I have to perform some task depending on the contents of response. If the html response contains some text input field, the first text input field should be automatically focused otherwise leave the response as it is.

Here is the javascript code :

<span id="ajax_spinner" style="display:none"></span>
<script type="text/javascript">
            jQuery("#ajax_spinner").ajaxComplete(function(event, xhr, options)
            {
                var data = jQuery.httpData(xhr,options.dataType);
		/* 
                 Now data contains the responseText if the response type
		 is text/html or text/palin otherwise it is undefined.
                 */
                var inputFieldIndex=-1;
                try{
			/* try-catch because data may be undefined as mentioned above. */
			inputFieldIndex=data.indexOf("<input");
		}catch(err){}
                if(inputFieldIndex>-1){	
                   /* response contains input tag */
                    jQuery('input:text:visible[disabled=false]:first').focus();
                }
            });
 
          });</script>

The above trick worked for me and hope it works for you guys too.

Helpful links :-
http://api.jquery.com/ajaxComplete/

~~~~Bhagwat Kumar~~~
bhagwat@intelligrape.com

Cheers!
~~Bhagwat Kumar~~
bhagwat(at)intelligrape(dot)com
http://twitter.com/bhagwatkumar
http://in.linkedin.com/in/bhagwatkumar

Tags: ,

Ajax Request Progress Indicator

Posted by on October 12th, 2009

In my current project, I used ajax to fetch data from the server to provide Desktop Application like Experience. I wanted to automatically show an indicator when an AJAX request is ongoing, and hide it when there is no such request. So I found the following solution for both the Prototype library and the JQuery library.

Make sure the following HTML is included on every page where AJAX requests are made. (Place it in body of the main layout so that you do not have to repeat this HTML on each page.

<span id="ajax_spinner" style="display:noneposition:absolute top:50% left:50% z-index:3000">
       <-- Design Busy indicator here -->
       <img src="/yoursite/images/spinner.gif"/>
</span>

Make sure the following javascript code has been executed before any AJAX request is made. (Move this to a js file and include it in Heading part of the main layout).

<script type="text/javascript">
 
/*
  Registering responders for prototype library.
  (If you are not using  prototype library then there is no need of the next statement.)
*/
 
Ajax.Responders.register({
          onCreate: function() {
              jQuery("#ajax_spinner").show();
          },
          onComplete: function() {
              jQuery("#ajax_spinner").hide();
          }
});
 
/*
   Registering responders for jQuery AJAX calls.
*/
 
jQuery("#ajax_spinner").ajaxStart(function() {
              jQuery(this).show();
 });
jQuery("#ajax_spinner").ajaxStop(function() {
              jQuery(this).hide();
});
 
/*
    Note : If you are not using jQuery you can show/hide the div
         using javascript(e.g. document.getElementById) to do the same
*/
</script>

The above trick worked for me and hope it works for you guys too.

Helpful links :-
http://www.prototypejs.org/api/ajax/responders
http://docs.jquery.com/Ajax/jQuery.ajax
http://blogs.aarohan.biz/2009/05/26/get-started-with-jquery-ajax-and-json-in-your-perl-web-applications (Thanks to Amit)

~~~~Bhagwat Kumar~~~
bhagwat@intelligrape.com

Cheers!
~~Bhagwat Kumar~~
bhagwat(at)intelligrape(dot)com
http://twitter.com/bhagwatkumar
http://in.linkedin.com/in/bhagwatkumar

Creating File Explorer with Context Menu using jQuery File Tree Plugin

Posted by on May 26th, 2009
You can create a customized, fully-interactive file tree using jQuery File Tree plugin Written by Cory S.N. LaViska. For a demo on File Explorer click here.Here are the quick steps to implement it in your application. For advanced information please go to the plugin website where you can find the detailed description of this plugin as well as links to demo, download etc pages.

At first glance this seems to be very lengthy blog but when you start copying and pasting the code shown here into your application you will get this lengthy explanation very useful.

Here is a snapshot of what we are going to achieve in few minutes.

File Explorer with context menu

  1. Install jquery plugin

  2. jQuery File Tree requires jQuery 1.2 or above.If you have already installed this plugin then you can skip this step.
    To install jQuery plugin use the following command :

    grails install-plugin jquery

    To get the list of commands to manage plugins (eg. create, install, uninstall, list of plugins) use the following command :

    grails --help | grep plugin

  3. Download jQuery File Tree plugin files

  4. You can download the required files from the plugins website or Click here to download.

    Unzip the downloaded zip file. The unzipped folder ‘jqueryFileTree’ contains a folder ‘connector’ that you can safely delete because we will write our own connector specific to grails.

  5. place the unzipped folder into web-app folder

  6. Using operating system file explorer tool move/copy the unzipped folder ‘jqueryFileTree’ to the applications web-app folder. If you are not interested in such an easy step then you can move the jqueryFileTree.js file to web-app/js folder, jqueryFileTree.css file to web-app/css and all the files from jQueryFileTree/images to web-app/images folder and correspondingly change the reference to these files in gsp page we will be creating next. I assume you followed the easier way i.e. copied the entire folder into web-app folder.

  7. Decide the controller, action and gsp page

  8. Suppose we have a controller ‘FileBrowser’(…grails-app/controllers/FileBrowserController.groovy) and its ‘showBrowser’ action renders the view (we call it : …/grails-app/views/FileBrowser/FileBrowser.gsp). The controller looks like

    class FileBrowserController {
    //...............
    def showBrowser = {
    //.................
    render( view : 'FileBrowser')
    }
    //................
    }

  9. Create gsp page and customize it

    Here is the contents of “/grails-app/views/FileBrowser/FileBrowser.gsp” file :

    <html>
    <head>
    <title>File Explorer</title>
    <script src=”${createLinkTo(dir: ‘js/jquery’, file: ‘jquery-1.3.2.js’)}” type=”text/javascript”></script>
    <link rel=”stylesheet” href=”${createLinkTo(dir: ‘jqueryFileTree’, file: ‘jqueryFileTree.css’)}”>
    <script src=”${createLinkTo(dir: ‘jqueryFileTree’, file: ‘jqueryFileTree.js’)}” type=”text/javascript”></script>
    <script type=”text/javascript”>

    function YourFunctionToProcessThisFilePath(file){
    alert(‘You selected : ‘+file);
    }

    $(document).ready(function() {
    $(‘#file_list’).fileTree({
    root:’/',    /*DESCRIPTION 1*/
    script: ‘generateFileList.gsp’,    /*DESCRIPTION 2*/
    expandSpeed: 1000,
    collapseSpeed: 1000,
    multiFolder: false
    }, function(file) {
    YourFunctionToProcessThisFilePath(file); /* DESCRIPTION 3*/
    });
    });
    </script>
    </head>
    <h1>File Explorer</h1>
    <body>
    <div id=”file_list”>    <!– DESCRIPTION #4 –>
    <%=”Empty”%>
    </div>
    </body>
    </html>

    • DESCRIPTION #1: absoulute path of the folder which will be treated as root level folder in our file explorer. There exists a potential for malicious individuals to be able to view your entire directory structure by spoofing the root parameter. However you can control this from the script file described in DESCRIPTION #2.
    • DESCRIPTION #2: connector file(server side script) that generates the list of files and subdirectories for the selected folder. This is a gsp file where you get the absolute path of the folder in dir attribute of params map for which the files and subfolders is to be found and output an unsorted list in the following format:
      We will create this gsp page parallel to FileBrowser.gsp i.e. …/grails-app/views/FileBrowser/generateFileList.gsp in Step 6. Later we will move this logic into an action and hence no need of connector script (see step 8).
    • DESCRIPTION #3: this javascript function is called with absolute path to the selectd file whenever a file is clicked in the file browser page.
    • DESCRIPTION #4: The id of the div tag is used in jQuery. So it must match at both places.
  10. Create connector script

  11. Here is the code for connector script "...grails-app/views/FileBrowser/generateFileList.gsp"

    <%
    String dir = params?.dir
    if (dir == null) {
        return;
    }
    /* you can put here your own custom check with dir variable to protect from malicious request.  */
    if(!dir.endsWith(File.separator)){
        dir+=File.separator
    }
    
    File f=new File(dir)
    if (f.exists()) {
        List<File> files=[]
    
        f.eachFile { File file->
            if(!file.hidden)
                files<<file
        }
    
        files.sort{File file-> file.name.toUpperCase()}
        StringBuffer output=new StringBuffer('<ul class="jqueryFileTree" style="display: none;">')
        // All dirs
        files.each{File file->
            if(file.directory){
                output.append("""<li class="directory collapsed"><a href="#" rel="${dir+file.name+File.separator}">${file.name}</a></li>""")
            }
        }
        // All files
        files.each{File file->
            if(file.file){
                int dotIndex = file.name.lastIndexOf('.');
                String ext = dotIndex > 0 ? file.name.substring(dotIndex + 1) : "";
                output.append("""<li class="file ext_${ext}"><a href="#" rel="${dir+file.name}">${file.name}</a></li>""");
            }
        }
        output.append("</ul>");
        println output.toString()
    }
    %>
    
  12. Test Your File Explorer

    It’s time to test your file explorer. If everything went perfectly then you have successfully created your file explorer. Type the url of the action responsible for rendering FileBrowser.gsp.You can also experiment with various Parameters that are passed as an object to the fileTree() function in FileBrowser.gsp. List of Valid options can be found at the pluging website under ‘Configuring the File Tree’ heading.

  13. Moving the connector script  to an action of the controller

    Here is the modified controller FileBrowserController having an action generateFileList. This contains the same code as in generateFileList with few new statements appended and obviously <% and %> has been removed.The modified lines has been shown in different color.

    class FileBrowserController {
    //……………
    def showBrowser = {
    //……………..
    render( view : ‘FileBrowser’)
    }
    def generateFileList={
    String dir = params?.dir
    if (dir == null) {
    return;
    }
    /* you can put here your own custom check with dir variable to protect from malicious request.  */
    if(!dir.endsWith(File.separator)){
    dir+=File.separator
    }

    File f=new File(dir)
    if (f.exists()) {
    List<File> files=[]

    f.eachFile { File file->
    if(!file.hidden)
    files<<file
    }

    files.sort{File file->
    file.name.toUpperCase()
    }

    StringBuffer output=new StringBuffer(‘<ul class=”jqueryFileTree” style=”display: none;”>’)
    // All dirs
    files.each{File file->
    if(file.directory){
    output.append(“”"<li class=”directory collapsed”><a href=”#” rel=”${dir+file.name+File.separator}”>${file.name}</a></li>”"”)
    }
    }
    // All files
    files.each{File file->
    if(file.file){
    int dotIndex = file.name.lastIndexOf(‘.’)
    String ext = dotIndex > 0 ? file.name.substring(dotIndex + 1) : “”
    output.append(“”"<li class=”file ext_${ext}” id=”${dir+file.name}”><a href=”#” rel=”${dir+file.name}”>${file.name}</a></li>”"”)
    }
    }
    output.append(“</ul>”)
    OutputStream out = response.getOutputStream()
    out.write (output.toString().getBytes())
    out.flush()
    out.close()

    }
    }
    //…………….
    }

  14. Making changes to FileBrowser.gsp to use generateFileList action instead of generateFileList.gsp file

    Here are the modified lines of FileBrowser.gsp file (Modified lines shown in different color ) :

    $(document).ready(function() {
    $(‘#file_list’).fileTree({
    root:’/',
    script: “${createLink(action:’generateFileList’)}”, /* you can also explicitly specify the controller */
    expandSpeed: 1000,
    collapseSpeed: 1000,

    After this change, you can test your File Explorer and if everything works perfectly, you can safely delete the file generateFileList.gsp.

  15. Forwarding to an action when a file is clicked

    To do so we will modify FileBrowser.gsp page to include a form and a hidden field for absolute path of the selected file.
    The modified FileBrowser.gsp(with modified lines shown in different color) is now :

    <html>
    <head>
    <title>File Explorer</title>
    <script src=”${createLinkTo(dir: ‘js/jquery’, file: ‘jquery-1.3.2.js’)}” type=”text/javascript”></script>
    <link rel=”stylesheet” href=”${createLinkTo(dir: ‘jqueryFileTree’, file: ‘jqueryFileTree.css’)}”>
    <script src=”${createLinkTo(dir: ‘jqueryFileTree’, file: ‘jqueryFileTree.js’)}” type=”text/javascript”></script>
    <script type=”text/javascript”>

    function YourFunctionToProcessThisFilePath(file){
    //        alert(‘You selected : ‘+file);
    document.getElementById(‘selectedFile’).value = file
    document.getElementById(‘fileBrowserForm’).submit()
    }

    $(document).ready(function() {
    $(‘#file_list’).fileTree({
    root:’/',    /*DESCRIPTION 1*/
    script: “${createLink(action:’generateFileList’)}”, //’generateFileList.gsp’,
    expandSpeed: 1000,
    collapseSpeed: 1000,
    multiFolder: false
    }, function(file) {
    YourFunctionToProcessThisFilePath(file); /* DESCRIPTION 3 */
    });
    });
    </script>
    </head>
    <h1>File Explorer</h1>
    <body>
    <div id=”file_list”>    <!– DESCRIPTION #4 –>
    <%=”Empty”%>
    </div>
    <g:form name=”fileBrowserForm” action=”processThisFile” method=”post”>
    <g:hiddenField name=”selectedFile” />
    </g:form>
    </body>
    </html>

    Now add an action ‘processThisFile’ or whatever you have used as forms action in FileBrowser.gsp file. Here is the modified FileBrowserController :

    class FileBrowserController {
    //……………
    def processThisFile={
    println params.selectedFile
    render(params.selectedFile)
    }

    //…………….
    }

  16. Installing the plugin for Context Menu(Right Click)

    Now we are going to add Context Menu functionality to our File Explorer. For this purpose we will be using one more plugin jQuery Context Menu Plugin Written by Cory S.N. LaViska(same author has written jQuery File Tree plugin). For advanced details go to the plugin website where you can see a demo as well as download necessary files to use this plugin. Click here to download the plugin.

    After you have downloaded the zip file, unzip it and copy it in applications web-app folder as you did for jQuery File Tree Plugin in Step 3.

  17. Create context menu options by Modifying FileBrowser.gsp file

    create a list in FileBrowser.gsp that will be the markup for your context menu:
    Actions are specified in the href attribute, preceeded by a # symbol. When selected, this is what will be passed back to the action parameter in the callback. You can add class attributes to the list items to assist with styling, but they have no functional meaning. Thus, class names do not have to correspond with actions.

    Let’s create a contextMenu (UL with id myFolderMenu) with four options cut, paste, rename and delete also a separator beteween paste and rename option which is displayed whenever a folder is right-clicked. When you click an option from the displayed context menu the javascript function HandleFolderContextMenu is called with parameters action and folderPath. action contains the href attribute excluding # character of the selected context menu option and folderPath contains the absolute path of the selected folder i.e. on which it was right clicked.

    Similarly a contextMenu(UL with id myFileMenu) with two options Open… and Properties which is displayed whenever a file is right-clicked has been created. Like Context Menu for folders, this time HandleFileContextMenu javascript function is called with action and filePath parameters.

    You can follow the similar steps as described in Step 10 to forward request to an action where it will be processed depending on the action and absolute path to the selected file or folder.

    <html>
    <head>
    <title>File Explorer</title>
    <script src=”${createLinkTo(dir: ‘js/jquery’, file: ‘jquery-1.3.2.js’)}” type=”text/javascript”></script>

    <link rel=”stylesheet” href=”${createLinkTo(dir: ‘jqueryFileTree’, file: ‘jqueryFileTree.css’)}”>
    <script src=”${createLinkTo(dir: ‘jqueryFileTree’, file: ‘jqueryFileTree.js’)}” type=”text/javascript”></script>

    <link rel=”stylesheet” href=”${createLinkTo(dir: ‘jquery.contextMenu’, file: ‘jquery.contextMenu.css’)}”>
    <script src=”${createLinkTo(dir: ‘jquery.contextMenu’, file: ‘jquery.contextMenu.js’)}” type=”text/javascript”></script>

    <script type=”text/javascript”>
    function HandleFolderContextMenu(action, folderPath){
    alert(action+’\n\n Folder Path : ‘+folderPath);
    }
    function HandleFileContextMenu(action, filePath){
    alert(action+’\n\n File Path : ‘+filePath);
    }

    function showMenu(){
    $(‘.directory>a’).contextMenu({
    menu: ‘myFolderMenu’
    },
    function(action, el, pos) {
    var folderPath=$(el).attr(‘rel’);
    HandleFolderContextMenu(action, folderPath);
    }
    );
    $(‘.file>a’).contextMenu({
    menu: ‘myFileMenu’
    },
    function(action, el, pos) {
    var filePath=$(el).attr(‘rel’);
    HandleFileContextMenu(action, filePath);
    }
    );
    }

    </script>

    <script type=”text/javascript”>

    function YourFunctionToProcessThisFilePath(file){
    //        alert(‘You selected : ‘+file);
    document.getElementById(‘selectedFile’).value = file
    document.getElementById(‘fileBrowserForm’).submit()
    }

    $(document).ready(function() {
    $(‘#file_list’).fileTree({
    root:’/',    /*DESCRIPTION 1*/
    script: “${createLink(action:’generateFileList’)}”, //’generateFileList.gsp’,
    expandSpeed: 1000,
    collapseSpeed: 1000,
    multiFolder: false
    }, function(file) {
    YourFunctionToProcessThisFilePath(file); /* DESCRIPTION 3 */
    });
    });
    </script>
    </head>
    <h1>File Explorer</h1>
    <body>
    <div id=”file_list”>    <!– DESCRIPTION #4 –>
    <%=”Empty”%>
    </div>
    <g:form name=”fileBrowserForm” action=”processThisFile” method=”post”>
    <g:hiddenField name=”selectedFile” />
    </g:form>
    <ul id=”myFolderMenu” class=”contextMenu”>
    <li class=”copy”><a href=”#copy”>Copy</a></li>
    <li class=”paste”><a href=”#paste”>Paste</a></li>
    <li class=”separator rename”><a href=”#rename”>Rename</a></li>
    <li class=”deleteFolder”><a href=”#deleteFolder”>Delete</a></li>
    </ul>
    <ul id=”myFileMenu” class=”contextMenu”>
    <li class=”open”><a href=”#open”>Open…</a></li>
    <li class=”properties”><a href=”#properties”>Properties</a></li>
    </ul>
    </body>
    </html>

    Finally modify generateFileList action by adding a statement output.append(““) as shown below the modified lines of generateFileList action to get the changes made to FileBrowser.gsp to work. It just calls the showMenu javascript function defined in FileBrowser.gsp which in turn enables the context menu for the explored folder.

    def generateFileList={
    //…………………..
    output.append(“</ul>”)
    output.append(“<script>showMenu(); </script>”)
    OutputStream out = response.getOutputStream()
    out.write (output.toString().getBytes())
    //…………………..
    }

Hope this helps you guys in creating file explorer with context menu.

Bhagwat Kumar
bhagwat@intelligrape.com

Cheers!
~~Bhagwat Kumar~~
bhagwat(at)intelligrape(dot)com
http://twitter.com/bhagwatkumar
http://in.linkedin.com/in/bhagwatkumar