Open weddingdj opened 7 years ago
That check is in place so that WASD controls won't move when the player is typing into an <input/>
or <textarea/>
— say, a chatbox or signup form. Other ideas? How are you using the modal dialog?
I see. In my case the modal-body contains the scene and I show the modal dialog when the users clicks a button (http://getbootstrap.com/javascript/#modals). It is a standard use. The console shows that document.activeElement is <div class="modal fade" tabindex="-1" role="dialog">
instead of body, because the focus is set on the modal div and not the body.
Would it be possible to just take WASD user input when the focus is on the canvas?
I will play with it, either we leave the impl. as it is, or I propose a change. I just saw that I can manually set the focus to an element so I could force the focus to the body, even if the modal is open. Let's see how it goes.
I think my use case is specific and I guess that not having WASD navigation in a scene which is embedded is ok for most people.
I had no success in setting the focus on body manually, after opening the bootstrap modal dialog. My personal solution would be to patch aframe.js and override the method in utils.js unless you say that WASD navigation must work for embedded scenes, no matter where they are embedded. But I have no idea how this could be achieved, without eg. triggering input in textfields.
One possible solution would be to add tabindex="1"
( http://stackoverflow.com/questions/29992688/how-to-keep-the-focus-on-a-canvas-always ) to each injected canvas which forces the focus on the canvas and not on the body. If I could reference the current canvas in https://github.com/aframevr/aframe/blob/master/src/utils/index.js#L176 we could do return document.activeElement === canvas
How do I get the current canvas in utils?
I could setup a codepen with several embedded canvas including one in a bootstrap modal and see if the behaviour is as expected.
@chriscar you should have access to the canvas by doing sceneEl.canvas
. We can maybe create a specific method in wasd-controls
instead of using the utils one to test the solution
@cvan might have some ideas.
@chriscar: @dmarcos: @donmccurdy: if the iframe is on the same origin, then you should be able to do this:
window.addEventListener('DOMContentLoaded', function () {
// Find an iframe already on the page.
var iframe = document.querySelector('iframe');
if (iframe) {
iframe.addEventListener('load', function () {
try {
iframe.contentWindow.focus();
} catch (err) {
console.warn('Could not focus iframe', err);
}
});
if (iframe.contentWindow) {
iframe.contentWindow.focus();
}
}
});
Or, ideally, if you're dynamically creating an <iframe>
from JS:
// Create an iframe.
var iframe = document.createElement('iframe');
iframe.src = 'my_scene.html';
iframe.allowfullscreen = 'true';
iframe.enable = 'vr'; // See https://github.com/w3c/webvr/issues/86
iframe.addEventListener('load', function () {
try {
iframe.contentWindow.focus();
} catch (err) {
console.warn('Could not focus iframe', err);
}
});
document.body.appendChild(iframe);
Let me know if that solves your problems.
@cvan Thank you for your code examples, I am sure it works that way. In my case I am dynamically loading a template partial from an REST endpoint depending on a certain type of content (photo sphere, video sphere, models, etc.) and I append the loaded template code (a-frame scene) to an element within the bootstrap modal dialog. I don't like the idea of loading a template which represents an html document (and I don't like iframes). But that's just my personal taste and my special use case. ;-)
I think for all other people wanting to load an a-frame scene into any sort of modal dialog window (which takes the focus) your solution should be fine. Although the canvas tabindex="1"
solution is not too bad in my opinion (http://stackoverflow.com/questions/29992688/how-to-keep-the-focus-on-a-canvas-always).
Description:
The scene is embedded inside a bootstrap modal dialog and the shouldCaptureKeyEvent method ( https://github.com/aframevr/aframe/blob/master/src/utils/index.js#L176 ) returns false because, in my case document.activeElement is the modal dialog div which does not equal to the document.body.
return document.activeElement === document.body;
What is the reason for this statement?