Trigger JavaScript event when using Google auto fill on Firefox - javascript

I have a form, in which I am disabling the submit button until an user has typed in all the mandatory fields. I was initially using onkeyup to keep a tab on the mandatory fields and enable the button when all the mandatory fields are filled.
But I had users complaining that they filled in the form using AutoFill button on the Google toolbar and the submit button was still disabled.
I fixed this problem in IE by calling the onpropertychange event for each input element and it worked nicely.
But in Firefox, I couldn't find an event which will get triggered when the Google autofill button is clicked.
Help much appreciated.

Thanks for your answers. I had to respond quickly to this issue hence I used the 'setTimeOut()' function to check for mandatory fields and enable the submit button.
$().ready(function() {
CheckRequiredFields();
timeOutRtn = setTimeout("AutoMonitorMandatoryField()", "3000");
});
function AutoMonitorMandatoryField() {
if ($("#btnSave").attr("disabled")) {
CheckRequiredFields();
timeOutRtn = setTimeout("AutoMonitorMandatoryField()", "3000");
}
}
crescentfresh - I will look into the DOMAttrModified event and see if I can get it to work for me.Thanks

Judging from this google toolbar support thread, it seems autofill is not only a huge PITA for developers, but also very difficult to turn off. As of Aug 09 google claims it will honor the autocomplete="off" attribute on the containing form but as of today this feature does not seem to be released yet.
You used to be able to give your input elements non-sensical names (eg name="xx_Address_32423423") to confuse autofill (and thereby effectively disable it), but they've made autofill more "intelligent" by looking at substrings within your element names in order to determine if the field can be autofilled or not (again, judging from complaints in that thread).
In your case, you may as well roll with the punches and find an equivalent for onpropertychange for Firefox. Have a look at the DOMAttrModified event. Specifially, try checking the event.attrName property to see if the value has been changed by autofill:
function realOnChange(event) {
var attrName = event.propertyName || event.attrName;
if(attrName === 'value') {
// etc
}
}
The check for event.propertyName is to stay compatible with your current onpropertychange implementation (if that is even possible).

There's no need to add complex setTimeOut nor setInterval.
Just catch the "change" event of any refillable textbox of the form, go through every refillable field and if it's not empty hide the label

Related

Android Espresso WebView webClick() and webKeys() does not trigger blur event on input field

I'm trying to test a WebView using Espresso. The WebView contains some input fields and a button to continue to the next page. I am able to enter the text in the input fields. After leaving the input field a blur event should get called that performs some additional formatting and validation. However the blur event never gets called and therefore I cannot continue to the next page.
It looks like webKeys() is just injecting some text and that webClick() simply triggers a click event. That's probably why focus never changes and the blur event never gets called. When I physically press the input field myself the event does get triggered and I also see the Android input cursor. When the test case is running I don't see the cursor when text is entered in the input fields.
Is there a way to trigger the blur event programmatically or set focus to an element within the WebView using Espresso?
This is the code I'm using for inserting text.
public static void insertText(String label, String content)
{
onWebView().withElement(findElement(Locator.XPATH, "//div[preceding::span[.='" + label + "']]/input")).perform(clearElement()).perform(webClick())
.perform(webKeys(content));
}
Edit: Added relevant dependencies.
implementation "androidx.test.espresso:espresso-idling-resource:3.2.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.2.0"
androidTestImplementation "androidx.test.espresso:espresso-intents:3.2.0"
androidTestImplementation "androidx.test.espresso:espresso-web:3.2.0"
androidTestImplementation "androidx.test.espresso:espresso-contrib:3.2.0"
You can send any javascript to your Web view.
Every "atom" (webKeys is one of atoms) is just some javascript code, which is sent to your Web View. webKeys atom probably sends keypress events, which does not fire focus/blur/change events in browsers. This is sort of standard browsers behaviour for userspace code dispatched events.
As you can manually trigger keypress, you can trigger focus too etc. You can create and dispatch focus by using:
onWebView().withElement(...)
.perform(SimpleAtom("function(elem) {\n" +
"var e = document.createEvent('Event');\n" +
"e.initEvent('focus', true, true);\n" +
"elem.dispatchEvent(e);}"
))
This should set focus to given element. You are sending function, which is then invocated with yours element as first argument.
You should create some classes like SetFocusAtom or RemoveFocusAtom etc. which will extend SimpleAtom instead of copy&paste whole javascript everywhere.
Be aware:
You can send any javascript to WebView, but you probably don't want. You're free to edit values of currently invisible inputs etc. You're writing UI test, so you could test only visible parts of UI. Original atoms (webClick, webKeys etc.) are checking items for actual visibility. You should everytime use some of original atom or at least match for visibility.
You can do only what is possible in userspace Javascript. There are some limitations. Like current question for example. In projects with complex WebViews, you should consider using UIAutomator or some implementation of Selenium (using chromedriver). Espresso-web is not "acting as real user would". This is not achievable by javascript injections only. Chromedriver is much powerfull in user-like acting.
My answer is not generic. Sometimes you don't need to set focus/blur on inputs. Sometimes you want to send change event for example, which is also not triggered by webKeys.

Appending input element to the DOM in safari transfers focus to the new input

I'm having trouble with the Safari browser, in that it, unlike other browsers including Chrome and Firefox, seems to be transferring focus to a newly created input field when it's appended to the DOM.
The use case is this:
I have a single email input field, into which users type an email (for sending invites). On the keyup event, we append a new email field underneath, to allow them to fill that one out too.
The logic (not exact code) is as follows:
$(document).on("keyup", ".invites input[type='email']", function(){
if("there isn't an empty email field, we'll add one"){
var parent = $(this).closest('wrapper');
var cloned_parent = parent.clone(); // we also remove content and classes here
$('.invites-container').append(cloned_parent);
}
})
It's at this point that the newly created element takes focus in Safari, but not in Chrome or Firefox. This is a problem, as the user may be typing an email address in the first input box, when the focus is snatched away, and all of a sudden they're typing in the second box, and so on. The end result is that multiple email fields are very quickly created just when typing a normal email address.
Strangley, I can't see much documentation around this difference - as appending a new element seems to be a very common function. I'm obviously missing something simple - can anyone advise what might be happening?
Things I've already tried:
Removing all javascript on the page, then cloning just the element
using .cloneNode() (no jquery) in the console - same issue, only in
safari
Removing all site css - same issue in safari
Cloning the input element itself, instead of the parent - same issue
Text inputs instead of email inputs - same issue
Please help!

Capture "auto-suggest" event using JavaScript

I have created a nice cross-browser utility which ensures that form "placeholders" behave in the same way (including IE which does not implement them)
However, this has created a different problem when a user fills a form and the browser helpfully provides an auto-suggest for the remaining fields in the form, eg, for a registration form: You might type your name, and the browser will auto-suggest your surname, email address, postal address, etc...
I don't care what the auto-suggested values are, but I need find a way of capturing "event" on each field so I may hide my implementation of the place holder.
I've had a look at the DOM elements in Chrome to see if the auto-suggest value is stored in a custom attribute, but have been unsuccessful.
Has anyone else seen or experienced this? Does anyone know if its even possible to capture such an event?
NOTE: This issue disappears when the user accepts the auto-suggest, and this becomes an auto-complete, which fires a change event on the fields; so I only need to capture the suggest event
I have produced the following script which "detects" when the fields have become auto-suggested by Webkit:
I am assuming anyone using this knows Underscore and jQuery.
var $form = $('form'),
autoCompleteSetting = $form.attr('autocomplete');
if (_.isUndefined(autoCompleteSetting) || autoCompleteSetting === "on") {
_($form.find('input')).each(function($input){
setInterval(function() {
if ($input.is(":-webkit-autofill")) {
// do your code here to detect the webkit autofill setting
}
}, 100);
});
}
I personally have put the webkit-autofill check into a ternary operator.
Obviously use at your own risk; having these intervals running for every field on your page every millisecond may cause problems for some users!

Using enter to submit a form breaks after input fields are inserted - why and how to fix?

If an HTML form field has focus and you hit enter, the form will be submitted (unless you've done fancy things to bypass that). Weirdly though, if JavaScript adds a field into the form, that enter-to-submit behavior appears to break. For example:
http://jsfiddle.net/SChas/1/
function goose() {
document.getElementById("addhere").innerHTML="<input name=goose value=honk>";
}
function checkForm() {
alert("ok");
}​
--
<form onsubmit="checkForm();">
<input name="duck" value="quack">
<div id="addhere"></div>
</form>
<button onclick="goose();">add a goose</button>
​
(This is a contrived example attempting to be as concise as possible. The original code involved is more modern code with events attached in JavaScript, etc. But this is the simplest code that replicates the issue. Also, it is necessary in the real use case to dynamically modify the form by adding/removing fields.)
Anyway, you'll get a form that has a single field with a value "duck". Click into it and hit enter, and the form will submit (you'll see an "ok" alert and then JSFiddle will tell you not to post!).
However, if you click "add a goose", you get a new field. And now, you cannot hit enter to submit the form.
Why is this happening? I can't find anything about this behavior via google, perhaps I'm using the wrong search terms. But it happens in IE on Windows and Chrome and FF on OSX at least. So it seems like an intentional, perhaps to-specification, behavior. Is it some kind of security protection?
And, is there any way to restore the enter-to-submit behavior on the form once a field is inserted? A way other than to add onkey* events to the input fields?
FWIW, it doesn't seem to matter if the inputs are added via DOM methods (appendChild), or setting the innerHTML, using jQuery or old fashioned JavaScript.
This is because the enter-to-submit behaviour only happens when it's the only input on the form.
You can restore it by putting a input with type=submit on the form, it doesn't even have to be visible.
Check it out: http://jsfiddle.net/SChas/10/

Allow Copy/Paste in a disabled input text box in Firefox browsers

I have a input text box disabled:
<input type="text" name="name" disabled="disabled" />
In IE and in Chrome you can copy and paste the value populated in that input field but in Firefox you cannot.
Firefox does not allow clipboard manipulation through JavaScript for valid security concerns.
Any suggestion? Is there a work around this?
readonly="readonly" will do the job
it should be supported by the major browsers
I don't like using readonly="readonly", ever. It leaves the field focusable and reachable via tab keypress and, if, god forbid, the user hits the backspace key while the read-only field is focused, then most browsers treat it like the user hit the 'back' button and bring up the previously viewed page. Not what you want to see happen when you're filling out a large form, especially if you are using some archaic browser that doesn't preserve the form data when you hit the 'next' button to return to it. Also very, very bad when using some single-page web application, where 'back' takes you to a whole other world, and 'next' doesn't even restore your form, much less its data.
I've worked around this by rendering DIVs instead of input fields when I need the field disabled (or PRE instead of a textarea). Not always easy to do dynamically but I've managed to make fairly short work of it with AngularJS templates.
If you have time, head over to the Mozilla Bugzilla and ask them to fix it.
tl;dr: Support for selecting and copying text in a disabled field is unreliable; use the readonly attribute or a non-input element, such as a <span> instead, if this functionality is necessary. Use JavaScript to modify the behavior of the readonly input to prevent unwanted behavior such as going back a page when someone hits the backspace key while the readonly input has focus.
*UPDATE: 2018.12.24
The spec has changed since this answer was originally posted (thanks to Wrightboy for pointing this out); it now includes the following caveat with regards to disabled fields:
Any other behavior related to user interaction with disabled controls, such as whether text can be selected or copied, is not defined in this standard.
— https://html.spec.whatwg.org/multipage/input.html#the-readonly-attribute
Disabled fields still cannot receive focus nor click events.
Because the standard does not define whether or not text within disabled controls can be selected or copied and because at least one major browser doesn't support that functionality, it's probably best to avoid relying on that behavior.
Original Answer
This is the expected behavior for a disabled field (as of the original date of this answer). IE and Chrome are being generous, but Firefox is behaving appropriately.
If you want to prevent the user from changing the value of the field, but you still want them to be able to read it, and/or copy it's value, then you should use the readonly attribute. This will allow them to set focus to the element (necessary for copying), and also access the field via the tab button.
If you are concerned about a user accidentally hitting the backspace button inside the readonly field and causing the browser to navigate back a page, you can use the following code to prevent that behavior:
document.addEventListener("DOMContentLoaded", function() {
var inputs = document.querySelectorAll('[readonly]');
for(var i=0; i < inputs.length; i++){
inputs[i].addEventListener('keydown', function(e){
var key = e.which || e.keyCode || 0;
if(key === 8){
e.preventDefault();
}
})
}
});
<input value="Hello World" readonly=readonly />
As quick answer, one can have another not disabled element to enable + copy/paste + redisable your input text, like this:
$('#btnCopy').click(function(){
$('#txtInputDisabled').removeAttr('disabled');
$('#txtInputDisabled').select();
document.execCommand("copy");
$('#txtInputDisabled').attr('disabled','disabled');
});
You can se my complete response to this post
Refer to my post to the same question. It does the following:
Makes the textbox just like readonly without using the readonly attribute on the input tag, but will honor tab index and set focus
Supports all clipboard functions win and mac with mouse or keyboard
Allows undo, redo and select all
Restrict HTML input to only allow paste
You can accomplish this in share point by utilizing the contenteditable attribute as follows with jquery.
$("#fieldID").attr("contenteditable", "false");
This will allow the user to highlight the text and copy it but will not allow them to enter anything in the field.

Categories

Resources