Table of Contents

Debug Console

About

This debug console is a recreation in 2021 of what was used to debug JavaScript on the Cure Interactive website in 2014 and 2015 while on the Safari mobile browser on Apple's iOS operating system, where access to the browser log was not possible without hooking up the device to a development application via a USB to PC connection.

The way it works is by firing a simple command such as debugConsole().log("A basic log message");, which will send the message to the on-screen Debug Console as well as the browser console log. The idea is that instead of using the console log as is typical (such as console.log("A basic log message");) you would use the former command to see the results of you log message in both the webpage and the log, allowing easier review of log entries on mobile than otherwise would be possible.

The entries that are viewable in the Debug Console on this page are shown below.

function debug_console_test() {
  debugConsole()  .log( "A basic log message"       );
  debugConsole() .info( "An information message"    );
  debugConsole() .warn( "A warning message"         );
  debugConsole().error( "An error message"          );

  debugConsole().log( " " );

  for (i = 0; i <   3; i++) { debugConsole()  .log( "Duplicate basic log messages"   ); }
  for (i = 0; i < 153; i++) { debugConsole() .info( "Duplicate information messages" ); }
  for (i = 0; i <  28; i++) { debugConsole() .warn( "Duplicate warning messages"     ); }
  for (i = 0; i <   4; i++) { debugConsole().error( "Duplicate error messages"       ); }

  debugConsole().log( " " );

  debugConsole().info( "A very long log message to demonstrate word wrapping in the Debug Console as well as demonstrating the behavior of the Debug Console Log title's sticky position. Just to be on the safe side, here is even more text to occupy space and ensure this adds enough height to the Debug Console Log." );
  debugConsole().info( "A second very long log message to demonstrate word wrapping in the Debug Console as well as demonstrating the behavior of the Debug Console Log title's sticky position. Just to be on the safe side, here is even more text to occupy space and ensure this adds enough height to the Debug Console Log." );
  debugConsole().info( "A third very long log message to demonstrate word wrapping in the Debug Console as well as demonstrating the behavior of the Debug Console Log title's sticky position. Just to be on the safe side, here is even more text to occupy space and ensure this adds enough height to the Debug Console Log." );
}

Known Issues

  • When displaying line and column location for a minified file that has a map generated for it, the Debug Console does not show the map's line and column numbers. This functionality has not been added.

The Code

HTML

<div id="debug_console">
  <h2 class="debug_console__name toc-ignore">Debug Console</h2>
  <div class="debug_console__inner">
    <ul type="none" id="debug_console__page_details" class="clearfix">
      <li class="clearfix"><span>window</span><span class="debug_console__page_details__value">.innerWidth: <span id="debug_console__screen_width"></span>, .innerHeight: <span id="debug_console__screen_height"></span></li>
      <li class="clearfix"><span>window.screen</span><span class="debug_console__page_details__value">.width: <span id="debug_console__window_width"></span>, .height: <span id="debug_console__window_height"></span></li>
      <li class="clearfix"><span>window.devicePixelRatio:</span><span id="debug_console__pixel_ratio" class="debug_console__page_details__value"></span></li>
      <li class="clearfix">
        <div id="debug_console__url__title">
          <span>[window.location.*]<br></span><!--
          --><span class="debug_console__url__protocol">[protocol]</span><!--
          -->//<!--
          --><span class="debug_console__url__hostname">[hostname]</span><!--
          -->:<!--
          --><span class="debug_console__url__port">[port]</span><!--
          --><span class="debug_console__url__pathname">[pathname]</span><!--
          --><span class="debug_console__url__search">[search]</span><!--
          --><span class="debug_console__url__hash">[hash]</span>
        </div>
        <div id="debug_console__url" style="position:initial"></div>
      </li>
    </ul>
    <h2 class="toc-ignore">console.log</h2>
    <ul type="none" id="debug_console__log"></ul>
  </div>
  <div class="debug_console__panel">
    <button id="debug_console__input_shrink" class="btn btn-default btn-inline" type="button" title="Shrink Debug Console">Shrink</button>
    <button id="debug_console__input_open" class="btn btn-default btn-inline" type="button" title="Open Debug Console">Open</button>
  </div>
</div>

CSS

#debug_console {
  background: #0e0e0e;
  color: #D7D7DB;
  border-radius: 4px;
  padding: 8px 0px;
  pointer-events: auto;
  width: 100%;
}

#debug_console .debug_console__panel {
  padding-left: 16px;
  padding-right: 16px;
  text-align: right;
  width: 100%;
}

#debug_console .debug_console__panel>* {
  display: inline-block;
  text-align: right;
}

#debug_console .debug_console__panel>*:last-child {
  margin-right: 0px;
}

#debug_console #debug_console__page_details {
  border-bottom: 1px solid #29536a;
}

#debug_console #debug_console__page_details .debug_console__page_details__value {
  float: right;
}

#debug_console #debug_console__page_details li>:first-child {
  margin-right: 0.5em;
}

#debug_console #debug_console__page_details .debug_console__url__protocol {
  color: #ff7f7f;
}

#debug_console #debug_console__page_details .debug_console__url__hostname {
  color: #FF9f7f;
}

#debug_console #debug_console__page_details .debug_console__url__port {
  color: #FFFF7f;
}

#debug_console #debug_console__page_details .debug_console__url__pathname {
  color: #7fFF7f;
}

#debug_console #debug_console__page_details .debug_console__url__search {
  color: #7fffff;
}

#debug_console #debug_console__page_details .debug_console__url__hash {
  color: #7f9fff;
}

#debug_console #debug_console__log li {
  padding-left: 2.125em;
}

#debug_console h2.debug_console__name {
  bottom: 1.5em;
  margin: 0px;
  padding-bottom: 2px;
  padding-left: 16px;
  position: absolute;
}

#debug_console:not(.opened) #debug_console__input_shrink {
  display: none;
}

#debug_console,#debug_console .debug_console__inner {
  -webkit-transition: all 375ms cubic-bezier(0.25, 0, 0.25, 1);
  -moz-transition: all 375ms cubic-bezier(0.25, 0, 0.25, 1);
  -o-transition: all 375ms cubic-bezier(0.25, 0, 0.25, 1);
  transition: all 375ms cubic-bezier(0.25, 0, 0.25, 1);
}

#debug_console .debug_console__inner {
  background: inherit;
  border: 0px solid rgba(85,146,172,0);
  font-size: 0.875em;
  margin-bottom: 0px;
  max-height: 0px;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}

#debug_console .debug_console__inner h2 {
  background: inherit;
  border-bottom: 1px solid rgba(85,146,172,0.25);
  padding: 8px;
  position: sticky;
  top: 0;
  z-index: 1;
}

#debug_console .debug_console__inner ul {
  font-family: monospace;
  line-height: 1.5;
  padding: 0px;
  margin: 0px;
}

#debug_console .debug_console__inner ul li {
  margin-bottom: 0px;
  margin-top: 0px;
  padding: 8px;
  word-wrap: break-word;
}

#debug_console .debug_console__inner ul li:not(:first-of-type) {
  border-top-width: 1px;
  border-top-style: solid;
  border-top-color: #fff;
  border-top-color: rgba(255,255,255,0.2);
}

#debug_console .debug_console__inner ul li span.debug_console__log__entry__details {
  float: right;
  margin-left: 8px;
  text-align: right;
}

#debug_console .debug_console__inner ul li span.debug_console__log__entry__details>*:not(:last-child):not(.debug_console__log__entry__details__location--file) {
  margin-right: 8px;
}

#debug_console .debug_console__inner ul li span.debug_console__log__entry__details__count {
  background: #9898A8;
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
  color: black;
  font-weight: bold;
  padding: 0px 0.45em;
  min-width: 1.45em;
  opacity: .75;
  filter: alpha(opacity=75);
}

#debug_console .debug_console__inner ul li div.debug-icon {
  display: inline-block;
  height: 1em;
  width: 1em;
  margin-left: -1.625em;
  margin-right: 0.625em;
  vertical-align: text-top;
}

#debug_console .debug_console__inner ul li span.debug_console__log__entry__details__level {
  display: none;
}

#debug_console .debug_console__inner ul li.debug-info,#debug_console .debug_console__inner ul li.debug-info span.debug_console__log__entry__details__level {
  color: cyan;
}

#debug_console .debug_console__inner ul li.debug-info span {
  color: lightblue;
}

#debug_console .debug_console__inner ul li.debug-info span.debug_console__log__entry__details__count {
  background: lightblue;
}

#debug_console .debug_console__inner ul li.debug-info div.debug-icon {
  background-image: url("/images/interface/debug_console/info.png");
  background-size: contain;
}

#debug_console .debug_console__inner ul li.debug-warn,#debug_console .debug_console__inner ul li.debug-warn span.debug_console__log__entry__details__level {
  color: yellow;
}

#debug_console .debug_console__inner ul li.debug-warn span {
  color: khaki;
}

#debug_console .debug_console__inner ul li.debug-warn span.debug_console__log__entry__details__count {
  background: khaki;
}

#debug_console .debug_console__inner ul li.debug-warn div.debug-icon {
  background-image: url("/images/interface/debug_console/warning.png");
  background-size: contain;
}

#debug_console .debug_console__inner ul li.debug-error,#debug_console .debug_console__inner ul li.debug-error span.debug_console__log__entry__details__level {
  color: red;
}

#debug_console .debug_console__inner ul li.debug-error span {
  color: indianred;
}

#debug_console .debug_console__inner ul li.debug-error span.debug_console__log__entry__details__count {
  background: indianred;
}

#debug_console .debug_console__inner ul li.debug-error div.debug-icon {
  background-image: url("/images/interface/debug_console/error.png");
  background-size: contain;
}

#debug_console .debug_console__inner ul li span.debug_console__log__entry__details__count {
  color: black;
}

#debug_console .debug_console__inner ul li span.debug_console__log__entry__details__location {
  margin-top: 3px;
}

#debug_console .debug_console__inner>*:first-child {
  border-top: 4px solid #29536a;
  background: #000000;
  background: -webkit-gradient(linear, left top, left bottom, from(rgba(41,83,106,0.25)), to(rgba(41,83,106,0)));
  background: -moz-linear-gradient(top, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  background: -webkit-linear-gradient(top, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  background: -o-linear-gradient(top, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  background: -ms-linear-gradient(top, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  background: linear-gradient(to bottom, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0A151B', endColorstr='#000000',GradientType=0 );
}

#debug_console .debug_console__inner>*:last-child {
  border-bottom: 4px solid #29536a;
  background: #000000;
  background: -webkit-gradient(linear, left bottom, left top, from(rgba(41,83,106,0.25)), to(rgba(41,83,106,0)));
  background: -moz-linear-gradient(bottom, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  background: -webkit-linear-gradient(bottom, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  background: -o-linear-gradient(bottom, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  background: -ms-linear-gradient(bottom, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  background: linear-gradient(to top, rgba(41,83,106,0.25) 0px, rgba(41,83,106,0) 100px);
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0A151B', endColorstr='#000000',GradientType=0 );
}

#debug_console.opened .debug_console__inner {
  border: 1px solid rgba(85,146,172,0.25);
  margin-bottom: 8px;
  max-height: 50vh;
}

#debug_console.opened.shrunk .debug_console__inner {
  max-height: 15vh;
}

#debug_console #debug_console__url__title,#debug_console .debug_console__inner li span.debug_console__log__entry__details__location {
  opacity: .5;
  filter: alpha(opacity=50);
}

@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2), (min-resolution: 192dpi), (min-resolution: 2dppx) {
  #debug_console .debug_console__inner ul li.debug-info div.debug-icon {
    background-image: url("/images/interface/debug_console/info.x2.png");
  }

  #debug_console .debug_console__inner ul li.debug-warn div.debug-icon {
    background-image: url("/images/interface/debug_console/warning.x2.png");
  }

  #debug_console .debug_console__inner ul li.debug-error div.debug-icon {
    background-image: url("/images/interface/debug_console/error.x2.png");
  }
}

JavaScript

// =============================================================================
// events.js

function addEvent(evnts, elems, func) {
  var evntLength = 1;
  if ( evnts instanceof Array ) evntLength = evnts.length;

  var elemLength = elems.length || 1;
  if ( elems instanceof Array ) elemLength = elems.length;

  for (var i = 0; i < evntLength; i++) {
    var evnt = evntLength == 1 ? evnts : evnts[i];

    for (var i = 0; i < elemLength; i++) {
      var elem = elemLength == 1 ? ( NodeList.prototype.isPrototypeOf(elems) ? elems[0] : elems ) : elems[i];

      if (elem.addEventListener) { // W3C DOM
        elem.addEventListener(evnt, func, false);
      }
      else if (elem.attachEvent) { // IE DOM
        elem.attachEvent('on' + evnt, func);
      }
      else { // No much to do
        elem['on' + evnt] = func;
      }
    }
  }
}

// =============================================================================
// classes.js

/**
 * Returns whether the given element has the given class.
 *
 * @param {Element} element
 * @param {string} className
 * @returns {boolean}
 */
function hasClass( element, className ) {
	className = ' ' + className + ' ';
	return ( ' ' + element.className + ' ' ).replace( /[\n\t]/g, ' ' ).indexOf( className ) > -1
}

function addClass( elements, className ) {
  if ( elements.length === undefined ) elements = [ elements ];
  for ( var i = 0; i < elements.length; i++ ) {
    var element = elements[ i ];

    if ( !hasClass( element, className ) ) {
      if ( element.classList ) {
        element.classList.add( className );
      } else {
        element.className = ( element.className + ' ' + className ).replace( /\s+/g, ' ' );
      }
    }
  }
}

function removeClass( elements, className ) {
  if ( elements.length === undefined ) elements = [ elements ];
  for ( var i = 0; i < elements.length; i++ ) {
    var element = elements[i];

    if ( hasClass( element, className ) ) {
      if ( element.classList ) {
        element.classList.remove( className );
      } else {
        element.className = element.className.replace( new RegExp('(^|\\b)' + className.split( ' ' ).join( '|' ) + '(\\b|$)', 'gi'), ' ' );
      }
    }
  }
}

function toggleClass( elements, className ) {
  if ( elements.length === undefined ) elements = [ elements ];
  for ( var i = 0; i < elements.length; i++ ) {
    var element = elements[ i ];

    if ( hasClass( element, className ) ) {
      removeClass( element, className );
    }
    else {
      addClass( element, className );
    }
  }
}

// =============================================================================
// elements.js

function insertElementBefore( element, target ) {
  target.parentNode.insertBefore( element, target );
}

function insertElementAfter( element, target ) {
  target.parentNode.insertBefore( element, target.nextSibling );
}

// insertType = 0: (default) add to end of parentElement, 1: insert before parentElement, 2: insert after parentElement
function addElement( parentElement, elementType, elementId, elementClasses, elementInnerHTML, insertType ) {
  var newElement = document.createElement( elementType );

  if ( elementId != undefined && elementId != '' ) {
    newElement.id = elementId;
  }

  if ( elementClasses.length === undefined || !Array.isArray( elementClasses ) ) {
    elementClasses = [ elementClasses ];
  }
  for ( var i = 0; i < elementClasses.length; i++ ) {
    var elementClass = elementClasses[ i ];

    addClass( newElement, elementClass );
  }

  if ( elementInnerHTML != undefined && elementInnerHTML != '' ) {
    newElement.innerHTML = elementInnerHTML;
  }

  switch ( insertType ) {
    case 0: default:
    {
      parentElement.appendChild( newElement );
      break;
    }
    case 1:
    {
      insertElementBefore( newElement, parentElement );
      break;
    }
    case 2:
    {
      insertElementAfter( newElement, parentElement );
      break;
    }
  }

  return newElement;
}

function addElementBefore( parentElement, elementType, elementId, elementClasses, elementInnerHTML ) {
  return addElement(       parentElement, elementType, elementId, elementClasses, elementInnerHTML, 1 );
}

function addElementAfter( parentElement, elementType, elementId, elementClasses, elementInnerHTML ) {
  return addElement(      parentElement, elementType, elementId, elementClasses, elementInnerHTML, 2 );
}

// =============================================================================
// debug_console.js

var debug_console                 = document.getElementById( "debug_console" );
var debug_console__input_open     = document.getElementById( 'debug_console__input_open' );
var debug_console__input_shrink   = document.getElementById( 'debug_console__input_shrink' );
var debug_console__window_width   = document.getElementById( 'debug_console__window_width' );
var debug_console__window_height  = document.getElementById( 'debug_console__window_height' );
var debug_console__screen_width   = document.getElementById( 'debug_console__screen_width' );
var debug_console__screen_height  = document.getElementById( 'debug_console__screen_height' );
var debug_console__pixel_ratio    = document.getElementById( 'debug_console__pixel_ratio' );
var debug_console__input_shrink   = document.getElementById( 'debug_console__input_shrink' );
var debug_console__input_open     = document.getElementById( 'debug_console__input_open' );
var debug_console__url            = document.getElementById( 'debug_console__url' );
var debug_console__log            = document.getElementById( 'debug_console__log' );

var debugConsoleLog = 1;

var lastDebugMessage, lastDebugFile, lastDebugLoc;
var debugLogLast = [ '','','' ];

var levelText = [ [ '', 'Info: ', 'Warning: ', 'Error: ' ], [ '', 'debug-info', 'debug-warn', 'debug-error' ] ];

function isDebugConsoleEntryNew( idx, newer ) {
  if( idx > 0 && debugConsoleLog <= 0 ) return false;
  var debugConsoleEntryIsNew = newer !== debugLogLast[ idx ];
  if( debugConsoleEntryIsNew ) debugLogLast[ idx ] = newer;
  return debugConsoleEntryIsNew;
}

function debug_console_process( level, message, stack, forced ) {
  if( forced !== undefined || !forced ) {
    if( debugConsoleLog == -1 ) return;
    else if( debugConsoleLog == 0 ) {
      level = 1;
      message = "<i>debugConsoleLog</i> set to <b>false</b>";
      debugConsoleLog = -1;
    }
  }

	var debugMessage = "<span class='debug_console__log__entry__details__level'>" + levelText[ 0 ][ level ] + "</span>" + message;
	var debugData = new Array(), debugRegex = /((?:(?:https?|file)\:\/\/[^\s\)]+)(?:\/))([^:]+).([^\D\s]+).([^\D\s]+)/ig;

  while( debugRegex.exec( stack ) ) debugData.push( [ RegExp.$0, RegExp.$1, RegExp.$2, RegExp.$3, RegExp.$4 ] );

  var debugPath = debugData[ 0 ][ 1 ], debugFile = debugData[ 0 ][ 2 ], debugLineNum = debugData[ 0 ][ 3 ], debugColNum = debugData[ 0 ][ 4 ], debugLoc = debugLineNum + ":" + debugColNum;

  if ( isDebugConsoleEntryNew( 0, debugMessage ) ) {
    var newFile = isDebugConsoleEntryNew( 1, debugFile );
    var entryClasses = new Array();

    if ( !newFile ) entryClasses.push( 'debugconsole-samefile' );
    if ( levelText[ 1 ][ level ] != '' ) entryClasses.push( levelText[ 1 ][ level ] );
    entryClasses.push( 'clearfix' );

    var debug_console__log__entry = addElement( debug_console__log, 'li', '', entryClasses );

    var debug_console__log__entry__details = addElement( debug_console__log__entry, 'span',  '', 'debug_console__log__entry__details' );
    if ( newFile ) {
      var debugLink = addElement( debug_console__log__entry__details, 'a',  '', [ 'debug_console__log__entry__details__location', 'debug_console__log__entry__details__location--file' ], debugFile );
      debugLink.href = debugPath + debugFile;
      addElement( debug_console__log__entry__details, 'span',  '', [ 'debug_console__log__entry__details__location', 'debug_console__log__entry__details__location--file' ], ': ' );
    }
    if ( newFile || isDebugConsoleEntryNew( 2, debugLoc ) ) addElement( debug_console__log__entry__details, 'span',  '', 'debug_console__log__entry__details__location', debugLoc );
    addElement( debug_console__log__entry, 'div',  '', 'debug-icon' );
    addElement( debug_console__log__entry, 'span',  '', 'debug-text', debugMessage );
  }
  else {
		var lastEntry = debug_console__log.lastElementChild, target = lastEntry.getElementsByClassName( 'debug_console__log__entry__details__count' )[ 0 ];

    if( target === undefined ) addElementBefore( lastEntry.getElementsByClassName( 'debug_console__log__entry__details__location' )[ 0 ], 'span',  '', 'debug_console__log__entry__details__count', '2' );
		else {
			var content = parseInt( target.innerHTML );
			target.innerHTML = ( !isNaN( content ) && content !== undefined ? content : 1 ) + 1;
		}
	}

  return [ message ];
}

var debugConsole = Error;

debugConsole.prototype.write = function ( msg, forced ) {
  // var msg = Array.prototype.slice.call(arguments, 0);
	debug_console_process( 0, msg, this.stack, forced );
	console.log.apply( console, msg );
};

debugConsole.prototype.log   = function ( msg, forced ) { return console.log  .apply( console, debug_console_process( 0, msg, this.stack, forced ) ); };
debugConsole.prototype.info  = function ( msg, forced ) { return console.info .apply( console, debug_console_process( 1, msg, this.stack, forced ) ); };
debugConsole.prototype.warn  = function ( msg, forced ) { return console.warn .apply( console, debug_console_process( 2, msg, this.stack, forced ) ); };
debugConsole.prototype.error = function ( msg, forced ) { return console.error.apply( console, debug_console_process( 3, msg, this.stack, forced ) ); };

function debug_console_test() {
  debugConsole()  .log( "A basic log message"       );
  debugConsole() .info( "An information message"    );
  debugConsole() .warn( "A warning message"         );
  debugConsole().error( "An error message"          );

  debugConsole().log( " " );

  for (i = 0; i <   3; i++) { debugConsole()  .log( "Duplicate basic log messages"   ); }
  for (i = 0; i < 153; i++) { debugConsole() .info( "Duplicate information messages" ); }
  for (i = 0; i <  28; i++) { debugConsole() .warn( "Duplicate warning messages"     ); }
  for (i = 0; i <   4; i++) { debugConsole().error( "Duplicate error messages"       ); }

  debugConsole().log( " " );

  debugConsole().info( "A very long log message to demonstrate word wrapping in the Debug Console as well as demonstrating the behavior of the Debug Console Log title's sticky position. Just to be on the safe side, here is even more text to occupy space and ensure this adds enough height to the Debug Console Log." );
  debugConsole().info( "A second very long log message to demonstrate word wrapping in the Debug Console as well as demonstrating the behavior of the Debug Console Log title's sticky position. Just to be on the safe side, here is even more text to occupy space and ensure this adds enough height to the Debug Console Log." );
  debugConsole().info( "A third very long log message to demonstrate word wrapping in the Debug Console as well as demonstrating the behavior of the Debug Console Log title's sticky position. Just to be on the safe side, here is even more text to occupy space and ensure this adds enough height to the Debug Console Log." );
}

function amendButton( buttonSelect, buttonText, altTitle ) {
  buttonSelect.innerHTML = buttonText;
  buttonSelect.title = ( altTitle !== undefined ? altTitle : buttonText ) + ' Debug Console';
}

function debug_console_update_stat( element, text ) {
  if ( element.innerHTML != text ) element.innerHTML = text;
}

function debug_console_update_stats_screen() {
  debug_console_update_stat( debug_console__screen_width,  window.innerWidth );
  debug_console_update_stat( debug_console__screen_height, window.innerHeight );
  debug_console_update_stat( debug_console__pixel_ratio,   window.devicePixelRatio );
}

function debug_console_update_stats_viewport() {
  debug_console_update_stat( debug_console__window_width,  window.screen.width );
  debug_console_update_stat( debug_console__window_height, window.screen.height );
}

function debug_console_update_stats() {
  debug_console_update_stats_screen();
  debug_console_update_stats_viewport();
}

function debug_console_resize( init ) {
  if ( init ) debug_console_update_stats_screen();
  debug_console_update_stats_viewport();
}

function debug_console_init() {
  var debug_console__url__port_text   = window.location.port;
  var debug_console__url__search_text = window.location.search;
  var debug_console__url__hash_text   = window.location.hash;

  addElement( debug_console__url, 'span',  '', 'debug_console__url__protocol', window.location.protocol );
  debug_console__url.innerHTML = debug_console__url.innerHTML + '//';
  addElement( debug_console__url, 'span',  '', 'debug_console__url__hostname', window.location.hostname );
  if ( debug_console__url__port_text ) {
    debug_console__url.innerHTML = debug_console__url.innerHTML + ':';
    addElement( debug_console__url, 'span',  '', 'debug_console__url__port', debug_console__url__port_text );
  }
  addElement( debug_console__url, 'span',  '', 'debug_console__url__pathname', window.location.pathname );
  if ( debug_console__url__search_text ) addElement( debug_console__url, 'span',  '', 'debug_console__url__search', debug_console__url__search_text );
  if ( debug_console__url__hash_text ) addElement( debug_console__url, 'span',  '', 'debug_console__url__hash', debug_console__url__hash_text );
}

debug_console_init();
debug_console_resize( true );
debug_console_test();

addEvent( 'resize', window, debug_console_resize );

var windowMoveInterval;

function windowMouseMoveUpdate( event ) {
  if ( event !== undefined && event.relatedTarget !== null ) {
    clearInterval( windowMoveInterval );
  }
  else {
    windowMoveInterval = setInterval( function () {
      debug_console_resize();
    }, 1000 );
  }
}

windowMouseMoveUpdate();

addEvent( 'mouseout', window, windowMouseMoveUpdate );

function queueRefreshFrame() {
  setTimeout( function() {
    document.dispatchEvent( new CustomEvent( "refreshFrame" ) );
  }, 500 ); // 500ms is resize mixin duration
}

debug_console__input_open.addEventListener('click', function ( event ) {
  event.preventDefault();

  toggleClass( debug_console, 'opened' );

  if( hasClass( debug_console, 'opened' ) ) {
    amendButton( debug_console__input_open, 'X', 'Close' );
  }
  else {
    amendButton( debug_console__input_open, 'Open' );
  }

  queueRefreshFrame();

  return false;
} );

debug_console__input_shrink.addEventListener('click', function ( event ) {
  event.preventDefault();

  if( hasClass( debug_console, 'opened' ) ) toggleClass( debug_console, 'shrunk' );
  if( hasClass( debug_console, 'shrunk' ) ) amendButton( debug_console__input_shrink, 'Expand' );
  else amendButton( debug_console__input_shrink, 'Shrink' );

  queueRefreshFrame();

  return false;
} );

Debug Console

  • window.innerWidth: , .innerHeight:
  • window.screen.width: , .height:
  • window.devicePixelRatio:
  • [window.location.*]
    [protocol]//[hostname]:[port][pathname][search][hash]

console.log