203

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.

46
  • 7
    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
    Commented Sep 21, 2014 at 8:25
  • 2
    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"). Commented Sep 29, 2014 at 8:20
  • 1
    @Unihedron If you don't realise the "console exists" then you can't call yourself a "programmer" (well not a web one at least). This is 2014 people not the 90s.
    – user692942
    Commented Oct 10, 2014 at 15:17
  • 2
    Two words: scope creep.
    – Travis J
    Commented Feb 11, 2015 at 19:02
  • 27
    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. Commented Feb 23, 2015 at 19:04
  • 10
    @T.J.Crowder Maybe you should award the bounty to canon so that he can offer another one.
    – Scimonster
    Commented May 6, 2015 at 14:13
  • 6
    @Scimonster: That is just clever. Thank you, that's exactly what I'll do. We can ping-pong until this gets done. :-) Commented May 6, 2015 at 14:55
  • 2
    @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 StaffMod
    Commented Jun 4, 2015 at 21:07
  • 4
    Oh for heaven's sake, more than a year later, nothing. Yeesh. Commented Oct 6, 2015 at 11:49
  • 3
    @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. Commented Jan 29, 2016 at 19:00
  • 2
    I am one of the people that will regularly include one of these scripts in most of my JS answers. Thanks canon & T.J.Crowder, these are very helpful, and it's really sad that SO doesn't already implement it.
    – Amadan
    Commented Mar 22, 2016 at 8:29
  • 2
    @ShadowWizard: I don't think it's abuse to use a bounty to draw attention to a question, which is my only goal here. I couldn't care less about MSE rep. So I've asked if this is abuse. Commented Apr 12, 2016 at 13:58
  • 6
    @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. Commented Apr 12, 2016 at 14:10
  • 2
    @T.J.Crowder - I'm going to start posting bounties here until my 3k meta reputation runs out. It's ridiculous that this still hasn't been implemented. Commented Apr 26, 2016 at 18:48
  • 2
    @ShadowWizard - I missed that other meta post, thanks for pointing that out. Unless the bounty here draws any unnecessary feedback, then I don't see a problem with it. I also don't see a reason to close this question as a duplicate of the other one since this is clearly a [feature-request] that has been implemented whereas the other question is an announcement asking for feedback. Commented May 18, 2016 at 20:47

6 Answers 6

49
+1000

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!

6
  • 2
    Thanks for finally taking care of this!
    – Scimonster
    Commented May 18, 2016 at 20:04
  • 2
    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. Commented May 18, 2016 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 StaffMod
    Commented May 18, 2016 at 20:30
  • 1
    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... Commented May 20, 2016 at 14:54
  • 1
    @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 StaffMod
    Commented May 20, 2016 at 15:23
  • 1
    @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. Commented May 20, 2016 at 15:44
86
+2000

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(), table(), and clear()) are passed along to the actual console
  • Loosely imitates Chrome's output (colors and styles excluded)
  • Handles circular references via lazy-expansion.
  • 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.

Here's a demo:

/* config stuff... ignore this line */ console.config({ maximize: true, timeStamps: false });

// sample data
const values = [
  1e100, 
  "a",
  true, 
  new Date(), 
  x => 1, 
  /(?:)/ig, 
  undefined, 
  null,
  document.querySelector("button")
];

// add a circular reference
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));

// table output
console.table([
  { Name: "Zoe", Age: 20 },
  { Name: "Xander", Age: 21 },
  { Name: "Cthulhu", Age: Infinity },
]);

// 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>

6
  • 12
    This answer is not receiving enough upvotes Commented Jul 9, 2015 at 3:23
  • 2
    I wish I could assign another bounty for this answer alone
    – cat
    Commented Mar 2, 2016 at 2:59
  • 4
    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
    Commented Apr 10, 2016 at 23:58
  • @bmende It's actually being discussed whether it is a form of abuse.
    – unbindall
    Commented Apr 14, 2016 at 2:49
  • Is there any issue with using firebug instead? It seems perfect for this: codepen.io/anon/pen/vGvXYW
    – Marie
    Commented May 4, 2016 at 13:56
  • 1
    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! Commented May 19, 2016 at 13:52
53
+2600

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 (they've discontinued that URL, though the project is still there) 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) {
         document.body.insertAdjacentHTML(
             "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) {
        document.body.insertAdjacentHTML("beforeend", html);
    }
};

I've made a version available here on GitHub Pages (they've discontinued that URL) 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?

Answer:

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) {
    document.body.insertAdjacentHTML(
        "beforeend",
        "<p>" + msg + "</p>"
    );
}

14
  • 3
    @canon: I've been using the snippet object above, loading the script from github. Commented Feb 11, 2015 at 8:13
  • 1
    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
    Commented May 15, 2015 at 13:27
  • 1
    @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. Commented May 15, 2015 at 13:41
  • 1
    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
    Commented May 15, 2015 at 14:11
  • 2
    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. Commented May 15, 2015 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? Commented Aug 15, 2015 at 16:50
  • 1
    @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... Commented Aug 15, 2015 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
    Commented Sep 4, 2015 at 4:06
  • 1
    @canon: LOL! Get this: I never upvoted yours, either. Crikey. Commented Apr 24, 2016 at 10:01
  • @T.J.Crowder -- Quick heads up, a console has finally been implemented. Commented May 18, 2016 at 20:33
  • @canon - Interesting! FWIW, I wouldn't use the dark background, doesn't fit with SO's design and of course for the demo part it's not what browsers do by default... Do you have any SE engagement on this, or is this just your own project? Commented Dec 2, 2018 at 9:16
  • @canon - Cool. (Yes, I prefer a dark background for coding as well.) Commented Dec 2, 2018 at 11:13
  • looks like the link to your stack snippet's broken
    – Journeyman Geek Mod
    Commented Jul 28, 2020 at 18:39
  • @JourneymanGeek - Yeah, GitHub yanked those URLs. :-| But we have a snippets console these days, so... (I've been slowly working my way through the ~340 SO answers I had using that link to switch to the snippets built-in console...) Commented Jul 29, 2020 at 7:33
36
+500

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.


I've created a script to do this. You can read more about it here on Stack Apps. Download it from Greasy Fork.

See it in action! (Image from this post)

enter image description here

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

9

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.

8

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;
  -webkit-border-top-left-radius: 5px;
  -webkit-border-bottom-left-radius: 5px;
  -moz-border-radius-topleft: 5px;
  -moz-border-radius-bottomleft: 5px;
  border-top-left-radius: 5px;
  border-bottom-left-radius: 5px;
  background:white;
  cursor:pointer;
  float:left;
  padding-top:20px;
}
#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
2
  • "Sweet" doesn't begin to describe this
    – cat
    Commented Apr 10, 2016 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! Commented Apr 10, 2016 at 9:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .