If you are targeting browsers that support it, you can use the Page Visibility API available in HTML5. It doesn't directly detect tab changes, per-say, but visibility changes. Which would include (but not limited to) tab changes.
Working on a similar project. This worked the best. On the highest level component which wouldn't normally rerender, add:
setInterval( checkFocus, 200 );
function checkFocus(){
if(document.hasFocus()==false){
//Do some checking and raise a red flag if this runs during an exam.
}
}