Language:

Categories

Getting Started

General Use

Tutorials

Changelogs

Licensing

Tutorial 3 - Hooking Up Events

In this tutorial, we'll show how to hook up events between the page and host application via JavaScript callbacks.

Start With This Code

It’s quite a bit of work to set up an empty Windows GDI or Mac OSX Cocoa application. To save some time we’ve gone ahead and done some of the work for you.

Start by downloading the framework below and following the README for your platform:

Create Your HTML Interface

Create a new HTML file named app.html somewhere on your hard drive and add the following content to it:

<html>
<body>
<h1>Welcome to My App</h1>
<button onclick="app.sayHello()">Say Hello</button>
</body>
</html>

Load The File

After setting up your project using the tutorial framework, open up main.cc and find the following code:

// Inherited from Application::Listener
  virtual void OnLoaded() {
    view_ = View::Create(500, 300);
     // < Set up your View here. >
  }

Replace the // <Set up your View here. > code with the following, you’ll need to adjust the file path so that it points to your own app.html:

// Inherited from Application::Listener
  virtual void OnLoaded() {
    view_ = View::Create(500, 300);
    
    WebView* web_view = view_->web_view();

    WebURL url(WSLit("file:///C:/Users/awesomium/Documents/app.html"));
    web_view->LoadURL(url);
  }

Great, our app should now display the HTML file we created a little earlier. If you build and run now, you should get something that looks like this:

Screenshot 1

You’ll notice if you click the button right now, it won’t do anything. We need to modify our application so that it responds to calls from app.sayHello() via JavaScript.

Create Global JavaScript Object

Let’s create a special JavaScript object that will stay alive throughout the entire lifetime of our WebView. This will allow us to expose certain methods and properties that our pages can use via JavaScript.

// Inherited from Application::Listener
  virtual void OnShutdown() {
  }

  void BindMethods(WebView* web_view) {
    // Create a global js object named 'app'
    JSValue result = web_view->CreateGlobalJavascriptObject(WSLit("app"));
  }

And then add the following code underneath your LoadURL code:

// Inherited from Application::Listener
  virtual void OnLoaded() {
    view_ = View::Create(500, 300);
    
    WebView* web_view = view_->web_view();

    BindMethods(web_view);

    WebURL url(WSLit("file:///C:/Users/awesomium/Documents/app.html"));
    web_view->LoadURL(url);
  }

Custom JavaScript Methods

We now need to declare a custom method named sayHello to JavaScript and then bind this method to a callback in C++.

To do this, we’re going to save some time and use a special helper class included in the tutorial framework called MethodDispatcher.

Include MethodDispatcher

At the top of your application, add #include "method_dispatcher.h" underneath #include "view.h":

#include "application.h"
#include "view.h"
#include "method_dispatcher.h"
#include <Awesomium/WebCore.h>
#include <Awesomium/STLHelpers.h>
#ifdef _WIN32
#include <Windows.h>
#endif

using namespace Awesomium;

Alright, now we just need to add an instance of MethodDispatcher to our application class.

Find the top of your TutorialApp class definition and then go ahead and add MethodDispatcher method_dispatcher_; underneath View* view_;:

using namespace Awesomium;

class TutorialApp : public Application::Listener {
  Application* app_;
  View* view_;
  MethodDispatcher method_dispatcher_;
 public:

Define Our Callback

Let’s write the code that will be called by app.sayHello(). Add the following code underneath the BindMethods definition:

void BindMethods(WebView* web_view) {
    // Create a global js object named 'app'
    JSValue result = web_view->CreateGlobalJavascriptObject(WSLit("app"));
  }

  // Bound to app.sayHello() in JavaScript
  void OnSayHello(WebView* caller,
                  const JSArray& args) {
    app_->ShowMessage("Hello!");
  }

Bind Our Method

Now we just need to hook everything up using the MethodDispatcher instance.

Replace your BindMethods definition with the following:

void BindMethods(WebView* web_view) {
    // Create a global js object named 'app'
    JSValue result = web_view->CreateGlobalJavascriptObject(WSLit("app"));
    if (result.IsObject()) {
      // Bind our custom method to it.
      JSObject& app_object = result.ToObject();
      method_dispatcher_.Bind(app_object,
        WSLit("sayHello"),
        JSDelegate(this, &TutorialApp::OnSayHello));
    }

    // Bind our method dispatcher to the WebView
    web_view->set_js_method_handler(&method_dispatcher_);
  }

If you run your application now and click on the Say Hello button, you should get a little message box like the following:

Screenshot 1

Congratulations, you’ve made your first interactive HTML interface!

Complete Code

In case you had trouble following the tutorial, the complete code for main.cc has been included below (just remember to edit the file path for your app.html):

#include "application.h"
#include "view.h"
#include "method_dispatcher.h"
#include <Awesomium/WebCore.h>
#include <Awesomium/STLHelpers.h>
#ifdef _WIN32
#include <Windows.h>
#endif

using namespace Awesomium;

class TutorialApp : public Application::Listener {
  Application* app_;
  View* view_;
  MethodDispatcher method_dispatcher_;
 public:
  TutorialApp() 
    : app_(Application::Create()),
      view_(0) {
    app_->set_listener(this);
  }

  virtual ~TutorialApp() {
    if (view_)
      app_->DestroyView(view_);
    if (app_)
      delete app_;
  }

  void Run() {
    app_->Run();
  }

  // Inherited from Application::Listener
  virtual void OnLoaded() {
    view_ = View::Create(500, 300);
    WebView* web_view = view_->web_view();

    BindMethods(web_view);

    WebURL url(WSLit("file:///C:/Users/awesomium/Documents/app.html"));
    web_view->LoadURL(url);
  }

  // Inherited from Application::Listener
  virtual void OnUpdate() {
  }

  // Inherited from Application::Listener
  virtual void OnShutdown() {
  }

  void BindMethods(WebView* web_view) {
    // Create a global js object named 'app'
    JSValue result = web_view->CreateGlobalJavascriptObject(WSLit("app"));
    if (result.IsObject()) {
      // Bind our custom method to it.
      JSObject& app_object = result.ToObject();
      method_dispatcher_.Bind(app_object,
        WSLit("sayHello"),
        JSDelegate(this, &TutorialApp::OnSayHello));
    }

    // Bind our method dispatcher to the WebView
    web_view->set_js_method_handler(&method_dispatcher_);
  }

  // Bound to app.sayHello() in JavaScript
  void OnSayHello(WebView* caller,
                  const JSArray& args) {
    app_->ShowMessage("Hello!");
  }
};

#ifdef _WIN32
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, wchar_t*, 
  int nCmdShow) {
#else
int main() {
#endif

  TutorialApp app;
  app.Run();

  return 0;
}

Further Reading