I’m preparing to do my first web app and just looking for some guidance on “best practices”. Unfortunately for those who respond, I’ll probably have lots of questions and will continue to update this thread with those questions as time goes on.
Initial question is simply, should all controls be placed on a container and then the container added to the webpage in order to achieve the best results when opening the webpage on various monitors with different resolutions and, more importantly, should the enduser decide to resize the web browser page?
Additional question. Is there a general rule regarding what should be made a property/method of the session versus the webpages of the application?
Since Xojo Web doesn’t really have any sort of grid or flexbox model, I ended up coding a responsive design by hand.
I’m using controls on a single Webpage : no Containers.
Basically, I have code in the WebPage.Resized event which arranges controls based on the size of the WebPage, like this:
event WebPage1.Resized
dim w as integer = self.width
dim h as integer = self.height
dim x,y as integer
if w < 500 and h > w then
' --------------------------------------------------------------------------------
' small, Tall screen, such as iPhone 6,7, or 8 which is 375x667
' --------------------------------------------------------------------------------
' set up reasonable left margin and width
var x1 as integer = 4
var w1 as integer = w - 8
' hide the description header
lHeader.Visible = false
' question needs to wrap at screen size
y = logoBackground.Bottom + 8
lQuestion.width = w1
lQuestion.Height = 120
lQuestion.top = y
lQuestion.left = x1
y = lQuestion.Bottom + 4
if showTextArea then
' ta goes below it
ta.Width = w1
ta.Height = 280
ta.top = y
ta.left = x1
y = ta.Bottom + 4
elseif showgraph then
wc.Width = w1
wc.Height = 280
wc.top = y
wc.left = x1
y = wc.Bottom + 4
else
' rg goes below it
rg.Width = w1
rg.height = 280
rg.top = y
rg.Left = x1
y = rg.Bottom + 4
end if
' buttons below that
pbPrevious.top = y
pbCheck.top = y
pbNext.top = y
' status fields are below buttons
y = pbNext.Bottom + 4
lTimeLimit.left = pbPrevious.left
lTimeLimit.top = y
lStatus.left = pbNext.Right - lStatus.Width
lStatus.top = y
if showTextArea then
lCharCount.top = y
lCharCount.left = x1
end if
y = lStatus.Bottom + 8
elseif h < 500 and w > h then
' --------------------------------------------------------------------------------
' small, Wide screen, such as iPhone 6,7, or 8 which is 667x375
' --------------------------------------------------------------------------------
' set up reasonable left margin and width
var x1 as integer = 8
var w1 as integer = w - 16
' hide the description header
lHeader.Visible = false
' question needs to wrap at screen size
y = logoBackground.Bottom + 4
lQuestion.width = w1
lQuestion.Height = 76
lQuestion.top = y
lQuestion.left = x1
y = lQuestion.Bottom
if showTextArea then
' ta goes below it
ta.Width = w1
ta.Height = 146
ta.top = y
ta.left = x1
y = ta.Bottom + 4
' above/right of ta
lCharCount.top = ta.top - 32
lCharCount.left = ta.right - lCharCount.Width - 8
elseif showGraph then
wc.Width = w1
wc.Height = 146
wc.left = x1
wc.top = y
y = wc.Bottom + 4
else
' rg goes below it
rg.Width = w1
rg.height = 152
rg.Left = x1
rg.top = y
y = rg.Bottom
end if
' buttons below that
y = y + 4 // add some padding
pbPrevious.top = y
pbCheck.top = y
pbNext.top = y
' ### Special: status fields go to the Right of buttons!
y = y
lTimeLimit.top = y - 12
lTimeLimit.left = pbNext.right + 16
lStatus.top = y + 8
lStatus.left = lTimeLimit.left
else
' --------------------------------------------------------------------------------
' otherwise, assume it's a Tablet or computer with a big-enough screen
' --------------------------------------------------------------------------------
' show the description header
y = logoBackground.Bottom + 8
lHeader.top = y
lHeader.Visible = true
y = lHeader.Bottom + 8
' set up reasonable left margin and width
var x1 as integer = 16
var w1 as integer = Min(600, w-32)
lQuestion.top = y
lQuestion.left = x1
lQuestion.width = w1
lQuestion.Height = 110
y = lQuestion.Bottom + 8
if showTextArea then
' ta goes below it
ta.Width = w1
ta.Height = 280
ta.top = y
ta.left = x1
y = ta.Bottom + 4
elseif showGraph then
wc.Width = w1
wc.Height = 180
wc.top = y
wc.left = x1
y = wc.Bottom + 4
else
' rg goes below it
rg.Left = x1
rg.Width = w1
rg.height = 180
rg.top = y
y = rg.Bottom + 8
end if
This was not easy but it allows perfect customization, and in the end, the effort was worth it.
The answer for what you should do definitely depends on your specific UI design.
Depends on your design, but for my web app, I have the concept of a User, and each Session has one User instance as a property. When the User goes into WebPage to do something, information needed (for example, to graph some data, allow editing of a field, etc.) are all properties of the WebPage. Any data that needs to persist gets saved in the User object (which has a way to write to disk).
(Edit to add: in case it’s not clear, a WebPage is conceptually part of a Session, so one WebPage is never associated with more than one Session)
I did have to decide how to deal with one User trying to access the system at the same time; I decided to disallow this (if a User opens a new browser Tab, the prior session is terminated).