This code is changing rapidly. Always get the latest verions from https://github.com/joearms/SEBG
This is a minimal code example. First you need an Erlang handler, for example, demo1.erl which is as follows:
-module(demo1). -export([start/1]). start(Pid) -> Pid ! {eval, "document.body.innerHTML='';"}, Pid ! {eval, "document.body.style.backgroundColor='#eeffaa';"}, Pid ! {eval, "document.body.innerHTML+='<h1>Hello World</h1>'"}, event_loop(Pid). event_loop(Pid) -> receive Any -> io:format("??event loop:~p~n",[Any]), event_loop(Pid) end.
Then you need to some browser code to launch the example. A minimal code fragment to launch the example is:
<script type="text/javascript" src="./generic.js"></script> <a href="#" onclick="start_session('ws://127.0.0.1:1234/connect/demo1')">demo1</a>run the above code
Type make
Once you have a server running, click on any of the links below:
Writing a handler is trivial. Use the following pattern:
-module(myhandler). -export([start/1]). start(Pid) -> init(Pid), loop(Pid). loop(Pid) -> receive {browser, N, Str} -> ... loop(Pid) end.
Then launch the handler by from the browser by evaluating the javascript command start_session('ws://127.0.0.1:1234/connect/myhandler') The start_session command is defined in generic.js
In the above code Pid is a process that represents the brower.
Pid ! {send, Msg} sends Msg to the browser. Msg must contain a valid Javascript expression which is evaluated in the browser.
Javascript code executing in the browser can evaluate the Javascript function send(Str) this will emerge as a {browser,N,Str} message in the handler. N is a sequence number that increases by one for every message sent.
Using web sockets and SVG and a bit of Javascript it is pretty easy to make an impressive GUI in a a few hundred lines of code.
This example contains a complete web server, which supports web-sockets and shows how to interface web-sockets with jquery and the Raphael SVG javascript library. Using this we make a simple interactive graphics demo program.
Note: This is known to work with Google Chrome and Safari browsers on Mac OS-X and with Chromium on Ubuntu. It does not work with Firefox. Other browsers are untested
The code here is also intended an an intermediate example for new Erlang programmers to study and extend. The code is entirely self-contained, there are no dependence on any other modules, so you don't need to know about OTP applications or generic servers or anything. As such it is suitable for a beginner and for self-study.
I have also included a number of suggestions for small projects based on this code. We often get questions asking for suggestions for projects that are suitable for learning Erlang. I have added a list of possible projects based on this code at the end of this page.
If you are running on mac os-x then all you have to do is type make. On other platforms start erlang, give the command segb:start() in the shell. Then view the page http://localhost:1234/index.html in your browser.
For a minimal example see http://localhost:1234/generic.html
Actually what gets pushed is a fragment of Javascript. The Javascript in the browser just waits for a Javascript fragment, evaluates it, then waits for the next fragment. It's very easy to understated.
The server itself is a small 300 line program that communicates with a web socket. Once a web socket has been opened the web server spawns a handler process to communicate with the web socket and turns itself into a web socket middleman.
The handler process sends javascript expression to the web socket. At the client end of the web socket (ie in the server) all we do is a javascript eval of the data received from the web socket. The server acts as a middle man taking cars or the framing protocol between the browser and the server.
The client page in the server in in a sense "universal." All it has is the ability to execute code, which comes in the form of javascript messages.
In practise this is somewhat inconvenient. So instead of being entire universal and only opening a socket and eval'ing data it receives. The client does a few more thing. It turns the web page red if the socket connection is broken, and it preloads the jquery. jquery is so useful that I consider it to almost be a part of javascriopt.
The handler process svg_demo.erl shows how to communicate with the browser. The first thing svg_demo.erl does, is to send a request to load the Javascript library raphael-min.js. Raphael is a well documented javascript SVG library.
Having loaded Raphael. I create a draggable circle, and a clickable blue box. Nothing fancy. I deliberately don't want to make the example too complicated. You should at this stage be able to read and understand svg_demo.erl and sebg.erl in their entirely.
Using websockets, we can create a direct message passing channel between Erlang and a web server. Once the channel is established we can asynchronous messages between the an Erlang process and a browser window. Sending these message has a tidy overhead of 2 bytes per message.
This demo has only two Erlang modules. sebg.erl and svg_demo.erl. The example is completely self-contain, so makes no use of any Erlang libaries at all.
The work flow is:
function start_session(mod){ websocket = new WebSocket(wsUri); websocket.onopen = function(evt) { onOpen(evt, mod) }; websocket.onclose = function(evt) { onClose(evt) }; websocket.onmessage = function(evt) { onMessage(evt) }; websocket.onerror = function(evt) { onError(evt) }; return(false); } function onOpen(evt, mod) { websocket.send("start:" + mod + ":"); } function onClose(evt) { $("body").css({'background-color':'red'}); } function onMessage(evt) { { eval(evt.data); }
The directory clipper contains a plugin for goole chrome that talks to the web server. To install this see Readme.
Once installed you can select any region of the current web page you are browsing by dragging the mouse over the interesting region. Then click on the extension icon. A popup menu appears. You can add a few comments, click on save and a message is sent to a little erlang server sebg.erl the server. The date extracted from the webpage is put into a snippet file for future analysis.
Next steps:
We need better javascript to extract information on the web page make a pluging for firefox etc.
A large amount of assistance is needed here.
Here are few suggestions for improvements and exercises.
Stare at the code for the function etop_collect/2 in the module observer_backend.erl which you will find in the standard distribution.
Note: cut pates and minimise the code you need from the library, don't just call the library cut and paste when you need and understand every line.