views:

1503

answers:

4

Hello!

I am using Struts 2.1.6 with Dojo plugin, whole app has ajax links (sx:a).

Did anybody succeed to implement back button functionality and linking to certain content?

Does anybody have any experience how to implement? I am planning to implement (if there is no good solution already) something like so:

  • changing address bar link (adding parameters) with js which I can then read and get proper content and then publish it with notifyTopics.

Or should I just change whole app to use jQuery plugin? Do jQuery has good solutions for back button and linking on ajax pages?

A: 

Don't know Struts, but have you looked at dojo.undo (0.4.3)?

peller
I looked at this, try to implement (without any success) and I haven't found any solution compatible with Struts2. The biggest problem is how to "fill" in history dynamic content.
Trick
+1  A: 

I can think of 2 simple ways off the top of my head:

<s:form action="actionName">
    <input type="hidden" value="<s:property value="someProperty"/>" name="someProperty"/>
    <input type="hidden" value="<s:property value="someProperty2"/>" name="someProperty2"/>
    <s:submit value="Back" />
</s:form>

or

<s:url name="backURL" action="actionName">
    <s:param name="someProperty" value="someProperty"/>
    <s:param name="someProperty2" value="someProperty2"/>
</s:url>
<a href="<s:property value="#backURL"/>">Back</a>

If you already have query string parameters:

<a href="#" onclick="javascript.window=document.referrer;">Back</a>

or

<input type="button" value="Back" onclick="javascript.window=document.referrer;"/>
Droo
Good idea for start, but after this, you have to find a solution for publishing different targets.
Trick
+1  A: 

I have tried to use Struts 2 with dojo and implement the back button. You are already way over the head of Struts 2's ajax implementation. They mainly used and wrote it to write simple and quick ajax function calls and is not very well suited for more extensive uses. Plus when you do s:head theme='ajax' tag; struts will import every ajax js file you 'may' need which kills load time.

I would suggest either 1. Learn dojo and use the library independent of struts 2. Or 2. Get jQuery, I was able to implement a back button functionality relatively simple (more so then struts 2 theme='ajax').

John V.
I did not use Dojo in my solution, except publishing. I have made something similar to gmail.
Trick
A: 

All my links go through one action which looks for a parameter menuId (of course id of a menu which has to be shown).

From this action, before returning response I set one javascript function to be called:

setBackMenuId(menuId,sometext)

MenuId is the id, sometext is a name of that menu, so browser log history better.

function setBackMenuId(id,subtekst) {
 window.location.hash = "menuId="+id;
 document.title = subtekst;
 selectedHash = document.location.hash;
 if(intervalHashSearch == '') {
 initializeHashSearch();
 } 
}

Then, other needed js functions:

function publishLinkTarget() {
 var param = window.location.hash;
 if(param) {
  if(param.indexOf("menuId") > 0) {
   var id = param.split("=", 2);
   if(id[1]) {
    setCookie('backMenuId',id[1],1,false);
    setTimeout('publishLayoutContent()', 100);
   }
  }
 }
}

var selectedHash = '';
var intervalHashSearch = '';
function initializeHashSearch() {
 intervalHashSearch = window.setInterval('checkHash()', 500);
}

function stopHashSearch() {
 window.clearInterval(intervalHashSearch);
 intervalHashSearch = '';
}

function checkHash() {
 var currentHash = document.location.hash;
 if(selectedHash != currentHash) {
  selectedHash = currentHash;
  publishLinkTarget();
 }
}

function publishLayoutContent() {
    dojo.event.topic.publish("layoutContentTarget");
}

If you look at it you see, that first it is called 'setBackMenuId', which adds hash and parameter to address bar and changes title, and then remembers this hash, so interval hash search can find out the differrence. Then it initializes this hash search.

'checkHash' is running ever 500 miliseconds and is checking if hash has changed (that means, that back button was pressed, and not a new link was clicked (setBackMenuId sets selectedHash). If true (back/forward button was pressed) function 'publishLinkTarget' is called, which reads the parameters from hash, and if they are ok, first I set a cookie, so I can read it from the HttpServletRequest and find out for which menu id link is. If I am here it means that I have to also publish the content which is made with 'publishLayoutContent'.

In action class (this is MenuAction, method view, the same as published in ) only this is important:

    Integer menuId = null;
 if(request.getParameter("menuId") != null) {
  menuId = Integer.valueOf(request.getParameter("menuId"));
 } else {
  menuId = getIntCookie("hiddenMenuId");
 }

So, if I don't get the menu id from the parameter (link clicked) I get from a cookie (back/forward button).

And JSP with this target:

<s:url var="layoutContentUrl" action="Menu-view" namespace="/public" />
 <sx:div showLoadingText="false" indicator="ajaxIndicator"
  id="layout-content" href="%{layoutContentUrl}" theme="ajax"
  listenTopics="layoutContentTarget" preload="false"
     afterNotifyTopics="/ajaxAfter">
</sx:div>

NOTE: This is a special case if you have everything connected through one parameter, but it can be easily extended with other parameters which publish other targets. I will try to make it enough generic to publish it somewhere, but this is (I guess) a long way ahead :)

If you have any question, please post it.

Trick