I'm looking for different methods of injecting JavaScript into a WebView (in Cocoa).
I am trying to inject some javascript into the <head>
tag of a HTML file that has been loaded into the WebView.
The following method doesn't work for me. It seems to only work with very simple JavaScript with no nested brackets (from what I have tested):
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"var script = document.createElement('script');"
"script.type = 'text/javascript';"
"script.text = \"some simple JavaScript"
"}\";"
"document.getElementsByTagName('head')[0].appendChild(script);"]];
Are there any other ways of doing this with more complicated JavaScript / jQuery functions?
The full code I am trying to inject is as follows:
function submitFormForTime(time){
$(\".t_h\").each(function(i, obj) {
if ($(this).text() != time) return;
$(this).parent().find(\"form\").each(function(i, obj){
obj.submit();
});
});
}
You can't use jQuery to add <script>
tags. This has been asked many times. See:
You can do it with browser built-in functions, BUT:
Would it work to just assign your function to a variable on your page and then evaluate it? Something like:
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
// add function to page:
NSString * js = @"myFunction = function(){ return \"success!\"; }" ;
[ webView stringByEvaluatingJavaScriptFromString:js ] ;
// execute newly added function:
NSString * result = [ webView stringByEvaluatingJavaScriptFromString:@"myFunction();"] ;
NSLog(@"result=\"%@\"", result) ;
}
update explicit examples:
You should use my above example as a template!
Anyway, there's 2 parts to the process... The Javascript part and the Objective-C part. At the Javascript level, you are doing this:
// assign a function to the variable "someFunction":
var someFunction = function(){...};
// call the function in the variable "someFunction":
someFunction();
You can also do it without assigning the function to a variable, for example, if you don't care about referring to the function in the future. Doing it without a variable and using an anonymous function looks like this:
( function(){...} )() ;
i.e. instead of doing var A = <the function>; A();
you are doing (<the function>)();
Finally, if your anonymous function takes arguments, like yours does, the pattern looks like this:
( function(var0, ..., varN){...} )(arg0, ..., argN);
Using that as a template for your code, your JS ends up like:
( function(time) {
$(\".t_h\").each(function(i, obj)
{
if ($(this).text() != time) return;
$(this).parent().find(\"form\").each(function(i, obj) {
obj.submit();
});
});
})( 123.456 );
So, that's what you want the web view to execute... That's the code we pass to the webview. But you have to build that string in your Obj-C program, with the "complication" of inserting the current time argument (123.456
in the above code).
It looks like this:
NSString * jsTemplate =
@"( function(time) {"
@" $(\".t_h\").each(function(i, obj) {"
@" if ($(this).text() != time) return;"
@" $(this).parent().find(\"form\").each(function(i, obj) {"
@" obj.submit();"
@" });"
@" });"
@" })( %g );" ;
NSString * js = [ NSString stringWithFormat:jsTemplate, 123.456 ] ;
NSString * result = [ webView stringByEvaluatingJavaScriptFromString:js ] ;
I think I've written enough now :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With