Getting Creative with Web Popups

On the surface, you’d think the only use-case for a web popup within an app would be to display an embedded website without your user having to leave your app. While that’s true, with a little creativity there are plenty of other things web popups could be used for. If not, that’s fine too.

In this blog post, we’ll explore some of the various things you can do with web popups, as well as how you can integrate them into your app to do lots of cool things. As they say, the more tools you have in your toolbox, the easier it will be to find a solution to your problem in the future.

Quick API Explanation

To get the “how to” out of the way quickly, here’s what the API looks like for using web popups in Corona:

native.showWebPopup( x, y, width, height, url [, options] )

-- or just...

native.showWebPopup( url [, options] )

So in all actually, if you just want a website to show up (fullscreen), you’d simply call:

native.showWebPopup( "http://www.anscamobile.com/" )

Options is a table (that’s optional) with three possible parameters:

options.baseUrl

options.hasBackground

options.urlRequest

Below is an example of how you would pass an options table using the native.showWebPopup() function:

The options.baseUrl parameter is only used if you’re loading a local HTML file. Below is an example of how you’d load a file called info.html that’s in a sub-folder called “appfiles” in your project’s top-level folder (aka, resource directory):

In all actuality, only the first parameter would be needed in the example above, because *system.ResourceDirectory is the default. Here are the other two things you could assign to the baseUrl parameter:

system.TemporaryDirectory

system.DocumentsDirectory

The options.hasBackground parameter is a simple true or false that determines whether to render the web page with a normal background, or a transparent background. The default is true, that is, the web page rendered normally with an opaque background.

Lastly, the options.urlRequest is a callback (e.g. “listener”) function that will be triggered every time a new URL is requested from that web popup. For example, if the user touches a link on the page within the web popup, the listener function you assigned to the options.urlRequest parameter will be called.

Different sized web popups

You may have noticed the x, y, width, and height arguments that can be passed to native.showWebPopup(). If you don’t set these, by default, the web popup will take up the fullscreen width and height of your device.

If you don’t want the web popup to take up the entire screen, for example, if you want some of your app’s UI to show, or if you want buttons to appear above or below the web popup, then set the x, y, width, and height when you call native.showWebPopup().

It’s important to note that because web popups are actual native elements and not a simulated one, display objects cannot be placed above a web popup, and you cannot do things with it that you could with normal display objects (such as change the x/y properties, set the alpha property, rotate, etc).

And if you haven’t tried it out already, web popups do not currently work in the Corona simulator. You’ll have to either build for the Xcode simulator or for device to see them in action.

Your urlRequest Listener

This is where any magic you intend to happen between your app and the web popup will begin. In a nutshell, this is what goes on in the background when you show a web popup:

In the function above, the listener checks the url that’s being requested (via event.url) for a specific string (“corona:close”), and if it finds it, the function returns false and the web popup closes. Likewise, if there was an error loading the page, the listener has the web popup close.

So in the same example, if the user were to click a link that tried to take them to: corona:close, then the web popup would still close, because the string was found at the 1st character position of the string (hence the “1 == string.find…”). If you changed the line to:

if string.find( event.url, "corona:close" ) ~= nil then

Then you could have “corona:close” anywhere in the URL, even in the middle of a string and it would still execute the block of code. So the example clearly shows how you can detect a specific string within an URL to close the web popup, but you can do much more than just that.

Closing a Web Popup on Command

To close a web popup, you simply call:

native.cancelWebPopup()

And that will close any web popup that’s currently open. You can call this at any time, and is very useful if you have your own button that’s used to unload the web popup, or take you to a different screen—in which the web popup would need to close.

Invisible Background

Another great feature that web popups possess, that’ll really help integrate them into your app is the ability to turn the background “off”, so that it’s transparent… allowing any display objects you’ve created to show through behind it.

You can see an example of this in the open-source Tilt Monster game, in helpScreen.lua. On the Tilt Monster help screen, the help information is a local HTML file that is loaded through a transparent web popup. The result is scrolling, css-styled text over the graph-paper texture that fits in very naturally with the rest of the app.

For Local HTML

If you decide to construct your own HTML files to view with a web popup, there’s an an important meta tag you should add to the <HEAD> section of your HTML file, to ensure things look their best:

Depending on the width of your web app and orientation of your app, you may want to adjust the width section. Adding that meta tag to your pages will ensure the page is zoomed in just the right amount, so your users don’t see tiny text when the web popup first loads.

The Possibilities are Endless

Since web popups use the default browser of your platform to render webpages, they are also compatible with the plethora of open-source JavaScripts available out there as well. Using your own keywords with the URL mapped to other functions within your code, imagine the kind of web + native hybrid apps you can come up with!

And the best part is, the HTML/CSS/JavaScript files can all be completely local (e.g. dropped in your project’s folder so no internet connection is required), or be loaded from a remote location on the web.

You often hear about the advantages of web apps, and the advantages of native apps… so which do you choose? With Corona, you can get the best of both worlds: high performance native cross-platform apps, with whatever kind of web app functionality you need (via web popups).

One problem I’ve noticed with using web pages internally to an app is that it can be difficult (if not impossible) to limit a scrolling page so that you can’t push it half off the top and bottom and have it snap back (like the default behaviour in Safari) – any advice on stopping that?

Albertosays:

It would be really nice if you could get control the display of the gray background/loading indicator and make it invisible/transparent when the webPopup is loading. That way you wouldn’t be able to tell at all that it was a webPopup.

I hope you’ll consider adding a little bit more flexibility in integrating our host app with the DOM. If you have ever worked with the HTMLLoader support in Air you’ll know where I am coming from. Would this be something you guys would consider? It could lead to some really rich hybrid applications, since the current means of tapping into location changes and looking for a URI scheme is a little “hackish”.

Some basic ideas:

1. Event listeners in Lua for common first class dom events (onclick, touchStart, complete etc..) Basically just more extensions to what I am assuming is already a paper-thin wrapper on platform specific WebViews you already have in place.

2. Basic programmatic interaction with DOM elements (innerHTML etc..)

3. Ability to expose a Lua table to the DOM and have it be easily driven from JavaScript code via the window object in JS.

I really think this could be a great way to open up some more scenarios for Corona regarding enterprise (non-game) type applications. I applaud what you guys are doing with your native UI library, but this could be a great compliment. 3rd party libraries like jQuery Mobile and Sencha Touch are innovating rapidly. They could pose a great option for building rich UIs that are completely cross-platform with a native feel.

I’d love to be able to use Corona as my “PhoneGap” since it brings so much more to the “table” …see how I did that

I have weird problem with WebPopups in Android. They work otherwise ok, but when i add urlRequest parameter and assign function for it (function uses system.openURL to open page into fullscreen browser) all graphics turn into black squares. example background image is totally white, and all graphical buttons/assets on top of it, are plain black boxes..

This is quite frustrating. I use 320×48 webpopup to show ad, and when user clicks the ad, Corona should open that assignes URL into fullscreen browser, but now without the urlRequest it opens the url into the same small webpopup.

the web popup is useless in a professional app. Maybe cool for toying around with some local files or an info page from a server that you have control over, but using the web popup for showing external content is a huge risk. Here is why:

– It leaks like hell (try to scroll a page with the app loaded in Instruments)
– Appr. 30 % of visited pages reders nothing => blank
– Resources are not released on close, html 5 audio and video sound will continue to stream

I have bug reported this before, hope for a really quick fix, we’ve waited for a month already, and our 400+ hours invested in a rss and json newsreader app is a total waste of time and money until you fix at least the issue with blank rendered pages.

A thought occurred to me… Couldn’t the app save the HTML into a database instead of a file? And if so, the app could attempt to pre-load any “updated” html from a server someplace on startup, then store it in the database to be used later. This way you could provide a mechanism to constantly updated content, yes?

Just remember to test for the base URL (i.e., “www.apple.com” and not “www.apple.com/subfolder”), because as it states on the bottom of the “network.setStatusListener” page, there is a bug when subfolders are checked. I just tested on simulator, and it seems to work fine. So if the connection exists, load the online version, if not load the local version. Put your local html and CSS files in the same folder as “main.lua.” I don’t know if there are any “folder problems” with html/CSS like there is with having to put all sound files in the same folder as “main.lua” for Android builds, but I imagine there is no problems with using a CSS folder.

Great post Jonathan!
Question: Can i use a webpopup to replace native UI elements?
I need to ask the name of a winner player, and i was wondering if i can do that using an HTML’s input text and a submit button.

Jonathan Beebesays:

Christiansays:

I can confirm that it leaks like hell!!! It’s crashing my app. Aprox 20MB extra after opening it and I don’t have videos or audio, only a big background image.

Please move the bug 7390 up in your priority list. This is specially problematic with iOS 5. My app started to receive bad reviews due to crashes and I notice it’s a memory crash after opening the webpopup.

Christian, you’ll probably never see that update. See when I posted the bug? These guys have made a great SDK for developing games, but it is useless for apps. As soon as you need ANYTHING native, move away from Corona SDK.

As for their bug fixing stuff, Carlos told me this bug was high priority three months ago, and that Jonathan wrote this article to get some feedback since they were to rebuild the web popup implementation. Yeah right…

So, take my advice, Christian, find yourself another SDK or go native if you need to use native elements. Like the web popup.

Titussays:

Since many developers are asking for support for the awesome iCade (google it if you don’t know about it) I tried to use a tiny web popup with a local HTML file and some clever javascript to make the iCade controls work. Though extremely “hackish” and clumsy the Corona App and the iCade Controls (really just a Bluetooth keyboard) could -in theory- communicate via the invisible “document.location”.
I almost had it working, but I failed because in the HTML file (I think) we need
a) a text field, so that the keyboard would come up and accept key input
b) the text field needs autofocus.

Unfortunately the focus()-command won’t work in mobile Safari (at least not programmatically with onLoad or after a delay)

Other than that the HTML and therefore the app “around” it understand the joystick controls. If anyone has a bright idea how to use the iCade with the Javascript work-around… let me know.

Irri Tatedsays:

Hi all, I agree with Haakon, if you need anything native, you’d better make sure Corona supports it before attempting to do it in Corona. I just reported a bug I came across recently which I would assume should be something easy that would just work.

I couldn’t wait for a fix because I had to deliver something urgently. In the end, I rewrote the app in Objective C again. Lucky it wasn’t big and was just a demo app, however, I ended up spending more than double the time delivering the app. Not cool!

Another “gotcha”… I assumed I could play video in a non-fullscreen mode, I was wrong… not sure what are the difficulties relating to being able to do this… but I was “gotcha-ed”!

If I wanted to write game apps with custom buttons..etc Corona would probably still be my choice. I say “probably” because I no longer have the confidence that things would work as documented.

There is also a problem with the position of display.newText() between what you see in the simulator (Mac) and on the device. This seems to have been around for a while now and not fixed yet. I’ve had to shift the text down by a few pixels each time, which is a pain because if you’re trying to capture video from the simulator, you’d see the text position in the wrong place.

Newbies, you have been warned! Watch out for the gotchas!

Corona is still a great product overall, I think Ansca probably needs to have more developers/prioritise bug fixes better. Please do a UI for layout! Storyboard editor would be awesome!

Charlie C.says:

If I load a webpage with images on it in Safari on an iPhone I can press an image and get the pop up to save the image to my camera roll. When I load the same web page in native.showWebPopup that functionality is not available. Any idea why not?

Jonathan Beebesays:

@Charlie C: Native webviews use the same rendering engine as Mobile Safari, but is not the actual “Mobile Safari” app . Pressing an image to get the menu options is a feature of the Safari app, but it not a feature of the webview itself.

A Lot of Javascript actions do not work runningthe showWebPopup in an Andriod app. All the the controls seem to work fine in the iOS app. For instance alert() or document.getElementById(someForm).submit.
Inside Android showWebPopup will not read values from input boxes using Javascript
var test = document.getElementById(sometextbox).value;

Shaq chooses Corona to battle mutant zombies

Mobile Apps for Early Childhood Education

To build early childhood education apps, Redbytes Software founded tinytapps in 2011. Using Corona SDK, tinytapps has created over 45 apps that have enjoyed more than 500,000 downloads in Apple's App Store.

NuOffer: Digitizing the Real Estate Industry

NuOffer is a mobile app that brings negotiating and fulfilling real estate transactions into the 21st century. Built with Corona Enterprise, NuOffer connects buyers, sellers and agents to move faster, sell more, and make fewer mistakes in the process.

Fire Maple Games: An Indie Success Story

Joe Kauffman started Fire Maple Games in 2008 to create casual games for mobile. His latest titles, The Secret of Grisly Manor and The Lost City, have received 7M+ downloads, reaching #1 in paid apps in the App Store.