Home > Tutorials > UIWebView – Calling Javascript from iOS with passing parameters … Tutorial

UIWebView – Calling Javascript from iOS with passing parameters … Tutorial

Right now I am working on a project for my company which has to display a lot of content, that is delivered in the XML format and consists of small chunks of HTML formatted text-code.

The only way on iOS to display HTML is to use the UIWebView and so I had to write some small Javascript code which can be called to display the content. It has to be dynamic, as the content is sorted by chapters and the user can navigate through a tree structure to display only relevant content.

So what I did was, parsing the XML and than writing everything into Core Data (btw. Core Data is AWSOME!… the speed, the usability.. incredible). With Core Data I do the sorting and when the user opens content, I load my local HTML, which does actually nothing but tell the browser where the .JS files are.

The reason why I write this tutorial is because I couldn’t find a good one on the web that covers that topic which my requirements (.JS files, parameter passing from Objective C to JS)

Btw: this is not finished code , it works but is rough to get the basic system to work.

<html>

<head>

<meta http-equiv=“content-type”content=“text/html;charset=utf-8″ />

<title>DisplayContent</title>

<style>

</– th, td { vertical-align: top; } –>

</style>

<script src=“displayContent.js”></script>

</head>

<body>

</body>

</html>

The JS File looks like this:

function textNodeWithColorAndSize(text, rgb, size, font){

    var textNode=document.createTextNode(text);

    var font=document.createElement(“font”);

    font.style.color=rgb;

    font.style.fontSize=size;

    font.appendChild(textNode);

    return font;

}

function printHeadOfTable(code, headline) {

    var body = document.getElementsByTagName(“body”)[0];

    var table     = document.createElement(“table”);

    var tableBody = document.createElement(“tbody”);

    var row = document.createElement(“tr”);

    for (var i = 0; i < 3; i++) {

        var cell = document.createElement(“td”);

        var cellText;

        if (i==0){

            cell.width=40;

            cellText=textNodeWithColorAndSize(code, “#FF3344″, “12px”, “font”);

        } else if (i==1) {

            cellText=textNodeWithColorAndSize(headline, “#000000″, “18px”, “font”);

        } else {

            cellText=textNodeWithColorAndSize(“[E-Mail Button]“, “#555555″, “12px”, “font”);

        }

        cell.appendChild(cellText);

        row.appendChild(cell);

    }

    tableBody.appendChild(row);

    table.appendChild(tableBody);

    table.style.marginLeft=20;

    body.appendChild(table);

}

function resize(){

    var frames=document.getElementsByTagName(“div”);

    for (var i=0;i<frames.length;i++){

        frames[i].style.width=“94%”;

    }

}

function printBodyOfTable(bodyString){

    var body = document.getElementsByTagName(“body”)[0];

    var frame=document.createElement(“div”);

    frame.innerHTML=bodyString;

    frame.style.width=“94%”;

    frame.style.marginLeft=20;

    body.appendChild(frame);

}

So, fine enough. Resize does resize all elements <div> to 94% of the web view browser. This is important because of rotation.

printBodyToTable( … ) and printHeadToTable ( … ) are functions to print content.

So, when you load up now the webpage nothing appears of course. Thats why we have to call the JS from our Objective C code. This looks like this:

The array assets is passed from the fetchedResults.

-(void)loadWebViewWithAssets: (NSArray **const)assets{

    [self setWebViewFrame:CURRENT_ORIENTATION()];

    @autoreleasepool {

        _assetArray=[[NSArray alloc]initWithArray:*assets];

        NSURL *file = [NSURLfileURLWithPath:[[NSBundle mainBundle]pathForResource:@”contentView”ofType:@”html”]];

        NSURLRequest *urlRequest=[[NSURLRequest alloc]initWithURL:file];

        [self.webView loadRequest:urlRequest];

        [urlRequest release];

    }

}

So this loads our basic html. Now when the webView is done loading, we are free to call our Javascript functions.

I think it is a bit a pity, that the JS Script methods ONLY work AFTER the web view finished its loading. It would be cool to do that beforehand but well.. lives a b**** sometimes :-)

Code:

(Asset and Content are Core Data entities.)

The abort calls are there for debugging purposes.

-(void)webViewDidFinishLoad:(UIWebView *)webView{

     for (int i=0;i<[_assetArray count];i++){

         Asset*asset=[_assetArray objectAtIndex:i];

         Content*content=asset.content;

         if (!content){

             dbgAbort();

         }

         NSString *jsPrintHeadOfTable=[[NSString alloc]initWithFormat:@”printHeadOfTable(\”%@\”, \”%@\”)”, asset.at_code, asset.at_title];

         NSString *jsPrintBodyOfTable=[[NSString alloc]initWithFormat:@”printBodyOfTable((\”%@\”))”, content.at_content];

         if (!jsPrintBodyOfTable){

             dbgAbort();

         }

         [self.webView stringByEvaluatingJavaScriptFromString:jsPrintHeadOfTable];

         [self.webView stringByEvaluatingJavaScriptFromString:jsPrintBodyOfTable];

         [jsPrintHeadOfTable release];

         [jsPrintBodyOfTable release];

     }

     [_assetArray release];

}

So, you see, we are even able to pass parameters to our Javascript which is incredible awesome. The same webView method is able as well to retrieve values from the javascript by capturing the NSString return value. But there a lot of tutorials out there for this.

Ah yeah, and is very important that you prepare your parameters. content.at_content for example is a complete HTML formatted text. Before you pass it you have to make sure that there are no _ ” _ characters in it (replace them with _ ‘ _  . Now newline characters, no carriage return etc.. Just to tell you :-) Took me some while to get the idea. ;-)

From this point on we can now call the stringByEvaluatingJavaScriptFromString method wherever and whenever we like.. Cool huh?

Yeah, this was my first tutorial and I hope it helped ..

Greetings

Markus

  1. No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: