Hide soft keyboard for specific TextField in Nativescript - nativescript

My goal is to have a hidden Textfield which maintains focus so it can receive input from a Bluetooth barcode scanner. I have accomplished this so far, but the soft keyboard is always displaying which is a huge disruption in the application. I have tried using dismissSoftInput(), but the keyboard pops up for a moment before it is dismissed. I need to to never appear.
Right now, my code is
#ViewChild("scannerInput") scannerInput: ElementRef;
private _isRunning: boolean;
constructor() {}
ngOnInit(): void {
// as long as _isRunning is true, keepFocus will continue to call itself to make sure the input is focused
this._isRunning = true;
this.keepFocus();
}
ngOnDestroy(): void {
// when the component is destroyed, keepFocus will stop running
this._isRunning = false;
}
scanComplete($event) {
var scan = <TextField>this.scannerInput.nativeElement;
// Value of the barcode is evaluated here
scan.text = "";
}
keepFocus() {
setTimeout(() => {
// the input will receive focus every half second
var scan = <TextField>this.scannerInput.nativeElement;
scan.focus();
if(this._isRunning)
this.keepFocus();
}, 500)
}
and my HTML is
<StackLayout class="layout-container">
<TextField #scannerInput
name="scannerInput"
id="scannerInput"
(returnPress)="scanComplete($event)">
</TextField>
</StackLayout>
I've searched around for answers but none of them seem to fit my use case. I've found some solutions that disable the soft keyboard for the entire app/activity, however I need the keyboard in other sections of the app.

The physical scanner device I'm going to use finally arrived this afternoon, so I was able to test it on a real device instead of an emulator.
Thankfully, the Bluetooth scanner seems to disable the keyboard by default; so the issue is "resolved".
I am going to leave this question open for now in case anyone has a software solution.

Related

Pressed state of trumbowyg toolbar buttons not being read out by NVDA but are being read out by VoiceOver

I would like the pressed state of the trumbowyg toolbar buttons (bold/italic etc) to be read out by NVDA screen reader. I have implemented the aria-pressed solution, which works fine for VoiceOver; it reads out select/deselect when the buttons have been selected and deselected, however not for NVDA:
function addValuesToTextEditorButtons() {
const toggleButton = element => {
// Check to see if the button is pressed
var pressed = (element.getAttribute("aria-pressed") === "true");
// Change aria-pressed to the opposite state
element.setAttribute("aria-pressed", !pressed);
}
const handleBtnKeyDown = event => {
// Prevent the default action to stop scrolling when space is pressed
event.preventDefault();
toggleButton(event.target);
}
var buttons = $('.trumbowyg-button-pane .trumbowyg-button-group button[type="button"]');
buttons.each(function (index, element) {
let title = element.title.split(' ')[0]
element.value = title
element.setAttribute('aria-label', title)
element.setAttribute('aria-pressed', false)
element.setAttribute('role', 'button')
element.addEventListener('click', event => {
handleBtnKeyDown(event)
})
element.removeAttribute('tabindex')
});
}
First off, verify that the element you're setting aria-pressed on is a real button (or role='button'). It looks like that's true from your code snippet but would be the first thing to verify. ARIA attributes are only valid on certain elements. (See https://www.w3.org/TR/html53/dom.html#allowed-aria-roles-states-and-properties)
Some screen readers might still announce the value of the attribute even if it's not valid so sometimes that explains why one SR works (such as VO) whereas another does not (NVDA).
I've used aria-pressed successfully with all screen readers without a problem. For NVDA, it will announce the element as a "toggle button" and will say "pressed" or "not pressed" depending on the value.

NativeScript TextField canPerformActionWithSender

I have a custom keyboard (made from buttons) in my app and I'm using it to populate a numeric value into a TextField. When a button is pressed, I set the text of the TextField while sanitizing the data — making sure there's only 1 decimal, no letters are entered, etc.
However, I'm now trying to detect when a user attempts to paste into the field so I can either prevent it entirely or sanitize the pasted text before allowing it to be pasted.
The approach I've taken so far is to try to implement the canPerformActionWithSender method on a NativeScript TextField.
I've tried the following (I'm using NativeScript Vue):
<TextField
ref="amount"
hint="$0.00"
#loaded="onTextFieldLoaded"
#unloaded="onTextFieldUnloaded" />
And...
onTextFieldLoaded(event) {
let textField = event.object
textField.focus()
nativeView.canPerformActionWithSender = (action, sender) => {
// `action` may be 'paste' so I can handle that action here
}
}
But this doesn't work. Is there an easy way to accomplish this without creating a custom component?
I was able to solve this with the following:
UITextField.prototype.canPerformActionWithSender = function (action, sender) {
return false;
}
This will disable the copy/paste/etc. menu completely. You can be more specific and check the action to only disable certain functionality if you like.
UITextField.prototype.canPerformActionWithSender = function (action, sender) {
if (action == 'paste:') {
return false;
}
return true;
}

Nativescript Android - hide keyboard

In my Nativescript app, the application starts with the login page. On iOS everything looks good, but on android, the username field is focused and the keyboard is showing. Is there a way to prevent this from happening?
So far I have tried:
Getting a reference of another element (a label) and calling lbl.focus() in the page's onLoaded event
getting a reference of the username textfield and calling txt.dismissSoftInput() and txt.android.clearFocus()
None of this worked. Is there another way to hide the keyboard when the page is loaded?
Thank you
I guess the username field is either textview or textfield. If so, try this on loaded callback:
var myTextview = page.getViewById("myTextView");
myTextView.dismissSoftInput();
So I ended up implementing a different solution. This may not be the best approach, but it serves its purpose in my case and I wanted to share it for those of you that face a similar scenario.
in page's loaded event I included this code:
if (page.android) {
var un = page.getViewById('username');
var p = page.getViewById('password');
un.android.setFocusable(false);
p.android.setFocusable(false);
setTimeout(function () {
un.android.setFocusableInTouchMode(true);
p.android.setFocusableInTouchMode(true);
}, 300);
}
The key here is the setTimeout function (Thanks Emil Oberg for pointing me to the right direction). As far as I understand, here is what is happening:
The page loads and we call setFocusable(false) on the only 2 text fields to prevent Android from setting the focus on them
Then we wait 300ms to allow Android to do its initialization
When the timeout executes, call setFocusableInTouchMode(true) to allow the fields to gain focus.
At this point the page is loaded without any fields to be in focus and with the keyboard hidden. If the user taps any of the fields the keyboard will appear and they can proceed to log in as usual.
As I mentioned, this may not be the best, or correct, approach, but works for me. Hope this can save someone the time to research the issue.
You want to clear the focus of the field in the loaded callback:
var searchBar = page.getViewById('my-search-bar-id');
if (searchBar.android) {
searchBar.android.clearFocus();
}
What about combining both tips above?
onClear(args) {
const searchBar = <SearchBar>args.object;
if (isAndroid && searchBar.android != undefined){//avoid random unpleasant error
setTimeout(() => { // the key here was this timeout
searchBar.android.clearFocus();
}, 1)
}
}

Firefox add-on triggers code in each open window

I have a Firefox add on that displays a pop-up when it sees a certain response header. This works fine when I have a single window. However, when I have multiple windows open, and one of the tabs in a window triggers the pop-up code in my add-on (due to the presence of said header) I get a pop-up in each of my open windows. For example, if I have 3 windows open, I get 3 different pop ups, one for each windows. Is this the default behavior, and is there an easy in-built way to fix this using their SDK.
Edit:
I have the following code:
Util.requestBlock(httpChannel) {
/*load response headers here*/
if (responseHeaders.includes("header_xyz"))
alert("show popup");
}
Util.monitor = function(w) {
this.obsService = Components.classes['#mozilla.org/observer-service;1'].getService(Components.interfaces.nsIObserverService);
this.obsService.addObserver(this, 'http-on-examine-response', false);
}
Util.monitor.prototype = {
'observe': function(subject, topic, data). {
if (topic == 'http-on-examine-response'). {
var channel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
var block_response = new Util.RequestBlock(channel);
}
},
};
The Util.monitor adds an observer. Whenever a response is received, the "Observe" function is called.
var windows = require("window-utils");
for (window in windows.browserWindowIterator)
doToWindow(window);

map keyboard keys with mootools

I am looking to make the enter key behave exactly like the tab key on a form.
I am stuck on the fireEvent section.
var inputs = $$('input, textarea');
$each(inputs,function(el,i) {
el.addEvent('keypress',function(e) {
if(e.key == 'enter') {
e.stop();
el.fireEvent('keypress','tab');
}
});
});
How do I fire a keypress event with a specified key? Any help would be greatly appreciated.
this will work but it relies on dom order and not tabindex
var inputs = $$('input,textarea');
inputs.each(function(el,i){
el.addEvent('keypress',function(e) {
if(e.key == 'enter'){
e.stop();
var next = inputs[i+1];
if (next){
next.focus();
}
else {
// inputs[0].focus(); or form.submit() etc.
}
}
});
});
additionally, textarea enter capture? why, it's multiline... anyway, to do it at keyboard level, look at Syn. https://github.com/bitovi/syn
the above will fail with hidden elements (you can filter) and disabled elements etc. you get the idea, though - focus(). not sure what it will do on input[type=radio|checkbox|range] etc.
p.s. your code won't work because .fireEvent() will only call the bound event handler, not actually create the event for you.
Take a look at the class keyboard (MooTools More).
It can fire individual events for keys and provides methodology to disable and enable the listeners assigned to a Keyboard instance.
The manual has some examples how to work with this class, here's just a simple example how I implemented it in a similar situation:
var myKeyEv1 = new Keyboard({
defaultEventType: 'keydown'
});
myKeyEv1.addEvents({
'shift+h': myApp.help() // <- calls a function opening a help screen
});
Regarding the enter key in your example, you have to return false somewhere to prevent the enter-event from firing. Check out this SO post for more details.

Resources