Enhance debugging utilities for developers

This commit is contained in:
Ryan McGrath 2011-07-11 08:29:39 -04:00
parent 372cd854b1
commit 319bdaf885
4 changed files with 215 additions and 53 deletions

View file

@ -9,6 +9,19 @@
*/ */
Wii.util = { Wii.util = {
/**
* A placeholder for the original Error function, since we pretty much overwrite it to actually
* be useful to us. See "Wii.installListeners()" for more information on this.
*/
originalErrFunction: null,
/**
* Upon first call to Wii.util.debug(), this becomes a div that we keep
* a reference to. It's primarily used for logging information to the screen
* on the Wii itself.
*/
msgNode: null,
/** /**
* Wii.util.debug(err); * Wii.util.debug(err);
* *
@ -18,37 +31,46 @@ Wii.util = {
* try { ... } catch(e) { Wii.util.debug(e); } * try { ... } catch(e) { Wii.util.debug(e); }
*/ */
debug: function(err) { debug: function(err) {
if(Wii.debuggerDiv === null) { if(Wii.util.msgNode === null) {
Wii.debuggerDiv = document.createElement('div'); Wii.util.msgNode = document.createElement('div');
Wii.debuggerDiv.style.cssText = [ Wii.util.msgNode.style.cssText = [
'width: 90%;', 'min-width: 756px;',
'height: 90%;',
'padding: 10px;', 'padding: 10px;',
'font-size: 26px;', 'font-size: 28px;',
'line-height: 32px;',
'font-family: monospace;', 'font-family: monospace;',
'overflow: scroll',
'position: absolute;', 'position: absolute;',
'top: 10px;', 'top: 10px;',
'left: 10px;', 'left: 10px;',
'color: #f9f9f9;', 'color: #f9f9f9;',
'background-color: #010101;' 'background-color: rgba(44, 44, 44, .7);',
'border: 2px solid #42a2cc;'
].join(''); ].join('');
document.body.appendChild(Wii.debuggerDiv); Wii.util.msgNode.addEventListener('click', Wii.util.hideDebugger, false);
document.body.appendChild(Wii.util.msgNode);
} }
if(typeof err === 'string') { if(typeof err === 'string') {
Wii.debuggerDiv.innerHTML = err; Wii.debuggerDiv.innerHTML = err;
} else { } else {
var msg = ''; var msg = '';
for(var e in err) { msg += e + '=' + err[e] + '<br>'; } for(var e in err) { msg += '<span style="color: #42a2cc; font-weight: bold;">' + e + '</span>=' + err[e] + '<br>'; }
Wii.debuggerDiv.innerHTML = msg; Wii.debuggerDiv.innerHTML = msg;
} }
Wii.debuggerDiv.style.display = 'block'; Wii.debuggerDiv.style.display = 'block';
}, },
/**
* Wii.util.hideDebugger()
*
* Keep this around so we've got an easy reference to use for proper unloading
* of event handlers once someone leaves this page.
*/
hideDebugger: function() { this.style.display = 'none'; },
/** /**
* Wiimote.util.bind(bindReference, fn) * Wiimote.util.bind(bindReference, fn)
* *

View file

@ -23,31 +23,86 @@ var Wii = {
* through on each loop/iteration and poll for a new status on it. * through on each loop/iteration and poll for a new status on it.
*/ */
extraRemotes: [], extraRemotes: [],
/**
* A "global" reference to the (current) primary Wiimote. This can change if the
* primary Wiimote runs out of battery, and the library shoul transparently account
* for this.
*/
currentBrowsingRemote: null, currentBrowsingRemote: null,
setKeyListeners: false,
debuggerDiv: null /**
* Internal flag for whether or not we've actually set some document event listeners.
* A little messy, sure, but not the biggest guffaw in the world.
*/
setListeners: false,
/**
* A global debug flag. If this is enabled/set to true, any errors raised will be thrown
* up on the screen for the Wii. Should be set when the initial .listen() request is fired.
*
* e.g, Wii.listen({debug: true});
*/
debug: false,
/**
* The primary Wiimote depends on typical DOM-esque events to communicate what actions it's
* doing, and the other three use a whole bitmask-esque scenario. This is a "global" Array of
* the events we're interested in for the primary Wiimote.
*
* We catch multiple begin/endpoints for these full event "scopes" for
* future use, as it seems like it'll probably be the most performant way
* to do rapid-quick checks for the primary Wii-mote as to multiple-button
* press scenarios (among some other things).
*/
primaryWiimoteEvts: ['mouseup', 'mousedown', 'keyup', 'keydown', 'keypress'],
}; };
/** /**
* Wii.installListeners()
*
* Install some basic low-level event listeners to monitor how * Install some basic low-level event listeners to monitor how
* the primary wii_remote is interacting with the browser; it's treated * the primary wii_remote is interacting with the browser; it's treated
* differently than the other wii_remotes, more as a "browsing" tool than * differently than the other wii_remotes, more as a "browsing" tool than
* a controller. Doesn't mean we can't try and mend the gap... * a controller. Doesn't mean we can't try and mend the gap...
*/ */
Wii.installKeyListeners = function() { Wii.installListeners = function() {
document.addEventListener('mouseup', Wii.parsePrimaryWiimote, false); for(var i = 0, j = Wii.primaryWiimoteEvts.length; i < j; i++) {
document.addEventListener('keydown', Wii.parsePrimaryWiimote, false); document.addEventListener(Wii.primaryWiimoteEvts[i], Wii.parsePrimaryWiimote, false);
document.addEventListener('mousedown', Wii.parsePrimaryWiimote, false); }
document.addEventListener('keyup', Wii.parsePrimaryWiimote, false);
/** /**
* Some keys, like the directional ones, get... multiple events? * Since the Wii is already a fairly low-spec system, it's definitely worth
* In this case, just shut. down. everything. * cleaning up after ourselves if we can get around to it. This should (hopefully)
* * take care of most of what we need to worry about.
* ...and let the programmer deal with it.
*/ */
document.addEventListener('keypress', Wii.parsePrimaryWiimote, false); window.onbeforeunload = function() {
for(var i = 0, j = Wii.primaryWiimoteEvts.length; i < j; i++) {
document.removeEventListener(Wii.primaryWiimoteEvts[i], Wii.parsePrimaryWiimote, false);
}
};
/**
* If this is all listening in debug mode, we wanna try and catch everything that could
* possibly go wrong in the stack. try/catch is very expensive for the entire program, and can
* crash the Wii pretty easily if you push it too much.
*
* What we'll do instead is just patch the seemingly un-documented window.Error function to suit our
* debugging needs, and only try/catch while in debug mode in critical places (e.g, the constant polling
* section would be... yeah, not a fun idea).
*
* With this, "throw new Error(error)" will actually hit over to what we want, and anything else (outside code)
* using it will get the on-screen Wii debug which is actually useful. That's why we bother doing this, instead
* of just calling Wii.util.debug() everywhere. ;)
*/
if(Wii.debug) {
Wii.util.originalErrFunction = window.Error;
window.Error = function() {
if(arguments.length > 0) Wii.util.debug(arguments[0]);
else Wii.util.originalErrFunction.apply(this, arguments);
}
}
return true; return true;
}; };
@ -57,8 +112,12 @@ Wii.installKeyListeners = function() {
* The main game loop. This must stay very performant; try to keep things as absolutely * The main game loop. This must stay very performant; try to keep things as absolutely
* low-level as possible here. * low-level as possible here.
*/ */
Wii.listen = function() { Wii.listen = function(optional_opts) {
if(!Wii.setKeyListeners) Wii.setKeyListeners = Wii.installKeyListeners(); if(typeof optional_opts !== 'undefined') {
if(typeof optional_opts.debug !== 'undefined' && optional_opts.debug) Wii.debug = true;
}
if(!Wii.setListeners) Wii.setListeners = Wii.installListeners();
var i = Wii.extraRemotes.length; var i = Wii.extraRemotes.length;

133
js/wii.js
View file

@ -46,31 +46,86 @@ var Wii = {
* through on each loop/iteration and poll for a new status on it. * through on each loop/iteration and poll for a new status on it.
*/ */
extraRemotes: [], extraRemotes: [],
/**
* A "global" reference to the (current) primary Wiimote. This can change if the
* primary Wiimote runs out of battery, and the library shoul transparently account
* for this.
*/
currentBrowsingRemote: null, currentBrowsingRemote: null,
setKeyListeners: false,
debuggerDiv: null /**
* Internal flag for whether or not we've actually set some document event listeners.
* A little messy, sure, but not the biggest guffaw in the world.
*/
setListeners: false,
/**
* A global debug flag. If this is enabled/set to true, any errors raised will be thrown
* up on the screen for the Wii. Should be set when the initial .listen() request is fired.
*
* e.g, Wii.listen({debug: true});
*/
debug: false,
/**
* The primary Wiimote depends on typical DOM-esque events to communicate what actions it's
* doing, and the other three use a whole bitmask-esque scenario. This is a "global" Array of
* the events we're interested in for the primary Wiimote.
*
* We catch multiple begin/endpoints for these full event "scopes" for
* future use, as it seems like it'll probably be the most performant way
* to do rapid-quick checks for the primary Wii-mote as to multiple-button
* press scenarios (among some other things).
*/
primaryWiimoteEvts: ['mouseup', 'mousedown', 'keyup', 'keydown', 'keypress'],
}; };
/** /**
* Wii.installListeners()
*
* Install some basic low-level event listeners to monitor how * Install some basic low-level event listeners to monitor how
* the primary wii_remote is interacting with the browser; it's treated * the primary wii_remote is interacting with the browser; it's treated
* differently than the other wii_remotes, more as a "browsing" tool than * differently than the other wii_remotes, more as a "browsing" tool than
* a controller. Doesn't mean we can't try and mend the gap... * a controller. Doesn't mean we can't try and mend the gap...
*/ */
Wii.installKeyListeners = function() { Wii.installListeners = function() {
document.addEventListener('mouseup', Wii.parsePrimaryWiimote, false); for(var i = 0, j = Wii.primaryWiimoteEvts.length; i < j; i++) {
document.addEventListener('keydown', Wii.parsePrimaryWiimote, false); document.addEventListener(Wii.primaryWiimoteEvts[i], Wii.parsePrimaryWiimote, false);
document.addEventListener('mousedown', Wii.parsePrimaryWiimote, false); }
document.addEventListener('keyup', Wii.parsePrimaryWiimote, false);
/** /**
* Some keys, like the directional ones, get... multiple events? * Since the Wii is already a fairly low-spec system, it's definitely worth
* In this case, just shut. down. everything. * cleaning up after ourselves if we can get around to it. This should (hopefully)
* * take care of most of what we need to worry about.
* ...and let the programmer deal with it.
*/ */
document.addEventListener('keypress', Wii.parsePrimaryWiimote, false); window.onbeforeunload = function() {
for(var i = 0, j = Wii.primaryWiimoteEvts.length; i < j; i++) {
document.removeEventListener(Wii.primaryWiimoteEvts[i], Wii.parsePrimaryWiimote, false);
}
};
/**
* If this is all listening in debug mode, we wanna try and catch everything that could
* possibly go wrong in the stack. try/catch is very expensive for the entire program, and can
* crash the Wii pretty easily if you push it too much.
*
* What we'll do instead is just patch the seemingly un-documented window.Error function to suit our
* debugging needs, and only try/catch while in debug mode in critical places (e.g, the constant polling
* section would be... yeah, not a fun idea).
*
* With this, "throw new Error(error)" will actually hit over to what we want, and anything else (outside code)
* using it will get the on-screen Wii debug which is actually useful. That's why we bother doing this, instead
* of just calling Wii.util.debug() everywhere. ;)
*/
if(Wii.debug) {
Wii.util.originalErrFunction = window.Error;
window.Error = function() {
if(arguments.length > 0) Wii.util.debug(arguments[0]);
else Wii.util.originalErrFunction.apply(this, arguments);
}
}
return true; return true;
}; };
@ -80,8 +135,12 @@ Wii.installKeyListeners = function() {
* The main game loop. This must stay very performant; try to keep things as absolutely * The main game loop. This must stay very performant; try to keep things as absolutely
* low-level as possible here. * low-level as possible here.
*/ */
Wii.listen = function() { Wii.listen = function(optional_opts) {
if(!Wii.setKeyListeners) Wii.setKeyListeners = Wii.installKeyListeners(); if(typeof optional_opts !== 'undefined') {
if(typeof optional_opts.debug !== 'undefined' && optional_opts.debug) Wii.debug = true;
}
if(!Wii.setListeners) Wii.setListeners = Wii.installListeners();
var i = Wii.extraRemotes.length; var i = Wii.extraRemotes.length;
@ -298,6 +357,19 @@ Wii.DISPATCHER = {
*/ */
Wii.util = { Wii.util = {
/**
* A placeholder for the original Error function, since we pretty much overwrite it to actually
* be useful to us. See "Wii.installListeners()" for more information on this.
*/
originalErrFunction: null,
/**
* Upon first call to Wii.util.debug(), this becomes a div that we keep
* a reference to. It's primarily used for logging information to the screen
* on the Wii itself.
*/
msgNode: null,
/** /**
* Wii.util.debug(err); * Wii.util.debug(err);
* *
@ -307,37 +379,46 @@ Wii.util = {
* try { ... } catch(e) { Wii.util.debug(e); } * try { ... } catch(e) { Wii.util.debug(e); }
*/ */
debug: function(err) { debug: function(err) {
if(Wii.debuggerDiv === null) { if(Wii.util.msgNode === null) {
Wii.debuggerDiv = document.createElement('div'); Wii.util.msgNode = document.createElement('div');
Wii.debuggerDiv.style.cssText = [ Wii.util.msgNode.style.cssText = [
'width: 90%;', 'min-width: 756px;',
'height: 90%;',
'padding: 10px;', 'padding: 10px;',
'font-size: 26px;', 'font-size: 28px;',
'line-height: 32px;',
'font-family: monospace;', 'font-family: monospace;',
'overflow: scroll',
'position: absolute;', 'position: absolute;',
'top: 10px;', 'top: 10px;',
'left: 10px;', 'left: 10px;',
'color: #f9f9f9;', 'color: #f9f9f9;',
'background-color: #010101;' 'background-color: rgba(44, 44, 44, .7);',
'border: 2px solid #42a2cc;'
].join(''); ].join('');
document.body.appendChild(Wii.debuggerDiv); Wii.util.msgNode.addEventListener('click', Wii.util.hideDebugger, false);
document.body.appendChild(Wii.util.msgNode);
} }
if(typeof err === 'string') { if(typeof err === 'string') {
Wii.debuggerDiv.innerHTML = err; Wii.debuggerDiv.innerHTML = err;
} else { } else {
var msg = ''; var msg = '';
for(var e in err) { msg += e + '=' + err[e] + '<br>'; } for(var e in err) { msg += '<span style="color: #42a2cc; font-weight: bold;">' + e + '</span>=' + err[e] + '<br>'; }
Wii.debuggerDiv.innerHTML = msg; Wii.debuggerDiv.innerHTML = msg;
} }
Wii.debuggerDiv.style.display = 'block'; Wii.debuggerDiv.style.display = 'block';
}, },
/**
* Wii.util.hideDebugger()
*
* Keep this around so we've got an easy reference to use for proper unloading
* of event handlers once someone leaves this page.
*/
hideDebugger: function() { this.style.display = 'none'; },
/** /**
* Wiimote.util.bind(bindReference, fn) * Wiimote.util.bind(bindReference, fn)
* *

2
js/wii.min.js vendored
View file

@ -1 +1 @@
(function(a){if(!a){return false}var b={extraRemotes:[],currentBrowsingRemote:null,setKeyListeners:false,debuggerDiv:null};b.installKeyListeners=function(){document.addEventListener("mouseup",b.parsePrimaryWiimote,false);document.addEventListener("keydown",b.parsePrimaryWiimote,false);document.addEventListener("mousedown",b.parsePrimaryWiimote,false);document.addEventListener("keyup",b.parsePrimaryWiimote,false);document.addEventListener("keypress",b.parsePrimaryWiimote,false);return true};b.listen=function(){if(!b.setKeyListeners){b.setKeyListeners=b.installKeyListeners()}var e=b.extraRemotes.length;while(e--){var g=b.extraRemotes[e],f=g.isEnabled();if(f){if(f.isBrowsing){b.currentBrowsingRemote=g}else{g.x=f.dpdScreenX;g.y=f.dpdScreenY;for(var c in g.evtsInterestedIn){var d=b.DISPATCHER[c](g,f);if(d){g.evtsInterestedIn[c](g,f)}}}}}return setTimeout(b.listen,100)};b.parsePrimaryWiimote=function(g){g.preventDefault();var f=b.currentBrowsingRemote,d=f.isEnabled(),c=b.PRIMARY_CONTROLLER_DISPATCHER[f.opts.horizontal?"horizontal":"vertical"][g.keyCode];f.x=d.dpdScreenX;f.y=d.dpdScreenY;if(typeof c!=="undefined"&&typeof f.evtsInterestedIn[c]==="function"){f.evtsInterestedIn[c](f,d)}if(typeof f.evtsInterestedIn.roll_change==="function"){if(b.DISPATCHER.roll_change(f,d)){f.evtsInterestedIn.roll_change(f,d)}}if(typeof f.evtsInterestedIn.distance_change==="function"){if(b.DISPATCHER.distance_change(f,d)){f.evtsInterestedIn.distance_change(f,d)}}return false};b.PRIMARY_CONTROLLER_DISPATCHER={vertical:{0:"pressed_a",13:"pressed_a",170:"pressed_minus",171:"pressed_b",172:"pressed_1",173:"pressed_2",174:"pressed_plus",175:"pressed_up",176:"pressed_down",177:"pressed_right",178:"pressed_left"},horizontal:{0:"pressed_a",13:"pressed_a",170:"pressed_minus",171:"pressed_b",172:"pressed_1",173:"pressed_2",174:"pressed_plus",175:"pressed_left",176:"pressed_right",177:"pressed_up",178:"pressed_down"}};b.DISPATCHER={pressed_up:function(d,c){if(d.opts.horizontal){return c.hold&2}return c.hold&8},pressed_right:function(d,c){if(d.opts.horizontal){return c.hold&4}return c.hold&2},pressed_down:function(d,c){if(d.opts.horizontal){return c.hold&1}return c.hold&4},pressed_left:function(d,c){if(d.opts.horizontal){return c.hold&8}return c.hold&1},pressed_plus:function(d,c){return c.hold&16},pressed_minus:function(d,c){return c.hold&4096},pressed_2:function(d,c){return c.hold&256},pressed_1:function(d,c){return c.hold&512},pressed_b:function(d,c){return c.hold&1024},pressed_a:function(d,c){return c.hold&2048},roll_change:function(e,d){var c=Math.atan2(d.dpdRollY,d.dpdRollX);if(c!==e.roll){e.roll=c;return true}return false},distance_change:function(d,c){if(c.dpdDistance!==d.last_known_distance_from_screen){d.last_known_distance_from_screen=c.dpdDistance;return true}return false},pressed_z:function(d,c){return c.hold&8192},pressed_c:function(d,c){return c.hold&16384}};b.util={debug:function(c){if(b.debuggerDiv===null){b.debuggerDiv=document.createElement("div");b.debuggerDiv.style.cssText=["width: 90%;","height: 90%;","padding: 10px;","font-size: 26px;","font-family: monospace;","overflow: scroll","position: absolute;","top: 10px;","left: 10px;","color: #f9f9f9;","background-color: #010101;"].join("");document.body.appendChild(b.debuggerDiv)}if(typeof c==="string"){b.debuggerDiv.innerHTML=c}else{var f="";for(var d in c){f+=d+"="+c[d]+"<br>"}b.debuggerDiv.innerHTML=f}b.debuggerDiv.style.display="block"},bind:function(c,d){return function(){return d.apply(c,arguments)}}};b.Remote=function(e,d){this.remote_id=e;this.opts=d;this.x=undefined;this.y=undefined;this.roll=undefined;this.last_known_distance_from_screen=undefined;var c=this.isEnabled();if(c){if(!c.isBrowsing){b.extraRemotes.push(this)}else{b.currentBrowsingRemote=this}}};b.Remote.prototype={opts:{horizontal:false},evtsInterestedIn:undefined,isEnabled:function(){var c=opera.wiiremote.update(this.remote_id-1);return(c.isEnabled&&c.isDataValid?c:false)},when:function(d,c){if(typeof b.DISPATCHER[d]!=="undefined"){if(this.evtsInterestedIn===undefined){this.evtsInterestedIn={}}this.evtsInterestedIn[d]=b.util.bind(this,c);return this}return undefined}};window.Wii=b})(window.opera&&opera.wiiremote); (function(a){if(!a){return false}var b={extraRemotes:[],currentBrowsingRemote:null,setListeners:false,debug:false,primaryWiimoteEvts:["mouseup","mousedown","keyup","keydown","keypress"],};b.installListeners=function(){for(var d=0,c=b.primaryWiimoteEvts.length;d<c;d++){document.addEventListener(b.primaryWiimoteEvts[d],b.parsePrimaryWiimote,false)}window.onbeforeunload=function(){for(var f=0,e=b.primaryWiimoteEvts.length;f<e;f++){document.removeEventListener(b.primaryWiimoteEvts[f],b.parsePrimaryWiimote,false)}};if(b.debug){b.util.originalErrFunction=window.Error;window.Error=function(){if(arguments.length>0){b.util.debug(arguments[0])}else{b.util.originalErrFunction.apply(this,arguments)}}}return true};b.listen=function(h){if(typeof h!=="undefined"){if(typeof h.debug!=="undefined"&&h.debug){b.debug=true}}if(!b.setListeners){b.setListeners=b.installListeners()}var e=b.extraRemotes.length;while(e--){var g=b.extraRemotes[e],f=g.isEnabled();if(f){if(f.isBrowsing){b.currentBrowsingRemote=g}else{g.x=f.dpdScreenX;g.y=f.dpdScreenY;for(var c in g.evtsInterestedIn){var d=b.DISPATCHER[c](g,f);if(d){g.evtsInterestedIn[c](g,f)}}}}}return setTimeout(b.listen,100)};b.parsePrimaryWiimote=function(g){g.preventDefault();var f=b.currentBrowsingRemote,d=f.isEnabled(),c=b.PRIMARY_CONTROLLER_DISPATCHER[f.opts.horizontal?"horizontal":"vertical"][g.keyCode];f.x=d.dpdScreenX;f.y=d.dpdScreenY;if(typeof c!=="undefined"&&typeof f.evtsInterestedIn[c]==="function"){f.evtsInterestedIn[c](f,d)}if(typeof f.evtsInterestedIn.roll_change==="function"){if(b.DISPATCHER.roll_change(f,d)){f.evtsInterestedIn.roll_change(f,d)}}if(typeof f.evtsInterestedIn.distance_change==="function"){if(b.DISPATCHER.distance_change(f,d)){f.evtsInterestedIn.distance_change(f,d)}}return false};b.PRIMARY_CONTROLLER_DISPATCHER={vertical:{0:"pressed_a",13:"pressed_a",170:"pressed_minus",171:"pressed_b",172:"pressed_1",173:"pressed_2",174:"pressed_plus",175:"pressed_up",176:"pressed_down",177:"pressed_right",178:"pressed_left"},horizontal:{0:"pressed_a",13:"pressed_a",170:"pressed_minus",171:"pressed_b",172:"pressed_1",173:"pressed_2",174:"pressed_plus",175:"pressed_left",176:"pressed_right",177:"pressed_up",178:"pressed_down"}};b.DISPATCHER={pressed_up:function(d,c){if(d.opts.horizontal){return c.hold&2}return c.hold&8},pressed_right:function(d,c){if(d.opts.horizontal){return c.hold&4}return c.hold&2},pressed_down:function(d,c){if(d.opts.horizontal){return c.hold&1}return c.hold&4},pressed_left:function(d,c){if(d.opts.horizontal){return c.hold&8}return c.hold&1},pressed_plus:function(d,c){return c.hold&16},pressed_minus:function(d,c){return c.hold&4096},pressed_2:function(d,c){return c.hold&256},pressed_1:function(d,c){return c.hold&512},pressed_b:function(d,c){return c.hold&1024},pressed_a:function(d,c){return c.hold&2048},roll_change:function(e,d){var c=Math.atan2(d.dpdRollY,d.dpdRollX);if(c!==e.roll){e.roll=c;return true}return false},distance_change:function(d,c){if(c.dpdDistance!==d.last_known_distance_from_screen){d.last_known_distance_from_screen=c.dpdDistance;return true}return false},pressed_z:function(d,c){return c.hold&8192},pressed_c:function(d,c){return c.hold&16384}};b.util={originalErrFunction:null,msgNode:null,debug:function(c){if(b.util.msgNode===null){b.util.msgNode=document.createElement("div");b.util.msgNode.style.cssText=["min-width: 756px;","padding: 10px;","font-size: 28px;","line-height: 32px;","font-family: monospace;","position: absolute;","top: 10px;","left: 10px;","color: #f9f9f9;","background-color: rgba(44, 44, 44, .7);","border: 2px solid #42a2cc;"].join("");b.util.msgNode.addEventListener("click",b.util.hideDebugger,false);document.body.appendChild(b.util.msgNode)}if(typeof c==="string"){b.debuggerDiv.innerHTML=c}else{var f="";for(var d in c){f+='<span style="color: #42a2cc; font-weight: bold;">'+d+"</span>="+c[d]+"<br>"}b.debuggerDiv.innerHTML=f}b.debuggerDiv.style.display="block"},hideDebugger:function(){this.style.display="none"},bind:function(c,d){return function(){return d.apply(c,arguments)}}};b.Remote=function(e,d){this.remote_id=e;this.opts=d;this.x=undefined;this.y=undefined;this.roll=undefined;this.last_known_distance_from_screen=undefined;var c=this.isEnabled();if(c){if(!c.isBrowsing){b.extraRemotes.push(this)}else{b.currentBrowsingRemote=this}}};b.Remote.prototype={opts:{horizontal:false},evtsInterestedIn:undefined,isEnabled:function(){var c=opera.wiiremote.update(this.remote_id-1);return(c.isEnabled&&c.isDataValid?c:false)},when:function(d,c){if(typeof b.DISPATCHER[d]!=="undefined"){if(this.evtsInterestedIn===undefined){this.evtsInterestedIn={}}this.evtsInterestedIn[d]=b.util.bind(this,c);return this}return undefined}};window.Wii=b})(window.opera&&opera.wiiremote);