ipadやiphone用に、画面にログを出力する。console.log() の代わりに screenLog() で利用する。
נכון ליום
אין להתקין סקריפט זה ישירות. זוהי ספריה עבור סקריפטים אחרים // @require https://update.greasyfork.org/scripts/577436/1820905/Screen%20Display%20Log.js
// ==UserScript==
// @name Screen Display Log
// @namespace http://tampermonkey.net/
// @version 1.0
// @description ipadやiphone用に、画面にログを出力する。console.log() の代わりに screenLog() で利用する。
// @grant none
// ==/UserScript==
/**
* 画面端にデバッグ用UIを表示するクラス
*/
class ScreenLogger {
constructor() {
this.id = 'tm-debug-console';
this.container = null;
this.logArea = null;
this._setup();
}
/**
* 初期セットアップ
*/
_setup() {
if (document.getElementById(this.id)) return;
this._injectStyles();
this._createUI();
}
/**
* CSSを<style>タグとして注入(インラインスタイルの撤廃)
*/
_injectStyles() {
const style = document.createElement('style');
style.textContent = `
#${this.id} { position: fixed; bottom: 10px; right: 10px; width: 280px; max-height: 250px; background-color: rgba(0, 0, 0, 0.85); color: #00ff00; font-size: 11px; font-family: monospace; padding: 5px; border-radius: 5px; overflow-y: auto; z-index: 999999; pointer-events: auto; border: 1px solid #444; box-shadow: 0 0 10px rgba(0,0,0,0.5); }
#${this.id} .tm-header { border-bottom: 1px solid #444; margin-bottom: 5px; padding-bottom: 3px; display: flex; justify-content: space-between; align-items: center; }
#${this.id} .tm-header b { color: #fff; }
#${this.id} button { font-size: 9px; cursor: pointer; margin-left: 4px; }
#${this.id} .tm-log-area { display: block; }
#${this.id} .tm-line { border-bottom: 1px solid #222; padding: 2px 0; white-space: pre-wrap; word-break: break-all; }
#${this.id}.minimized { height: 25px; overflow: hidden; }
#${this.id}.minimized .tm-log-area { display: none; }
`;
document.head.appendChild(style);
}
/**
* UI要素の構築
*/
_createUI() {
this.container = document.createElement('div');
this.container.id = this.id;
const header = document.createElement('div');
header.className = 'tm-header';
header.innerHTML = `
<span><b>[DEBUG]</b></span>
<div>
<button id="tm-clear-log">Clear</button>
<button id="tm-toggle-log">Min</button>
</div>
`;
this.logArea = document.createElement('div');
this.logArea.className = 'tm-log-area';
this.container.appendChild(header);
this.container.appendChild(this.logArea);
document.body.appendChild(this.container);
// イベントリスナーの登録
this.container.querySelector('#tm-clear-log').onclick = () => this.clear();
this.container.querySelector('#tm-toggle-log').onclick = (e) => this._toggle(e.target);
}
/**
* 表示・非表示の切り替え
*/
_toggle(btn) {
const isMinimized = this.container.classList.toggle('minimized');
btn.innerText = isMinimized ? 'Max' : 'Min';
}
/**
* ログの消去
*/
clear() {
if (this.logArea) this.logArea.innerHTML = '';
}
/**
* 引数を文字列に整形(HTML要素、オブジェクト対応)
*/
_format(arg) {
if (arg === null) return 'null';
if (arg === undefined) return 'undefined';
if (arg instanceof HTMLElement) {
const id = arg.id ? `#${arg.id}` : '';
const classes = arg.className ? `.${Array.from(arg.classList).join('.')}` : '';
return `<${arg.tagName.toLowerCase()}${id}${classes}>`;
}
if (typeof arg === 'object') {
try {
return JSON.stringify(arg);
} catch (e) {
return String(arg);
}
}
return String(arg);
}
/**
* 画面にログを出力
*/
log(...args) {
const msg = args.map(arg => this._format(arg)).join(' ');
const line = document.createElement('div');
line.className = 'tm-line';
line.innerText = `> ${msg}`;
this.logArea.appendChild(line);
this.container.scrollTop = this.container.scrollHeight;
}
}
/**
* 外部から呼び出すためのエントリーポイント
*/
function initOnScreenConsole() {
const logger = new ScreenLogger();
// 既存の「関数として呼び出す」挙動を維持するため、メソッドをバインドして返す
return logger.log.bind(logger);
}
// 利用開始
const screenLog = initOnScreenConsole();