62

It's been a long time since we worked on Stack Snippets. I'm sorry. It's mostly because I created it, then I got promoted to management, and now I don't code much anymore and nobody else has time to work on it. So you can blame me.

But before you do blame me, read on for good news!

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>

The system now offers a new "include console" checkbox in the editor window, which is selected by default. If you hate this new virtual console, you can either unselect it there, or set console: false in the Stack Snippet markdown. So everybody wins!

Special thanks again to canon who did most of the work on this upgrade!

11
  • 1
    Awesome, good job!
    – Konamiman
    Commented May 18, 2016 at 20:03
  • 3
    YES YES YES! This is the best thing since stack snippets :D
    – Cerbrus
    Commented May 19, 2016 at 8:06
  • 1
    Note to self: don't implement a console or you might get promoted again Commented May 19, 2016 at 8:18
  • Not working in Firefox ("Mozilla/5.0 (X11; Linux x86_64; rv:48.0) Gecko/20100101 Firefox/48.0") but works in Chrome ("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2723.2 Safari/537.36"). Haven't had time to debug but just quick report. Commented May 19, 2016 at 9:05
  • Doesn't work with stackoverflow.com/a/21457293/259953 :( Thus, it's useless Commented May 19, 2016 at 11:18
  • 2
    Answering questions yesterday, it was so nice not having to include my workaround for this!! Commented May 20, 2016 at 7:05
  • This needs to be featured!
    – Oriol
    Commented May 21, 2016 at 0:17
  • 1
    Good work, though here is one problem/issue that I think needs to be addressed ASAP
    – user255093
    Commented May 22, 2016 at 19:07
  • 1
    Work on this stuff seems to have stalled again. This comment from more than two weeks ago says a minor change will be "in the next build" but it still isn't there; this significant enhancement that canon's made to the script doesn't seem to be getting any UI attention. Could we please get those in? canon's done the hard work. Commented Jun 6, 2016 at 13:05
  • @T.J.Crowder yes it has stalled for the moment. We're still working on it but other things internally have taken priority for a few weeks.
    – Haney
    Commented Jun 6, 2016 at 14:34
  • I have create stack-snippets-console to be able to discuss, report, and propose about the console in a proper way.
    – Oriol
    Commented Jun 12, 2016 at 22:54

12 Answers 12

17

The console script has been moved to the head and now it waits until DOMContentLoaded, so console elements are inserted at the end of the body.


The console element should be inserted at the end of the body, just like the script one.

For example, the following code should log Hello! instead of <div class="as-console"></div>.

console.log(document.querySelector('div').innerHTML);
<div>Hello!</div>

It seems the problem is in content/Js/snippet-javascript.en.js

'writeResult': function () {
  var t = this,
  n = t._state.css,
  i = t._state.js,
  a = t._state.html,
  r = t._state.console;
  if ('' != n || '' != i || '' != a) {
    var o = '';
    null != p && (o = '//' + p),
    r === !0 && (a = '<script src="' + o + '/scripts/snippet-javascript-console.min.js"></script>' + a);

The last assignment should be

a += '<script src="' + o + '/scripts/snippet-javascript-console.min.js"></script>'
8
  • Nice catch! ... Commented May 22, 2016 at 8:17
  • Now that I think about it, querySelector is just the tip of the iceberg. Even if moved to the end, console elements will be affected by CSS and alter the length of querySelectorAll and getElementsByTagName collections. The proper way would be moving the user input inside an iframe, and place the console in the outer page.
    – Oriol
    Commented May 22, 2016 at 18:31
  • This is already creating problems
    – Oriol
    Commented May 22, 2016 at 18:58
  • @T.J.Crowder Read up on this and help getting this fixed ASAP
    – user255093
    Commented May 22, 2016 at 19:04
  • 1
    I ran into it in a snippet just yesterday, as I was going to do an example with a series of divs and opened it with document.querySelectorAll("div"). Moving it to the end may help some, but then it'll get mixed with any dynamically-added content, and wouldn't have helped in my case yesterday. Having the console div in the same document at all is likely to be an ongoing issue. Think it needs to be moved to a frame. Commented May 23, 2016 at 6:33
  • @canon Assuming the iframes have same domain, it would be something like contentIframe.contentWindow.console.log = function(){ ... }
    – Oriol
    Commented May 23, 2016 at 16:20
  • @canon I was thinking something like this. But inserting snippet contents at DOMContentLoaded would break snippets which use DOMContentLoaded.
    – Oriol
    Commented May 23, 2016 at 16:55
  • @canon: Thanks for the head's up. FYI: meta.stackexchange.com/questions/279420/… Commented May 24, 2016 at 13:39
14

You cannot XSS using this method, however, the console breaks on HTML style formatting inside a log statement:

console.log("<script>alert('omg');</script>");

4
  • 2
    @canon must be escaping thingy. <script></script> throws, but not <a></a>. <script></script\> doesn't throw. Commented May 18, 2016 at 21:08
  • 1
    Keep in mind there's no huge risk here as-is. We'll get it fixed, but Stack Snippets are sandboxed and secured on a 3rd party domain. Nothing bad will come of anyone's best efforts here. :)
    – Haney
    Commented May 18, 2016 at 21:14
  • 7
    Instead of putting the code inside of a script tag, you could use src= with a data URL (without base64, if you get the encoding right) to avoid this issue. (cc @canon)
    – Jeremy
    Commented May 18, 2016 at 23:09
  • 3
    Perhaps this is growing into a new feature request @canon <_<
    – Quill
    Commented May 19, 2016 at 4:44
11

The console now grows and shrinks with the available width. The box doesn't overflow any more.


The Stack Snippets console overflows on mobile devices if the viewport isn't wide enough.

This is actually just a small layout bug with a wonderful feature. (Thanks Haney!)

The post in the screenshot is this one.

6
  • 4
    Fixed and live momentarily.
    – Haney
    Commented May 20, 2016 at 19:13
  • @Pat did you do that when viewing the full site theme, or mobile site theme? Commented Apr 3, 2017 at 9:53
  • @ShadowWizard mobile view Commented Apr 3, 2017 at 9:54
  • Oh. And now it still works for you? Commented Apr 3, 2017 at 9:55
  • I can't run the snippet any more @Sha Commented Apr 3, 2017 at 9:57
  • @Haney the snippets are not working anymore for mobile, is this on purpose? Commented Apr 3, 2017 at 9:57
9

Is the date in the log really necessary ?

It doubles the height of a console line and we rarely wait more than 24 hours to see how our snippet behaves (when we do, we lose the fastest gun race and nobody sees our answer so the snippet doesn't really matter).

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

6
  • 4
    Yeah, good point. I think I'll dump the date part this morning.
    – Haney
    Commented May 19, 2016 at 13:55
  • 3
    Going live in a few here.
    – Haney
    Commented May 19, 2016 at 16:36
  • @Haney much cleaner! Commented May 19, 2016 at 19:18
  • @Haney: Nice one! Commented May 20, 2016 at 7:00
  • TBH the time isn't probably useful either... Commented May 20, 2016 at 10:04
  • 4
    Could be, for demonstrating how long something takes. Commented May 20, 2016 at 12:11
9

(this is now implemented and live)


The virtual console currently implements log, info, warn, error, and clear, but many other console methods don't write to the virtual console (just the real one):

console.log("This uses the virtual console");
console.dir({o:"testing"}); // This doesn't
console.time("timed");      // This doesn't
console.timeEnd("timed");   // This doesn't

Aggregating data from several DSE queries (because of timeouts; links below), here are the number of questions and answers (combined) in which various console methods occur (roughly), looking only at the and tags:

console.log    287,489
console.error    4,291
console.dir      2,025
console.info     1,940
console.warn       979
console.time       431
console.timeEnd    407
console.clear      277
console.assert     155
console.dirxml      20
console.count       17

Based on that and level of difficulty, I suggest implementing:

  • dir as an alias for log initially, more can be done if appropriate but the distinction is more for interactive consoles.
  • time and timeEnd, as they're quite easy

It's clearly not feasible to expect that the virtual console will have a union of all of the features offered by Chrome, Firefox, IE, and others! But if it's going to be called console, I think to minimize surprise we need to ensure it implements the more commonly-used methods.

DSE query links:

3
  • 1
    @canon: Fantastic! Extremely good of you to take the time to enhance SE in this way. Any idea when they'll put that on the site? Commented May 20, 2016 at 17:51
  • 1
    Going live in a few!
    – Haney
    Commented May 20, 2016 at 18:24
  • 1
    @canon: I was! :-) Commented May 21, 2016 at 6:56
8

Move the console outside the document.

Placing the console inside the document can produce lots of interferences. For example:

  • CSS selectors like div will select console elements
  • JS collections like document.querySelectorAll('div') will include console elements

I think the proper way would be:

  • Move the HTML, CSS and JS entered by the user inside an inner content iframe which occupies all the snippet iframe.
  • Place the console in the snippet iframe, outside the content iframe

This is how the console behaves in a browser. The content of a page can't interfere with the console.

Here's a simple example of how the console being in the same document is a problem:

console.log("This is...");
setTimeout(function() {
  var d = document.createElement('div');
  d.appendChild(document.createTextNode("...a problem"));
  document.body.appendChild(d);
}, 0);
div {
  position: relative !important;
}
<div>Hmmm</div>

Here's another example:

// Demonstration that `length` on the jQuery instance will be 0
// if there are no matching elements. There are no `div` elements
// in this snippet.
$(function() {
  console.log($("div").length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

That demonstration should be logging 0, not 2. Moving the console out of the document entirely is the only way to prevent this kind of cross-talk between the console and the various different snippets people use to demonstrate things.

7
  • Thanks for reporting this bug. I have modified Stack Snippets to include the console in the <head> tag which alleviates DOM assumptions. This fix is now live.
    – Haney
    Commented May 23, 2016 at 16:06
  • 1
    @Haney Thanks, but that can't work directly. The console script appends some elements to document.body, so that will throw an error in the head. Better move the script to the end of the body, or use an event listener in the head.
    – Oriol
    Commented May 23, 2016 at 16:13
  • It has been modified to use an event listener, not to worry!
    – Haney
    Commented May 23, 2016 at 16:14
  • 1
    @Haney OK, it was a caching problem XD
    – Oriol
    Commented May 23, 2016 at 16:16
  • 2
    @Haney: While moving the script is a start, the bigger problem is that the console adds elements to body, which interact with the snippet. Have to strongly disagree with the statement that the cost/benefit isn't there. Not only worth doing, but as Oriol points out, it needs doing soon. Here's an example of how it could work: output.jsbin.com/wicofa (Source: main page, console page, example snippet) Commented May 24, 2016 at 13:39
  • 2
    @Haney: Sorry, the first JSBin link above is to the wrong page. Here's the example: output.jsbin.com/himarux Commented May 25, 2016 at 6:36
  • 4
    @canon: Great! Can't imagine you need any help, but the offer's there if you like. I know I've said it before, but I'll just say it one last time: I really appreciate your work on this, and I know I'm not the only one who does. It's rubbish that the only reason this is moving forward is that you're doing the work, but it's really great you're doing the work and we're fortunate to have you doing it. Commented May 25, 2016 at 23:57
6

THIS IS NOW IMPLEMENTED IN THE SCRIPT (demo). Just waiting for SE to add a UI for it.


Could we add a flag saying that the console is the entire output? This would do two things:

  1. Let the console fill the result area

  2. Default to not scrolling to the end on ouput (leaving the scrolling up to the user)

In the tag, I post a lot of answers where the console output is the only output of the snippet. In those snippets, all of the Result area other than the virtual console is just wasted space. So how 'bout a "console is result" or similar checkbox:

"console is result" option

The default would be off, of course.

Here's an example from this answer — here's the snippet currently in that answer, using my rubbish workaround snippets.js script:

var str = "j and j and j x";
snippet.log("Search string: '" + str + "'");
for (var n = 0; n < str.length; ++n) {
  test(str, n);
}
function test(s, start) {
  var index = s.indexOf("j", start);
  snippet.log("Starting at " + start + ": " + index);
}
<!-- Script provides the `snippet` object, see https://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

And here it is with the lovely virtual console canon wrote for us:

var str = "j and j and j x";
console.log("Search string: '" + str + "'");
for (var n = 0; n < str.length; ++n) {
  test(str, n);
}
function test(s, start) {
  var index = s.indexOf("j", start);
  console.log("Starting at " + start + ": " + index);
}

As you can see, it shows the end of the output rather than the beginning, a lot more scrolling is required, and clicking the "Full page" link doesn't help.

5
  • i second that, but i would request a variable splitter, too, because the console output is fixed in size and it would be better if the size can be adjusted. Commented May 20, 2016 at 19:02
  • @NinaScholz: Thanks. I'd post the variable thing as a separate suggestion. This one is just a simple all-or-nothing. Commented May 21, 2016 at 6:58
  • I'd love to hear from the downvoters why they don't think this would be useful. I'd be using it every day, several times a day. Commented May 21, 2016 at 6:59
  • 2
    @canon: You rock. Yes, normal consoles scroll (well, most do) and we want what you originally did as the default, no question. But the use case for most of my answers is more document.write-like, e.g., just output that usually should be read from the top down. (I just refuse to use document.write and lead people into bad habits. :-) ). So your autoScroll: false and maximize options work perfectly for that. Hope to see a way from SE to use it soon! Commented May 21, 2016 at 15:01
  • 1
    @canon: BTW, happy to pitch in if you ever want another pair of hands in there. Just say the word. You clearly don't need the help on a technical level, but everyone has time limitations. Commented May 21, 2016 at 15:04
6

"Show console" (the label on the checkbox for enabling the feature as of the current UI; previously "include console") doesn't say much of anything. I suggest "Use in-snippet console" or similar, with one of those little (i) icons next to it with a fuller sentence.

4
  • 2
    This makes a lot of sense, gonna spend a few working something more informative up. Thanks!
    – Haney
    Commented May 20, 2016 at 15:29
  • Done and live in next build.
    – Haney
    Commented May 20, 2016 at 18:17
  • @Haney: When does that build go live? And will it include a UI for the new options? Commented May 28, 2016 at 9:45
  • This idea was recently raised as a standalone question.
    – LWC
    Commented Mar 15, 2017 at 18:58
4

When throwing errors, it would be helpful to actually print the line that the error occurred on, especially as the line mentioned doesn't match up with the source code. Of course, it's good that it shows anything for errors.

console.log('console!!')
console.log([1,2,3])
console.log({i: 'think', this: 'is', cool: '!'})
console.log(console.log)
throw new Error('test')

4
  • Not only JS-only, but for any error that comes from the JS code, if that's possible.
    – Scimonster
    Commented May 18, 2016 at 20:24
  • Correct, but here at least we have some measure of control over what it shows. ;)
    – Scimonster
    Commented May 18, 2016 at 20:32
  • Or instead of adjusting the line number, just give the line of code the error occurred on, as i actually wrote in the answer.
    – Scimonster
    Commented May 18, 2016 at 20:33
  • This needs more upvotes. :-) Commented May 20, 2016 at 16:42
3

Do not include the console by default, at least until it has been stabilized.

Including the console has collateral effects like Bug in stack snippet?.

People which creates snippets may not realize that this is a bug which (hopefully) will be fixed. So they might rely on the buggy behavior.

Then, once the fix lands, these snippets will break.

Not including the console by default would alleviate this possibility. Moreover, even if the console will be useful to lots of snippets, I think they are still a minority.

Only once the console has been stabilized, it might be considered to enable it by default.

1
  • 2
    Thanks for reporting this bug. I have modified Stack Snippets to include the console in the <head> tag which alleviates DOM assumptions. This fix is now live.
    – Haney
    Commented May 23, 2016 at 16:06
3

I can't put a bounty on this answer, so I've raised a formal feature-request instead. If you want this done, please go upvote and or bounty as appropriate.

@canon has implemented several useful options in the script (there's a demo here). Please add a UI for them so people don't start using console.config directly.

I'd suggest making it a Console Options button or some such that shows options driven by the script itself, so that when an option is added to the script, the UI for it can be added at the same time. The options would be serialized to JSON and inserted in the stack snippet's introductory comment node.

For instance, where a snippet might currently start with this:

<!-- begin snippet: js hide: false console: true -->

If the user uses the dialog to set options, it might look like this:

<!-- begin snippet: js hide: false console: true console-options: {"maximize":true,"autoScroll":false} -->

Those options get converted into a hidden call to console.config at the beginning of the snippet script.

3

Logging events directly to the console causes the browser to whirrr for a couple of seconds (probably trying to stringify the whole subtree), and throw some errors (in the same console).

Also, it takes a lot longer than necessary to execute the console.log statement (due to the entire stringification process I guess.)

It currently takes roughly 2-3 seconds for me in Chrome 61. Here's how it looks in the browser console:

image

function clicked(event) {
  var startTime = new Date();
  console.log(event);
  var endTime = new Date();
  
  console.log("Total time (ms): " + (endTime - startTime));
}
<button onclick="clicked(event)">Click me</button>

1
  • Almost 16 seconds for me Commented Apr 10, 2018 at 13:18

You must log in to answer this question.

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