Add a console to Stack Snippets

Currently, to see console.log() entries from StackSnippets, you need to open your browser console, and make sure it's recording from frames. Things could be a lot simpler if you would add a console to the snippets. Maybe something at the bottom of the snippet.

This could be done by overwriting the default console.log function with a custom one that both writes to the browser console (keep a reference to the original function), and also writes to the snippet's console.

EDIT:
And perhaps also show errors thrown in this console.

• Yes please. It's a lot of work to realize that there's no output because we haven't opened the console. Plus, not every programmer realizes the console in the developer tools exists. – Unihedron Sep 21 '14 at 8:25
• Big +1, right now I have to include an unrelated function in every snippet so the results show where the reader can easily see them, which is noise distracting from the question/answer. Worse, you see people using document.write, which is just a terrible idea. It doesn't have to be console.log, just something. Perhaps snippet.write("HTML goes here"). – T.J. Crowder Sep 29 '14 at 8:20
• Two words: scope creep. – Travis J Feb 11 '15 at 19:02
• SERIOUSLY, could we please move forward on this. It's very distracting to have to include a script just to do this. It negatively impacts answers. It's really been far too long since this request was made for this to still be outstanding. – T.J. Crowder Feb 23 '15 at 19:04
• @T.J.Crowder we need more bounties. – canon Feb 25 '15 at 17:42
• @T.J.Crowder I've added another bounty. Unfortunately, now I'm pretty tapped out rep-wise. – canon Apr 27 '15 at 13:07
• @T.J.Crowder my bounty expired. What do we even do at this point? Give up? Keep offering bounties until we're down to 1 rep? – canon May 4 '15 at 13:10
• @T.J.Crowder Maybe you should award the bounty to canon so that he can offer another one. – Scimonster May 6 '15 at 14:13
• @Scimonster: That is just clever. Thank you, that's exactly what I'll do. We can ping-pong until this gets done. :-) – T.J. Crowder May 6 '15 at 14:55
• @canon: For better or worse bounties have almost no effect when it comes to getting features implemented. I'd save your reputation, if I were you. – Jon Ericson Jun 4 '15 at 21:07
• Oh for heaven's sake, more than a year later, nothing. Yeesh. – T.J. Crowder Oct 6 '15 at 11:49
• Nevermind, it's way worse for @T.J.Crowder... – canon Dec 23 '15 at 15:24
• @canon: :-) Too bad it's not over on meta.so, we wouldn't have to worry. But we won't run out of rep as long as we keep trading the bounties. :-) I just Do Not Understand why snippets are being completely ignored. It's insane, given the traffic the site has in the JS, HTML, and CSS tags. The flippin' things should be absolutely first rate experience, but sod-all has been done since they were introduced. – T.J. Crowder Jan 29 '16 at 19:00
• Sure, I'm happy to be helpful. Though, I'd rather not have 700+ posts include 3rd party scripts in order to display output... much less the thousands (I'm sure) using document.write() instead... – canon Mar 1 '16 at 23:02
• @ShadowWizard: I have no control over whom canon awards bounties to. There is exactly zero "cheating" going on here, and frankly I find the suggestion offensive. (In the mild way anything on MSE can provoke a reaction. I'm hardly going to demand satisfaction at dawn with pistols!) All I am doing, and as far as I'm aware, all canon is doing, is trying to draw attention to a significant missing feature in what should be a good feature of Stack Overflow (specifically). That's it. – T.J. Crowder Apr 12 '16 at 14:10

Thanks for bringing this up!

Thanks in large part to the efforts of canon and his MIT licensed virtual console library for Stack Snippets, we now have a virtual console!

Normally I'd do screenshots, but with Stack Snippets I can just give you a live demo instead. Check it out!

console.log("virtual!");
console.log("console!");
<b>Here's some HTML</b>

Feedback welcomed!

• Thanks for finally taking care of this! – Scimonster May 18 '16 at 20:04
• Yeah, thanks for finally implementing this. Did all the bounties draw attention to this and have any influence on your decision? By the way, here are 500 meta reputation points. – Josh Crozier May 18 '16 at 20:29
• Thanks @JoshCrozier. And no, not really honestly. Or at least not in the way you might think. I don't care about the points so much as the fact that it matters to people enough for them to drop huge bounties on it. That spells out a big need: so I went and solved it with the help of canon. – Haney May 18 '16 at 20:30
• David, like several others, I've taken the "Feedback welcomed!" link to mean we should post answers there with feedback, including bug reports and feature requests. Should we be doing that? Or posting them separate as bug or feature-request questions as appropriate? You've implemented one of them in response to one of those answers, but I'm not sure how long you want that model to continue... – T.J. Crowder May 20 '16 at 14:54
• @T.J.Crowder either is fine honestly. Having them as answers to that post makes it easy for me to review. And BTW haven't been ignoring you, am contemplating your thoughts and thinking about possibilities. :) – Haney May 20 '16 at 15:23
• @Haney: Cool, as more comes up, I'll post them there. Really, really appreciating the renewed attention on Stack Snippets and the console in particular. – T.J. Crowder May 20 '16 at 15:44

A duplicate of this question came up on meta.SO where I suggested a solution, copied here:

I whole-heartedly agree. If the point of these snippets is to enable us to demo functionality and display its output inline, the output pane needs to be adapted to (optionally) mirror logged messages.

Why should we bother avoiding document.write() and alert()?

• Both assume a browser environment even if we're demonstrating a purely javascript concept. We certainly don't want either method in the middle of what should be a node.js function.
• Neither are what we're using to debug (I hope)
• alert() is extremely intrusive.
• document.write() shouldn't even be suggested to the novice user without a littany of caveats
• Neither method offers robust serialization... forget serializing objects.
• Our debugging messages deserve more love than that from our demo tool. We can do much, much better.

My Temporary Solution

I've created a small script to include via the html snippet1 (please leave the comment intact):

<!-- console visualization; see http://meta.stackexchange.com/a/242491 -->
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>


1 If we ever get integrated console visualization, we can just remove this script wholesale and it should be very low-impact.

Notes:

• All calls to console.log() (info(), warn(), error(), and clear()) are passed along to the actual console
• Loosely imitates Chrome's output (colors and styles excluded)
• Objects are printed using a variation of JSON.stringify() (including functions, regex, undefined, etc) with custom handling for HTMLElement
• Works by injecting elements into the page... so, it obviously pollutes the DOM.
• The number of entries is limited to 50. Older entries will be removed to make room for newer entries.
• Logs unhandled errors.
• Handles circular references. You could log window; though, I wouldn't recommend it.

Here's a demo:

// sample values
var values = [1e100, "a", true, new Date(), x => 1, /(?:)/ig, undefined, null];

values.push(values);

// log whole array with circular reference
console.log("array with circular reference: %o", values);

// log each value individually
values.forEach((v, i) => console.log("%i: %o", i, v));

// sample click handler
console.log("clicked: %o", this);
});

// throw a test error
throw new Error("test!");
<!-- console visualization; see http://meta.stackexchange.com/a/242491 -->
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
<button>click me</button>

• This answer is not receiving enough upvotes – Samuel Liew Jul 9 '15 at 3:23
• I wish I could assign another bounty for this answer alone – cat Mar 2 '16 at 2:59
• Wow, if I understand this correctly, T.J. Crowder gave Canon an enormous bounty, who in turn gave T.J. Crowder an enormous bounty. I just wanted to point out this beautiful sportsmanship. – bmende Apr 10 '16 at 23:58
• – boxspah Apr 14 '16 at 2:49
• Spoiler alert... it's not. – canon Apr 27 '16 at 18:58
• Is there any issue with using firebug instead? It seems perfect for this: codepen.io/anon/pen/vGvXYW – Marie May 4 '16 at 13:56
• @Marie even firebug lite is massive... and rightly so. It does a lot. I think our chief concern is simply standardizing visualization for logging methods. I don't think we need a console input field or HTML, script, CSS, and DOM tabs. – canon May 4 '16 at 14:01
• Just want to say: You've done a great job with this console. Really fantastic, and I'm glad that SE management have had the sense to take it on board. All of us in the javascript tag salute you! – T.J. Crowder May 19 '16 at 13:52
• @T.J.Crowder updated object visualiazation. See this post. – canon Jan 8 '18 at 3:38

TL;DR

1. Best to leave the actual console alone, not least because interfering with it can prevent asking and answering questions related to the console (such as when and how data is expanded on V8's console, which is a non-trivial thing).

2. Snippets definitely need a built-in, simple means of generating output without promoting poor practices like document.write.

3. Specific suggestion for what to provide below, including a version hosted on GitHub Pages for use until/unless Snippets have their own way.

I think the console should be left alone, not least because interfering with it can prevent asking and answering questions related to the console (such as when and how data is expanded on V8's console, which is a non-trivial thing).

But I'm very keen to see what I think is the main point of this request: A simple means of writing output to the output pane of the snippet.

Right now, people are doing four things:

1. Using document.write. This is awful, it promotes 1990s code in 2014+.

2. Using some function for output, like my usual:

function display(msg) {
"beforeend",
"<p>" + msg + "</p>"
);
}


This is also not good, because it adds a lot of noise, esp. to short snippets.

3. Using console.log, which just makes the output pane of the snippet wasted space.

4. Writing scripts they include in snippets (like mine below), which means the snippet relies on an off-site resource.

None of those is a good solution.

My suggestion is Keep It Simple and inject a snippet object into snippets (without showing it in the snippet) with a log (or whatever) method; perhaps both log and logHTML:

// MIT license, see: https://github.com/tjcrowder/simple-snippets-console/blob/master/LICENSE
var snippet = {
version: "1.3",

// Writes out the given text in a monospaced paragraph tag, escaping
// & and < so they aren't rendered as HTML.
log: function(msg, tag) {
var elm = document.createElement(tag || "p");
elm.style.fontFamily = "monospace";
elm.style.margin = "2px 0 2px 0";
if (Object.prototype.toString.call(msg) === "[object Array]") {
msg = msg.join();
} else if (typeof msg === "object") {
msg = msg === null ? "null" : JSON.stringify(msg);
}
elm.appendChild(document.createTextNode(msg));
document.body.appendChild(elm);
},

// Writes out the given HTML at the end of the body,
// exactly as-is
logHTML: function(html) {
}
};


I've made a version available here on GitHub Pages for use until snippets have their own way of doing it. Feel free to insert that at the top of a snippet like this:

<!-- Provides the snippet object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>


A simple snippet object like that solves the issues with what people are doing now. Consider this example:

Question:

How do I create an array with just a subset of the contents of an existing array in JavaScript? For instance, only non-negative numbers?

You can use ES5's Array#filter for that. It calls a function you supply, passing in each entry in the array, and builds a new array from the entries you return a truthy value for:

var a = [10, 0, -5, 7, 12, -3, -1];
var filtered = a.filter(function(entry) {
return entry >= 0;
});
snippet.log("original: " + a.join(", "));        // "10, 0, -5, 7, 12, -3, -1"
snippet.log("filtered: " + filtered.join(", ")); // "10, 0, 7, 12"

(Obviously if you try to run that, you'll get an error, as snippet isn't defined.)

Isn't that better than:

var a = [10, 0, -5, 7, 12, -3, -1];
var filtered = a.filter(function(entry) {
return entry >= 0;
});
display("original: " + a.join(", "));        // "10, 0, -5, 7, 12, -3, -1"
display("filtered: " + filtered.join(", ")); // "10, 0, 7, 12"

function display(msg) {
"beforeend",
"<p>" + msg + "</p>"
);
}

• Out of curiosity, what have you been doing in practice while we wait? – canon Feb 10 '15 at 20:22
• @canon: I've been using the snippet object above, loading the script from github. – T.J. Crowder Feb 11 '15 at 8:13
• I'm not sure if having a separate snippet object is very discoverable. Right now I think the first thing most people will do is try to use "console.log" and then wonder why its not working. – hugomg May 15 '15 at 13:27
• @hugomg: Very easy to detect /\bconsole\./ and show a fadeover message saying what to do. Whenever you take over something like that, you immediately open yourself up to getting in the way of improvements/innovations for it, special features it has on some platforms, questions like this one today about the console itself, etc., etc., etc. Or we could try to fully emulate console, but if so, I'd want an opt-out option (like var console = realConsole;), but I think it would be much better just not to get in the way in the first place. – T.J. Crowder May 15 '15 at 13:41
• Another alternative would be adding a tab titled "snippet.log output". I just think its important to get "in the way" somehow to avoid the common problem of trying console.log and it just showing a blank result tab. – hugomg May 15 '15 at 14:11
• I'd prefer to see us detect and handle that, which is trivial. But it's just my view. Also, given the complete absense of any kind of meaningful development on Stack Snippets in the last eight months, I think smaller = slightly more likely to actually happen. – T.J. Crowder May 15 '15 at 14:13
• msg = msg === null ? "null" : JSON.stringify(msg); vs msg = JSON.stringify(msg);? JSON.stringify returns null if null. or do i miss something? – Nina Scholz Aug 15 '15 at 16:50
• @NinaScholz: At the time, I wasn't sure that was specified behavior. Now, I'm pretty sure it is. Still, the check prevents converting null to "null" and then parsing "null" back to null, so... – T.J. Crowder Aug 15 '15 at 16:53
• Yep, in the absence of any built-in snippet behavior, I'm usually using document.write() just because it's simplest and seems the least complicated to viewers. in jsFiddles, I use my own off-site script resource because that script resource can be added to the jsFiddle, yet not complicate the code display. Since that is not the case with snippets, I just use document.write() and live with that 80's feel to it. There really should be something built into StackOverflow snippets. It doesn't need to be much (perhaps 5 lines of code to expose a log() function. – jfriend00 Sep 4 '15 at 4:06
• Here, have another bounty. :/ – canon Mar 9 '16 at 14:54
• I'm baffled, T.J.. somehow I never upvoted your answer or sci's? – canon Apr 23 '16 at 23:05
• @canon: LOL! Get this: I never upvoted yours, either. Crikey. – T.J. Crowder Apr 24 '16 at 10:01
• @T.J.Crowder you may want to vote on this proposal for the town hall meeting. – canon May 4 '16 at 16:36
• @T.J.Crowder fyi... – canon May 5 '16 at 20:22
• @T.J.Crowder -- Quick heads up, a console has finally been implemented. – Josh Crozier May 18 '16 at 20:33

This actually isn't the best snippet. See the answers below by T. J. Crowder and canon for better console simulations.
There is an important difference though. Mine is a userscript which applies to all posts. The others are for including in a specific snippet, for everyone to benefit from.

See it in action! (Image from this post)

Update (2014-10-12):
Now shows errors.

I bring news (and hope) from the inaugural meta.SE Community Town Hall chat event.

Here's a partial transcript:

canon: @Haney any chance we can have a discussion about Stack-Snippets™?

Undo: @canon What specifically?

canon: @Undo console output (meta.stackexchange.com/a/279053/159427)

Haney: @canon I don't want to hijack the conversation, but know that's it's on our radar for sure. We definitely want to do it, just a matter of finding time right now

canon: @Haney Just to clarify, you definitely want to have a discussion... or definitely want to implement console visualization?

Haney: @canon we think a console offering would be an awesome benefit (and win-win, could enable / disable it probably within snippets). Just need to find time to implement.

canon: @Haney great!

Haney: hey @canon what kinda license do you have on your stopgap console js there? ;)

canon: @Haney I think I blindly picked MIT

Haney: good, good

Haney: @canon see my job gets easier when the groundwork has been done for us... MIT license would let us adopt this readily. I'll see what team thinks next week

Update:

Haney posted a comment on the town hall chat proposal:

@canon we've agreed to investigate the library over the next couple of weeks, we're leaning towards including it but no promises... yet.

After a long time, I've decided to post my answer.

I've started it in April this year and I've improved it these days.

My code, currently, takes control over the console object in a 'different' way (I'm missing the right word).

The code handles the following methods in the console object:

• log
• error
• warn
• info
• time
• timeEnd
• clear

Also, it shows objects and arrays in a tree-like view.

A few examples of what the code can do:

//starts the console and tells to use the specific element to add the messages there

console._RELAY_TO_DOC = document.getElementById('messages');

//misc stuff, only _USE_JSON has the default value

console._USE_JSON = false;
console._SHOW_COOL_NUMBERS = true;
console._SHOW_TYPES = true;
console._SHOW_STRING_LENGTH = true;

//just use the console now:

console.time('test');

console.log(1,[],{},'string',[1,2,3,4,5],{a:1,b:2,c:3});
console.warn('Too much awesomeness!');
console.info('You are informed.');
console.error('Oh no! We divided by 0!');

console.timeEnd('test');

throw new Error('This will show in the console');
* {font-family:sans-serif;}

html,document {overflow:hidden;}

#console{
position:absolute;
top:0px;
right:-300px;
-webkit-transition: right 1s;
transition: right 1s;
height:100%;
max-height:100%;
}
#show {display:none;}
#show:checked+#console{right:0px;}
#show_button{
display:inline-block;
width:20px;
height:40px;
text-align:center;
border:1px solid #ccc;
background:white;
cursor:pointer;
float:left;
}
#messages {
width:300px;
float:right;
min-height:100%;
max-height:100%;
height:100%;
background:white;
overflow-y:scroll;
border-left:1px solid #ccc;
}

textarea {width:350px; height:130px;}
<!-- load the script -->
<script src="http://ismael-miguel.github.io/console-log-to-document/files/console.log.min.js"></script>

<span> All the messages are present there --> </span>
<input type="checkbox" id="show" />
<div id="console">
<label id="show_button" for="show" checked="checked"> &#9654; </label>
<div id="messages"><span>List of all messages:</span></div>
</div>

<div>
Eval you code here: (write and click outside)<br>

<textarea onchange="Function(this.value)();">console.time('test');

console.log(1,[],{},'string',[1,2,3,4,5],{a:1,b:2,c:3});
console.warn('Too much awesomeness!');
console.info('You are informed.');
console.error('Oh no! We divided by 0!');

console.timeEnd('test');

throw new Error('This will show in the console');</textarea>
</div>

I've asked @canon to lend me an important feature of his code: the ability to handle exceptions when uncaught.

There are also a few options in the console object:

• _RELAY_TO_DOC - Enables/disables the logging of the messages in the document.
You can set it to true or set it with an Element.
• _USE_JSON - Simply returns a JSON string. Overrides all and every option from now on.
• _SHOW_COOL_NUMBERS - Show numbers in binary, octal and hexadecimal representation
• _SHOW_TYPES - Show the data type of an element.
• _SHOW_STRING_LENGTH - Shows the string length.

It also adds 2 methods to the console object:

• _restore_old_method - Restores a method (e.g.: log) to the default value
• _restore_relay_method - Does the oposite of the above method

I hope you like it!

You can visit http://ismael-miguel.github.io/console-log-to-document/ for a full explanation of the code and it's functionality.

To make it work in any page, just paste <script src="http://ismael-miguel.github.io/console-log-to-document/files/console.log.min.js"></script> into your <head>.

Warning:

• This does not like recursion (it is safe to use with Elements, it is prepared to ignore it's recursion)
• The code can't handle very huge elements (like document)
• This may burn a lot of CPU if misused
• The time and timeEnd aren't accurate, but close enough to the real result
• "Sweet" doesn't begin to describe this – cat Apr 10 '16 at 0:54
• @cat Thank you! I still see some rough edges that need some polishing. If you have any ideas on how I can improve it, I'm listening. I had fun making this code and hoped someone would find it useful. Once again, thank you for your comment! – Ismael Miguel Apr 10 '16 at 9:39