ID:2153345
 
So, in trying to get my game webclient-ready, I keep running into issues where I'm not sure if it's my lack of understanding/experience or an issue with the system. I don't want to spend whole days of my time banging my head against a wall when I'm doing it right and it's working wrong, but nor do I want to take up LummoxJR's timewith bug reports that are actually my own mistakes.

At the same time, the webclient's reference guide is denser than most BYOND references and (probably as a side effect of not being for a finished product) is much more the sort of technical writing that makes perfect sense to people who already know what it's telling them. Important relationships among different elements are mentioned but never properly explained.

So let me just go over a few of the things I'm trying (and failing) to do, and ask how I should be doing them.

1. What is the DM code required to send an HTML file to a specified browser control in a specified main control (a pop, specifically)? I have tried recipient << output('file.htm',"browserID") and recipient << output('file.htm',"mainID.browserID") with no effect. I have tried specifying the browser "is-default=true" and using recipient << browse('file.htm'). In a shotgun-style approach to troubleshooting, I have tried browse() with the control IDs in, even though I know that's not how the browse command works (or is it?). Am I missing something or is this just not working?

2. In DMF, it's possible to have a verb/command execute when a window is closed. I discern that this is possible in the webclient because it functions seamlessly on my translated DMF skin, yet I can find no on-close parameter mentioned in the webclient reference. The closest obvious equivalent, on-hide, does not apply to main controls like pops, and does not seem to be called when I close the pop containing the browser (that I can't get anything to browse into, so in fairness I guess I'm not 100% sure the browser's actually there). To put it simply, how do I implement the behavior that is being translated (verb given when a pop is closed) in a custom skin?

3. I have realized it's possible to override the definitions of a default element by copying the default scripts from the BYOND web folder and then editing them. Is it possible for me to hook something into the browser pop-up definition that would send a verb input when it is closed? If so, how? Because that would free me up from having to use my own pop controls at all in this project.

4. I notice that support for focus is listed as "limited". None of the focus-foo in my translated skin works in translation. Has anyone discovered any workaround methods that would work with a custom skin? At a bare minimum, I am looking for a way to cause a text input to grab and lose focus.

5. In general terms, how similar is interacting with webclient controls to interacting with DMF-style skin controls? Should I expect winset() and winget() in the BYOND code to work seamlessly with same-ID elements in both styles? Do I use the same nomenclature of "main.control" in identifying them in DM?

I'm normally a trial-and-error kind of learner so I feel silly asking these questions instead of simply experimenting and discovering for myself how it works, but right now when something I try does not work, I have no ability to discern if this is the correct behavior or not.</<></<></<>
Follow-up question: When a DMF interface is translated into a webclient skin, does that skin exist in the same format as the DMS ones, and is it human-accessible/human-readable?

Because that would be a huge step up in figuring out how things work and how they fit together.
AlexandraErin wrote:
1. What is the DM code required to send an HTML file to a specified browser control in a specified main control (a pop, specifically)? I have tried recipient << output('file.htm',"browserID") and recipient << output('file.htm',"mainID.browserID") with no effect. I have tried specifying the browser "is-default=true" and using recipient << browse('file.htm'). In a shotgun-style approach to troubleshooting, I have tried browse() with the control IDs in, even though I know that's not how the browse command works (or is it?). Am I missing something or is this just not working?

You should be able to use output(). If the browser ID is unique, you don't need to qualify it with the full mainID.browserID name. The only qualifier is, sending that output won't automatically make the pop visible, so you'd want to use winset/winshow to make the pop appear.

browse() contains some internal logic to create a pop if need be, and make it appear.

2. In DMF, it's possible to have a verb/command execute when a window is closed. I discern that this is possible in the webclient because it functions seamlessly on my translated DMF skin, yet I can find no on-close parameter mentioned in the webclient reference. The closest obvious equivalent, on-hide, does not apply to main controls like pops, and does not seem to be called when I close the pop containing the browser (that I can't get anything to browse into, so in fairness I guess I'm not 100% sure the browser's actually there). To put it simply, how do I implement the behavior that is being translated (verb given when a pop is closed) in a custom skin?

Some of this oddity might stem from my design choices and it's likely that I got something not quite right. Looking at the pop control afresh, it seems that it doesn't really bother to handle on-close on its own, but rather only calls it for its child. I'll double-check this because I know there's also some internal logic that might be relevant.

The fact that on-close isn't documented as being supported in the webclient is an oversight, though.

3. I have realized it's possible to override the definitions of a default element by copying the default scripts from the BYOND web folder and then editing them. Is it possible for me to hook something into the browser pop-up definition that would send a verb input when it is closed? If so, how? Because that would free me up from having to use my own pop controls at all in this project.

Based on the pop control, suppling an on-close parameter to the browser itself ought to do the trick.

4. I notice that support for focus is listed as "limited". None of the focus-foo in my translated skin works in translation. Has anyone discovered any workaround methods that would work with a custom skin? At a bare minimum, I am looking for a way to cause a text input to grab and lose focus.

Each control has a default implementation for the focus parameter. Setting its focus to true should work, but setting it to false presently does nothing. I think it would make sense for me to alter the implementation to set focus to the main window when setting focus=false. You can also set the focused element by using winset(player,null,"focus=[id]").

5. In general terms, how similar is interacting with webclient controls to interacting with DMF-style skin controls? Should I expect winset() and winget() in the BYOND code to work seamlessly with same-ID elements in both styles? Do I use the same nomenclature of "main.control" in identifying them in DM?

Basically yes, winget/winset should work the same in both. The main exceptions are that some parameters aren't supported on the webclient, like "border" for instance. The webclient's design goal is to act as close to DS as possible for all supported parameters.

In the webclient I've been trying to get around that main.control nomenclature in favor of unique names. Ideally unique names are best skin-wide if you can manage it, though for cloned controls that's obviously not possible. Basically you can expect it to behave the same as DS in that regard, except it's way less tolerant of names that stray from using proper identifier characters (e.g., alphanumerics and underscore). While in DS weird characters in the ID like $ and # and such could theoretically work, they were never meant to; the webclient disallows them entirely and will sanitize them out.

Follow-up question: When a DMF interface is translated into a webclient skin, does that skin exist in the same format as the DMS ones, and is it human-accessible/human-readable?

Because that would be a huge step up in figuring out how things work and how they fit together.

It gets sent in a message, but doesn't get saved anywhere for easy access. But it is in the same format as the .dms ones. I think it would be a very good idea for me to add functionality to view that translated skin, and sooner rather than later.
Thank you, this was very helpful. I certainly do favor unique names for controls, preferably descriptive of what they do in the game. I am glad to know that on-close is supported.

I think it would be a very good idea for me to add functionality to view that translated skin, and sooner rather than later.


It would seriously make it a lot easier to make an "enhanced translation" for the webclient if we didn't have to start from scratch.
I did some more research, and the reason on-close isn't working in the pop control (though it will be in the next build, and going forward) is that the pop control is generally only created on the fly to display a pane/browser/etc. when their popup() routine is called. The pop control currently doesn't even support permanency, although I'll be changing that.

The default pos and size winset routines look to see if the control is being held by a pop (in this.config._pop), and if so they transfer the winset/winget to the pop instead. So the general pattern here is:

- control.popup() is called on a control to put it into a new, temporary pop control; the pop is referenced in control.config._pop.

- Winsets/wingets to the control for its size and position will be transferred to the pop by default.

- When the pop is closed, it moves the control back to a hidden staging area and calls control.onclose(), which triggers the on-close command. The pop is destroyed.

This means I think I led you wrong on pops before; in your custom skin, you basically don't want to define them directly. A pane would be the better bet, with is-pane=false in its skinparams. If the pane has is-visible=true it will create a pop when it's loaded, and setting pane.is-visible should call popup() or close the pop as needed.
That's great to know for the future. Meanwhile, I discovered I can do what I wanted to do with a pop-up browser by using winset() to set on-close for the ad hoc browser created by the browse() proc.