Excel VBA fill textbox with autocomplete in IE11 - javascript

How can I fill a textbox that uses javascript to suggest available entries using Excel VBA? Filling the textbox manually, I would start typing a few letters and a list of available inputs I could choose from will appear below the textbox. I need to click with my mouse or use the arrow keys to navigate to the entry I want in the javascript dropdown box and click enter.
This is the key difference with other regular input boxes. If I simply enter the text in the input box and proceed to the next input box without choosing the entry from the dropdown box, the input does not register. So I cannot simply find the element of the input box and change its value. I believe I need to execute the javascript that activates the dropdown box which I must then select from it.
The HTML code for the input textbox is:
<td id="input2" class="createInputField" colspan="0" valign="middle"
<input value="" id="" name="docTypeDisplay" title="Document Type" size="18" type="text">
<input value="" name="docType" type="hidden">
<input value="" name="docTypeID" type="hidden">
There are 5 event listeners on the first input tag line of the code above - blur, dblclick, focus, keydown and keypress from a javascript. I tried looking up the javascript but it is not readily understandable and is H-U-G-E! So with this limitation in mind, here's what I've tried:
IE.Document.getElementById("input2").getElementsByTagName("input")(0).Value = "Monthly Report"
Set objEvent = IE.Document.createEvent("HTMLEvents")
objEvent.initEvent "change", False, True
IE.Document.getElementById("input2").getElementsByTagName("input")(0).dispatchEvent objEvent
and variations by changing the first argument in objEvent.initEvent to "blur", "dblclick", "focus", "keydown" and "keypress". I don't get any errors and the input does not register.
Then I've tried:
IE.Document.getElementById("input2").getElementsByTagName("input")(0).Value = "Monthly Report"
IE.Document.getElementById("input2").getElementsByTagName("input")(0).FireEvent ("onchange")
and also tried:
IE.Document.getElementById("input2").getElementsByTagName("input")(0).Focus
IE.Document.getElementById("input2").getElementsByTagName("input")(0).Value = "Monthly Report"
IE.Document.getElementById("input2").getElementsByTagName("input")(0).Blur
and nothing has worked.
Can anyone help please? I think I've exhausted google looking for a solution for this.

Using sendkeys, I was able to fill the input box, wait for the suggested input to show up in the dropdown box and then simulate an "Enter" keypress to register the input. I found Application.SendKeys "Enter" didn't work and so I had to improvise. I suspect the "Enter" key may be tied to the Keypress javascript event.
IE.Document.getElementById("input2").getElementsByTagName("input")(0).Focus
Application.SendKeys "Monthly Report"
Application.Wait (Now + TimeValue("0:00:05")) 'Wait for javascript to fire and suggest an input
Application.SendKeys "~" 'This simulates an "Enter" keypress on the first suggested input
This script will fail though if at anytime during the Excel VBA execution I click on another window. I am hoping someone will come along with a more reliable solution.

Y-E-S! I finally found something that worked through trial and error without using SendKeys. Credit to #QHarr to suggest trying combining events, which kept me going in the right direction. So this is what worked for me:
'First fill the input box with text
IE.Document.getElementById("input2").getElementsByTagName("input")(0).Value = "Monthly Report"
'Fire the keypress event to start the javascript to suggest an input
Set objEvent = IE.Document.createEvent("keyboardEvent")
objEvent.initEvent "keypress", True, False
IE.Document.getElementById("input2").getElementsByTagName("input")(0).dispatchEvent objEvent
'Wait for a few seconds for the javascript to complete creating the dropdown box
Application.Wait (Now + TimeValue("0:00:05"))
'Select the first suggested input from the dropdown box. I noticed a new element was created when the dropdown box appeared, which I simulated a click on.
IE.Document.getElementById("suggest_input2").getElementsByClassName("object")(0).Click
Only one more thing I would like to change with this answer before it's perfect, which is to replace the application.wait time with a more robust line. Trying the code below didn't work. Any ideas how I can tell Excel VBA to wait for a javascript to finish loading before proceeding?
While IE.Busy Or IE.ReadyState <> 4: DoEvents: Wend

Related

How can I trigger a JS Events on HTML using another JS script?

I am trying to reverse engineer a work website to allow me to use a JS script no jquery to enter the details for me in a form.
I have saved the HTML on my desktop, pointed all the src files to the right places, now I am creating the script to autofill by using document.getElementById & .click and entering strings into input boxes no problem.
The problem is that there is some kind of Data Validation on one of the boxes in the form of a JS Event, like click, input and Keypress.
This is no problem when I manually type the details in the input boxes no problem, but when JS does this for me it doesn't trigger and doesn't allow me to move on.
Is there another way I can trigger this event without me clicking the input boxes? I can't edit Index.js for reasons.
Input box
<input _ngcontent-c4="" class="input-cust-style-orderForm ng-touched ng-dirty ng-valid" type="text" id="order_id_restrict" placeholder="Enter Reference Number" required="">
It has, Click, Keypress, blur, compositionstart & end, ngmodelchange and there are about 4 other input boxes with the same events.
My code has things like:
//click the first li in the dropdown list
document.getElementsByTagName('input')[0];
document.getElementsByTagName("ul")[0]
.getElementsByTagName("li")[0].click();
var cpName = document.getElementById('cp_name');
cpName.value = 'something something'
Can I trigger events that are already on the website by calling them somehow?

Can't focus back to input field after blur

So I have look at most related link on my problem and can't seems to make it work.
Tried the workaround on this link jquery focus back to the same input field on error not working on all browsers but it didn't work for me.
I have a javascript that evaluate the value of an input field on exit (blur). That works well. The problem is when the value is wrong, I show an alert, delete the content of the field and set the focus back on the faulty field.
There comes the problem. In Firefox, the focus will still go on the other field which I clicked on (triggering the blur() of the previous field).
In IE(11.0.9600) or Chrome(64.0), the alert shows but keeps coming back in some sort of infinite loop. I have to kill the browser.
So here is a VERY truncated version of my HTML:
<!DOCTYPE html>
<html class="OUTPUT WEB CHANNEL_WEB simplex" section="ChargesLinesList" dpi="96" scale="1.0">
<input id="dateBilled" class="myDateField" name="dateBilled" value="2018-01-18" type="text">
<input id="dateBilled" class="myDateField" name="dateBilled" type="text">
<input id="dateBilled" class="myDateField" name="dateBilled" type="text">
and this is my code to validate the value and show the alert:
$(".myDateField").on("blur", function(event){
var myDateFormat = /^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$/;
if(!myDateFormat.test($(this).val())){
alert('Invalid date or format. Make sure you the format his YYYY-MM-DD and the date is valid');
$(this).val("");
$(this).focus();
}
})
The blur event triggers whenever a field loses the focus, but in your case, when someone leaves a field and clicks into another one, blur will fire for the first field, and if that field fails your validation, the focus will switch back to it, causing the other field that the user clicked into to lose the focus and then blur will fire for that field and so on.
Instead, you should be using the change event, which triggers when the focus is lost, but only if the value of the field has changed since it got the focus. This will avoid an infinite loop and .focus() will then work properly.
Also, you can't have multiple elements with the same id and each text box should also have a unique name.
Lastly, your <html> tag is full of attributes that are not valid for HTML. Most of what you are doing there should be accomplished via media queries.
$(".myDateField").on("change", function(event){
var myDateFormat = /^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$/;
if(!myDateFormat.test($(this).val())){
alert('Invalid date or format. Make sure you the format his YYYY-MM-DD and the date is valid');
$(this).val("");
$(this).focus();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="dateBilled1" class="myDateField" name="dateBilled1" value="2018-01-18" type="text">
<input id="dateBilled2" class="myDateField" name="dateBilled2" type="text">
<input id="dateBilled3" class="myDateField" name="dateBilled3" type="text">

How to get Next button on android softkeyboard in place of Go Button in phonegap

I am developing Phonegap application and have many inputs in application form. I am getting Go button on keyboard of android.I want to replace go button with next button. As clicking on Go button (as shown in image) submits form.
In android native we can specify next button in XML but for Phonegap how to specify next button in place of go button.?
Some Samsung devices have by default Next Prev button on top.
By Default there is Go button. I need Next but in Phonegap. is there any plugin for specifying that for android.
Having a "Next" button instead of "Go" is not possible with Android as of now.
Android will always display "Go" button for form input fields. "Go" is basically reflecting the same behavior as of an "Enter" button on a normal browser & keyboard. You can achieve through below code:
if (event.keyCode == 13) {
//Handling "Go" Button to move to next input field
}
OR
If your input fields are more, then data-dependency will be best solution.
If you want to prevent users from submitting the form, you can put required validations on the form using javascript, where you can specify data-dependency inside input field with required, which helps move cursor to a particular field which you specified in data-dependency.
<input type="text" id="first" data-dependency="second" />
<input type="text" id="second" data-dependency="third" />
<input type="text" id="third" />
It move focus to next fields in form until its your last field. Once last field reaches you can allow it to act as enter. So basically Go will keep moving focus to next fields until its your last field & then will submit the form.
Its been said that if have input fields without or outside the form tag means you will get next button as tab button
As far as i know there is no proper solution to get next button instead of go . There are only workarounds do it. Most common one is to capture the 'Go' button as enter key(keycode '13') in javascript and do your thing.
$('selector').on("keydown",function(event){
if (event.keyCode == 9) {
//you got tab i.e "NEXT" Btn
}
if (event.keyCode == 13) {
//you got enter i.e "GO" Btn
}
});
for tab button instead of enter
There has been also sources that already discusses these GO Vs NEXT button
have you tried the attribute enterkeyhint
The enterKeyHint property is an enumerated property defining what action label (or icon) to present for the enter key on virtual keyboards. It reflects the enterkeyhint HTML global attribute and is an enumerated property, only accepting the following values as a DOMString:
'enter' typically indicating inserting a new line.
'done' typically meaning there is nothing more to input and the input method editor (IME) will be closed.
'go' typically meaning to take the user to the target of the text they typed.
'next' typically taking the user to the next field that will accept text.
'previous' typically taking the user to the previous field that will accept text.
'search' typically taking the user to the results of searching for the text they have typed.
'send' typically delivering the text to its target.
If no enterKeyHint value has been specified or if it was set to a different value than the allowed ones, it will return an empty string.
The enterKeyHint property is an enumerated property defining what action label (or icon) to present for the enter key on virtual keyboards. It reflects the enterKeyHint HTML global attribute and is an enumerated property, only accepting the following values as a DOMString:
<main>
<h2>Using the <code>enterkeyhint</code> Attribute</h2>
<p>View this demo on a mobile device. Note the text in the "enter" key on your mobile device's virtual keyboard.</p>
<input type="text" enterkeyhint="Next">
</main>
You can simply use the following logic to let users focus on the next input field. This is a better approach, which I used in my one of the PhoneGap applications, as currently there are no 3rd party plugins which offer such functionality.
x$('#input1').on('keyup', function(e) {
var mEvent = e || window.event;
var mPressed = mEvent.keyCode || mEvent.which;
if (mPressed == 13) {
// On enter, go to next input field
document.getElementById('input2').focus();
}
return true;
});
For whom this may be of use:
I'm working on a react pwa and I was having issues getting the next button to show so users could move from one input element to the next (within the same screen). It turns out that android requires a <form> to be wrapping the input text elements. I did a series of tests:
input texts inside a (no tabindex, no attributes other than type, nothing)
input texts outside a (same as above)
input texts inside a inside a
input texts inside a outside a
Only those inputs inside a get android's default next-next-next-go behaviour where go = last input in the form.
Have you tried using the tabindex parameter on your input fields?
The default action of the keyboard should be to show next if tabindex is detected.
Example:
<input name="first" tabindex="1" /> //should show next
<input name="second" tabindex="2" /> //should show next
<input name="third" tabindex="3" /> //should show go
EditText android:imeOptions= "actionNext"

Making a text field uneditable and not just readonly

When i click on a textfield, i get a dropdown so the user could select a value from the list.
After the user selects the date from the dropdown, he/she could edit the date by even adding characters to it. So i want to find a way to prevent this. I thought of making the field un-editable. So i used readonly but, this prevents the user from clicking and displaying the list. So can someone tell me how can i make the field uneditable.
<input id="datePiccc" type="text" class="dates" />
You can use the below code. This will make the text input field clickable but when the user types in anything, nothing would happen.
document.getElementById('datePiccc').onkeydown = function(e){
e.preventDefault();
}
Fiddle Demo
As pointed out by nnnnnn, onkeydown is a better option than onkeypress as it would stop the delete and backspace key functions.
You could add the below also to your code to nullify Cut and Paste events1. (Note: Not doing anything for Copy as that operation isn't going to change the value of the text field).
document.getElementById('datePiccc').oncut = function(e){
e.preventDefault();
}
document.getElementById('datePiccc').onpaste = function(e){
e.preventDefault();
}
1 I think these should work in all browsers. Currently tested in Chrome 31, Opera 15, IE10 and FireFox 24. (Note: In IE10, there is an x mark which appears on the right side of the input field which when clicked clears the entire field value. Could not find a way around this.)
I'm assuming the text field is being set in javascript. If so, you can use the following line to disable the field:
document.getElementById('datePiccc').disabled=true;
The input will remain as it is and the value from the selection field can also be set.
Disable the input in JQuery as
$("#datePiccc").attr("disabled", true);
And in pure JS
document.getElementById('datePiccc').disabled = true;
May be this can help!

onchange isn't working

I am learning JavaScript through the Head First series book by O'Reilly media, and I just reached a chapter where I have to use the onchange event.
I'm testing using Safari/OS X Lion, Firefox, Chrome, Opera, and IE/Windows, but got the same result.
Given this code:
<html>
<head>
<title>onChange Test</title>
<script type="text/javascript">
function itWorks(){
alert("it works!");
}
</script>
</head>
<body>
<form>
<input type="text" onchange="itWorks();" />
<input type="text" onchange="itWorks();" />
</form>
</body>
<html>
Is it correct to say that the onchange event works whenever we change from one field to another, whether it is activated only by clicking or by using the TAB key?
The onchange event fires when:
Focus leaves the field
if the value has changed since focus was gained
It doesn't matter how focus was lost, and focus doesn't need to move to another field (a link could be focused, or nothing in the document could be, etc).
"we change from one field to another, whether its by clicking or by
using the TAB key" -
Thats onblur.
the event you have coded fires whenever you change the value of the input, then leave the field. EG: Enter something into the field, then press the TAB key.
Your example code works as expected for me.
The behaviors you described is onfocus. onchange executes when the value of the input changes.
If you type something into the field, it should run.
"Just to clarify, the onchange event works whenever we change from one field to another, whether its by clicking or by using the TAB key, right?"
Yes - as long as the value has changed
I'm not sure what the question is tbh - your code works!
I tested it on jsfiddle.net - which is great for learing / testing javascript.
(you should close your html tag btw)...
This is what the HTML5 draft spec says:
The unfocusing steps are as follows:
If the element is an input element, and the change event applies
to the element, and the element does not have a defined activation
behavior, and the user has changed the element's value or its list of
selected files while the control was focused without committing that
change, then fire a simple event that bubbles named change at the
element.
Unfocus the element.
Fire a simple event named blur at the element.
Note that change can fire at other times too. The spec also says:
... any time the user commits a change to the element's value or list of
selected files, the user agent must queue a task to fire a simple
event that bubbles named change at the input element.
And goes on to provide a couple of examples of "committing a change"
An example of a user interface with a commit action would be a File
Upload control that consists of a single button that brings up a file
selection dialog: when the dialog is closed, if that the file
selection changed as a result, then the user has committed a new file
selection.
Another example of a user interface with a commit action would be a
Date control that allows both text-based user input and user selection
from a drop-down calendar: while text input might not have an explicit
commit step, selecting a date from the drop down calendar and then
dismissing the drop down would be a commit action.

Categories

Resources