UIWebView vs WebView Javascript Injection - javascript

Im trying to execute javascript on iPhone by stringByEvaluatingJavaScriptFromString,
i made script
function execute() {
//dosent matter
alert('works');
}
execute();
This script works fine while using in developer console in safari.
But this way :
[self.webView1 stringByEvaluatingJavaScriptFromString:#"javascript: function execute() { alert('works');}execute();"];
Dosent work, i dont see alert, i tried also without "javascript:"
Thats confusing because im using stringByEvaluatingJavaScriptFromString with succes but without using function declaration.
[self.webView1 stringByEvaluatingJavaScriptFromString:#"alert('check');"];
works fine

If anyone is looking for answer, i have noticed that some functions could not work properly without putting them in file.js and then execute by using:
- (void)injectJavascript:(NSString *)resource {
NSString *jsPath = [[NSBundle mainBundle] pathForResource:resource ofType:#"js"];
NSString *js = [NSString stringWithContentsOfFile:jsPath encoding:NSUTF8StringEncoding error:NULL];
[self.webView1 stringByEvaluatingJavaScriptFromString:js];
}

Related

WKWebview's javascript call returns nil

I'm trying to migrate from using a UIWebview to a WKWebview, and I need to invoke various Javascript functions that live in the webview.
In the UIWebview I have no trouble doing this, but the WKWebview throws an WKErrorDomain Error 4 for any and all calls. I thought it might be a race condition where I was calling functions that didn't exist in the DOM yet, but I added a debug statement to make those same calls once the page loaded and they're not working. I even did a 'document.body.innerHTML' which returned nil when there's clearly content being displayed in the webview.
The twist is that when inspecting the web code via Safari Web Inspector, everything works well and all calls work.
Why and how could this be? I do initialize the WKWebView with a WKWebViewConfiguration so that it'll share cookies across different webviews, so there might be something there, but I'm stumped.
This is how i initialize the WKWebView
WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init];
config.processPool = [[WKProcessPool alloc] init];
WKUserContentController* userContentController = WKUserContentController.new;
WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource: #"document.cookie = 'cookie1=value1; domain=blah; path=/;';" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[userContentController addUserScript:cookieScript];
config.userContentController = userContentController;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0,0,50,50) configuration:config];
Here's a debugging statement where I log the document's innerHTML into the console log, which prints (nil) instead of the HTML.
NSLog(#"%#", [self.webView evaluateJavaScript:#"document.body.innerHTML" completionHandler:nil]);
WKWebView executes JS async unlike UIWebView; You cannot print like how you are doing..
Try this
[self.webView evaluateJavaScript:#"document.body.innerHTML" completionHandler:^(id result, NSError *error) {
NSLog(#"Error is %#",error);
NSLog(#"JS result %#" ,result);
}];

Load JS Function stringByEvaluatingJavaScriptFromString with IOS

I have a simple javascript function with two variables for the geolocation. I need to pass two variables that I already have in my iOS application to this javascript function.
When I send the code via console in the browser everything is OK:
geoCallBackSuccess({coords:{'longitude':9.598470,'latitude':50.903697}})
Is my code correct?
In the simulator I see no effect...
NSString * param = #"{coords:{'longitude':9.598470,'latitude':50.903697}}";
NSString * jsCallBack = [NSString stringWithFormat:#"geoCallBackSuccess(%#)",param];
NSLog(#"viewDidLoad - jsCallBack: %#", jsCallBack);
[self.offerUrl stringByEvaluatingJavaScriptFromString:jsCallBack];
Log:
viewDidLoad - jsCallBack:
geoCallBackSuccess({coords:{'longitude':9.598470,'latitude':50.903697}})
For example, this works for me:
[self.offerUrl stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"anzeige\").innerHTML=\"Hello World\";"];
I want to do the same as I do in Android:
#java...
public void getLocation() {
// magic
if (locationOk) {
webview.loadUrl("javascript:geoCallBackSuccess({coords:{'longitude':9.598470,'latitude':50.903697}})");
} else { webview.loadUrl("javascript:geoCallBackError({code:})");
}
}
Thanks
I believe you are missing just one semi colon in the string, semicolon after function name -
NSString * jsCallBack = [NSString stringWithFormat:#"geoCallBackSuccess(%#);",param];

I would like to export the contents of ios web view as html

I am writing an app for ios to extract information from a webpage, however, the relevant pieces on the page are built by javascript. So when it is loaded by webview, the javascript is executed and the information displays no problem. If I try to load the page into a string by using the following method, the javascript is loaded, but not actually executed, therefore the string has no useful data in it.
NSData *urlData = [NSData dataWithContentsOfURL:[NSURL URLWithString:fullURL]];
NSString *responseString = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
Is there another way besides loading the page into webview and exporting it from there? If not, how do you do that?
I'm not sure if there's another way outside of letting the UIWebView execute the JS and render the page, but if you do end up going this route, you could just grab the HTML of the whole page and pass that to the native end like so:
[dummyWebView stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('html')[0].outerHTML;"];
Listening to the window.load event might be better to know when the page has finished going through all the JS
Good luck!
You set delegate to webView: self.webView.delegate = self; and implement UIWebViewDelegate:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *html = [webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.outerHTML"];
NSLog(#"html1 = %#", html);
// or use
NSString *html2 = [webView stringByEvaluatingJavaScriptFromString:#"document.body.innerHTML"];
NSLog(#"html2 = %#", html2);
}

(iOS) Run bookmarklets in UIWebView?

I am trying to add Readability (a third party app) compatibility with my web browser, and I tracked down a bookmarklet to save a page to Readability:
javascript:(%28function%28%29%7Bwindow.baseUrl%3D%27http%3A//www.readability.com%27%3Bwindow.readabilityToken%3D%27bbRmvVb9nTNRWSVEGb9yrcFP4USUHnTjk2EVWXjn%27%3Bvar%20s%3Ddocument.createElement%28%27script%27%29%3Bs.setAttribute%28%27type%27%2C%27text/javascript%27%29%3Bs.setAttribute%28%27charset%27%2C%27UTF-8%27%29%3Bs.setAttribute%28%27src%27%2CbaseUrl%2B%27/bookmarklet/read.js%27%29%3Bdocument.documentElement.appendChild%28s%29%3B%7D%29%28%29)
however, I can't seem to get it to work. It works in desktop Safari and mobile/iPhone Safari. But both of the methods below do nothing:
[webview stringByEvaluatingJavaScriptFromString: readability];
[webview loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: readability]]];
(readability is a string with the value above)
Is there another method to run javascript bookmarklets that I am unaware of or am I doing something wrong? Help is much appreciated.
Greg
You got this error is because the javascript url is encoded, you should decode the javascript string, (may be you use NSURL to pass the string, so it was encoded by NSURL)
then use the webview stringByEvaluatingJavaScriptFromString, this solution work well
-(void)loadUrl:(NSURL*)url
{
if ([[url scheme] isEqualToString:#"javascript"])
{
NSRange range = [[url absoluteString] rangeOfString:#"javascript:"];
NSString *javaScriptString = [[[url absoluteString] substringFromIndex:range.location + range.length] URLDecodedString];
[self stringByEvaluatingJavaScriptFromString:javaScriptString];
}
else
{
[self loadRequest:[NSURLRequest requestWithURL:url]];
}
}
You probably need to use their API. What you are trying to do is likely prevented for security reasons, and you need to put your own API key in the request.

Call javascript - click() in a WebView from Cocoa Objective-C code

In a MacOS X application, I create a Window containing a WebView.
The WebView is initialized on a html page that contains an anchor:
Go To Google.
I would like to click on that link from another class.
It seems clear that a simple javascript code would do the trick: document.getElementById("myLink").click();
So, I wrote that small objective-c code that should do it:
NSString *cmd = #"document.getElementById(\"myLink\").click();";
id result = [[attachedWebView windowScriptObject] evaluateWebScript:cmd];
if ([result isMemberOfClass:[WebUndefined class]]) {
NSLog(#"evaluation of <%#> returned WebUndefined", cmd)
But I can't make it work.
If anybody has an idea, that would really help.
I think it is nothing todo with webview, but just your javascript.
Does it work if you try it in Safari's console? I wouldn't expect it to as you can only click() input elements (buttons) reliably cross-browser. A JQuery click() should work tho.
see How do I programmatically click a link with javascript?
So here is the solution I used.
Created a file: WebAgent.js containing the following code:
function myClick(id) {
var fireOnThis = document.getElementById(id);
var evObj = document.createEvent('MouseEvents');
evObj.initEvent( 'click', true, true );
fireOnThis.dispatchEvent(evObj);
}
And the following code in my objective-c class
// load cmd.js
NSString *path = #"/code/testagent/WebAgent/WebAgent/WebAgent.js";
NSString *jsCode = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[[self attachedWebView ]stringByEvaluatingJavaScriptFromString:jsCode];
//do the click
NSString * anchorId = #"myId";
NSString *call = [NSString stringWithFormat:#"WebAgent_click('%#')",anchorId];
[[self attachedWebView] stringByEvaluatingJavaScriptFromString:call];
NB: I used this solution to have the JS code in a specific file, as I expect to have more JS code in the future.
Thanks for your help.

Categories

Resources