I am building a modal plugin and I would like to be able to set focus to the address bar.
I'd like to be able to do this because I need to be able to restrict tabbing to objects inside of the modal window, but keyboard users and accessibility users should be able to tab out of the modal window to the address bar when they have reached the final element (so that they are not stuck inside the modal). I'm aware that I can do this by setting all of the tabbable elements outside of the modal to have a tabindex of -1, but I'd like to avoid that solution if possible.
I'm aware that it may not be possible to directly set focus to the address bar due to security restrictions. Is there, however, a way to either do this, or defocus the page so that the next element is the address bar?
Having a modal element does not remove the other elements from the visual buffer. A screenreader may read automatically any other element after your modal. So removing the tabindex of elements which might be announced is indeed not a solution.
You may try to remove the focus from any other element using some code like $(".outside_modal").onfocus() {$("#modal-first-link").focus()} but you will have incoherence between your visual focus which will read link targets and the action provided by the keyboard focus.
The only viable solution is to set the modal element in the last position of your DOM.
Related
I'm using the MDL tab component. After a tab is clicked and it displays the content for that tab, I'd like to set the cursor focus in a certain text input within that tab's content.
My initial approach was just to handle the click event of the tab element and then set focus accordingly. The problem I'm having is that calling .focus() on the text input element isn't working because it tries to set focus before the text element is actually visible, which no browser seems to like doing for you. If I set focus inside a setTimeout() delay it works, but that doesn't feel like a very clean way to go about it.
Is there any kind of event that can be handled for when a tab is clicked and has finished displaying it's contents? I've also looked at using mutation observers to detect when the text input element is visible but browser support for those is fairly limited still.
No there is no such option. I think you have to use setTimeout or setInterval
You can look into the source. Perhaps write your own MaterialTabs constructor and register it.
Material-Design-Lite source, MaterialTab
I think there are also some libs that can do this like jQuery. You can also see
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
This works only in modern browser but has a legacy implementation.
I've added this line :
window.dispatchEvent(new Event("tabSelected"));
to the material.js file, at the end of the selectTab() function. This way, the event is fired right after the tab content is shown.
In my tests I have a number of modals and dropdowns which open and automatically have focus set on their input boxes.
I have seen that it is possible to assert that an element is in focus. But is there any shortcut way to send keys to the element currently in focus? I'd like to be able to skip all the work of finding each element every time.
You can use activeElement() feature of selenium to access the currently focused element source.
E.g.
// select the current page context's active element
browser.switchTo().activeElement().sendKeys('Test')
Alternatively, you may use "browser actions":
browser.actions().sendKeys('Test').perform();
Is it possible to prevent iFrame element to get focus or if not, at least to return focus instantly to parent window once such iFrame gets focus? Please advise with code example.
It depends upon what you're really trying to accomplish and which focus methods you are trying to prevent. There's no magic setting you can set that prevents focus going to an iframe.
You can put a transparent element over the top of the iframe and have it capture all clicks so nothing in the iframe is clickable. You can likely just position this with CSS and wouldn't necessarily need javascript unless the iframe size is dynamic or not known in advance. This won't prevent javascript code from setting focus to the iframe, but will prevent mouse clicks from moving the focus to the iframe.
You can regularly check (javascript polling) where focus is and if it's not in your own document, then put it back in your document. This is kind of a hack.
Here's a demo of the first option: http://bit.ly/10jzdlp
If the problem that you're encountering is due to script in the iframe's document focusing one of its element, then one solution may be to use the iframe's sandbox attribute to prevent the iframe's document from running script (that is, setting the attribute to a value that does not contain the flag 'allow-scripts'). Whether that's acceptable will depend on whether it will break other things, of course.
As we know can set contenteditable in DIV to allow editable. It can make same like Textarea.
However there's the most big different are the "content copy and paste" to DIV and Textarea.
DIV is allow html/plain but Textarea only serve plain text.
Below are the method to solve those problem:-
Method 1 - Direct using window.clipboardData.getData('Text') ( will prompt for asking permission).
Problem : Mozilla and chrome are not support clipboarddata.
Method 2 - Using flash.
Problem : Flash v.10 has upgraded to new rules which cannot get clipboarddata without user first initialize.
Method 3- Using "onpaste" event. When data paste on div -> Set focus
on hidden textarea -> Get value from hidden textarea and set into div
by using setTimeout -> clear hidden textarea.
Problem : The timing set value to hidden textarea are not consistent.
I have saw google was doing well on this.
For IE , use clipboarddata.
For Mozilla,others (not support html5) - Anyone know how google done it ?
Hint: use iframe designmode ?
For Chrome (support html5) - Just set DIV to Contenteditable="plaintext-only".
The trick that I use for this kind of thing is to have an offscreen <textarea>, which is not visible to the user.
The textarea is focussed and has a keyboard handler that notices whether the user is typing in the textarea. As I detect the user is typing, I grab the value of the textarea and dump it in the div.
This is the basic idea. You'll need a bit more to get the look and feel right:
you can't just hide the textarea with display:none or visibility:hidden because that will generally make it insensitive to typing and events too. So you need to make it really small and position it outside the screen, or stack it behind some other element.
you're going to have to detect whether the textarea blurs and decide if you need to refocus it.
You'll want a click handler on the div so that if people click the div you can focus to the textarea instead so people can start typing again.
The nice thing about this approach is that general keyboard handling, like ctrl+cursor, and cut+paste etc. all work exactly as expected without having to code that yourself - you're just piggybacking on the existing functionality of the textarea.
Here's an example of how this works:
http://js1k.com/2012-love/demo/1168
(A javascript shell)
Let's say I have a document full of focusable elements, either because they are innately focusable (like <input type="text">) or because they have tabindex="0" or the like.
Now let's say there's a section of my document that I want to display as a modal dialog box, and I don't want the user to be distracted by anything outside the dialog box. I would like for the tab key to cycle only through focusable elements inside the container element for the dialog box. What is the simplest way to do this?
If possible, I am looking for a solution that doesn't care what the contents of the dialog or the rest of the page are and doesn't try to modify them. That is, I don't want to make the elements outside of the dialog not focusable, for example. First, this requires making a reversible change and keeping track of state. Second, this requires knowing all the possible ways an element could be made focusable. This feels messy, fragile, and unscalable to me.
My first attempt looks like this, but works only in the forward direction (pressing Tab). It doesn't work in the reverse direction (pressing Shift+Tab).
<div>Focusable stuff outside the dialog.</div>
<div class="dialog" tabindex="0">
<!-- Focus should be trapped inside this dialog while it's open -->
<div class="content">
Form contents and focusable stuff here.
</div>
<div class="last-focus" tabindex="0" onfocus="this.parentNode.focus()"></div>
</div>
<div>More focusable stuff outside the dialog.</div>
I'd rather see pure JavaScript solutions. If there is a means of doing this with a library such as jQuery, I would prefer a link to the library code that does this.
In the interest of completeness, I'm taking the link to jQuery UI dialog that #Domenic provided and filling in the details.
To implement this in the jQuery fashion requires two things:
Listening for Tab or Shift+Tab (on keydown) for the modal element that should trap focus. This is the only means of moving focus via the keyboard. (If you want to prevent mouse interaction with the rest of the document, that is a separate problem solved by covering it with an element to prevent any mouse events from getting through.)
Finding all tabbable elements inside the modal element. These are a subset of all focusable elements, excluding those that have tabindex="-1".
Tab goes forward. Shift+Tab goes backwards. Any time Tab is pressed while the last tabbable element in the modal element is focused, the first should receive focus. Similarly, any time Shift+Tab is pressed while the first tabbable element is focused, the last should receive focus. This will keep focus inside the modal element.
The hard part is knowing which elements are tabbable. Since tabbable elements are all focusable elements that don't have tabindex="-1", then we need to know know which elements are focusable. Since there's no property to determine if an element is focusable, jQuery does it by hard-coding the following cases:
input, select, textarea, button, and object elements that aren't disabled.
a and area elements that have an href or have a numerical value for tabindex set.
any element that has a numerical value for tabindex set.
It's not enough to check for these three cases. jQuery goes on to ensure that the element is visible. This means both of the following must be true:
None of its ancestors are display: none.
The computed value of visibility is visible. This means that the nearest ancestor to have visibility set must have a value of visible. If no ancestor has visibility set, then the computed value is visible.
It should be noted that jQuery's :visible selector does not look correct for this implementation because it says "elements with visibility: hidden…are considered to be visible," but they are not focusable.
The jQuery UI dialog does this by capturing keydown events, checking if they are for TAB or not, then manually focusing the correct element.
The jqModal jQuery plugin does this out of the box by setting the modal option to true. The examples on this page with forms should show it. I remember going through the code to see what was happening and you could do it quite easily with plain JS.