I run the following code on my IPhone, and log console.log returns null:
let webview = new WebView();
await webview.loadURL("https://google.com");
let dataGets = `
(function() {
var x = document.getElementsByClassName('o3j99');
completion(x[0]);
return;
})();
`
let response = await webview.evaluateJavaScript(dataGets, true);
console.log(response);
But if I run on the browser:
var x = document.getElementsByClassName('o3j99');
console.log(x[0]);
I get: <div class="o3j99 n1xJcf Ne6nSd">…</div>flex<style data-iml="1639526495170"> .
I’m probably showing my ignorance here on more advanced JavaScript, but what is completion(x[0]);, and where is the x[0] element being passed back as a response value to be logged?
The completion function can be used to run async code with WebView.evaluateJavaScript( script, true) and any argument passed to it is returned in Scriptable.
You probably missed that it is in a string that is passed to evaluateJavaScript.
@jacku The element might not exist when Scriptable is executing your javascript code. You can try to add a delay with setTimeout before you query for the element. If this works out, then you can reduce the waiting time and retry until you find the element.
I caught that it’s in the string, but I don’t recall ever coming across the completion function before. I can’t seem to find it through JavaScript documentation searches on Google, or in the Scriptable docs. My Google Fu has obviously deserted me this morning
Presumably you are only ever allowed one completion call per function scope and that is tied directly to the return then for this to work.
I’ve been at this the whole day yesterday, the scriptable app can’t find some elements for whatever reason. I’m in a rush for time too, so this is driving me crazy.
It’s right there in the Scriptable docs. Ok, it’s a bit hidden:
When passing true to the useCallback parameter, evaluation will only complete after the globally available completion function is called. Any value passed to the function, will be carried by the promise returned by evaluateJavaScript.
Yes, plenty a time. But it returns gibberish when I try to find “body” or “html”. On the Shortcurts app the “Run Javascript On” runs my scripts fine, and even running the javascript on mobile mode on my PC it runs fine too.
Yes, it returns gibberish because Scriptable can only transfer primitive values (boolean, string, number) and it serializes any object into JSON. DOM Elements will also be serialized but that won’t give any meaningful result. You have to use .outerHTML on the element.
But that still doesn’t solve the issue that the element is not found. I’ve tried it myself with Scriptable and Shortcuts and both don’t find the element.
I can’t help you any further for now since I don’t know what you are trying to find.
It’s in German but it says that nothing was passed to the Quick Look action
No, it’s because Google feels to have to be funny. I’ve now loaded google.com in mobile mode on my desktop and it returned a completely different HTML tree than in desktop mode. You will get different pages depending on the user agent string the browser is sending.
No, the WebView is totally fine. Google is being funny. Try it with another page e.g. https://duckduckgo.com
let webview = new WebView();
await webview.loadURL("https://duckduckgo.com");
let dataGets = `
(function() {
var x = document.getElementsByClassName('content-wrap--home');
completion(x[0].outerHTML);
return;
})();
`
let response = await webview.evaluateJavaScript(dataGets, true);
console.log(response);
When you run the commands in mobile mode on your desktop, what user agent string are you using? If you are using a Chrome or Firefox to check the HTML using the devtools, do you reload the page after switching to device mode? When I do that, I get a completely different HTML tree for google.com. This is not the case with duckduckgo.com.