When developing in JavaScript, I always get a little annoyed about the lack of a debug console on iOS. And when I say ‘lack’ I mean the complete ass backwards obfuscation introduced in iOS 6, requiring you to physically hook your iPhone to your (Mac only!) development computer to view debug output. This approach, including various remote debuggers that are out there, is much too tedious when you simply need to view a value, see the contents of an object or – more likely – see the error message(s) your script caused, indicating why it isn’t working in the first place.
To that goal, I have developed mobileConsole; a JavaScript console for mobile devices. It ‘extends’ the window.console
to a visual, HTML-based console that shows you a console similar in appearance to Chrome’s excellent web inspector console. The main goal was to keep mobileConsole unobtrusive: not requiring any additional code. This is why I extended window.console
so I could keep using all my regular console
events, without having to add extra error reporting in my projects. This has resulted in mobileConsole being a ‘click-on’ script; it will just intercept all console
(and window.onerror
) events and display them, without modifying anything*.
*Just one small caveat: While mobileConsole is active, the reporting of source file and line numbers in the regular console is not always correct, as mobileConsole is ‘hijacking’ them, so lines appear to come from the mobileConsole script file. This is not really a downside, as mobileConsole is aimed at devices that do not have a console to begin with.
Demo
On a mobile device, mobileConsole should have already opened automatically. Otherwise, open it by clicking the green button. The buttons each trigger some regular, native console
commands, as described. The ‘Trigger an error’ button triggers a non-existing function, which will result in an window.onerror
‘undefined’ error, which is handled by mobileConsole as well.
On a desktop, you can also open your Web Inspector’s console to see what is happening over there. Hint: while your ‘real’ console is open, trigger some console
events (log, info, warn, error, trace) yourself to see mobileConsole handling them. Or, additionally, trigger some events from mobileConsole’s own console commandline (introduced in mobileConsole 0.5).
There is a separate demo-page, too. Click here.
Supported console methods
Currently, at v1.3.3, mobileConsole supports (hooks into) console
methods:
console.log
console.trace
console.info
console.warn
console.error
console.group
console.groupEnd
console.table
console.assert
console.time
console.timeEnd
console.clear
Features
- Snap-in / click-on / fire and forget: just add it to your project, and it should work out of the box, completely unobtrusive (unless, of course, you’re using the global variable
mobileConsole
for some reason) and requiring no additional code. It will just catch your existing console-calls. - Small: 58.4 KB / 11.7 KB minified
- Acts much like Chrome’s Web Inspector console in terms of coloring, layout and design.
- If available, mobileConsole shows details for each method: shows the contents of objects and elements and shows error stack trace for all errors. Note that large string properties inside objects will be truncated to 400 characters.
- Groups repeating events by displaying a single event message, prefixed with a dot holding a counter that increases with each consecutive repeat.
- Displays a link to the file that caused the event, including the line- and column number that triggered it.
- Hooks into
window.onerror
to catch and display (uncatched) JavaScript errors. - Supports a commandline / console input field, allowing for the execution of custom code, setting and checking variables, outputting elements or objects, etc.
- Keeps a history of all entered commands in sessionStorage, meaning commands are stored as long as the browser’s tab is opened. Command history can be recalled using up and down arrows on the keyboard (if available), and it also sports an autocomplete-based pop-up, which is especially useful on mobile devices.
- Has buttons to toggle the visibility of the logging types (log, trace, info, warn and error) and a button to clear the console completely (no undo).
- Can be minimized to ‘dock’ on the underside of the screen; compensates for its own height when maximized (or minimized) by adding (to any existing) padding to the
body
of the page. This prevents mobileConsole from covering parts of the page.
Download
View/fork it on Github: https://gist.github.com/c-kick/2d717790aadd3aa86884ee0b07c3119f
Usage
Include it as your first script, preferrably as the first line inside your <head>
section. You can check the demo page’s source for reference.
Notes
- Since it renders as HTML, it needs to have a
document.body
to render to. As the script is (should be) included before the body is available, it waits for a windowload
(onload
) event before it renders itself. This does not mean you’ll miss some early console calls, though: these will be picked up immediately after the script is included (preferrably placed as the first script in the<head>
), and they are displayed as soon as the window is loaded. - As mentioned above; while mobileConsole is active, the reporting of source file and line numbers in the regular console is incorrect (they will all appear to come from somewhere inside
hnl.MobileConsole.js
, as that is technically triggering the events). Note that source file and line numbers in mobileConsole are correct. - Clicking the link to the caller, will not neatly jump to the corresponding line. But it *will* jump to the file. In a new window! How about that?
- It’s just a console, nothing more. No element inspection, no network waterfall diagrams.. sorry ¯\_(ツ)_/¯
- Syntax errors will not be logged, only runtime errors. This is by design; JavaScript does not provide a way to hook into syntax errors.
- mobileConsole is still being developed; let me know if you run into any bugs, using the comments below!
- If mobileConsole doesn’t start (mobile detection fails), you can either override autostart by setting
overrideAutorun
totrue
or add the following script to your page:
if (!mobileConsole.status.initialized) {
mobileConsole.init();
}
- As of version 1.3.5, mobileConsole can be closed using the ‘X’ at the right-hand side. Two things to note: mobileConsole cannot be rebuilt again until you reload the page, so if the console is ‘in your way’ of viewing content, I suggest you use the minimize button (left-hand side) instead. The other is that, while closed, the script wil still ‘pipe’ the original
console
‘s logging.
Compatibility
As of version 1.3.3, mobileConsole was tested (and working) on:
- iOS Safari (applewebkit 601.1.46 & applewebkit 602.1.50)
- Mozilla (5.0)
- Firefox (37+) – Note that Firefox/Mozilla reports some events (such as onclick) as coming from line 1, column 1 in the document. I am still looking into why this is.
- Chrome (50+)
- Internet Explorer (8+) (Trident 4.0+) – IE8 support is flimsy, at best, but it seems to work. Console input is hit-and-miss. Note that IE8 and IE9 do not support a proper stack trace, so no linenumbers and error details are available.
- Edge (38) (EdgeHTML 14.14393)
- Opera (30+)
[…] There are some alternatives that can help (alongside some ugly console.logs). One of them is adding a library that provides console functionality. There are some projects readily avilable out there such as Eruda or mobileConsole. […]
[…] the mobile & desktop clients. For mobile debugging I’m using a locally copied version of https://www.hnldesign.nl/work/code/mobileconsole-javascript-console-for-mobile-devices/ to render console.log commands on […]
Hello,
Anyone got this to work with WebAR, namely AR.js? It seems to put a white background over the video camera so it can’t be used. Any way to fix this?
Not experienced with WebAR, but you could try removing the white background that mobileConsole sets on its main DIV, though it will impact the readability of things. Remove line 354 (and don’t forget the comma from the preceding line) to see if it helps.
Note: linenumber is based on v1.3.6
Sorry that’s a react native webview. Also the fail for me occurs on the 2nd call to load an html template, the first time it works fine, very strange and impossible for me to track down.
FYI, my js app is running in a react webview.
Great work! FYI on android 5.1.1 just loading the script, not even initing it, causes silent fails with $ajax calls. The same exact code works perfectly on android 9. I have pretty much driven myself crazy trying to track this down and have to move on, I would love to use it so if you have any suggestions shoot them to me.
Hi, sorry for getting back so late. I don’t see why the script should throw ajax calls. I can only speculate, and say that it might be due to the fact that you load mobileConsole after other scripts, and need to run it asap, as high in the head of your html as possible. That said: I really can’t say why it happens, as I don’t have any Android device to replicate this, sorry!
PS: threaded comments are broken… like much of my website, sorry about that (will fix this later)
[…] over to hnldesign.nl and check out hnl mobileConsole, the HTML JavaScript Console for […]
Very useful; thank you. Is there a way to add a ‘close’ function that completely disables the console, and removes it from the DOM? Sadly, my JS chaps are not on the same level as yours!
Fair point, and I have just added that to the console. Check the update script (1.3.5) @ https://gist.github.com/c-kick/2d717790aadd3aa86884ee0b07c3119f
I tried using this library. It does work on my mobile app but I am unable to enable/disable it when I need to.
Also mobileConsole variable is not defined for me and I have a suspicion that these errors are the reason.
I see this error when the page loads. I am using angular version 7.
Unhandled Promise rejection: Cannot read property ‘0’ of null ; Zone: ; Task: Promise.then ; Value: TypeError: Cannot read property ‘0’ of null
Thank you for this nice little library! I‘m writing to report a potential issue (because your gist page does not seem to allow issue report anyway).
The issue is, although I follow the “Usage” to include the script in my webpage, the console does not show up on my device (which is a non-mainstream Android tablet). It then took a very determined developer to read through the dialogs in your current website to realize: (1) adding a manual init() would do the trick; (2) and your good intention to make it automatic.
But, based on my experience, also based on another similar question asked at the end of your gist page, I suspect the automatic method might not always work on the vast variation of Android devices. Therefore I would suggest you at least mention “users may need to manually call init()” in your Usage section. Thanks for you consideration.
Fair point; the mobile-detection can indeed fail. That’s why I exposed the internal
init
function, and provided anoverrideAutorun
variable, forcing it to always run. I realized I had not explained this in the notes, so I just added it. Thanks!Wow,
you spent a lot of extra effort – but now the mobileConsole works like a charm! I simply added my extra “if” statement to get rid of those empty messages after opening a group, but everything else worked right out of the box!
Congratulations and many thanks!
I think, I can now stop flooding your web page with comments…
With greetings from Germany,
Andreas Rozek
No problem, glad I could help. Thanks for your feedback!!
What I forgot:
there is still the problem of the empty message right after opening a new group – I already fixed that in my version of mobileConsole by simply only adding that message “if (method !== ‘group’)”.
But you may probably want to check it as well.
With greetings from Germany,
Andreas Rozek
That’s just how it works I’m affraid, even regular web consoles (check out Chrome’s inspector, for example) return an ‘undefined’ after opening a group
Indeed,
it runs now without crashing – and it displays nested objects – well done!
Unfortunately,
– null objects
– empty objects and
– empty arrays
are no longer shown at all – all one can see is a gap and an increased line height
I can understand if gets annoying now – you already did a lot of work – but personally, I may be able to live with the first nesting level of an object only, but I cannot forgive not showing empty arrays and null values!
Please, tell me if you decide not to continue enhancing your mobileConsole: I will then make my personal version of it for my own purpose.
Thanks anyway for your marvellous work!
Andreas Rozek
I’m looking into it now and have found what goes wrong. Hold on
It works now. It was evaluating some value types (empty arrays, objects, null and undefined) as objects, creating empty tables. See the gist for 1.3.2, and let me know if this fixes it for you!
I am planning on modifying the display of elements (logging an element shows only the outer most tags, but you can’t expand them, as in the regular console) and then I will leave it alone for a while. Until someone asks for improvements again 😉
Done. At 1.3.3 now, and HTML object logging is much improved now.
see gist https://gist.github.com/rozek/cabde4d258505dc04bafae28cb7c512c
and iterate over the keys of “TestObject”
Phew, it took a while, but I think I have now fixed it for you! See the Gist for 1.3.1
But it’s really small:
/**** asString – can also convert Object.create(null) to string ****/
asString = function asString (Value) {
switch (Value) {
case undefined: return ‘[object Undefined]’;
case null: return ‘[object Null]’;
default:
if (Array.isArray(Value)) { return ‘[object Array]’ };
return (
(typeof Value === ‘object’) && (Object.getPrototypeOf(Value) == null)
? ‘[object]’
: String(Value)
);
};
};
Thanks. What would help best for me, is if you could share the object you’re trying to log, so I can emulate it over here and come up with a proper fix. Thanks!
see https://gist.github.com/rozek/200821864e824d5349010084cc0e4a35
sent…
While “JSON.stringify” is a really nice idea, it seems to suffer from the same (browser-internal) bugs as “String” itself.
I think I will stick with my “asString” function, which has been tested on the old iPad as well.
Can you share this ‘asString’ method/function?
Sorry,
but the object -> string conversion still crashes in older browsers
Hmm, ok. What did you do to fix it for you? Perhaps you can mail me at hnldesign@hnldesign.nl, which should be faster 😉
I added “asString” to
– the last line of “colorizeData” and
– “htmlToString” (instead of “String(html)”)
and now mobileConsole is also able to log objects – yeah!
Greetings from Germany,
Andreas Rozek
Nice to hear! If you want, you can try updating to 1.3.0 (just updated) which fixes a lot of small bugs, and fills in some missing polyfills. Perhaps this version will work for you straight out of the box!
Hello Klaas!
I just created a GIST my self with a function that could be used to (safely) convert any JS value into a String.
See https://gist.github.com/rozek/200821864e824d5349010084cc0e4a35
Indeed,
the same call (namely “String(Object.create(null))”) also causes my object logging problems in modern browsers and on desktops.
I think I’ll have to check all “String(…)” invocations in my own code – they seem to have the potential of a crash!
(JavaScript is more complicated than people might think)
With greetings from Germany,
Andreas Rozek
Yes, that’s a tricky situation. I am currently working on the mobileConsole code, and have solved this particular issue by falling back to JSON.stringify():
try { string = String(html); } catch(e) { string = JSON.stringify(html); }
So the htmlToString function would look like this:
function htmlToString(html) {
var string;
try { string = String(html); } catch(e) { string = JSON.stringify(html); }
return string.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/ /g, '\u00a0').replace(/(?:\r\n|\r|\n)/g, '
').trim();
}
Give it a try, see if it works for you.
Ok,
I found it: the problem is in “htmlToString(html)”, where you call “String(html)” – if you provide “Object.create(null)” (which may happen if you “console.log” such an object), a TypeError is thrown on my iPad.
That’s an interesting finding I will have to consider in my code as well!
With greetings from Germany,
Andreas Rozek
The error seems to occur when I try to “console.log” an object with an (empty) object as one of its properties.
Well, it seems as if this “TypeError” is explicitly “alert”ed on mobile devices if logging an object fails. I’m still looking for more details…
I’m using a 1st generation iPad, my navigator.useragent is “Mozilla/5.0 (iPad; CPU OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3”
Thanks, I think I have one of those lying around somewhere.. else I’ll see if I can emulate them somehow.
Oops,
now I first get a TypeError “No default value” (can’t tell you right now where it stems from) but the mobileConsole comes up without explicitly init()-ing it.
Will do more tests as soon as I find some time
If it launches without initing it, then the addition of ‘ipad’ to the navigator check works. I designed mobileConsole to start automatically, as it is meant to be fire and forget (just add the js to the page, without further configuration necessary, and it will launch automatically on mobile devices such as the ipad).
overrideAutorun
will make it run always; even on desktop browsers – which is usually not the desired effect.Is the ‘no default value’ error logged inside mobileConsole? Then that would indicate that it works, and perhaps the error is originating from another script. Is it reporting a file + line and column number as the origin?
Hello Klaas!
Thanks a lot for the quick fix – I just ran a very first test, here are my outcomes:
– I no longer seem to be able to log objects, instead I now get an “(Empty String)”
– after starting a new group I also get this “(Empty String)” message. In my opinion, the new group should just be started, without any additional output
– well, the new “Note: this method is not supported on…original console” is not really necessary, isn’t it? If you decide to keep it, I will simply “polyfill” missing console functions with dummies just to avoid the message
One last remark: I did not have the time to look into your object -> string conversion, but on my Android phone, it throws an error (and on my iPad it now results in “undefined”)
Again, thanks a lot for your effort!
With greetings from Germany,
Andreas Rozek
Somehow the ‘reply’ function is broken in my theme.. oh well. Anyway:
I really don’t understand how the object logger suddenly broke down, and I can’t replicate it here. I didn’t touch this part (
objectToString
) in my update.The same goes for the
group
method; not touched by my update.Can you check if it happens on the demo page as well?
– Fair point on the note, I have removed it.
– Also added ‘ipad’ to the user agent string detection, somehow it was missing, perhaps this will fix the autostart for you. If not, just set
'overrideAutorun'
(currently at line 97) to true.– I also included the
function.bind
polyfill, which I forgot in 1.2.7I have updated the gist to 1.2.8.
What model ipad do you have?
Additionally, I had to apply the following changes to make it work:
– not far below “case ‘group’: case ‘groupCollapsed’: case ‘groupEnd’:” I had to remove the line “msgContainer.innerHTML = ‘‘ + message + ‘‘;” as “message” seems to be udnefined;
– “originalConsole.clear” is not always available, thus, I added a check “if (typeof originalConsole.clear === ‘function’)” before actually calling it
But now, the mobileConsole works fine on my old iPad!
Thanks a gain for the marvellous work!
Hi Andreas, thanks for you useful feedback! I will need to revise the code, as you have pointed out quite a big coding flaw, in that I do check if the original console functions are present, but later on I don’t re-check if they are available to use (at least, that is my assumption, will have to look into the code).
And that undefined message… ouch!
Cheers, I will look into it soon, and glad you got it to work and it was of use to you!
Well, I had some time on my hands so I fixed the bugs you mentioned. I don’t have the same device as you, so I can’t be sure, but fixed is:
– When evaluating the device’s console methods, it returns a function when no method is found. This function simply logs
'Note: this method is not supported on this device's original console'
to the console.– Checking for an empty message has been improved, as somehow I never thought of checking if it was
undefined
.– Undefined evaluations have all been modified (
typeof var === 'undefined'
instead ofvar === undefined
)See v 1.2.7 on Github!
Thank you very much for your effort – it’s very helpful for WebApp debugging on older devices (such as a 1st generation iPad or a Smartphone running Android 4.1). However, I additionally had to provide a polyfill for “Function.prototype.bind” and mobileConsole.init() “manually” since “isMobile()” failed for my old iPad. You may contact me for further details, if you like.
With greetings from Germany,
Andreas Rozek
Hey! Thank you for this tool, it’s awesome! Don’t you think to publish it on npm?
Good point! Never though of that. I’ll look into it
hello, i really appreciated what you have created here. i have found that i cannot clear the console by clicking the clear button on firefox for android. the same code will however run on chrome, am i doing something wrong?
strangely tho it will work on your site, but not when running a html file with the hnl console js file stored locally.
That’s really weird indeed, I’ll look into it, see if I can reproduce the problem!