Titanium Community Questions & Answer Archive

We felt that 6+ years of knowledge should not die so this is the Titanium Community Questions & Answer Archive

pass data to webview

Has anyone ever been able to pass data back and forth between app.js and an open webview.

I've been going over this for a few days now and none of the examples work.

I'm trying to pass data from the webview to app.js and then data back from app.js back to webview

I have successfully been able to pass data from an open webview back to app.js, but I have not been able to pass data from app.js to an open webview.

Such a basic requirement it should be easy to do! Hmm.

To get data from open webview to app.js I am doing the following

my.js
Ti.App.fireEvent('helloWorld', { data : "Hello World" );
app.js
Ti.App.addEventListener('helloWorld', function(passedData) 
{    
    Titanium.API.info('I said:' + passedData.data);
});

So, anyone know how to get data from app.js into an open webview?

.

UPDATED: See below for a working answer.

— asked May 21st 2010 by Justin Vincent
  • data
  • pass
  • webview
0 Comments

9 Answers

  • Ok finally got it. This is a way to pass data back and forth.

    This sends data round trip from webview to app.js and then back again.

    app.js
    
    // This creates the webview and opens it in a window
    var webView = Titanium.UI.createWebView({url:'index.html'});
    var appWin = Titanium.UI.createWindow({fullscreen: true});
    appWin.add(webView);
    appWin.open();
    
    // This registers an event listener that you can call 
    // from within the loaded index.html javascript
    Ti.App.addEventListener('helloWorld', function(passedData) 
    {
        // Pass data to the webView
        webView.evalJS("alert(unescape('"+passedData.data"+'))");
    });
    
    index.html - Javascript
    
    <script>
    // This is how you trigger the event listener created above
    // from within javascript inside index.html
    Ti.App.fireEvent('helloWorld', { data : escape("Hello World") } );
    </script>
    

    I've added in the escape function because it helps you pass serialized objects around without fear of syntax errors.

    — answered May 21st 2010 by Justin Vincent
    permalink
    0 Comments
  • Hi!
    WebViews are able to listen to and fire Titanium events as well.
    We use this in our word game Golingo, and wrap the event-handling to get transparent callbacks. The code is as follows:

    var Test = {
        name: 'test',
    
        init: function(){
            this.proxiedHandleEvents = $.proxy(this.handleEvents, this);
            Ti.App.addEventListener('app', this.proxiedHandleEvents);
        },
    
        // Event cannon with callback fix.
        fire: function(opts){
            // If we're providing a callback, save a reference to it here
            // to be able to call it when the response returns from the other side.
            if (opts.func && opts.callback) {
                var c = ++this.callbackCounter;
                this.callbacks[c] = opts.callback;
    
                // Must remap the callback to a callback id since we cannot
                // pass functions between the native context and the webview context
                opts.callback = c;
            }
            opts.from = this.name;
            Ti.App.fireEvent(opts.to, opts);
        },
    
        // Event delegator
        handleEvents: function(e){
            // If the event object has a 'func' property,
            // and that property is a function available in our singleton - call it.
            if (typeof this[e.func] === 'function') {
                // If a callback id is provided, the caller is waiting for a response.
                // Overwrite the callback id with a replier function responding with that id.
                // When our referenced function is done, it passes its result to the replier
                // function, which makes sure the callback on the other side is passed that result.
                if (e.callback) {
                    var c = e.callback,
                        self = this,
                        from = e.from;
    
                    e.callback = function(data){
                        self.fire({
                            data: data,
                            to: from, // Return to sender
                            callback: c // Call the callback with this id on the other side
                        });
                    };
                }
                if (!e.data) {
                    e.data = {};
                }
                // Call the specified function
                this[e.func](e);
            }
            // Was it a callback - eg a response from the other side?
            else
                if (e.callback && this.callbacks[e.callback]) {
                    // Execute the correct callback and pass it the result object
                    this.callbacks[e.callback](e);
                    delete this.callbacks[e.callback];
                }
        },
    
        checkWords: function(words){
            this.fire({
                to: 'app',
                func: 'saveHighscore',
                data: { words: words },
                callback: function(e){
                    alert("We found " + e.data.correctWords.length + " correct words");
                }
            });
        }
    };
    
    Test.init();
    Test.checkWords(['hi', 'ho', 'foo']);
    

    You use this pattern both in the native part and in the webview.

    /Jacob

    — answered May 21st 2010 by Jacob Waller
    permalink
    2 Comments
    • How are you able to use the $. in this (first line in your init function)? Is that a jQuery implementation in the native part?

      — commented October 3rd 2010 by John Pataki
    • thats a language more old than greek

      — commented July 19th 2012 by Abhishek Shah
  • I've spent hours fiddling with this, and Justin's method above is the only one I've been able to make work. There are a couple of things I had to change, though: first, there's a typo with the quote/plus sign reversed in the unescape call, in case you just want to paste this in and test it. Second, I had to put the fireEvent call in an onload function within the web view, instead of just a head script.

    It drives me crazy that the webView.fireEvent function doesn't work at all, even though it's in the API doc. Eval is bad! No one should be forced to use eval!

    — answered July 6th 2010 by Brendan Adkins
    permalink
    3 Comments
    • Brendan - checkout these files http://gist.github.com/465698 - this is working with the current build on android. I'd be interested to see if it causes you problems.

      — commented July 6th 2010 by David Ashwood
    • David, that works fine for me on HTC Hero, Android 2.1

      — commented July 7th 2010 by Rolf Dohrmann
    • @Brendan Eval si bad? That is not even eval but a method which helps you to execute bit of JS in the webpage scope.

      — commented November 14th 2011 by Stanislav Cmakal
  • hey Jacob,

    is it possible for you to break your example down into as simple "hello world" function as possible?

    Its hard to destinguish between your application specific code and the generic transport mechanism.

    Thx very much for your post :)

    — answered May 21st 2010 by Justin Vincent
    permalink
    0 Comments
  • Can I do this with a html file that is not located in the phone? Hosted in a server?

    So the WebView would have a "url" parameter like this:

    Var webView = Ti.UI.createWebView({url:'http://www.mysite.com/index.html'});

    And then fireEvent on my server?

    Tried without success.

    — answered June 2nd 2010 by Antonio Silveira
    permalink
    0 Comments
  • Something I noticed (on iOS at least), is that the <body> tags in your webView's html must be wrapped in an <html> tag otherwise the Ti.App.fireEvent isn't picked up by app.js

    — answered August 17th 2011 by Deryck Wallace
    permalink
    0 Comments
  • The official way to go, if you're working with a REMOTE page, is to set up a listener on the webview for the 'load' event (to make sure you don't kick in too early), and then to fire an evalJS command which retrieves data from the webview.

    If you are waiting for a specific event to occur, you can't add an event listener either to the webview or to the webpage document. You can set an interval in Titanium which executes evalJS every second (or whatever) and then wait for the result to change to whatever value you were waiting for.

    webview.addEventListener('load',function(e) {
                //EvalJS executes the string as Javascript inside the webpage and
                //returns the value to the Titanium context.
    
                var checkForAnswer = setInterval(function(){
    
                    var evaluateThis = "document.cookie";
    
                        var result = webview.evalJS(evaluateThis);//.split(";"); 
    
                    Ti.API.debug("EVALJS" + result + " " + result.length)
    
                },1000)
    });
    

    In my case, we are using a webpage inside a WebView for user registration and login. So the webpage being shown is our own creation. Thus, as soon as our webpage has connected to the server and received a response like " Login ok", the webpage javascript can set a local variable, and the Titanium interval function can check for changes to that value.

    — answered October 30th 2012 by remko posthuma
    permalink
    0 Comments
  • is there a way like the native android webview support where you can send data back to the webview (Android natively supports JavaScriptInterfaces whic accomplish to and frp communication between webview and native)

    — answered August 7th 2013 by Ankur Shukla
    permalink
    0 Comments
  • it's easy to pass data from js to html by when u r setting url 4 webview give it parameter and handle it in html file by java script

    — answered April 4th 2012 by ramzi shadid
    permalink
    1 Comment
    • This actually sounds promising for allowing information to pass from a remotely loaded webpage to the wwebview object. Any more thoughts or comments about why and how this is (or isn't) possible?

      — commented October 30th 2012 by remko posthuma
The ownership of individual contributions to this community generated content is retained by the authors of their contributions.
All trademarks remain the property of the respective owner.