Progress Bar?

205 views
Skip to first unread message

Tamika

unread,
Oct 1, 2010, 4:06:46 PM10/1/10
to InterSystems: Zen Community
Could someone direct me to an example or documentation of how to
implement some sort of progress bar? I have an application that with
methods that will be running sql queries that don't complete
immediately.

Ideally it would be nice to have some sort of progress bar for each
method as opposed to the page looking like it froze. I didn't find
anything in SAMPLES and I haven't done something like this before.

Dave

unread,
Oct 1, 2010, 4:43:29 PM10/1/10
to intersys...@googlegroups.com
A nice trick is to use a "loading" icon that is on the page and hidden (use an <image> component). Then, before the server method is called do an image.setProperty('hidden',false); then when the method completes, do image.setProperty('hidden',true); ... If your server call is asynchronous, you would need to put the re-hiding of the image as a &js<> segment in your server-side ZenMethod.. So you'd have a javascript method that unhides the image before calling the server side method and then something like &js<zenPage.getComponentById('loadingImage').setProperty('hidden',false);> in your server side method.

I found this page with examples of loading icons with a quick google search, but there are tons of them if you search more:


Of course this isn't a progress bar, but it gives the user feedback that the server is doing something... As far as a progress bar is concerned, it's much more complex. I did something similar by JOBbing a process (using the JOB command in Caché) that writes its progress to a temporary global, then I use a periodic call to the server every few seconds to check the value of the global, and update the progress accordingly. In my case I wrote text out to tell the progress as a percentage, but you could extend that to pretty much anything.



--
You received this message because you are subscribed to the Google Groups "InterSystems: Zen Community" group.
To post to this group, send email to InterSys...@googlegroups.com
To unsubscribe from this group, send email to InterSystems-Z...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/InterSystems-ZEN?hl=en
Zen Community Terms and Conditions: http://groups.google.com/group/InterSystems-ZEN/web/community-terms-and-conditions

Dawn Wolthuis

unread,
Oct 1, 2010, 5:31:26 PM10/1/10
to intersys...@googlegroups.com
For the icon, check out http://www.ajaxload.info/
--dawn

--
Dawn M. Wolthuis

Take and give some delight today

Kurt Hofman

unread,
Oct 6, 2010, 9:54:09 AM10/6/10
to InterSystems: Zen Community
I tried to do this in a page but it doesn't seems to work, the image
doesn't show !
Can anyone help me out here ?

On my page I have a html-component :
<input id="#(tBijgevoegdId)#" name="cellBijgevoegd" type="text"
onchange="zenPage.onchangeBijgevoegd(this.id);" onkeypress=";return
zenPage.submitenter(this,event);"/>

On my page I have method's :
ClientMethod onchangeBijgevoegd(id) [ Language = javascript ]
{
zen('loadingImage').setProperty('hidden',false);
try {
var status=zenPage.Bijvoegen('1','1'); // this is the server-
method that I call when the <input>-box has changed
}
catch(err) {
alert(err.description);
}
zen('loadingImage').setProperty('hidden',true);
}

Method Bijvoegen(scanlijn As %String, bijgevoegd As %String) As
%String [ ZenMethod ]
{
Set tMessage=""
Try {
&SQL(
SELECT
reDoos,
reOpdracht->reAanvrBewProd->rfProd,
reOpdracht->reAanvrBewProd->reLigVan,
reOpdracht->reAanvrBewProd->reLigVan->reHuidigeRol->Functie
INTO
:doosid,
:produkt,
:ligplaatsid,
:ligplaatsfunctie
FROM
Wms.Scanlijnen
WHERE
%ID=:scanlijn
)
Throw:(SQLCODE'=0) ##class(%Exception.SQL).CreateFromSQLCODE(SQLCODE,
%msg)
Set data(produkt,ligplaatsfunctie)=ligplaatsid_"\"_bijgevoegd
Set tMessage=$$CHECK1T^agaWMSEindcontr(doosid,.data)
If (tMessage="0\Ok") {
&SQL(UPDATE Wms.Scanlijnen Set LigplaatsGecheckt1=1 WHERE
%ID=:scanlijn)
Throw:(SQLCODE'=0)
##class(%Exception.SQL).CreateFromSQLCODE(SQLCODE,%msg)
}
}
Catch(exception) {
Set tMessage="9\"_exception.DisplayString()
}
Quit tMessage
}

Roberto

unread,
Oct 6, 2010, 10:03:14 AM10/6/10
to InterSystems: Zen Community
Hello Kurt!

In my experience with hiding/unhiding images on a screen like this,
this is a timing issue.

I would place the unhiding in a separate method and use the javascript
setTimeout function to unhide.

So do something like this:

onchange="setTimeout('zenPage.unhidePicture()',
1);zenPage.onchangeBijgevoegd(this.id);"

ClientMethod unhidePicture() [ language = javascript ]
{
zen('loadingImage').setProperty('hidden',false);
}

-Roberto
> }- Hide quoted text -
>
> - Show quoted text -

Kurt Hofman

unread,
Oct 6, 2010, 11:03:12 AM10/6/10
to InterSystems: Zen Community
No solution, it seems that the image shows up after my ZenMethod
(Method Bijvoegen(scanlijn As %String, bijgevoegd As %String) As
%String [ ZenMethod ] ) is finished

Vlado

unread,
Oct 6, 2010, 12:56:46 PM10/6/10
to InterSystems: Zen Community
>it seems that the image shows up after my ZenMethod
>(Method Bijvoegen(scanlijn As %String, bijgevoegd As %String) As
>%String [ ZenMethod ] ) is finished

It is true.Here is the evidence:
===============================================
XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ]
{
<page xmlns="http://www.intersystems.com/zen" title="">
<text id="text" name="text" onchange="zenPage.startProgressBar();"/>
</page>
}

ClientMethod startProgressBar(btnStart) [ Language = javascript ]
{
zen('text').startProgressBar();
var x=zenPage.MyMethod();
alert(x);
//zen('text').stopProgressBar();
}

Method MyMethod() As %String [ ZenMethod ]
{
s x=""
for i=1:1:10 s x=x_1
quit x
}
===============================================
So, if you uncoment //zen('text').stopProgressBar();
you will not see the progress bar because it will disappear
immediately.
> > > - Show quoted text -- Hide quoted text -

Derek Day

unread,
Oct 6, 2010, 1:18:01 PM10/6/10
to intersys...@googlegroups.com
startProgressBar is asynchronous(it displays the progress bar after a timeout), so if you make the asynchronous call followed by a synchronous call, the asynchronous call will never get a chance to run until the synchronous call completes (MyMethod below is a synchronous ZenMethod). I'd reserve synchronous calls for cases when you always expect an immediate response (e..g. one that does not require a progress indicator), and use asynchronous calls for everything else; a good case for a synchronous call might be to check on the status of a longer running background task. There is a reason we don't call Ajax something like "Sajax" or "Asjax" :)

Dave

unread,
Oct 6, 2010, 1:37:07 PM10/6/10
to intersys...@googlegroups.com
My way of handling this (at least with the "loading" image I described above, is to have the javascript method that's calling your server method do the image unhiding, then the server method is an asynchronous method, then within the server method have a piece of &js<> code that re-hides the image. This way, when the server method finishes it sends the javascript code to the web browser to re-hide the image. It makes for a seamless appearance to the user. This could be accomplished with startProgressBar and stopProgressBar too.

Derek Day

unread,
Oct 6, 2010, 1:54:15 PM10/6/10
to intersys...@googlegroups.com
startProgressBar is defined in %ZEN.Component.component.cls.

It has pretty simple logic:
  if in synchronous mode, do nothing, otherwise set a timer to start the progress bar handler calls (waiting longer the first time).

It would be pretty simple to enhance this or override it to take an argument that starts progress bar immediately. The problem is that it will never be able to check up on the synchronous call, since there will never be a free JavaScript thread. You'd need to display an image that served as a fake progress bar. You could do as Dave describes or via the onServerMethodCall/Return callbacks.

On Wed, Oct 6, 2010 at 1:37 PM, Dave <xar...@gmail.com> wrote:
My way of handling this (at least with the "loading" image I described above, is to have the javascript method that's calling your server method do the image unhiding, then the server method is an asynchronous method, then within the server method have a piece of &js<> code that re-hides the image. This way, when the server method finishes it sends the javascript code to the web browser to re-hide the image. It makes for a seamless appearance to the user. This could be accomplished with startProgressBar and stopProgressBar too.

On Wed, Oct 6, 2010 at 12:18 PM, Derek Day <Dere...@intersystems.com> wrote:
startProgressBar is asynchronous(it displays the progress bar after a timeout), so if you make the asynchronous call followed by a synchronous call, the asynchronous call will never get a chance to run until the synchronous call completes (MyMethod below is a synchronous ZenMethod). I'd reserve synchronous calls for cases when you always expect an immediate response (e...g. one that does not require a progress indicator), and use asynchronous calls for everything else; a good case for a synchronous call might be to check on the status of a longer running background task. There is a reason we don't call Ajax something like "Sajax" or "Asjax" :)

Matthew Gage

unread,
Oct 6, 2010, 4:31:16 PM10/6/10
to InterSystems: Zen Community
I have the same problem. In my case, I need to check to see if a
tablePane has any rows before displaying it (on a <modalGroup>, with a
progress indicator shown whilst it's working - the execute needs to
call an external web service, which can take 2 or 3 seconds, even if
there are no results.

My solution - as has been suggested was to unhide an animated gif,
then call the client method to initiate the call using setTimeout - my
call has a section that runs in synchronous mode. Then on completion,
the call hides the gif again.

Only problem, on most browsers, the animated gif doesn't animate - but
the users are happier with this than no indication of work under way.

e.g.

/// Need to invoke the call in background to enable the wait icon to
be displayed.
ClientMethod callMyMethod() [ Language = javascript ]
{
zenSetProp('waitImg', 'hidden', 0);
setTimeout('zenPage.myMethod()', 1);
}

/// Run a check for existing person based on name and DOB
ClientMethod myMethod() [ Language = javascript ]
{

zenSynchronousMode = true;

zen('theList').setProperty('parameters', 1, 'ABC');
zen('theList').setProperty('parameters', 2, 123);

zen('theList').executeQuery();

if (parseInt(zen('theList').getProperty('rowCount'))>0) {
zen('modalgroup').show('Results','','',100,100);
}

zenSynchronousMode = false;

zenSetProp('waitImg', 'hidden', 1);
}


On Oct 7, 4:54 am, Derek Day <Derek....@intersystems.com> wrote:
> startProgressBar is defined in %ZEN.Component.component.cls.
>
> It has pretty simple logic:
>   if in synchronous mode, do nothing, otherwise set a timer to start the progress bar handler calls (waiting longer the first time).
>
> It would be pretty simple to enhance this or override it to take an argument that starts progress bar immediately. The problem is that it will never be able to check up on the synchronous call, since there will never be a free JavaScript thread. You'd need to display an image that served as a fake progress bar. You could do as Dave describes or via the onServerMethodCall/Return callbacks.
>
> On Wed, Oct 6, 2010 at 1:37 PM, Dave <xarm...@gmail.com<mailto:xarm...@gmail.com>> wrote:
>
> My way of handling this (at least with the "loading" image I described above, is to have the javascript method that's calling your server method do the image unhiding, then the server method is an asynchronous method, then within the server method have a piece of &js<> code that re-hides the image. This way, when the server method finishes it sends the javascript code to the web browser to re-hide the image. It makes for a seamless appearance to the user. This could be accomplished with startProgressBar and stopProgressBar too.
>
> On Wed, Oct 6, 2010 at 12:18 PM, Derek Day <Derek....@intersystems.com<mailto:Derek....@intersystems.com>> wrote:
> startProgressBar is asynchronous(it displays the progress bar after a timeout), so if you make the asynchronous call followed by a synchronous call, the asynchronous call will never get a chance to run until the synchronous call completes (MyMethod below is a synchronous ZenMethod). I'd reserve synchronous calls for cases when you always expect an immediate response (e...g. one that does not require a progress indicator), and use asynchronous calls for everything else; a good case for a synchronous call might be to check on the status of a longer running background task. There is a reason we don't call Ajax something like "Sajax" or "Asjax" :)
>
> On Wed, Oct 6, 2010 at 12:56 PM, Vlado <viliyc...@earthlink.net<mailto:viliyc...@earthlink.net>> wrote:
>
> >it seems that the image shows up after my ZenMethod
> >(Method Bijvoegen(scanlijn As %String, bijgevoegd As %String) As
> >%String [ ZenMethod ] ) is finished
>
> It is true.Here is the evidence:
> ===============================================
> XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ]
> {
> <page xmlns="http://www.intersystems.com/zen" title="">
> <text id="text" name="text" onchange="zenPage.startProgressBar();"/>
>  </page>
>
> }
>
> ClientMethod startProgressBar(btnStart) [ Language = javascript ]
> {
>        zen('text').startProgressBar();
>        var x=zenPage.MyMethod();
>        alert(x);
>        //zen('text').stopProgressBar();
>
> }
>
> Method MyMethod() As %String [ ZenMethod ]
> {
>        s x=""
>        for i=1:1:10 s x=x_1
>        quit x}
>
> ===============================================
> So, if you uncoment //zen('text').stopProgressBar();
> you will not see the progress bar because it will disappear
> immediately.
>
> On Oct 6, 8:03 am, Kurt Hofman <kurth...@gmail.com<mailto:kurth...@gmail.com>> wrote:
>
>
>
>
>
> > No solution, it seems that the image shows up after my ZenMethod
> > (Method Bijvoegen(scanlijn As %String, bijgevoegd As %String) As
> > %String [ ZenMethod ] ) is finished
>
> > On 6 okt, 16:03, Roberto <rcaha...@gmail.com<mailto:rcaha...@gmail.com>> wrote:
>
> > > Hello Kurt!
>
> > > In my experience with hiding/unhiding images on a screen like this,
> > > this is a timing issue.
>
> > > I would place the unhiding in a separate method and use the javascript
> > > setTimeout function to unhide.
>
> > > So do something like this:
>
> > > onchange="setTimeout('zenPage.unhidePicture()',
> > > 1);zenPage.onchangeBijgevoegd(this.id<http://this.id>);"
>
> > > ClientMethod unhidePicture() [ language = javascript ]
> > > {
> > > zen('loadingImage').setProperty('hidden',false);
>
> > > }
>
> > > -Roberto
>
> > > On Oct 6, 9:54 am, Kurt Hofman <kurth...@gmail.com<mailto:kurth.....@gmail.com>> wrote:
>
> > > > I tried to do this in a page but it doesn't seems to work, the image
> > > > doesn't show !
> > > > Can anyone help me out here ?
>
> > > > On my page I have a html-component :
> > > > <input id="#(tBijgevoegdId)#" name="cellBijgevoegd" type="text"
> > > > onchange="zenPage.onchangeBijgevoegd(this.id<http://this.id>);" onkeypress=";return
> To post to this group, send email to InterSys...@googlegroups.com<mailto:InterSys...@googlegroups.com>
> To unsubscribe from this group, send email to InterSystems-Z...@googlegroups.com<mailto:InterSystems-ZEN-unsub scr...@googlegroups.com>
> For more options, visit this group athttp://groups.google.com/group/InterSystems-ZEN?hl=en
> Zen Community Terms and Conditions:http://groups.google.com/group/InterSystems-ZEN/web/community-terms-a...
>
> --
> You received this message because you are subscribed to the Google Groups "InterSystems: Zen Community" group.
> To post to this group, send email to InterSys...@googlegroups.com<mailto:InterSys...@googlegroups.com>
> To unsubscribe from this group, send email to InterSystems-Z...@googlegroups.com<mailto:InterSystems-ZEN-unsub scr...@googlegroups.com>
> For more options, visit this group athttp://groups.google.com/group/InterSystems-ZEN?hl=en
> Zen Community Terms and Conditions:http://groups.google.com/group/InterSystems-ZEN/web/community-terms-a...
>
> --
> You received this message because you are subscribed to the Google Groups "InterSystems: Zen Community" group.
> To post to this group, send email to InterSys...@googlegroups.com<mailto:InterSys...@googlegroups.com>
> To unsubscribe from this group, send email to InterSystems-Z...@googlegroups.com<mailto:InterSystems-ZEN-unsub scr...@googlegroups.com>
> For more options, visit this group athttp://groups.google.com/group/InterSystems-ZEN?hl=en
> Zen Community Terms and Conditions:http://groups.google.com/group/InterSystems-ZEN/web/community-terms-a...

Kurt Hofman

unread,
Oct 7, 2010, 2:51:55 AM10/7/10
to InterSystems: Zen Community
This seems to work, but no I have one minor problem : the loading.gif-
image is an animated gif, the image appears and disappears fine but no
animation.
This is not a problem, I'll just change the image. The most important
thing is that it shows.
Thanks for all your efforts in helping me out !


My code :
XData paneBody [ XMLNamespace = "http://www.intersystems.com/zen" ]
{
<pane xmlns="http://www.intersystems.com/zen">
<button caption="Methode starten" onclick="zenPage.onclickStart();"/>
<image id="loadingImage" hidden="true" src="./images/loading.gif"/>
<text id="txtResult"/>
</pane>
}

ClientMethod onclickStart() [ Language = javascript ]
{
zenSetProp('loadingImage','hidden',0);
setTimeout('zenPage.executeMethodJS()',1);
}

ClientMethod executeMethodJS() [ Language = javascript ]
{
zenSynchronousMode = true;
var tSC=zenPage.ExecuteMethod();
zenSynchronousMode = false;
zenSetProp('loadingImage', 'hidden', 1);
}

Method ExecuteMethod() As %Status [ ZenMethod ]
{
Hang 5
Set %page.%GetComponentById("txtResult").value="OK ?"
Quit $$$OK
> ...
>
> meer lezen »

Vlado

unread,
Oct 7, 2010, 5:58:38 PM10/7/10
to InterSystems: Zen Community
Continuing the game
>the image appears and disappears fine but no
>animation.
I think it will remain static if you hide it.
One way to be animated is dynamically to add,
remove it. Something like:
===============================================
XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ]
{
<page xmlns="http://www.intersystems.com/zen" title="Progress Bar">
<hgroup id="holder">
<button id="button" caption="Start" onclick="zenPage.onclickStart();"/
>
<text id="text" onchange="zenPage.onclickStart();"/>
<spacer width="50"/>
</hgroup>
</page>
}

ClientMethod onclickStart() [ Language = javascript ]
{
setTimeout('zenPage.executeMethodJS()',1);
}

ClientMethod executeMethodJS() [ Language = javascript ]
{
zenSynchronousMode = true;
var x=zenPage.AddImageMethod();
zenSynchronousMode = false;
zenPage.ExecuteMethod();
//zenPage.RemoveImageMethod();
}

Method AddImageMethod() As %Status [ ZenMethod ]
{
#; use server-side methods to create new image
Set tHolder = %page.%GetComponentById("holder")
Set tComp = ##class(%ZEN.Component.image).%New()
S tComp.id = "image"
S tComp.src="images/ajax-loader.gif"
Do tHolder.%AddChild(tComp)
Quit $$$OK
}

Method ExecuteMethod() As %Status [ ZenMethod ]
{
for i=1:1:100000000
Set %page.%GetComponentById("text").value=i_" OK!"
Quit $$$OK
}

Method RemoveImageMethod() As %Status [ ZenMethod ]
{
#; if present, remove the image
Set tHolder = %page.%GetComponentById("holder")
Set tComp = %page.%GetComponentById("image")
If $IsObject(tComp) {
#; remove component from its group
Do tHolder.%RemoveChild(tComp)
}
Quit $$$OK
}

}
================================================
I made many attempts but still unsuccessful. And the main
question remain-

-Why ExecuteMethod() is executed before AddImageMethod() ?

Even if I put everything in one ZenMethod end execute it directly
the result is the same?!.
================================================
XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ]
{
<page xmlns="http://www.intersystems.com/zen" title="Progress Bar">
<hgroup id="holder">
<button id="button" caption="Start" onclick="zenPage.executeMethod();"/
>
<text id="text" />
</hgroup>
</page>
}

Method executeMethod() As %Status [ ZenMethod ]
{
#; use server-side methods to create new image
Set tHolder = %page.%GetComponentById("holder")
Set tComp = ##class(%ZEN.Component.image).%New()
S tComp.id = "image"
S tComp.src="images/ajax-loader.gif"
Do tHolder.%AddChild(tComp)


for i=1:1:100000000
Set %page.%GetComponentById("text").value=i_" OK!"


#; if present, remove the image
Set tHolder = %page.%GetComponentById("holder")
Set tComp = %page.%GetComponentById("image")
If $IsObject(tComp) {
#; remove component from its group
Do tHolder.%RemoveChild(tComp)
}
Quit $$$OK
}

}
===============================================
> ...
>
> read more »- Hide quoted text -
Reply all
Reply to author
Forward
0 new messages