Welcome to the developer documentation for the Aloqa TraX Javascript API !
This API lets you integrate location-based services in your web pages. You can poll the position of a target or register for certain location-based events like a target entering an area or two persons approaching each other. In order to use this API, you need to request an API key.
We're looking forward to your feedback, so send us an email to support@aloqa.com.
The following show cases should give you a rough idea of location-based services supported by this API. The first case focuses on the Low Level Location Mangement (LLPM), which lets you poll the position of a target or register for events of a target. The second show case presents the High Level Location Management (HLPM), which provides functions to detect spatial relations between targets, like proximity, k-nearest neighbors or clique detection.
Elvis is running the TraX Client application on his mobile. Presley is sitting in the office, while Elvis is still at home. Presley would like to await Elvis in his office, so he asks you, the developer, if it's possible to "program something" to notify him when Elvis is near the building - this way, Presley can head over to Elvis' office and wait for him there. You say: "No problem, pal."
Elvis (from the previous example) has a son named Costello. Sadly, Costello's been in puberty and is hanging around in places where he should not be. Elvis promised Costello that he won't use the same trick on him as Presly did on Elvis, but somehow, Elvis sometimes likes to know where his son his. So he asks Costello if it's ok for him to monitor the position of him and his friends, knowing that they're still together and not separated by evil folks. Costello refuses, but allows his father to arbitrarily track his position. Satisfied with this solution, Elvis asks you, the developer, if it's possible to "program something" to enable him doing so. You say: "Man, that sounds like Orwell's 1984, but since you're my boss, I'll do it". After testing the system for several days, Elvis tells you that in the beginning, it worked wonderful, but then Costello got fed up and switched his phone off, leaving Elvis in sorrow while getting drunk as hell. Asked if you could "program something" to circumvent this "problem", you say: "Sorry, but this is not Orwell's 1984. TraX (the technology i use) is not capable of tracking your son when his phone is switched off or the TraX client is not running, and it will never be because it cares about individual privacy". Ashamed, Elvis understands and promotes you to a senior developer position.
Alicia has two wonderful children named Barbie and Ken. Barbie is a bright, responsible twenty-year-old. So, sometimes when Alicia is not at home, she's watching over little Kenny. Ken is not allowed to go anywhere other than Barbie, so Alicia wants to be notified when Ken's distance to barbie gets too large. She asks you, the developer, if you could "program something" to notify her when Ken and Barbie are separated by more than 20 meters. You say: "As good as done."
It's late afternoon, and Alicia (from the previous example) thinks about going out with some friends to their favorite location, since Barbie is so reliable. However, Alicia is bothered by their friends because they're always late. So, she asks you, the developer, to "program something" that would inform her when at least two of her friends already arrived at their favorite location. You say "Wait a sec ... ok, done". Alicia is so happy that she asks you out for dinner (without Barbie and Ken).
The TraX Javascript library exposes the Low Level Position Management and the High Level Position Management API to web developers. There is no need to program Java code or running a java application on some dedicated server. All you need is the TraX Javascript library and you're all set.
In the following sections, you'll be gracefully introduced to how to use the library. We'll start with the LLPM API alone, and extend the examples on the HLPM API later. You may also head over to the class reference section.
All you need to do to get started with the library is including it into your web page. This is as simple as including arbitrary javascript:
<html> <head> <script type="text/javascript" src="http://ajax.aloqa.com:8080/TraX/Proxy/js/trax.js"></script> </head> <body> </body> </html>
This alone won't do much. It just connects to the TraX Server and enables you to use the LLPM and HLPM API.
To actually receive results, you need to invoke actions on the TraX Server first. After including the javascript as shown above, add a monitor job on a certain mobile.
<html>
<head>
<script type="text/javascript" src="http://ajax.aloqa.com:8080/TraX/Proxy/js/trax.js"></script>
<script type="text/javascript">
<!--
TraX.LLPM.addMonitorJob('some_mobiles_name', 'my_job', new TraX.DistanceJob());
-->
</script>
</head>
<body>
</body>
</html>
Assuming that a TraX client is running on a mobile phone, and the username is set to some_mobiles_name, then you'll soon see an alert box popping up, informing you about the received position update. This is the default behaviour which is informative, but is of not much use to end-users. Of course, you'd like to override this default behaviour to match your needs.
In response to adding monitor jobs on mobiles, a callback function is invoked when results are received from the TraX Server. In case of the LLPM, this callback function can be found at TraX.LLPM.onPositionUpdated(String mobileTerminal, String jobId, TraX.PositionUpdate positionUpdate). By default, this function pops up a message box, informing you about the received position update. To override this behaviour, specify a callback function like this:
<html>
<head>
<script type="text/javascript" src="http://ajax.aloqa.com:8080/TraX/Proxy/js/trax.js"></script>
<script type="text/javascript">
<!--
TraX.attach({
onPositionUpdated: function(mt, jobId, update) {
alert("My own callback function! I received an "+update);
}
});
TraX.LLPM.addMonitorJob('some_mobiles_name', 'my_job', new TraX.DistanceJob());
-->
</script>
</head>
<body>
</body>
</html>
Now, instead of the default callback, your custom callback will be invoked on result retrieval.
As you might have noticed, the call to TraX.LLPM.addMonitorJob('mt','jobid', new TraX.DistanceJob()) does not return a single result, but multiple results. It consequently is invoked in an asynchronous manner and causes a callback function to be executed when results are received. But you might wonder how the synchronous calls of the LLPM API, like LLPM.pollPosition(String mt) are implemented. Say, you'd like the TraX Server to ask for the position of a single mobile, and for some reason it takes ages to respond - will the browser be rendered unusable then, since the procedure call is synchronous? And if the procedure call is somehow implemented asynchrous, how are results retrieved then? It's as simple as this:
<html>
<head>
<script type="text/javascript" src="http://ajax.aloqa.com:8080/TraX/Proxy/js/trax.js"></script>
<script type="text/javascript">
<!--
TraX.LLPM.pollPosition(
'some_mobiles_name',
function(update) {
if(update)
alert("i got an update: "+update);
else
alert("No update for me :(");
}
);
-->
</script>
</head>
<body>
</body>
</html>
It's similar to the TraX.LLPM.onPositionUpdated call above. You need to specify a callback function which is able to handle the expected value, and pass it to the TraX.LLPM.pollPosition call as aditional argument. When a result is returned from the TraX Server, then your callback function is executed and the result is applied to its parameters.
As described above, you can also poll the position of multiple mobile terminals at once by writing something like this:
<html>
<head>
<script type="text/javascript" src="http://ajax.aloqa.com:8080/TraX/Proxy/js/trax.js"></script>
<script type="text/javascript">
<!--
// first, retrieve the names of the mobile terminals to poll & feed them into an array
var mts = []; mts.push('mt1'); mts.push('mt2');
TraX.LLPM.pollPositions(
mts, // takes an array as argument
function(updates) { // your callback function gets an array of position updates as parameter
for(k in updates) {
if(updates[k]) {
alert("i got an update: "+updates[k]);
}
}
}
);
-->
</script>
</head>
<body>
</body>
</html>
Internally, the length of the array is submitted to the TraX Server. Sadly, objects added to an array like mts[0]="mt1";mts[1]="mt2"; break the array object, and the length is not returned correctly. So, it's mandatory to add mts as introduced above by using the push method. Also note that one or more of the received updates may be null.
The concept introduced above is consequently implemented in any call of the LLPM and HLPM API, which (in their respective java version) return a result and are therefore executed in a synchronous manner. Let's look at the LLPM.getMonitorJob(String mt, String jobId) call. In the Javascript TraX Library, it's implemented like this:
<html>
<head>
<script type="text/javascript" src="http://ajax.aloqa.com:8080/TraX/Proxy/js/trax.js"></script>
<script type="text/javascript">
<!--
TraX.LLPM.getMonitorJob(
'some_mobiles_name',
function(job) {
if(job)
alert("i got a job: "+job);
else
alert("No job for me :(");
}
);
-->
</script>
</head>
<body>
</body>
</html>
Just a hint: This example will always pop up a message box saying "No job for me :(", since you first need to add a job to actually retrieve it. The following example should get you going. It will add a new DistanceJob on the mobile named some_mobiles_name, wait for five seconds, and then retrieve it:
<html>
<head>
<script type="text/javascript" src="http://ajax.aloqa.com:8080/TraX/Proxy/js/trax.js"></script>
<script type="text/javascript">
<!--
TraX.LLPM.addMonitorJob('some_mobiles_name', 'my_job', new TraX.DistanceJob());
window.setTimeout(function() {
TraX.LLPM.getMonitorJob(
'some_mobiles_name',
function(job) {
if(job)
alert("i got a job: "+job);
else
alert("No job for me :(");
}
);
}, 5000);
-->
</script>
</head>
<body>
</body>
</html>
As simple as it can be! The following example adds a monitor job, waits five seconds and then removes the very same monitor job:
<html>
<head>
<script type="text/javascript" src="http://ajax.aloqa.com:8080/TraX/Proxy/js/trax.js"></script>
<script type="text/javascript">
<!--
TraX.LLPM.addMonitorJob('some_mobiles_name', 'my_job', new TraX.DistanceJob());
window.setTimeout(function() {
TraX.LLPM.removeMonitor('some_mobiles_name', 'my_job');
}, 5000);
-->
</script>
</head>
<body>
</body>
</html>
DistanceJob
As you may know, there are more subtypes of MonitorJob than just DistanceJob. You're free to use a ZoneJob, having a circular or polygonal area assigned as shape, or a PeriodicJob.
ZoneJob
A ZoneJob has a certain area assigned. As soon as someone enters or leaves this area, a position update will be triggered and delivered by TraX.LLPM.onPositionUpdated (when added earlier by TraX.LLPM.addMonitorJob. At the moment, the areas may be of circular or polygonal shape. Besides, you're able to assign a mode to a zone job, meaning that a position update will be triggered when
... var zoneJob = new TraX.ZoneJob(); zoneJob.mode = 1; // entering zoneJob.mode = 2; // leaving zoneJob.mode = 3; // entering or leaving ...
ZoneJob
The assigned area may be a circular area. To assign a CircularArea to a ZoneJob, do something like this:
... var zoneJob = new TraX.ZoneJob(); var area = new TraX.CircularArea(); // by default, the circular area is a circle of radius 0, // located at WGS84-Coordinate (x,y,z)=(0.0,0.0,0.0); area.radius = 10; // set radius to a value of ten meters area.center = new TraX.Coord(11.0, 49.0, 0.0); // set the center of this circular area zoneJob.zone = area; // finally, assign the area to the zone job ...
ZoneJob
Besides circular areas, polygonal areas are also supported. This means, you can create a new PolygonalArea with n coordinates. Please note that TraX itself supports millions of coordinates, but because of limitations set by browser vendors, we're limited to around 100 coordinates on Firefox and Opera. Internet Explorer, Safari and Konqueror are not affected Please read why. To assign a PolygonalArea to a ZoneJob, do something like this:
... var zoneJob = new TraX.ZoneJob(); var area = new TraX.PolygonalArea(); // by default, the polygonal area has no coords which is senseless area.coords.push(new TraX.Coord(11.02343,49.98436,0.0)); // by default, area.coords is an empty array ... // add as much coordinates as you like - at least, add three coordinates area.coords.push(new TraX.Coord(11.45233,48.27638,0.0)); zoneJob.zone = area; // finally, assign the area to the zone job ...
PeriodicJob
A PeriodicJob causes a mobile terminal to periodically report its position (hence the name). You can create a PeriodicJob like this:
... var periodicJob = new TraX.PeriodicJob(); periodicJob.millis = 5000; // report position every 5 seconds ...
Earlier, you learned about TraX.attach and how to use it to override the default callback function TraX.LLPM.onPositionUpdated. But this is not the only function which can be overridden by TraX.attach. When deployed, the error and informational messages are displayed as alert boxes, and debug messages are dropped. To override this behaviour, simply specify your own functions:
<html>
<head>
<script type="text/javascript" src="http://ajax.aloqa.com:8080/TraX/Proxy/js/trax.js"></script>
<script type="text/javascript">
<!--
TraX.attach({
onError: function(msg, e) {
document.getElementById('log').innerHTML += "An Error occured: "+msg+"(e?(" Exception is "+
new String(e)):"")+"<br />";
},
onInfo: function(msg) {
document.getElementById('log').innerHTML += msg+"<br />"
},
onDebug: function(msg) {
document.getElementById('debug').innerHTML += msg+"<br />"
}
});
-->
</script>
</head>
<body>
<div id="log"></div>
<div id="debug"></div>
</body>
</html>
Note that the above example is just to show you the possibilities. Since messages (especially debug messages) are likely to occur before the DOM tree is rendered, you'll certainly run into errors since a call to document.getElementById("log") won't return something useful as long as the DOM tree is not rendered yet.
In the last few sections, we discovered the possibilities of the Low Level Position Management API. But what is to be done when proximity and/or separation between two mobile terminals is to be monitored?
Well, we'll use the High Level Position Management API. You can find the implementation of this API in the singleton TraX.HLPM.
The following example schedules the monitoring of two mobile terminals. As soon as they approach each other by more than 100 meters, then a message will pop up.
...
TraX.HLPM.startProximityDetection('mt1', 'mt2', new TraX.HLPM_Parameters(100, 0, 2));
...
To stop the proximity detection, simply write:
...
TraX.HLPM.stopProximityDetection('mt1', 'mt2');
...
Analoguously, the detection of a separation between two mobile terminals is also possible. The following example schedules the monitoring of two mobile terminals. As soon as they separate by more than 100 meters, a message will pop up.
...
TraX.HLPM.startSeparationDetection('mt1', 'mt2', new TraX.HLPM_Parameters(0, 100, 2));
...
Stopping the separation detection works the same as above:
...
TraX.HLPM.stopSeparationDetection('mt1', 'mt2');
...
...
TraX.attach({
onPositionUpdated: function(mt, jobId, update) {
alert("My own callback function! I received an "+update);
}
});
...
Well, guess what to do next ...
...
TraX.attach({
onProximityDetected: function(results) {
if(results) {
alert("Got some HLPM results: "+results);
}
},
onSeparationDetected: function(results) {
if(results) {
alert("Got some HLPM results: "+results);
}
}
});
...
The only thing which has to be mentioned is the type of the argument which is fed into the callback. It's of type TraX.HLPM_Results and holds both mobile terminals which are affected as well as their respective positions of type TraX.PositionUpdate. You may want to refer to the Class Reference for further recherche about these object types.
... TraX.HLPM.stopAll(); ...
TraX.HLPM_Parameters you specify, such as a proximity/separation distance and a borderline tolerance. First, let's check if the two mobile terminals mt1 and mt2 are positioned less then 100 meters to each other.
...
var params = new TraX.HLPM_Parameters(0,0,0);
params.proximityDistance = 100;
TraX.HLPM.checkProximity(
'mt1',
'mt2',
params,
function(nearby) {
if(nearby) {
alert("mt1 is less than 100 meters from mt2");
}
}
);
...
OK, and now let's check if mt1 and mt2 are more than 50 meters separated.
...
var params = new TraX.HLPM_Parameters(0,0,0);
params.separationDistance = 50;
TraX.HLPM.checkProximity(
'mt1',
'mt2',
params,
function(separated) {
if(separated) {
alert("mt1 is more than 50 meters away from mt2");
}
}
);
...
TraX is both a namespace where every object which is somehow related to the TraX JavaScript API lives as well as a class with some static methods. These methods include:
TraX.PositionUpdate as arguments.TraX.HLPM_Results as argument.TraX.HLPM_Results as argument.null since we don't want the arbitrary user to see debug messages. Needs a function which takes one string argument as value.
...
function info(message) {
alert("### INFO ###\n"+message);
}
TraX.attach({
onPositionUpdated: function(update) { alert("my update: "+update); },
onError: function(message) { alert("### ERROR ###\n"+message); },
onAlert: info
});
...
...
TraX.ready(function() {
alert("Hello DOM Tree!");
});
...
TraX.LLPM exposes the LLPM API to web developers. It is not instantiable; all functions must be accessed statically.
mt with job id jobId.
...
TraX.LLPM.addMonitorJob('schorsch', 'distjob1');
...
mt with job id jobId. Returns null when no such mobile terminal is known to the TraX Server. As a third argument, a callback function must be supplied. The callback must be able to take a TraX.MonitorJob as argument.
TraX.LLPM.getMonitorJob('schorsch', 'distjob1', function(job) {
if(job) {
alert("Got job: "+job);
}
});
jobId from the mobiel terminal mt.
...
TraX.LLPM.removeMonitorJob('schorsch', 'distjob1');
...
mt. The position update is returned as argument to the supplied callback function. Note that also null may be returned.
...
TraX.LLPM.pollPosition('schorsch', function(update) {
if(update) {
alert('Got position of schorsch: '+update);
}
});
...
mts which stores the names of all mobile terminals from which the positions shall be polled. The result is returned as an array of TraX.PositionUpdate and fed into the supplied callback function. The order of the received updates equals the order of the supplied names. Note that for single array values also null may be returned.
...
var mts = []; mts.push('hansi');
mts.push('schorsch');
mts.push('alfons');
TraX.LLPM.pollPositions(mts, function(updates) {
for(i in updates) {
if(updates[i]) {
alert("Got update: "+update[i]);
}
}
});
...
TraX.HLPM exposes the HLPM API to web developers. It is not instantiable; all functions must be accessed statically.
mt1 and mt2, according to the supplied params of type TraX.HLPM_Parameters. Results are received by means of TraX.onProximityDetected.
...
var params = new TraX.HLPM_Parameters(10, 10, 2);
TraX.HLPM.startProximityDetection('schorsch', 'hansi', params);
...
mt1 and mt2.
...
TraX.HLPM.stopProximityDetection('schorsch', 'hansi');
...
mt1 and mt2, according to the supplied params of type TraX.HLPM_Parameters. Results are received by means of TraX.onSeparationDetected.
mt1 and mt2.
...
TraX.HLPM.stopSeparationDetection('schorsch', 'hansi');
...
... TraX.HLPM.stopAll(); ...
mt1 and mt2, according to the given params of type TraX.HLPM_Parameters. Also expects a callback function which takes one argument of type boolean.
...
TraX.HLPM.checkProximity(
'schorsch',
'hansi',
new TraX.HLPM_Parameters(10, 10, 2),
function(p) {
alert('schorsch and hansi are '+(p?'nearby':'separated'));
}
);
...
mt1 and mt2, according to the given params of type TraX.HLPM_Parameters. Also expects a callback function which takes one argument of type boolean.
...
TraX.HLPM.checkSeparation(
'schorsch',
'hansi',
new TraX.HLPM_Parameters(10, 10, 2),
function(p) {
alert('schorsch and hansi are '+(p?'separated':'nearby'));
}
);
...
... var coord1 = new TraX.Coord(0, 0, 0); coord1.x = 11.0; coord1.y = 13.0; var coord2 = new TraX.Coord(11.0, 13.0, 0); // coord1 and coord2 are the same ...
TraX.MonitorJob, such as a TraX.DistanceJob, a TraX.PeriodicJob or a TraX.ZoneJob.
... var job = new TraX.DistanceJob(); job.distance = 100; job.startCoord = new TraX.Coord(11.0, 49.0, 0.0); ...
... var job = new TraX.PeriodicJob(); job.millis = 5000; ...
TraX.Shape. Implementing classes of TraX.Shape are TraX.CircularArea and TraX.PolygonalArea. Both properties are accessible via the initialized zone job.
... var job1 = new TraX.ZoneJob(); job1.mode = 1; // ENTERING job1.zone = new TraX.CircularArea(); ... var job2 = new TraX.ZoneJob(); job2.mode = 3; // ENTERING OR LEAVING job2.zone = new TraX.PolygonalArea();
TraX.Coord and a radius of type float.
... var area = new TraX.CircularArea(); area.center = new TraX.Coord(11.0, 49.0, 0); area.radius = 120.0; ...
TraX.Coord and stored as an array. Please note: Adding coordinates to this array shall only happen by using the array's native push function, as introduced in the sample code.
... var area = new TraX.PolygonalArea(); // CORRECT area.coords.push(new TraX.Coord(11.0, 49.0, 0)); area.coords.push(new TraX.Coord(11.4875, 48.974, 0)); area.coords.push(new TraX.Coord(11.2958, 49.1423, 0)); // WRONG - will break the serialization mechanism area.coords[0] = (new TraX.Coord(11.0, 49.0, 0)); area.coords[1] = (new TraX.Coord(11.4875, 48.974, 0)); area.coords[2] = (new TraX.Coord(11.2958, 49.1423, 0)); ...
point) itself of type TraX.Coord, the coordinate reference system (refsys), given as integer, accuracy (acc) of JavaScript's native integer type and a warning flag of type boolean.
... var update = new TraX.PositionUpdate(); update.point = new TraX.Coord(11.0, 49.0, 0); update.refsys = 1; // WGS84 update.acc = 10; // accuracy is set to ten meters update.warning = true; // warning flag is set ...
proximityDistance, separationDistance and borderlineTolerance, all three of type integer
... var params = new TraX.HLPM_Parameters(/*prox.Dist.*/ 10, /*sep.Dist.*/ 10, /*borderl.Tol.*/ 2); params.borderlineTolerance = 3; ...
string and their respective positions of type TraX.PositionUpdate. Both mobile terminals and their respective positions must be set in the constructor or may be accessed when the object is created.
...
var updateOfHansi = new TraX.PositionUpdate();
var updateOfSchorsch = new TraX.PositionUpdate();
var results = new TraX.HLPM_Parameters('schorsch', 'hansi', updateOfHansi, updateOfSchorsch);
results.firstMT = 'schorsch der zweite';
results.secondMT = 'hansi der zweite';
results.firstPositionUpdate = new TraX.PositionUpdate();
results.secondPositionUpdate = new TraX.PositionUpdate();
...
Currently, Mozilla-based browsers like Firefox 2.x, Microsoft Internet Explorer 5.x, Opera 9.x, Apple's Safari 3.x as well as recent versions of Konqueror are supported. On mobile devices, Opera Mobile (but not Opera Mini) as well as Minimo are supported. Support for Microsoft's Mobile Internet Explorer is worked on, but don't count on it - sorry.
Send an email to requestkey@aloqa.com containing your contact info and a short description of your service.
The type of the license hasn't been determined yet.
Hey, you're lucky, it runs on your KHTML-based browser! The activity you're seeing is due to limitations of these browsers. Actually, every time you see such activity, data is pulled from the server backend. In contrary, Firefox uses lazy HTTP streaming, also known as Comet which does not suffer from such usability issues. Internet Explorer also suffers from this, but thanks to the geniuses at Google, we managed to hide it from the user ;)
We're really happy to answer your questions or to get feedback from you. So send us an email (support@aloqa.com) and we'll reply as soon as possible.
TraX.LLPM.onPositionUpdated are not executed when a position update actually occured in the server backend (like it's the case with Firefox, Netscape, Mozilla and Opera), but may suffer from a time lag of up to five seconds.