The Problem
Most mobile devices come with little if any debugging support. Debugging is usually done by connecting the device to a host computer (e.g., iPhone to a Mac) and using tools on the host computer. That's great if you have an iPhone and a Mac. But what if you Just Want to see what the JavaScript console is putting out, since you went to the trouble to put so much helpful debug information there?The Solution
Give your console some soul |
...Is barely even worth of a blog post, or 'blst' for short (as the kids here at SXSW are saying this week). Essentially, the secret is to hook the console's log function, then use it for our own purposes. At that point we can choose to forward the log statements on to the console, or 'swallow' them and only let our code have access.
The magic happens with just a few lines of code:
// console.log is just a function... store a reference var oldf = console.log; // redefine it and insert our own code console.log = function () { // use the console output for our own purposes someFunctionToShowConsole(arguments[0]); // also send it to the console, if we want oldf.apply(console, arguments); }
Everything else is just window dressing. But, in order to give us a nice little debug window that doesn't take up too much of the page and lets us scroll etc., etc., we'll wrap it all up in a div docked to the bottom of the page, and show timestamps for log entries, and add a way to clear the console if the log gets too long.
When we're done, it should look something like this:
The 'real' (Chrome) console is on the right, our faux console is on the left.
The full code is below, and any updates will be posted to https://gist.github.com/jasonbrice/8131e38c14695afb4127
// set an identifier for the console div var consoleId = 'debug_console'; // initialize the debug console, dock to bottom of page var debugConsole = function () { var body = document.getElementsByTagName('body')[0]; // since this function also gets called on clear(), // we'll remove the div if it exists so we can re-add it if (document.getElementById(consoleId)) body.removeChild(document.getElementById(consoleId)); // create new div and set whatever attributes we want var div = document.createElement('div'); div.id = consoleId; // dock to bottom of page. styles are merely a matter of preference: move, color, change to suit. div.setAttribute('style', 'position: fixed; bottom: 0px; left: 0px; width: 100%; height: 200px; color: #fff; background: #666; overflow: scroll;' ); // make our new div part of the DOM body.appendChild(div); // add a link to call this function var href = document.createElement('a'); href.innerHTML = "<a href='javascript:debugConsole();' style='text-decoration: none;'>" + "<span style='text-decoration: none; color: white;'>Clear</span></a><br/>"; div.appendChild(href); // hook the console output function var oldf = console.log; console.log = function () { // use the console output for our own purposes div.innerHTML += '<br/><span style="font-size: 12px; font-family: monospace;">' + timestamp() + '.$ ' + arguments[0] + '</span>'; // also send it to the console oldf.apply(console, arguments); } } // timestamp adapted from https://gist.github.com/hurjas/2660489 var timestamp = function timeStamp() { // Create a date object with the current time var now = new Date(); // Create an array with the current month, day and time var date = [now.getFullYear(), (now.getMonth() < 9 ? "0" : "") + (now.getMonth() + 1), now.getDate() ]; // Create an array with the current hour, minute and second var time = [now.getHours(), now.getMinutes(), now.getSeconds()]; // Determine AM or PM suffix based on the hour var suffix = (time[0] < 12) ? "AM" : "PM"; // Convert hour from military time time[0] = (time[0] < 12) ? time[0] : time[0] - 12; // If hour is 0, set it to 12 time[0] = time[0] || 12; // If seconds and minutes are less than 10, add a zero for (var i = 1; i < 3; i++) { if (time[i] < 10) { time[i] = "0" + time[i]; } } // Return the formatted string return date.join(".") + " " + time.join(":") + " " + suffix; } // initialize the console once the rest of the // document has finished loading window.onload = debugConsole;
Conclusion
Even in 2015, there is no nice and convenient way to debug web pages on mobile devices. This solution would be even cooler if we could look at raw code and set breakpoints. But for now we can at least know what the console is spitting out, which, let's face it, is probably how the majority of NodeJS debugging is done.Happy debugging, and if you like it, steal it!