Hi, The reason that it did not work is because you have to handle the event onUpdate in your page otherwise it throws a NPE. I have modified that and indicated that in bold.
The alert that you saw was a debug alert...(Oops!!). Java import org.apache.tapestry5.BindingConstants; import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.Link; import org.apache.tapestry5.MarkupWriter; import org.apache.tapestry5.annotations.AfterRender; import org.apache.tapestry5.annotations.Environmental; import org.apache.tapestry5.annotations.Import; import org.apache.tapestry5.annotations.Parameter; import org.apache.tapestry5.internal.util.CaptureResultCallback; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.json.JSONObject; import org.apache.tapestry5.services.Request; import org.apache.tapestry5.services.javascript.JavaScriptSupport; @Import(library = "progressbar.js") public class ProgressBar { @Parameter(value = "1", defaultPrefix=BindingConstants.LITERAL) private int period; @Parameter(defaultPrefix = BindingConstants.LITERAL) private String clientFunc; @Inject private ComponentResources resources; @Environmental private JavaScriptSupport javaScriptSupport; @Inject private Request request; @AfterRender void afterRender(MarkupWriter writer){ Link link = resources.createEventLink("timer"); JSONObject spec = new JSONObject(); spec.put("url", link.toAbsoluteURI()); spec.put("period", period); spec.put("clientFunc", clientFunc); javaScriptSupport.addScript("new ProgressBar(%s);", spec); } Object onTimer(){ JSONObject spec = new JSONObject(); double value = 0.0; try { value = Double.parseDouble(request.getParameter("value")); }catch(NumberFormatException nfe){ return spec; } CaptureResultCallback<Double> callback = new CaptureResultCallback<Double>(); resources.triggerEvent("update", new Object[]{value}, callback); * if(callback.getResult() == null){* * return spec;* * }* value = callback.getResult(); spec.put("value", value); return spec; } } Javascript ProgressBar = Class.create({ initialize:function(spec){ this.value = 0; this.url = spec.url; this.clientFunc = spec.clientFunc; this.executer = new PeriodicalExecuter(this.execute.bind(this), spec.period); }, execute:function(transport){ new Ajax.Request(this.url + "?value=" + this.value, { method:"get", onSuccess:function(transport){ this.onSuccess(transport); }.bind(this) }, this.period); }, onSuccess:function(transport){ var json = transport.responseText.evalJSON(); if(typeof(json.value) == "undefined"){ * this.stopExecuter();* * return;* * }* this.value = json.value; if(this.clientFunc){ var func = this.clientFunc +"(" + json.value+")"; eval(func); } if(json.value >= 100){ this.stopExecuter(); } }, stopExecuter:function(){ this.executer.stop(); } }); Usage :- Template File <t:progressbar t:id='progressBar' clientFunc='updateFunc'/> <div id='updateDiv'></div> <script> var updateFunc = function(percentage){ $("updateDiv").update(percentage + "%"); } </script> double onUpdateFromProgressBar(double percentage){ return percentage + 10.0; } I tested it on Firefox and Chrome and it works fine... On Tue, Dec 14, 2010 at 4:24 PM, Newham, Cameron <cameron.new...@bl.uk>wrote: > Further to this. > > The part I think I am not understanding that is critical to the operation > of this is: > > resources.triggerEvent("update", new Object[]{value}, callback); > value = callback.getResult(); > It returns null because you did not create an event handler in your page for "update" event triggered from ProgressBar component. What is happening here is that the component is triggering an event and tries to handle the result value from the handler but if no handler is called the result will be null.(This case is now handled) > > getResult() is always null. So I'm failing to understand how you are > getting value set (it triggers an event - but...?) Sorry if this seems > obvious, but it unfortunately isn't to me. > > triggerEvent triggers an event which has to be handled by the container event handler. This event handler's return value is callback.getResult(). If there is not handler, it returns null. > c. > > Hope it helps regards Taha > > -----Original Message----- > From: Newham, Cameron [mailto:cameron.new...@bl.uk] > Sent: 14 December 2010 09:35 > To: Tapestry users > Subject: RE: T5: Progress indicator and AJAX example? > > Thanks Taha for going to the trouble of providing source. > > > It is very simple. > > LOL. When people say this it usually isn't! And I'm afraid my knowledge of > AJAX and Javascript make your code fairly impenetrable to me. When I use > your code I just get a dialogue box tell me that the page says {} was > returned and the value on the page is printed as undefined. > > I've read your follow-up below and looked at the code and understand the > gist of how it works but I'm afraid I don't understand what is wrong. > > Thanks, > c. > > > -----Original Message----- > From: Taha Hafeez [mailto:tawus.tapes...@gmail.com] > Sent: 12 December 2010 01:35 > To: Tapestry users > Subject: Re: T5: Progress indicator and AJAX example? > > Hi > > It is very simple. In ProgressBar#afterRender an event "timer" is created > which is passed on to javascript. Javascript is a periodicExecuter > with period passed as a parameter. For each period it calls the event url > with the previous value of percentage as a parameter. > > When the event is called onTimer() method is invoked in ProgressBar which > triggers an update event and expects a percentage value. > It then returns this percentage as a JSON object to the javascript ajax > call. > > Finally javascript calls the method passed as clientFunc parameter of the > ProgressBar. In case the percentage has reached 100, it stops the > PeriodicExecuter > > regards > Taha > > 2010/12/11 françois facon <fra.fa...@gmail.com> > > > Hi Taha, > > > > Thanks for sharing your code. > > > > It make me discover the CaptureResultCallback (new in 5.2). > > > > If I understand well your sample, to get progress value > > the progressBar component raise a server side event called 'update' and > > get the value from this callback. > > > > is it right? > > > > > > > > > > 2010/12/11 Taha Hafeez <tawus.tapes...@gmail.com> > > > > > Hi, > > > > > > Here is a simple example > > > > > > Java Code :- > > > > > > import org.apache.tapestry5.BindingConstants; > > > import org.apache.tapestry5.ComponentResources; > > > import org.apache.tapestry5.Link; > > > import org.apache.tapestry5.MarkupWriter; > > > import org.apache.tapestry5.annotations.AfterRender; > > > import org.apache.tapestry5.annotations.Environmental; > > > import org.apache.tapestry5.annotations.Import; > > > import org.apache.tapestry5.annotations.Parameter; > > > import org.apache.tapestry5.internal.util.CaptureResultCallback; > > > import org.apache.tapestry5.ioc.annotations.Inject; > > > import org.apache.tapestry5.json.JSONObject; > > > import org.apache.tapestry5.services.Request; > > > import org.apache.tapestry5.services.javascript.JavaScriptSupport; > > > > > > @Import(library = "progressbar.js") > > > public class ProgressBar { > > > @Parameter(value = "1", defaultPrefix=BindingConstants.LITERAL) > > > private int period; > > > > > > @Parameter(defaultPrefix = BindingConstants.LITERAL) > > > private String clientFunc; > > > > > > @Inject > > > private ComponentResources resources; > > > > > > @Environmental > > > private JavaScriptSupport javaScriptSupport; > > > > > > @Inject > > > private Request request; > > > > > > @AfterRender > > > void afterRender(MarkupWriter writer){ > > > Link link = resources.createEventLink("timer"); > > > JSONObject spec = new JSONObject(); > > > spec.put("url", link.toAbsoluteURI()); > > > spec.put("period", period); > > > spec.put("clientFunc", clientFunc); > > > javaScriptSupport.addScript("new ProgressBar(%s);", spec); > > > } > > > > > > Object onTimer(){ > > > JSONObject spec = new JSONObject(); > > > double value = 0.0; > > > try { > > > value = Double.parseDouble(request.getParameter("value")); > > > }catch(NumberFormatException nfe){ > > > return spec; > > > } > > > > > > CaptureResultCallback<Double> callback = new > > > CaptureResultCallback<Double>(); > > > resources.triggerEvent("update", new Object[]{value}, callback); > > > value = callback.getResult(); > > > System.out.println("Value = " + value); > > > spec.put("value", value); > > > return spec; > > > } > > > } > > > > > > JavaScript Code :- > > > > > > ProgressBar = Class.create({ > > > initialize:function(spec){ > > > this.value = 0; > > > this.url = spec.url; > > > this.clientFunc = spec.clientFunc; > > > this.executer = new PeriodicalExecuter(this.execute.bind(this), > > > spec.period); > > > }, > > > > > > execute:function(transport){ > > > new Ajax.Request(this.url + "?value=" + this.value, { > > > method:"get", > > > onSuccess:function(transport){ > > > this.onSuccess(transport); > > > }.bind(this) > > > }, this.period); > > > }, > > > > > > onSuccess:function(transport){ > > > var json = transport.responseText.evalJSON(); > > > if(typeof(json.value) == "undefined"){ > > > alert(transport.responseText + ": returned") > > > this.stopExecuter(); > > > } > > > this.value = json.value; > > > if(this.clientFunc){ > > > var func = this.clientFunc +"(" + json.value+")"; > > > eval(func); > > > } > > > > > > if(json.value >= 100){ > > > this.stopExecuter(); > > > } > > > }, > > > > > > stopExecuter:function(){ > > > this.executer.stop(); > > > } > > > }); > > > > > > > > > Usage :- > > > > > > <t:progressbar clientFunc="updateFunc"/> > > > <div id='progressBar'> > > > </div> > > > <script> > > > updateFunc = function(percentage){ > > > $("progressBar").update(percentage + "%"); > > > }; > > > </script> > > > > > > > > > Hope it helps > > > regards > > > Taha > > > > > > On Fri, Dec 10, 2010 at 6:55 PM, Richard Hill <r...@su3analytics.com> > > > wrote: > > > > > > > Hi Cameron, > > > > > > > > For an example of how to make an ajax call from your own js see the > > mail > > > > I sent yesterday. > > > > > > > > Richard. > > > > > > > > > > > > > > > > On Fri, 2010-12-10 at 09:14 -0200, Thiago H. de Paula Figueiredo > wrote: > > > > > On Fri, 10 Dec 2010 09:04:49 -0200, Newham, Cameron < > > > > cameron.new...@bl.uk> > > > > > wrote: > > > > > > > > > > > Hi, > > > > > > > > > > Hi! > > > > > > > > > > > I imagine that if I wanted just a simple field on a page that > > updated > > > > > > with a % then I would have Javascript make an AJAX get and obtain > a > > > > > > value from the server. However, as I'm a complete newbie to AJAX, > > an > > > > > > example of how to do this would be extremely helpful. > > > > > > > > > > The AJAX part itself is completely Tapestry-unrelated and there are > > > many > > > > > examples in the Internet, maybe even in this mailing list archives. > I > > > > > answered something similar yesterday. The AJAX Prototype > > documentation > > > is > > > > > here: http://api.prototypejs.org/ajax/Ajax/Request/. > > > > > > > > > > > Example silly > > > > > > questions: does my field have to be in a Zone? > > > > > > > > > > No, as long as you write your own JavaScript code to do and handle > an > > > > AJAX > > > > > request and then update the page DOM. > > > > > > > > > > > Also, would the % value updated by my process just be held in a > > > > @Persist > > > > > > field? > > > > > > > > > > Absolutely no. Just get the % value when handling the request. You > > > don't > > > > > even need a field for that. > > > > > > > > > > > > > > > > > > > > > --------------------------------------------------------------------- > > > > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > > > > For additional commands, e-mail: users-h...@tapestry.apache.org > > > > > > > > > > > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > For additional commands, e-mail: users-h...@tapestry.apache.org > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > For additional commands, e-mail: users-h...@tapestry.apache.org > >