At first one tip for your login script: If you use a template literal instead of a normal string, you can embed local variables into the string like this:
let js = `let user = '${user}';
let pass = '${pass}';
document.getElementById('ap_email').value = user;
document.getElementById('ap_password').value = pass;
document.getElementById('ap-claim').value = user;
document.getElementById('ap-credential-autofill-hint').value = user;
document.getElementById('ap-credential-autofill-hint').dataset.claim = user;
document.getElementById('signInSubmit').click();`;
To explain that a little: `
(a backtick) starts and ends the template literal. It can contain line breaks, which are not removed from the resulting string. Using line breaks makes the whole thing easier to read in this case and doesn’t do any harm.
You can also “embed” other things in it with the expression ${expression}
where expression
can be any valid JavaScript.
As an example, you could do something like this:
let world = "world";
console.log(`Hello ${world}!`);
which would write Hello world!
to the console.
In the example of writing JavaScript into a string, we need to make sure that it is valid javascript.
If you write
let user = "Eric";
let js = `let user = ${user}`
and evaluate that with a WebView, it won’t work, because the JavaScript you pass to the WebView is let user = Eric;
. The script searches for a variable called Eric
which of course doesn’t exist in the scope of the webpage. To fix this we need to wrap the embedded value in a string like (notice the '
around ${user}
)
let user = "Eric";
let js = `let user = '${user}'`
Now to your last question: to return somthing from a script inside a WebView you can use any one line as the last line in your script:
usd;
return usd;
If you run the script asynchronous (evaluated with v.evaluateJavaScript(js, true)
(the second parameter is true
)), you actually have to pass the value to the completion()
function: completion(usd)
. This is all done inside the script you pass to the WebView.
Note that you can only return strings, numbers and booleans from the WebView. If you want to return an object, you can use one of the lines
JSON.stringify(usd);
return JSON.stringify(usd);
completion(JSON.stringify(usd)); // when the script is executed asynchronously
as the last line in your script. To get back the object in Scriptable you would use let result = JSON.parse(await v.evaluateJavaScript(js));
So a complete example would be:
let user = 'Eric';
let pass = '123';
let v = new WebView();
await v.loadURL('<your URL>');
let js = `let user = '${user}';
let pass = '${pass}';
document.getElementById('ap_email').value = user;
document.getElementById('ap_password').value = pass;
document.getElementById('ap-claim').value = user;
document.getElementById('ap-credential-autofill-hint').value = user;
document.getElementById('ap-credential-autofill-hint').dataset.claim = user;
document.getElementById('signInSubmit').click();`;
await v.evaluateJavaScript(js);
await v.waitForLoad();
js = `
let usd = document.getElementsByClassName('royalities')[0]
.getElementsByTagName('currency-summary-sold-USD')[0]
.innerText;
return usd;`;
const result = await v.evaluateJavaScript(js);
// use result in the widget
If you want to use this script in a widget, don’t forget to remove the code that presents the WebView because that won’t work in the widget. It will throw an error and therefore prevent all other code from running.