This tutorial illustrates connecting the HTML DOM to listen for node events coming from an X3D SAI, a capability that is fundamental for building dynamic applications which respond to user input.
The 3D Text elements Ajax (X3D sensor 1)
and X3D (X3D sensor 2) appear.
Clicking either geometry causes the scene to change and the
click to be reported by the HTML text.
Setup: Embed X3D content in the page.
The X3D content is embedded in the html document using
the technique shown in Tutorial 1..
In this case the X3D browser is starting with no scene loaded
because we will load the replacement scene dynamically
using DOM and SAI.
Step 1: Create a browser listener object.
In the file AJAX3D2b.js,
we have defined a function initAjax3d() which
is called by the DOM body onLoad event
when the page is loaded.
This function sets up a DOM listener as follows:
dom.js
web3Dbrowser = document.objx3d.getBrowser();
listener = new Object();
listener.browserChanged = web3DbrowserChanged;
web3Dbrowser.addBrowserListener(listener);
The X3D browser listener is an object with a specially named
callback function browserChanged() that is called
by the DOM when interesting SAI events happen,
such as when a new X3D file is loaded.
We want to know when the X3D file is completely loaded
because only then can we be sure that we can get handles to nodes
using the getNode() method of the
SAI ExecutionContext object.
If, for example, we tried to call context.getNode() in
response to the DOM body onLoad event, the call might fail.
Why? Because web browsers may operate asynchronously, i.e. they do not
guarantee the order in which the X3D viewer component is loaded
and the onLoad handler for the page is
called. We get around this by loading an empty scene, setting up
the browser listener, and then asking the browser to
load the named file and produce a callback when the
scene is loaded and running.
Note that with this code we are now introducing the beginnings of a general-purpose framework for building AjaX3D applications. At the moment this file is quite simple; it has just 3 functions defined to help the application connect to the X3D world. We will be building on this framework in following tutorials.
Step 2: Dynamically load a world file.
Now that we have set up a browser listener, we can ask
the browser to load a specific file, and the application
will be notified when the X3D scene is fully loaded:
dom.js
web3Dbrowser.loadUrlS("AJAX3Dlogo.x3d");
This loads the file AJAX3Dlogo.x3d,
which has a nicely modeled AjaX3D logo using real 3D extruded text geometry.
The function browserChanged() will be called when the new scene is
fully loaded:
dom.js
function web3DbrowserChanged(evt)
{
if (evt == 0) // BROWSER_INITIALIZED
{
web3Dbrowsercontext = web3Dbrowser.getExecutionContext();
setupListeners();
}
}
Which obtains the current SAI execution context object then calls code to set up the listeners for X3D SAI node events.
Step 3: Create field listener objects.
Our browserChanged() calls out to a helper
function, setupListeners(),
which is defined specifically for this application.
The file AJAX3D2c.js contains the
application-specific code to create the SAI node and
field listeners which will alert the DOM when the user
interacts with objects in the scene.
In this example, the fields being listened to are from X3D
TouchSensor nodes: objects that respond
when a piece of geometry is clicked.
.x3d
<TouchSensor DEF='TouchSensor1' />
<TouchSensor DEF='TouchSensor2' />
The code first tucks away a handle to each node this application is
interested in: a TimeSensor node for starting/stopping
time-based animations, and two Material nodes for controlling the
color of the two groups of geometry that comprise the AjaX3D logo.
.x3d
<TimeSensor DEF='Timer' ... />
<Material DEF='AjaxTextMaterial'... diffuseColor='1 0 0'/>
<Material DEF='X3DTextMaterial' ... diffuseColor='0 0 1'/>
dom.js
// Get a handle to the nodes
timeSensor = web3Dbrowsercontext.getNode("Timer");
AjaxTextMaterial = web3Dbrowsercontext.getNode("AjaxTextMaterial");
X3DTextMaterial = web3Dbrowsercontext.getNode("X3DTextMaterial");
dom.js
// Set up the observers that detect clicks
touchObserver1 = setListenerObserver
("TouchSensor1", "touchTime", sensor1Touched);
touchObserver1 = setListenerObserver
("TouchSensor2", "touchTime", sensor2Touched);
}
setupListeners() calls a helper function in our new
framework, setListenerObserver() that creates a
field listener object with a callback function.
dom.js
function setListenerObserver(nodeName,fieldName,callback)
{
// obtain node and field
node = web3Dbrowsercontext.getNode(nodeName);
field = node.getField(fieldName);
// Set up observer and specify callback funtion
var observer = new Object;
observer.readableFieldChanged = callback;
observer.field = field;
field.addFieldEventListener(observer);
return observer;
}
The DOM is notified and the callback function executes when the value of the specified X3D node’s field changes.
Step 4: Respond to the events.
Once the field listeners are set up, we can now respond to
clicks on the geometry.
dom.js
function sensor1Touched(f, t)
{
AjaxTextMaterial.diffuseColor.g = .5;
X3DTextMaterial.diffuseColor.r = .5;
X3DTextMaterial.diffuseColor.g = .5;
document.getElementById('statusArea').innerHTML =
"Sensor 1 clicked.";
}
Click on the “Ajax” geometry and you will see two actions: i) the color of both the "Ajax" and the "X3D" geometries will change, and ii) the contents of the containing web page will be updated with a text message "Ajax Sensor clicked". The X3D behavior happens using internal SAI to sense the pointer action, send the event to the DOM which sends new colors to the SAI and then presents the new message in the status area.
The HTML behavior actually illustrates
a typical DOM programming trick employed in AJAX: changing
the innerHTML property of a DOM element of the web page to
provide additional user feedback without reloading the
document.
dom.js
function sensor2Touched(f, t)
{
timeSensor.startTime = t;
document.getElementById('statusArea').innerHTML =
"Sensor 2 clicked.";
}
Click on the “X3D” geometry and three things happen: i) the color of the geometry changes; ii) the logo starts spinning by setting the start time of the animation, and iii) once again, the html message is updated.
Actions i) and ii) result from animation coding in the X3D scene. From the X3D scene point of view, the DOM does "External" scripting of the scene while the SAI does "Internal" scripting of the scene. We have the host "live" DOM document object connected to the embedded "live" web3D X3D browser SAI execution context object and can easily pass events to produce a highly interactive result.
Next we add the
XMLHttpRequest object
to the DOM using
Ajax
and
Ajax3D tech
to achieve SAI<=>DOM<=>XMLHttpRequest happiness.
Refresh/Reload Example page to restart.
Next step Tut3 - Connect SAI events to DOM and XMLHttpRequest
Original Author: Tony Parisi tparisi@mediamachines.com
last updated: October 12, 2006
This version by: Joe D Williams joedw@hypermultimedia.com
last updated: April 42, 2007