iPhone UIWebView local resources using Javascript and handling onorientationChange
I'm trying to server HTML Javascript and CSS content from an iPhone application's local resources, and I'm having trouble handling onOrientationChange events and including external Javascript.
I seem to be able to link in CSS properly but not javascript. I'm trying to use the following example of handling onOrientationChange (How to build an iPhone website) but I'm serving the webpage from my app's NSBundle mainBundle.
I tried attaching a javascript function to body.onorientationchange and to window.onorientationchange but neither work when served from UIWebView locally (or remotely), but it works if I'm using the iPhone Safari.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>How to build an iPhone website</title>
<meta name="author" content="will" />
<meta name="copyright" content="copyright 2008 www.engageinteractive.co.uk" />
<meta name="description" content="Welcome to engege interactive on the iPhone!" />
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;">
<link rel="apple-touch-icon" href="images/template/engage.png"/>
<style type="text/css">
@import url("iphone.css");
</style>
<!--
<script type="text/javascript" src="orientation.js"></script>
-->
<script type="text/javascript">
function updateOrientation(){
try {
var contentType = "show_normal";
switch(window.orientation){
case 0:
contentType = "show_normal";
break;
case -90:
contentType = "show_right";
break;
case 90:
contentType = "show_left";
break;
case 180:
contentType = "show_flipped";
break;
}
document.getElementById("page_wrapper").setAttribute("class", contentType);
//alert('ORIENTATION: ' + contentType);
}
catch(e) {
alert('ERROR:' + e.message);
}
}
window.onload = function initialLoad(){
try {
loaded();
updateOrientation();
}
catch(e) {
alert('ERROR:' + e.message);
}
}
function loaded() {
document.getElementById("page_wrapper").style.visibility = "visible";
}
</script>
</head>
<body onorientationchange="updateOrientation();">
<div id="page_wrapper">
<h1>Engage Interactive</h1>
<div id="content_left">
<p>You are now holding your phone to the left</p>
</div>
<div id="content_right">
<p>You are now holding your phone to the right</p>
</div>
<div id="content_normal">
<p>You are now holding your phone upright</p>
</div>
<div id="content_flipped">
<p>This doesn't work yet, but there is a chance apple will enable it at some point, so I've put it in anyway. You would be holding your phone upside down if it did work.</p>
</div>
</div>
</body>
</html>
The answer can be traced from the warning I was getting in XCode:
warning: no rule to process file '$(PROJECT_DIR)/html/orientation.js' of type sourcecode.javascript for architecture i386
XCode setup *.js javascript as some type of source code needed to be compiled in the application when I wanted to include it as a resource so I solved it by doing 2 things.
- Select .js file and in the "Detail" view unselect the bullseye column indicating it is compiled code
- In the "Groups & files" view expand the "Targets" tree and expand the application then go to "Copy Bundle Resources" and drag the *.js files into it
The Apple dev forums has a posted solution:
- UIWebView and JavaScript
It appears that you are getting bit by the "Xcode thinks that .js are things to be compiled" feature. Basically, Xcode thinks that the script should somehow be run or compiles, so marks it as part of the source code. Source code, of course, is not copied into the resources.
So you need to do two things - select the .js file in your project, and turn off the checkbox that indicates that it is compiled (the "bullseye" column). If you don't do this, you'll get a warning in your build log about being unable to compile the file (which should be your first warning - always try to figure out and and correct any and all warning that appear in your build).
Then drag it and drop it in the target's "Copy Bundle Resources".
An answer to your second problem of the onorientationchange handler not being called in UIWebView:
I noticed that the window.orientation property does not work properly and the window.onorientationchange handler does not get called. Most apps suffer this problem. This can be fixed by setting the window.orientation property and calling window.onorientationchange in the willRotateToInterfaceOrientation method of the view controller that contains your UIWebView:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
switch (toInterfaceOrientation)
{
case UIDeviceOrientationPortrait:
[webView stringByEvaluatingJavaScriptFromString:@"window.__defineGetter__('orientation',function(){return 0;});window.onorientationchange();"];
break;
case UIDeviceOrientationLandscapeLeft:
[webView stringByEvaluatingJavaScriptFromString:@"window.__defineGetter__('orientation',function(){return 90;});window.onorientationchange();"];
break;
case UIDeviceOrientationLandscapeRight:
[webView stringByEvaluatingJavaScriptFromString:@"window.__defineGetter__('orientation',function(){return -90;});window.onorientationchange();"];
break;
case UIDeviceOrientationPortraitUpsideDown:
[webView stringByEvaluatingJavaScriptFromString:@"window.__defineGetter__('orientation',function(){return 180;});window.onorientationchange();"];
break;
default:
break;
}
}