Mobile Console
window._originalLog = window._originalLog || window.console.log;
window._consoleArea = (() => {
  var script_bank = document.createElement('div');
  var div = document.createElement('div');
  var shadow = div.attachShadow({mode: 'open'});
  var display = document.createElement('div');
  display.classList.add('display');
  var button_wrap = document.createElement('div');
  button_wrap.classList.add('wrap');
  var apply = document.createElement('button');
  apply.textContent = 'apply';
  var clean = document.createElement('button');
  clean.textContent = 'clean';
  var close = document.createElement('button');
  close.textContent = 'close';
  var textarea = document.createElement('textarea');
  var style = document.createElement('style');
  style.textContent = ':host {bottom: 0;font-family: Courier, monospace;left: 0;margin: auto;padding: 0;position: fixed;right: 0;width: 100vw;z-index: 999999;}:host .wrap {display: flex;}:host .display {background: #fff;border: 1px solid #aaa;}:host .display:empty {background: rgba(255, 255, 255, 0);border: none;}:host button {background: #eee;border: 1px solid #aaa;cursor: pointer;display: block;font-family: Courier, monospace;font-size: .8rem;padding: .5em 0;transition: all .25s;width: 100%;}:host button:hover {background: #e5e5e5;border-color: #31a0ce;}:host > textarea {background: #f6f6cb;border: 1px solid #aaa;bottom: 0;display: block;font-family: Courier, monospace;font-size: 16px;height: 300px;margin: 0;max-height: 30vh;transition: all .25s;width: calc(100% - 2px);}:host > textarea:focus {border-color: #31a0ce;outline: none;}';
  shadow.append(style);
  shadow.append(display);
  shadow.append(button_wrap);
  button_wrap.appendChild(apply);
  button_wrap.appendChild(clean);
  button_wrap.appendChild(close);
  shadow.append(textarea);
  document.body.appendChild(div);
  document.body.appendChild(script_bank);
  apply.onclick = e => {
    var _s = document.createElement('script');
    _s.textContent = textarea.value;
    script_bank.appendChild(_s);
  };
  clean.onclick = e => (textarea.value = '', display.innerHTML = '');
  close.onclick = e => (script_bank.innerHTML = '', script_bank.remove(), div.remove(), window.console.log = window._originalLog);
  return display;
})();
window.ObjectElm = class {
  constructor(obj, wrap) {
    this.wrap = wrap;
    this.obj = wrap ? {'__wrap__': obj} : obj;
    this.ul = document.createElement('ul');
  }
  init() {
    var Analyze = obj => {
      var tp = typeof obj, val = String(obj), name = obj?.constructor?.name;
      val = (tp == 'boolean' || tp == 'number' || tp == 'symbol' || obj == null || obj == void(0))
        ? val
        : tp == 'bigint'
          ? `${val}n`
          : tp =='string'
            ? `"${val}"`
            : name.match(/^.*?Array$/)
              ? `${name}(${obj.length}) [${obj.length ? '...' : ''}]`
              : (name == 'ArrayBuffer' || name == 'SharedArrayBuffer' || name == 'DataView')
                ? `${name}(${obj.byteLength}) {}`
                : name == 'Object'
                  ? `Object {${Object.keys(obj).length ? '...' : ''}}`
                  : `${name} {}`;
      return {val: val, type: tp, name: name};
    };
 
    var Create = key => {
      try {
        var li = document.createElement('li');
        var btn = document.createElement('btn');
        var str = document.createElement('b');
        btn.li = li;
        btn._next = this.obj[key];
        var {val} = Analyze(btn._next);
        str.textContent = `${key}: `;
        btn.textContent = val;
        this.wrap || li.appendChild(str);
        li.appendChild(btn);
        btn.onclick = e => {
          var b = e.target;
          if(b._obj) {
            b._obj.ul.remove();
            delete b._obj;
          }
          else {
            b._obj = new ObjectElm(b._next);
            b.li.appendChild(b._obj.init());
          }
        };
        this.ul.appendChild(li);
      }catch(e) {
        window._originalLog(`Ignoring exception: "${e.name}" >>> "${key}"`, this.obj);
      }
    };
 
    var str = Analyze(this.obj).type == 'string';
    var keys = [];
    for(var k in this.obj) keys.push(k);
    keys = [
      ...keys,
      ...(
        (this.obj == null || this.obj == void(0))
          ? []
          : [...Object.keys(this.obj), ...Object.getOwnPropertyNames(this.obj)]
      )
    ].filter((v, i, a) => a.indexOf(v) == i).filter(v => str ? !v.match(/^\d+$/) : true);
 
    keys.forEach(k => Create(k));
 
    this.wrap || this.obj?.__proto__ && Create('__proto__');
 
    return this.ul;
  }
  insert(parent) {
    var shadow;
    if(!parent.shadowRoot) {
      shadow = parent.attachShadow({mode: 'open'});
      var style = document.createElement('style');
      style.textContent = ':host {align-items: flex-start;display: flex;flex-wrap: wrap;font-family: Courier, monospace;font-size: .8rem;}:host * {scrollbar-color: rgba(50, 50, 50, 0.3) rgba(0, 0, 0, 0);scrollbar-width: thin;}::-webkit-scrollbar {border: solid 1px rgba(0, 0, 0, 0);height: 9px;width: 9px;}::-webkit-scrollbar-thumb {background: rgba(50, 50, 50, 0.3);}::-webkit-scrollbar-track {background: rgba(0, 0, 0, 0);}ul {background: #fff;border-left: .25em solid #901;box-shadow: 1px 1px 3px #aaa;list-style: none;margin: 0 0 0 .5em;max-height: 300px;overflow-y: auto;padding: .25em .15em .25em .75em;}:host > ul {flex-grow: 1;margin: .35em;text-align: left;}ul:empty {display: none;}';
      shadow.append(style);
    }
    parent.shadowRoot.append(this.ul);
  }
};
 
window.console.log = (...arg) => {
  var div = document.createElement('div');
  _consoleArea.appendChild(div);
  arg.forEach(a => {
    var e = new ObjectElm(a, true);
    e.init();
    e.insert(div);
  });
  window._originalLog.call(console, ...arg);
}
console.log(1, [1, 2], document.querySelector('a'));

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License