Problem
I'm setting text-field values on a form via Javascript (in Chrome Console). But when I submit the form, it is using the prior values.
Setup / testcase
I am writing a Javascript function to set the date-range on a TradingView chart. Javascript is run from Chrome console (or as a snippet).
Here's the setup:
I open https://www.tradingview.com/chart/?symbol=BINANCE:BTCUSDTPERP in an incognito tab (reproducible testcase etc.)
In the 'TimeInterval' dropdown (top left, to the right of the symbol (here: BTCUSDTPERP)) I select 1 minute. This is necessary (see below).
- I click the GoTo icon to the right of the 'TimeIntervals' tray (which is under the chart)
- I click 'Custom Range' tab on the popup
(Note that if I had not selected something like '1 minute' for the time-granularity, those 2 time boxes would be greyed out).
Now my challenge is to use Javascript to fill in those 4 input boxes and hit the GoTo button.
I can set text on the input boxes with:
$($('#overlap-manager-root > div input')[0]).val(startDate);
$($('#overlap-manager-root > div input')[2]).val(endDate);
$($('#overlap-manager-root > div input')[1]).val(startTime);
$($('#overlap-manager-root > div input')[3]).val(endTime);
... and click the 'goto' button with:
$('#overlap-manager-root > div button')[1].click();
The problem is that the values I injected are not used.
I don't even need to write code to replicate the problem.
I can just mauaally edit the value of one of the input-boxes in Chrome DevTools and click the 'GoTo' button, and I get the same thing.
So the question is: How to force the form to "update" with the new input-box values before submitting it?
Approaches
1 - first try
> u = $('#overlap-manager-root > div input')[1]
> u
<input ... value="15:00">
> u.val('16:00')
> u.value
'16:00'
> // And it is showing '16:00' in the inputbox in the browser window
> // but ...
> u
<input ... value="15:00">
> // WAAAT?
> u.dispatchEvent(new Event('change'))
> u
<input ... value="15:00">
The webpage is now showing 16:00, u.value gives '16:00', but dumping u to console, it is still showing the initial '15:00'.
This is very confusing.
2 - second try
u = $('#overlap-manager-root > div input')[1]
<input ... value="03:00">
v = $('#overlap-manager-root > div input')[3]
<input ... value="19:00">
> u.focus()
undefined
> u.value = '04:00'
'04:00'
> u.dispatchEvent(new Event('change',{ bubbles: true }))
true
> u.blur()
undefined
> v.focus()
> u
<input ... value="03:00">
3 -- third try
> u = $('#overlap-manager-root > div input')[1]
> u
<input ... value="15:00">
> $(u).attr('value', '16:00');
> u
<input ... value="16:00">
So the change can be seen in the DOM, webpage and also on the console. So, one step closer.
But when I hit the 'GoTo' button, I can see that '16:00' resetting to its old '15:00' value a moment before the form disappears.
I've tried code-injecting keystrokes, code-clicking the input box, many other attempts.
History / A/B-problem
Initially I tried to track down the API function that executes when the submit button is pressed -- that would be a cleaner solution. But that rabbitholed and I gave up on that approach.
Original code
Code below automates everything (except for setting the time-interval to 1-minute, which still needs to be done manually).
async function goToDateRange(startDate = '2022-02-01', startTime = '14:00', endDate = '2022-02-03', endTime = '15:00') {
console.log(startDate, startTime, endDate, endTime);
function delay(func, ms) {
return new Promise(res => {
setTimeout(() => {
func();
res();
}, ms);
});
}
function clickDivElement(attr, value) {
var divs = $('div');
divs.each(function(idx) {
var d = $(divs[idx]);
if (d.data()[attr] !== value) {
return;
}
d.click();
});
}
clickGoTo = () => clickDivElement('name', 'go-to-date');
clickCustomRange = () => clickDivElement('value', 'CustomRange');
clickGoToButton = () => $('#overlap-manager-root > div button')[1].click();
await delay(clickGoTo, 500);
await delay(clickCustomRange, 1000);
// Set the values of the start date and end date
$($('#overlap-manager-root > div input')[0]).val(startDate);
$($('#overlap-manager-root > div input')[0]).trigger('click');
$($('#overlap-manager-root > div input')[2]).val(endDate);
$($('#overlap-manager-root > div input')[2]).trigger('click');
// Set the values of the start time and end time
$($('#overlap-manager-root > div input')[1]).val(startTime);
$($('#overlap-manager-root > div input')[1]).trigger('click');
$($('#overlap-manager-root > div input')[3]).val(endTime);
$($('#overlap-manager-root > div input')[3]).trigger('click');
await delay(clickGoToButton, 3000);
};