I have html input[type=text] element.
I want user NOT TO use voice input / voice typing (actually I need to prevent voice input provided by Android/iOS on-screen keyboard) on my input element or entire document at all.
// Tryed hard to find any answers, but it looks like no one else got the problem.
// I've already put other preventive attribs on the input so it looks exactly:
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
And yes, I understand this feature is up to mobile's keyboard, not browser.
Anyway, please suggest any workarounds.
Update: The interface exactly needs user to type words with their hands. There are no accessibility issues due to interface's purpose.
This is simply not possible because of sandboxing. It's also an awful idea because it ruins accessibility.
You could try using Javascript to only listen to keydown events, but this depends on the voice-to-text program not emulating key presses, and also removes the ability to copy-and-paste.
You could have an on-screen keyboard which requires users to click the buttons instead of using their own keyboard, But you won't be able to override the native keyboard without accessing the phone's API, which is usually only exposed to native apps.
You're really playing with fire in terms of UX with either of those solutions, though. Is there any reason you can't allow voice-to-text, or are you trying to reduce errors?
Related
I'm struggling to implement an accessible input with increment/decrement behaviors, using an <input type="text" role="spinbutton" /> element in HTML/JavaScript. But it seems like with VoiceOver there are custom (fake?) input events for incrementing/decrementing which change the input's value in unexpected ways.
How do I make sure a user navigating the page with assistive technology doesn't get bad guidance from VoiceOver while trying to interact with my widget?
For example, using super trimmed-down code like this:
function logIt(...args) {
document.getElementById('output').appendChild(
document.createTextNode(`${args.join(', ')}\n`)
);
}
document.getElementById("myInput").addEventListener('input', (e) => {
debugger;
logIt(e.type, e.data, String(e));
e.target.setAttribute('aria-valuenow', e.target.value);
}, false);
document.getElementById("myInput").addEventListener('keydown', (e) => {
logIt(e.type, e.data, String(e));
}, false);
<input
id="myInput"
type="text"
role="spinbutton"
autocomplete="off"
defaultValue="1"
aria-valuenow="1"
aria-valuemin="0"
aria-valuemax="100"
/>
</div>
<pre id="output"></pre>
... VoiceOver will describe the input as a "stepper" and give instructions on how to increment/decrement using the keyboard. But using those keyboard commands results in some weird math, as seen in this screen cap:
You can also see (from the "logging" in the screen cap) that when the user types input, an InputEvent is triggered with event.type being input - but when the VoiceOver keyboard command for increment/decrement is used, a base-type Event is triggered with event.type again set to input.
And this doesn't seem to be unique to my implementations of role="spinbutton". The jQuery UI spinner doesn't behave well when incremented/decremented using VoiceOver keyboard commands:
I even tried some of the w3c's examples for role="spinbutton":
The font size widget on https://www.w3.org/TR/wai-aria-practices/examples/toolbar/toolbar.html
The date picker on https://www.w3.org/TR/wai-aria-practices/examples/spinbutton/datepicker-spinbuttons.html
... and even though VoiceOver described each of those UI controls as a "stepper" and gave instructions on how to increment/decrement them using the keyboard, those instructions didn't seem to work. Other keyboard behaviors worked - but the ones VoiceOver suggests don't.
What can I do to make sure that role="spinbutton" markup works correctly with VoiceOver's increment/decrement keyboard commands?
I don't believe role="spinbutton" is compatible with VoiceOver as it seems that VoiceOver hijacks the keydown events when using the VoiceOver cursor. So when focusing on an element with role="spinbutton" VoiceOver instructs the user to use "Control-Option DownArrow" or "Control-Option UpArrow" to decrement or increment the value. When those keys are pressed the event does not make it to any JavaScript keyDown event handler so we can't detect that those keys have been pressed and can't implement the actual incrementing or decrementing of the value. So I'm not sure there is any way to use role="spinbutton" and make it work with VoiceOver. The user will be given instructions that don't work and will be confusing.
As a workaround for an application that I'm working on I've implemented the key handling behavior described in the WAI ARIA authoring practices for spinbutton but I have not added role="spinbutton" or the other aria attributes listed. Instead, I've added aria-live="assertive" so that when the value is changed either by keyboard or clicking the increment/decrement buttons the user hears the new value. Additionally, I've added some visually hidden text that instructs the user on how to increment/decrement the value with the keyboard and associated that with the input using aria-describedby.
I just visited w3's spinbutton example, and it seems to be keyboard operable in VoiceOver Mac (OS Version 10.15.1 with Safari). You can inspect the code they have used, and get inspiration there.
However, the w3 spinbutton example does not announce the current value when the stepper receives focus, or the changes as you step up and down. I tried Medium and High verbosity settings with no luck.
This failure to announce the value (either aria-valuetext or aria-valuenow or perhaps both) seems to be a bug on Apple's side, so I just reported it. Good catch.
This could perhaps be hacked-in with an aria-live region, but you might end up with duplicate announcements on other browser/screen reader combinations.
I'm building a simple HTML page, and I have an input field followed by a search button; this is the code:
<input type="text" id="sfield" placeholder="Write something">
<button id="search">Search!</button>
I'm currently writing the javascript to assign some actions to the button and to the input field, when I thought that it would be a good idea to add a feature that needs the cursor to be on the field for the search to start. I'll explain it better: if someone wants to search something, it will appear just like a normal input field and work like that. However, if someone tries to launch a script for auto-submitting the form, it'll act like no input was inserted.
For example, if someone tries to inject this script:
document.getElementById('sfield').value="Some stuff";
document.getElementById('search').click();
the search would start but the "Some stuff" string wouldn't be saved, as if the user clicked the search button without writing in the search field. Furthermore, adding the line
document.getElementById('sfield').focus();
should also do nothing, so that the only way to put the cursor in the field would be a manual action by the user.
I'm wondering if it's possible to make such thing; I already managed to get the search field blank with EventListener, but I don't have a clue about making the script discern whether the user put the cursor on the field or not.
I'd prefer not using JQuery but it's ok also with it. Any idea would be greatly accepted. Thanks.
In that case, the program needs to retain state. I'd do it like this...
http://jsbin.com/hopicucuyi/edit?js,console,output
<input type="text" id="sfield" placeholder="Write something" data-validated = "false">
<button id="search">Search!</button>
<script>
const inputField = document.getElementById('sfield');
const searchButton = document.getElementById('search');
inputField.onfocus = () => {
inputField.setAttribute("data-validated", "true")
}
searchButton.onclick = () => {
const isValidated = inputField.getAttribute("data-validated");
console.log('Is Validated: ' + isValidated);
}
</script>
Generally neither of these solutions will stop a bot that uses a browser (which is a bot that runs javascript). There is no 100% solution, but there are stronger solutions than checking if something has focus or not. Remember the javascript environment is completely controllable from the browser side of things. For instance, all I would have to do to get past your security is change the state of the input in question to data-validated="true" and your security falls apart.
However, the browser vendors have taken this possibility into account and provide you with a little-known solution. Look at the event data coming from a mouse click or a keystroke. This event data can be generated. It used to be easier in the older browsers to spoof an event just by using new Event(), but now modern browsers use specific events for keyboard and mouse. The part that makes spoofing these very hard is that in the event there are properties that are read-only. More specifically there is an event property called "trusted" that cannot be set by javascript. If you spoof a MouseEvent or KeyboardEvent, the "trusted" property is set to false, but if you use the actual mouse or keyboard "trusted" is set to true.
Info on the isTrusted property here: https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted
Note: this is also not 100% as the bot can run a keyboard/mouse macro that creates genuine "trusted" events. However, it does make the system much harder to crack as many people dont know about this security trick, and most bots will not have mouse/keyboard control built in. If you encounter a bot that uses mouse/keyboard, you've reduced the security playing-field and further analysis of the events and interface usage can take place.
If you combine this method with other methods like browser fingerprinting etc. it makes your overall anti-bot security that much stronger and discourages many more possible bots.
Edit: Don't just use this method and others, obfuscate your code so that any attacker will have to take the time to deobfuscate and wade through a bunch of poorly labeled functions and encrypted strings if they want to see how your security works.
This is a fairly straight forwards question, but I cannot find the answer in the documentation.
I know it is possible to detect clicks, but is it possible to detect a key press using an InDesign script?
For example, if the user creates a text box, and types 'a' into it, I would like to capture that and do something with it.
Perhaps this can be done using hotkeys, where for example one script on startup adds a hotkey for each keyboard button, each hot key fires a script for handling it. This seems a bit of a hack (if it would even work). Is there not a on key press listener I can add?
Any help is much appreciated.
I have found this so far in the documentation:
Most of the things scripting cannot do—like setting up a workspace or
defining a set of keyboard shortcuts—are things that have to do with
the user interface.
For the specific example you give (typing something into a text frame), you can use the afterSelectionChanged event listener (whose parent can be the application, or a layout window, amongst others).
I am writing an application in JavaScript (with JQuery). The application has a lot of functionality that the user needs to access quickly and possibly at the same time (you could think of it as a game, even though it's not a game) so I've set it up to use the keyboard. I've got a prototype of the system working (in Chrome, at least), but there is a problem in that when I press, for example, Ctrl-T, it opens a new tab. I would like to use this as part of my application to, for example, toggle some setting. In general, I would like to disable the Ctrl-key functionality of the browser. This goes for Alt and Shift, too. In a different way, I would also like to disable the browser's usage of the Tab key. Basically, I want my application to have complete control over the keyboard while it's being used (if they want to navigate away, they will still be able to do so with the mouse). I will add the caveat that I don't care about some of the less-common keys (F1-F12, Windows/Mac-Command, Menu, anything right of the Enter key) because my application mainly targets laptops and many don't have those keys, so they won't be used.
My question is, how can I disable this browser functionality with JavaScript/JQuery/DOM?
I understand that taking over browser functionality in this way this sounds very authoritarian, but it's actually quite necessary. From the prototype and some target-audience test users (my family) everyone has agreed that this was a good idea.
I've also considered moving my application out of the browser and writing it in some application language (probably Java), but I want to find out if this kind of functionality is possible in JavaScript before making that kind of switch. This is prototyping time, though, so every idea is still up for consideration!
Basically, you return false at the right time. See this: How to create Ctrl+Key shortcuts in Javascript.
I should add and say sometimes this doesn't work - it's up to the browser to allow this.
Also, it is sometimes possible to change e.which to another key, but again, this wouldn't always work.
I have an interactive html5 canvas thing where sometimes users will want to undo their actions. I have the logic for doing that implemented, but I'm not sure of how to properly catch the "user wants to undo" event.
Currently, I just listen to keyboard events and interpret "CTRL+Z" as a request-to-undo, like this:
document.addEventListener("keydown", e => {
const Z_KEY = 90;
let isUndo = e.keyCode == Z_KEY && e.ctrlKey && !e.shiftKey;
if (isUndo) {
restore(revision.undo());
}
});
The problem is that the standard shortcut for undo-ing varies by OS, and there are totally orthogonal ways to trigger it (such as shaking your phone).
What I want is to somehow tell the browser that I'm supporting undo, and that it should forward all the crazy OS-specific ways of triggering undo to a method I specify. As things stand now, the browser has no idea the user is doing anything that would involve undo-ing. All the browser sees is a canvas being clicked on and drawn to.
Is there a standard way to ask the browser to catch all the undo events for me? In a future-proof way that keeps working even as vendors invent new undo actions? What about a hacky workaround? Or perhaps there's a library whose focus is to solve this particular problem?
Notes:
This question differs from How to handle undo/redo event in javascript?. That one is asking about catching changes to an element, whereas I always know about any changes because my code is the one performing those changes.
The question Listen to undo/redo event in contenteditable div is also about change-detection instead of implementing undo, and is limited to a particular type of element. I'm willing to use custom elements to make this work.
There's no standard javascript way of hooking things like undo/redo as there is no specific event for them.
Maybe Mousetrap does what you want. It's a library for abstracting keyboard events in javascript and includes a way to do a generic [system modifier]+key hotkey kind of thing.
That said, you'll probably need a button somewhere if you want mobile. (I'm not familiar with the shake-to-undo action. That seems like new age hippy nonsense. =P )