# PostMessage to Parent

This extension helps send messages between Numbas and the window it has been embedded in.
A key can be passed to the extension that is relayed back in future messages, so as to help with
identification in the case of embedding multiple frames on a single page.

## Example Usage in a Numbas Exam
By default messages are sent when the exam first loads, when the inner window height changes, or when a user submits an answer.

In addition, a JME function, `post_message`, has been added that can be used to send other messages to an outer frame.
The first argument of this function is the data to pass, the second argument is a dictionary of options.
The `origin` option can be added to target specific outer window hosts. By default the origin is `*`, which is a wildcard.

For example,
```
post_message(["a": 1, "b": 2, "c": 3], ["origin": "host.exampledomain.ac.uk"])
```

Messages are sent to the outermost window, via the Javascript varaible `window.top`.

## Example Usage in the Outer Window
The following is an example of some Javascript in an outer window setup to listen for the default messages from an
embedded Numbas exam that loads this extension.
```
<script>
	// Helper function to recursively post messages to embedded frames
	function postToFrames(frames, data, origin) {
		for (var i=0; i < frames.length; i++) {
			frames[i].postMessage(data, origin);
			if(frames[i].frames.length > 0)
				postToFrames(frames[i].frames, data, origin)
		}
	}

	// Post a message to an embedded Numbas exam passing in an identification key
	// The key lets us know which frame future recieved messages are coming from
	document.getElementById("a-numbas-exam").addEventListener("load", function(){
		setTimeout(function(){
			postToFrames(window.frames,JSON.stringify({"message":"send_id","id":"a-numbas-exam"}),"*");
		},0);
	});

	// Listen for messages from an embedded Numbas exam
	window.addEventListener('message', function(event) {
		var data = JSON.parse(event.data);
		if('message' in data) {
			switch(data['message']){
				case 'height_changed':
					var recvFrameID = data['frame_id'];
					document.getElementById(recvFrameID).style.height = parseInt(data.documentHeight+50) + "px";
					break;
				case 'exam_ready':
					var recvFrameID = data['frame_id'];
					document.getElementById(`${recvFrameID}_marks`).innerText = data.exam.marks;
					break;
				case 'part_answered':
					var recvFrameID = data['frame_id'];
					document.getElementById(`${recvFrameID}_score`).innerText = data.exam.score;
					break;
				default:
					console.log(data);
			}
		}
	});
</script>
```