UIWebView
has very few instance methods. One of them is
stringByEvaluatingJavaScriptFromString, which very powerful and
unfortunately poorly documented. (This is literally the extent of
Apple's explanation: "Returns the result of running a script.")
Let's explore this mysterious method with a couple of examples.
A trivial example of how to use stringByEvaluatingJavaScriptFromString is to get the title of the HTML document:
NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
You would typically place this line of code in webViewDidFinishLoad.
This technique is not limited to one-liners, or accessing simple
properties. Here's an example of two lines of JavaScript code executed
in order, as you would expect:
[webView stringByEvaluatingJavaScriptFromString:@"var field = document.getElementById('field_2');"
"field.value='Multiple statements - OK';"];
You can also call JavaScript functions this way. And if you want to
call a JavaScript function that does not already exist in the web page
that you're downloading, you can "inject" it yourself with this
technique:
[webView stringByEvaluatingJavaScriptFromString:@"var script = document.createElement('script');"
"script.type = 'text/javascript';"
"script.text = \"function myFunction() { "
"var field = document.getElementById('field_3');"
"field.value='Calling function - OK';"
"}\";"
"document.getElementsByTagName('head')[0].appendChild(script);"];
[webView stringByEvaluatingJavaScriptFromString:@"myFunction();"];
In essence I'm using Objective C to create a string which represents
JavaScript which which when executed adds a JavaScript function to the
HTML DOM. Apologies for the multiple meta levels... Let me try to
untangle this line by line.
Line 1 : First we create a <script> element using JavaScript.
Line 2 : Set the type of the <script> element to text/javascript.
Line 3-6 : Set the content of the <script> element to the JavaScript function that you want to inject.
Line 7 : Add the new <script> element as a child to the <head> element of the HTML DOM.
Line 9 : Call the new JavaScript function.
Bonus tip: You can break up NSString constants over
multiple lines in Xcode for increased readability. Just end the line
with a double-quote character and begin the next line with a
double-quote character. At compile time these lines will be joined into
one string. So the string that begins with "var script" on Line 1 is
one continuous string ending with "appendChild(script);" on Line 7.
Although it's not critical for the discussion above, here's the HTML that the example JavaScript refers to:
<html>
<head>
<meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0"/>
</head>
<body>
<p>This is the UIWebView</p>
<form>
<input id="field_1" type="text" name="value" /><br/>
<input id="field_2" type="text" name="value" /><br/>
<input id="field_3" type="text" name="value" /><br/>
</form>
</body>
</html>
You can use this generic technique to add JavaScript to any web page
that you're downloading and displaying in a UIWebView. The technique
and the possibilities are similar to what you can do with the Greasemonkey plugin for Firefox.
|