84

I would like to write the console.log output to a div layer.

For example:

document.write(console.log(5+1)); //Incorrect, random example

Can someone give me a solution to my problem?

Thank you.

EDIT:

what i meant is, for example:

console.log("hi");

and it shows the output "hi" on the screen.

Note: An example: http://labs.codecademy.com/#:workspace

leonneo
  • 1,058
  • 1
  • 10
  • 15

7 Answers7

122

You can override the default implementation of console.log()

(function () {
    var old = console.log;
    var logger = document.getElementById('log');
    console.log = function (message) {
        if (typeof message == 'object') {
            logger.innerHTML += (JSON && JSON.stringify ? JSON.stringify(message) : message) + '<br />';
        } else {
            logger.innerHTML += message + '<br />';
        }
    }
})();

Demo: Fiddle

Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
35

Slight improvement on @arun-p-johny answer:

In html,

<pre id="log"></pre>

In js,

(function () {
    var old = console.log;
    var logger = document.getElementById('log');
    console.log = function () {
      for (var i = 0; i < arguments.length; i++) {
        if (typeof arguments[i] == 'object') {
            logger.innerHTML += (JSON && JSON.stringify ? JSON.stringify(arguments[i], undefined, 2) : arguments[i]) + '<br />';
        } else {
            logger.innerHTML += arguments[i] + '<br />';
        }
      }
    }
})();

Start using:

console.log('How', true, new Date());
Nitin...
  • 1,274
  • 10
  • 18
  • 3
    To keep original `console.log` functionality add `old(...arguments);` at the end of new console log function. Remember to use the spread operator! – Tim Apr 19 '17 at 13:55
  • 4
    `old.apply(console, arguments);` will also work to keep original arguments. – Tim Apr 19 '17 at 18:01
  • 2
    I am a bit confused, I'm pretty new to Javascript, what is the structure of this function. the first bracket, why? and what is with the last bracketpair? – AdrianL Dec 10 '17 at 12:37
  • 1
    @DaPole it's wrapped in a self-executing anonymous function. – Chords Mar 01 '18 at 18:47
18

A little late to the party, but I took @Hristiyan Dodov's answer a bit further still.

All console methods are now rewired and in case of overflowing text, an optional autoscroll to bottom is included. Colors are now based on the logging method rather than the arguments.

rewireLoggingToElement(
    () => document.getElementById("log"),
    () => document.getElementById("log-container"), true);

function rewireLoggingToElement(eleLocator, eleOverflowLocator, autoScroll) {
    fixLoggingFunc('log');
    fixLoggingFunc('debug');
    fixLoggingFunc('warn');
    fixLoggingFunc('error');
    fixLoggingFunc('info');

    function fixLoggingFunc(name) {
        console['old' + name] = console[name];
        console[name] = function(...arguments) {
            const output = produceOutput(name, arguments);
            const eleLog = eleLocator();

            if (autoScroll) {
                const eleContainerLog = eleOverflowLocator();
                const isScrolledToBottom = eleContainerLog.scrollHeight - eleContainerLog.clientHeight <= eleContainerLog.scrollTop + 1;
                eleLog.innerHTML += output + "<br>";
                if (isScrolledToBottom) {
                    eleContainerLog.scrollTop = eleContainerLog.scrollHeight - eleContainerLog.clientHeight;
                }
            } else {
                eleLog.innerHTML += output + "<br>";
            }

            console['old' + name].apply(undefined, arguments);
        };
    }

    function produceOutput(name, args) {
        return args.reduce((output, arg) => {
            return output +
                "<span class=\"log-" + (typeof arg) + " log-" + name + "\">" +
                    (typeof arg === "object" && (JSON || {}).stringify ? JSON.stringify(arg) : arg) +
                "</span>&nbsp;";
        }, '');
    }
}


setInterval(() => {
  const method = (['log', 'debug', 'warn', 'error', 'info'][Math.floor(Math.random() * 5)]);
  console[method](method, 'logging something...');
}, 200);
#log-container { overflow: auto; height: 150px; }

.log-warn { color: orange }
.log-error { color: red }
.log-info { color: skyblue }
.log-log { color: silver }

.log-warn, .log-error { font-weight: bold; }
<div id="log-container">
  <pre id="log"></pre>
</div>
Benny Bottema
  • 11,111
  • 10
  • 71
  • 96
  • 1
    Botteman, it seem that doesn't working on chrome 68 on android! – r.zarei Sep 08 '18 at 09:40
  • 1
    now the question is, how can I easily add console.time and console.timeEnd? – Gareth Compton Oct 29 '18 at 01:30
  • What does this code means? rewireLoggingToElement( () => document.getElementById("log"), () => document.getElementById("log-container"), true); why are you passing arrow function to the function? it's valid javascript but it seems very unfamiliar to me. – Gaetano Piazzolla Sep 22 '19 at 13:18
  • @Gaetano, these are simple closures. Using function variables you can delay executing them until the result is actually needed (for example in case the DOM hasn't initialized yet or will change in the future). – Benny Bottema Sep 26 '19 at 11:38
  • Nice work. But what about grouping and tabular data? Is there not already some where a web component, or jQuery plugin that "gives you a developer console implemented as a webpage"? – jerng Feb 28 '20 at 23:15
  • A little late to the party, but this is the best solution. – Julian Aug 22 '21 at 05:50
  • Somehow I can't get ongoing updated content written to the `log-container`. I am running loops within loops with `ajax` calls set to `async: false,` which have many `console.log` calls in them, but the output only gets updated after my loops have finished processing. (I have been having the same problem with my animation, it only plays after my loops finish.) I tried adding a call inside the `ajax` `success: function( result ) {` but could not get it to work. Thanks for your help. – MeSo2 Dec 12 '22 at 19:59
  • PS. I just noticed that if I change the window size during the looping process, that I get sporadic writes to the `log-container`. So maybe I would just need to build in some pause for the update to have a chance of catching up with the looping. Not sure how.... – MeSo2 Dec 12 '22 at 21:18
17

I come a bit late with a more advanced version of Arun P Johny's answer. His solution doesn't handle multiple console.log() arguments and doesn't give an access to the original function.

Here's my version:

(function (logger) {
    console.old = console.log;
    console.log = function () {
        var output = "", arg, i;

        for (i = 0; i < arguments.length; i++) {
            arg = arguments[i];
            output += "<span class=\"log-" + (typeof arg) + "\">";

            if (
                typeof arg === "object" &&
                typeof JSON === "object" &&
                typeof JSON.stringify === "function"
            ) {
                output += JSON.stringify(arg);   
            } else {
                output += arg;   
            }

            output += "</span>&nbsp;";
        }

        logger.innerHTML += output + "<br>";
        console.old.apply(undefined, arguments);
    };
})(document.getElementById("logger"));

// Testing
console.log("Hi!", {a:3, b:6}, 42, true);
console.log("Multiple", "arguments", "here");
console.log(null, undefined);
console.old("Eyy, that's the old and boring one.");
body {background: #333;}
.log-boolean,
.log-undefined {color: magenta;}
.log-object,
.log-string {color: orange;}
.log-number {color: cyan;}
<pre id="logger"></pre>

I took it a tiny bit further and added a class to each log so you can color it. It outputs all arguments as seen in the Chrome console. You also have access to the old log via console.old().

Here's a minified version of the script above to paste inline, just for you:

<script>
    !function(o){console.old=console.log,console.log=function(){var n,e,t="";for(e=0;e<arguments.length;e++)t+='<span class="log-'+typeof(n=arguments[e])+'">',"object"==typeof n&&"object"==typeof JSON&&"function"==typeof JSON.stringify?t+=JSON.stringify(n):t+=n,t+="</span>&nbsp;";o.innerHTML+=t+"<br>",console.old.apply(void 0,arguments)}}
    (document.body);
</script>

Replace document.body in the parentheses with whatever element you wish to log into.

dodov
  • 5,206
  • 3
  • 34
  • 65
  • Took this solution a [bit further](https://stackoverflow.com/a/50773729/441662) still. Now inlcudes autoscrolling on overflow and rewires all console methods rather than just `.log()`. – Benny Bottema Jun 11 '18 at 06:41
  • I know this is an old thread, but I've just started using this in a mobile app. One question: how can I display the file and line that generated the log? – Mat Jun 07 '19 at 12:50
  • I don't think you can. You simply don't get that information. If it's an app, you should look for other debugging options like USB debugging. – dodov Jun 09 '19 at 05:13
  • take it a tiny bit further and add clear console! ;-) – vwvan Sep 02 '19 at 21:18
7

Create an ouput

<div id="output"></div>

Write to it using JavaScript

var output = document.getElementById("output");
output.innerHTML = "hello world";

If you would like it to handle more complex output values, you can use JSON.stringify

var myObj = {foo: "bar"};
output.innerHTML = JSON.stringify(myObj);
maček
  • 76,434
  • 37
  • 167
  • 198
2

This post has helped me a lot, and after a few iterations, this is what we use.

The idea is to post log messages and errors to HTML, for example if you need to debug JS and don't have access to the console.

You do need to change 'console.log' with 'logThis', as it is not recommended to change native functionality.

What you'll get:

  • A plain and simple 'logThis' function that will display strings and objects along with current date and time for each line
  • A dedicated window on top of everything else. (show it only when needed)
  • Can be used inside '.catch' to see relevant errors from promises.
  • No change of default console.log behavior
  • Messages will appear in the console as well.

function logThis(message) {
  // if we pass an Error object, message.stack will have all the details, otherwise give us a string
  if (typeof message === 'object') {
    message = message.stack || objToString(message);
  }

  console.log(message);

  // create the message line with current time
  var today = new Date();
  var date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
  var time = today.getHours() + ':' + today.getMinutes() + ':' + today.getSeconds();
  var dateTime = date + ' ' + time + ' ';

  //insert line
  document.getElementById('logger').insertAdjacentHTML('afterbegin', dateTime + message + '<br>');
}

function objToString(obj) {
  var str = 'Object: ';
  for (var p in obj) {
    if (obj.hasOwnProperty(p)) {
      str += p + '::' + obj[p] + ',\n';
    }
  }
  return str;
}

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

logThis(object1)
logThis('And all the roads we have to walk are winding, And all the lights that lead us there are blinding')
#logWindow {
  overflow: auto;
  position: absolute;
  width: 90%;
  height: 90%;
  top: 5%;
  left: 5%;
  right: 5%;
  bottom: 5%;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 20;
}
<div id="logWindow">
  <pre id="logger"></pre>
</div>

Thanks this answer too, JSON.stringify() didn't work for this.

Yigal
  • 185
  • 3
  • 7
1

Copy & paste the code below

console.log = (...e) => {for(var i=0;i<e.length;i++){document.getElementById("log").innerHTML += (typeof(e[i]) == "object" ? JSON.stringify(e[i]):e[i]) + "<br />"}};

console.log = (...e) => {for(var i=0;i<e.length;i++){document.getElementById("log").innerHTML += (typeof(e[i]) == "object" ? JSON.stringify(e[i]):e[i]) + "<br />"}};

console.log("Hello world",{objectWorks:true},["Array works?","Yes"])
<div id="log"></div>

If you would like to have the default "console.log", just change the "console.log" to "var CustomNameOfLog". Or Just copy & paste the code below.

var CustomNameOfLog = (...e) => {for(var i=0;i<e.length;i++){document.getElementById("log").innerHTML += (typeof(e[i]) == "object" ? JSON.stringify(e[i]):e[i]) + "<br />"}};

var customNameOfLog = (...e) => {for(var i=0;i<e.length;i++){document.getElementById("log").innerHTML += (typeof(e[i]) == "object" ? JSON.stringify(e[i]):e[i]) + "<br />"}};

customNameOfLog("Hello world",{objectWorks:true},["Array works?","Yes"])
<div id="log"></div>
Filip Blom
  • 11
  • 2