Page 1 of 1

Using Web History for Panel Navigation

Posted: Tue Feb 23, 2016 6:43 am
by jyoung
Hi, I am spiking out a solution that can use web history to maintain back button support when user "transitions" between panels.

TL;DR
When adding history, the first "click" of the back button works as expected, but subsequent clicks require two clicks of the back button.

I have a web page that is composed of 4 Panels (Green, Red, Blue and Purple), an application object to manage the panel transitions and a PanelManager to deal with adding panels to a layout.

If you execute, MMSPanelPage, you can see the app in action. Clicking through the panels on the left transitions to each panel and the panel identifier is added to the URL via #SYS_WEB.History. Click through to the purple panel and then click your brower's back button. The first click works as expected, the blue panel is displayed. The second click does nothing (I would expect the red panel to be displayed), but the third click transitions to the red panel. Like wise for the previous green panel.

If you open your brower's dev tools, I have added some Console.Log statements to help track it down. I tried some crazy tricks like adding all the panel history to a collection and always getting the last one, nothing seems to work.

Attached is the export. Could use some advice or guidance on how to make this work.

Thanks,
Joe

Re: Using Web History for Panel Navigation

Posted: Tue Feb 23, 2016 11:45 am
by Stewart Marshall
Hi Joe

I found exactly the same issues when making the xDemoWebBackForward example. It's slightly simpler than yours, but the concepts are the same.

Your current processing is similar to this

Click green. Show green. Add green.
Click red. Show red. Add red.
Click blue. Show blue. Add blue.
Click back. Show red. Add red!!!!
Click back. Show red, but as it's already red, ignore.
Click back. Show green. Add green.

All processing has to go via the URLchanged event. This is a necessity for all back, forward and deep linking processing. However, not all navigations are equal. If a user clicks a button to do something, that should be added to the history, but use of Back/Forward should not. They just navigate through it.

I've made a couple of alterations to the code. The application object now has an AddToHistory method. This is called by each of the items in the list when they're used.

Regards

Re: Using Web History for Panel Navigation

Posted: Wed Feb 24, 2016 2:03 am
by jyoung
Ok, I see what you did there.

I gotta remember about those demo apps, lots of good information in there if you remember to go look for it. :D

Thanks for the help.

Re: Using Web History for Panel Navigation

Posted: Sat Dec 10, 2016 7:23 am
by jyoung
I realize this is an old topic, but I've encountered another issue related to the topic so I thought I would add it here.

While adding to the history works as expected regarding navigation, there seems to be an anomaly with other querystring parameters.

In essence what I am trying to do is add an entry to the history keeping the current querystring values and/or replacing certain values so that history would become
  1. ?panel=ABC&Trace=True
  2. ?panel=DEF&Trace=True
  3. ?panel=GHI&Trace=True
What I have discovered is that when I first add and entry to the history it removes all the existing querystring parameters such as debug info, trace etc. So I thought to copy the current querystring parameters and add them to the history as well and that works the first time the entry is added.

Subsequenent adds however seem to concat the values on the existing querystring whereas the initial add, replaced the entire querystring.

For example:
If the querystring is `?myvalue=123&trace=true` and I add `panel=ABC` then the querystring becomes `?panel=ABC`.

If I copy the the querystring parameters, add my panel parameter and then add all that to the history the querystring becomes `?myvalue=123&trace=true&mypanel=ABC`. If I copy the parameters, change the panel parameter add it to the history the querystring becomes `?myvalue=123&trace=true&mypanel=ABC&myvalue=123&trace=true&mypanel=DEF`.

It seems the first call to Add does a replace and subsequent calls to Add concatenate.
Has anyone else seen this behavior or know how to deal with it?

This is the code I am using, perhaps I am doing something wrong?

Code: Select all

define_com class(#PRIM_ACOL<#PRIM_WEB.URLParameter>) name(#queryStringParameters)

mthroutine name(AddToPanelHistory) access(*PRIVATE)
define_map for(*INPUT) class(#STD_STRNG) name(#panelId)
define field(#queryString) type(*STRING)

#queryStringParameters.RemoveAll

for each(#urlParameter) in(#SYS_WEB.URLParameters)
* don't add a panel, we are going to add it later
continue if(#urlParameter.Name.Uppercase = PANEL)

#SYS_APPLN.TraceMessageText( ("Adding &1:&2 to parameters").Substitute( #urlParameter.Name #urlParameter.Value ) )

if (#queryStringParameters.Contains( #urlParameter ) = False)
#queryStringParameters.Insert( #urlParameter )
endif
endfor

* build up the querystring 
for each(#queryStringParameter) in(#queryStringParameters)
if (#queryString.CurChars = 0)
#queryString += ("&1=&2").Substitute( #queryStringParameter.Name #queryStringParameter.Value )
else
#queryString += ("&1&2=&3").Substitute( '&' #queryStringParameter.Name #queryStringParameter.Value )
endif
endfor

* add the panel id and add it to the history
if (#queryString.CurChars = 0)
#queryString += ("&1=&2").Substitute( panel #panelId )
else
#queryString += ("&1&2=&3").Substitute( '&' panel #panelId )
endif

#SYS_WEB.History.Add( #queryString )

endroutine

Re: Using Web History for Panel Navigation

Posted: Sat Dec 10, 2016 10:20 am
by Stewart Marshall
Hi Joe

Here's a simple page showing history working as it should. Run it from the IDE to get additional parameters in the QueryString.

Every time a label is clicked, its caption is added to the history. As the sequence of the parameters in the QueryString isn't important, I ignore a "Panel" item if its there and then tack it on the end.

Code: Select all

Begin_Com Role(*EXTENDS #PRIM_WEB) Height(488) Width(769) Theme(#SYS_THEME<2015Blue>)
Define_Com Class(#prim_labl) Name(#Label1) Caption('Panel1') DisplayPosition(3) Left(32) Parent(#COM_OWNER) TabPosition(3) Top(64) TabStop(False) ThemeDrawStyle('LightTitle') Height(34) Width(209) Alignment(Center) VerticalAlignment(Center)
Define_Com Class(#prim_labl) Name(#Label2) Caption('Panel2') DisplayPosition(2) Left(32) Parent(#COM_OWNER) TabPosition(2) Top(104) TabStop(False) ThemeDrawStyle('LightTitle') Height(34) Width(209) Alignment(Center) VerticalAlignment(Center)
Define_Com Class(#prim_labl) Name(#Label3) Caption('Panel3') DisplayPosition(1) Left(32) Parent(#COM_OWNER) TabPosition(1) Top(144) TabStop(False) ThemeDrawStyle('LightTitle') Height(34) Width(209) Alignment(Center) VerticalAlignment(Center)

Define_Com Class(#prim_kcol<#prim_labl #xDemoCaption>) Name(#Labels) Style(Collection)

Evtroutine Handling(#Com_owner.CreateInstance)

For Each(#Member) In(#Com_owner.ComponentMembers) Operation(*Instance_of #prim_labl)

#Labels<#Member.Caption.UpperCase> <= #Member

Endfor

Endroutine

Evtroutine Handling(#Labels<>.Click) Com_Sender(#Sender)

#Com_owner.AddHistory( #Sender.Caption )

Endroutine

Mthroutine Name(AddHistory)
Define_Map For(*Input) Class(#Prim_Alph) Name(#Panel)

Define_Com Class(#Prim_alph) Name(#QueryString)

For Each(#Parameter) In(#sys_web.URLParameters)
Continue If(#Parameter.Name.UpperCase = Panel)

If (#QueryString <> "")
#QueryString += "&"
Endif

#QueryString += #Parameter.Name + "=" + #Parameter.Value

Endfor

#QueryString += "&Panel" + "=" + #Panel

#sys_web.History.Add( #QueryString )

Endroutine

Evtroutine Handling(#sys_web.URLChanged)

#Labels<>.ThemeDrawStyle := LightTitle

If (#sys_web.URLParameters<Panel> *IsNot *null)

#Labels<#sys_web.URLParameters<Panel>.Value.UpperCase>.ThemeDrawStyle := DarkTitle

Endif

Endroutine

End_Com
Regards