#########
Callbacks
#########

The HOOPS Web Viewer component allows you to set callback functions that will be executed in response to certain events from the library. A full list of available callbacks can be found in the :doc:`CallbackMap </api_ref/viewing/interfaces/Communicator.CallbackMap>` portion of the HOOPS Web Viewer API Reference.


Setting callbacks
=================

When setting callbacks, first create the functions you want to get called when an event occurred. Then, pass an object containing all the events for which you wish to set callbacks. In the example below, we are setting callbacks for the ``sceneReady``, ``selection``, and ``info`` events.

.. code-block:: js
	
	function mySceneReadyFunc() {
		console.log("The scene is ready!");
	}
	
	function mySelectionFunc(selectionEvents) {
		for (const selectionEvent of selectionEvents) {
			const selection = selectionEvent.getSelection();
			if (selection && selection.getSelectionType() !== Communicator.SelectionType.None) {
				console.log(`Selected Node: ${selection.getNodeId()}`);
			} else {
				console.log(`Selected: None`);
			}
		}
	}

	function myInfoFunc(infoType, message) {
		switch (infoType) {
			case Communicator.InfoType.Error:
				console.log(`Error: ${message}`);
				break;
			case Communicator.InfoType.Warning:
				console.log(`Warning: ${message}`);
				break;
			case Communicator.InfoType.Info:
				console.log(`Info: ${message}`);
				break;
		}
	}
	
	hwv.setCallbacks({
		sceneReady: mySceneReadyFunc,
		selectionArray: mySelectionFunc,
		info: myInfoFunc,
	});	


Multiple callbacks
==================

The :ref:`setCallbacks() <api_ref/viewing/classes/Communicator.WebViewer:setcallbacks>` function can be called at any point after the :doc:`Communicator.WebViewer </api_ref/viewing/classes/Communicator.WebViewer>` object has been created. It is possible to bind multiple callbacks to the same event which then will be executed in the order they were registered in.

In the example below, we are setting two callback functions on the camera event:

.. code-block:: js

	function myCameraChangeFunc(camera) {
		console.log("Camera has changed!");
	}

	function anotherChangeFunc(camera) {
		console.log("Camera has changed again!");
	}

	hwv.setCallbacks({
		camera: myCameraChangeFunc,
	});

	hwv.setCallbacks({
		camera: anotherChangeFunc,
	});

After setting those callbacks the following output will be produced in the browser console every time the camera was changed:

``Camera has changed!
Camera has changed again!``


Unregistering callbacks
=======================

When unregistering callback functions, it is important to note that the function object passed to :ref:`unsetCallbacks()  <api_ref/viewing/classes/Communicator.WebViewer:unsetcallbacks>` must be the same one which was passed to :ref:`setCallbacks()  <api_ref/viewing/classes/Communicator.WebViewer:setcallbacks>` when the callback has been registered.

.. literalinclude:: /../../applications/client/docs/Callbacks.ts
   :start-after: //! [unset_callbacks]
   :end-before: //! [unset_callbacks]


Important callbacks
===================

Most of the important callbacks will be discussed in various topics throughout this Programming Guide. Below we briefly mention some of the more important callbacks along with their description:

**Info** - This callback gets triggered when an "informational" message is generated by the HOOPS Web Viewer component. Those can be errors or warnings or just general info.

**XHRonerror, XHRonloadend, XHRonprogress** - When loading an scs file, these callbacks gets triggered by the HTTPRequest to the webserver that retrieves the file. To detect if an error has occurred (e.g., a wrong filename has been specified) the XHRonerror callback can be useful.

**sceneReady** - When this callback is executed, the HOOPS Web Viewer component is initialized and functions that don't require the model structure (like setting the background color of the 3D Window) can be safely called.

**subtreeLoaded** - The above callback will be executed after a new model has been added to an existing scene usually by calling one of the ``loadSubtree(...)`` functions. Please see :doc:`here </prog_guide/viewing/data_model/stream_cache/loading-subtrees>` for more information.

**modelStructureReady, modelStructureHeaderParsed** - It is important to wait for the modelStructureReady callback before fully interacting with the model structure. This includes performing any kind of selection on the model. If you only want to query certain attributes of the model you can also set the ``modelStructureHeaderParsed`` callback which will be executed very shortly after the viewer has been initialized. Please see the :doc:`Model Tree Programming Guide </prog_guide/viewing/data_model/model-tree>` for more information.

**beginInteraction, endInteraction** - These callbacks get triggered at the beginning and end of an operator interaction. Please see :doc:`this page </prog_guide/viewing/operators/operators>` for more information on operators and operator-specific events.
		
**contextMenu** - By listening for this callback the application can be notified when the context menu is about to be shown and perform relevant actions.

**Deprecated** - The purpose of this callback is to make it easy for you to identify if your application uses functions that are deprecated and might be removed in a future version of HOOPS Communicator.

**streamingActivated, streamingDeactivated** - These callbacks get executed during model streaming whenever the HOOPS Web Viewer component starts or stops the streaming process. Because the Web Viewer retains some model data on the server depending on its location and size, those callbacks can trigger many times throughout a viewing session.

**timeout, timeoutWarning** - With setClientTimeout(), you can specify how long the viewer should be active if it is in an idle state and receives no user input. You can also call ``resetClientTimeout()`` to manually restart the timeout timer. These callbacks above get triggered when a timeout has occurred and when a timeout is imminent.

**webGlContextLost** - This callback is usually the sign of a catastrophic error in the browser, sometimes related to the Web Viewer component using too many resources. It is not possible to recover from this error without reloading the web page.

**websocketConnectionClosed** - This callback gets triggered if the server closes the websocket connection to the client, usually due to an unexpected error/crash of the HOOPS Server.
