Keyboard Events not triggering scripts in Perspective

I find that I can’t get any Keyboard Events on my views’ roots to work. I am trying to put hotkeys on buttons by putting a script on the onKeyUp keyboard event, and triggering the script from the event script, using a simple if event.key == "1": to make sure that the right key was used. When that didn’t work, I tried logging what key the onKeyUp was for, and it didn’t log anything. Since I was calling this from the root of a pop-up modal launched from a nested view, I put the same event script on the partial view, and the main view of the page. None of them even logged anything.

Has anyone else had a similar problem, or have any idea what I might be doing wrong here?

I just confirmed that scripts on Mouse Events are working as expected. So it seems to be specific to Keyboard Events.

Could this be because I don’t have a component which is expecting keyboard input in focus? Is that a requirement to fire a Keyboard Event?

“Global” key events in Perspective are a planned feature, but there are some technical hurdles. I believe that you’re essentially correct re: focus; for security reasons browsers don’t want to make it too easy for one JS component to receive key events sent to another (ie, a password field :slight_smile: )

So in the meantime, I guess the solution will have to be to put focus somewhere on the screen that can legitimately listen for key events without alarming the browser. My first attempt has been for the root component of the modal to call focus() in its onStartup script. I also put the same thing in onBlur, just in case it loses focus. It worked inconsistently, so I put some logging in before and after each call to focus() and in the onFocus script. And then it stated working perfectly.

Usually when I’ve had problems that go away when they’re logged, it’s been because of a timing issue, or possibly a threading problem. Since I’m not using threading or calling anything with a delay, any problems in that area are probably out of my control. In the meantime, I’ll try something like putting an actual input component on the screen, and letting it request focus and listen for keys. If that works well, I can make it hidden or invisible, since this is a screen which isn’t accepting any other kind of input than the button presses or their hotkey equivalents.

Looks like TextFields can’t listen for keys, or even get focus, when they’re hidden or not visible. Bother. I will try something else.

I tried making the TextField a thin line of black text on a black background, so it would just look like a border or something. That looks fine, but just like with the root component, none of it works unless I am logging. Here’s some of the code.


	logger.trace("onStartup: request focus")
	logger.trace("onStartup: focus request complete")


	logger.trace("onBlur: lost focus, request it back")
	logger.trace("onBlur: focus request complete")


	logger.trace("onFocus: focus received")	


	logger.trace("onKeyUp, event.key=%s" % event.key)
	if event.key == "1":
		logger.debug("Confirm via key")
		system.perspective.sendMessage(messageType=self.parent.parent.getChild("ButtonFlexContainer").getChild("ConfirmButton").custom.messageType, scope="page")
	elif event.key == "2":
		logger.debug("Cancel via key")
		system.perspective.sendMessage(messageType=self.parent.parent.getChild("ButtonFlexContainer").getChild("CancelButton").custom.messageType, scope="page")

If I leave these as first three blocks logging at a trace level, I never catch the key press. If I change them to debug (or set that logger to trace), then the key presses work perfectly.

The overhead associated with logging all of this seems like it would be too high, and at the very least would tend to clutter the logs. I guess the next thing to try will be putting a nap or sleep on the thread in place of the logger.

I suspect the logging is a red herring - that action literally doesn’t do anything on the frontend. I suppose it could be a timing thing; it’d have to get investigated by one of the front-end focused people. A call to a logging method should be extremely quick, though…

In the end it just took a 100 millisecond sleep before calling focus() in the onStartup. Everything else fell into place once I put that on the root, and it didn’t require any hacking around with fake TextFields. It may be that an even smaller sleep would to it, but at least for now I can live with a 10th of a second.