お手軽なCodePenもどきを作ったので紹介します。CodePenとは大雑把に言うとhtmlの動作検証をするようなprogramです。
本家CodePenの編集機能(最小限)と描画機能だけを搭載しています。編集領域と描画領域はmouseで伸縮可能。何なら非表示にもできます。
<!DOCTYPE html>
<meta charset=utf8>
<meta name=viewport content="width=device-width,initial-scale=1.0">
<title>TinyCodePen</title>
<style>
*{box-sizing:border-box;color:#fff;margin:0;font:14px "MS Gothic",monospace}
body{flex:1;flex-direction:column;height:100vh}
body,div{display:flex;overflow:hidden}
button,label{cursor:pointer}
button{padding:5px 15px;background:#4a5}
button:hover{background:#5b6}
p{background:#333}
div,textarea,iframe{flex:1 1 0;min-width:0;min-height:0}
textarea{background:#223;resize:none}
hr{background:#444;border:0}
hr:hover{background:#08c}
hr.h{width:5px;cursor:col-resize}
hr.v{height:5px;cursor:row-resize}
.hidden{display:none!important}
</style>
<p>See
<label><input id=th type=checkbox checked>HTML</label>
<label><input id=tc type=checkbox checked>CSS</label>
<label><input id=tj type=checkbox checked>JS</label>
<label><input id=tr type=checkbox checked>View</label>
<button onclick="run()">Run</button>
<div id=ed>
<textarea id=html placeholder=HTML></textarea>
<hr class=h id=s1>
<textarea id=css placeholder=CSS></textarea>
<hr class=h id=s2>
<textarea id=js placeholder=JS></textarea>
</div>
<hr class=v id=s3>
<div id=pv>
<iframe id=out srcdoc=preview></iframe>
</div>
<script>{
const sized=[html,css,js,ed,pv],
hide=(x,f)=>x.classList.toggle('hidden',!f),
pos=(e,axis)=>axis=='x'?e.clientX:e.clientY,
len=(r,axis)=>axis=='x'?r.width:r.height,
near=(x,dir)=>{while(x=x[dir])if(!x.classList.contains('hidden'))return x},
t0='<!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1.0"><title></title><style>';
//描画
function run(d){
let h=html.value.trim(),c=css.value.trim(),j=js.value.trim();
out.srcdoc=j&&!h&&!c
?`<script>${j}<\/script>`
:/^(<html|<!doctype)/i.test(h)
?h
:`${t0+c}</style></head>${h}<script>${j}<\/script>`
}
//編集領域と描画領域の再構成
function update(n){
let h=th.checked,c=tc.checked,j=tj.checked,r=tr.checked;
for(n of sized)n.style.flex='';
hide(html,h);hide(css,c);hide(js,j);
hide(ed,n=h+c+j);hide(pv,r);
hide(s1,h&&(c||j));hide(s2,c&&j);hide(s3,n&&r)
}
//境界線drag時の動作
function drag(bar,axis){
bar.addEventListener('mousedown',e=>{
const a=near(bar,'previousElementSibling'), b=near(bar,'nextElementSibling');
if(!a||!b)return;
e.preventDefault();
out.style.pointerEvents='none';//cursorがiframeに重なった時の対策
const p0=pos(e,axis),
a0=len(a.getBoundingClientRect(),axis),
b0=len(b.getBoundingClientRect(),axis),
move=e=>{
let d=pos(e,axis)-p0,na=a0+d,nb=b0-d;
if(na>9&&nb>9)a.style.flex=`0 0 ${na}px`,b.style.flex=`0 0 ${nb}px`
};
addEventListener('mousemove',move)
addEventListener('mouseup',e=>removeEventListener('mousemove',move,out.style.pointerEvents=''))
})
}
for(let a of[th,tc,tj,tr])a.onchange=update;
drag(s1,'x');drag(s2,'x');drag(s3,'y');(self.onresize=update)()
}</script>
説明書
- See: 表示と非表示を切り替える
- HTML
htmlのbody要素を記述。
<!doctypeや<htmlで始まる文字列(空白類除外)の場合は後述のCSSとJSは無視されるので、ここに全て記述する事になる - CSS
style要素の中身を記述(
headの子要素) - JS
JavaScriptを記述(
body最後の子要素)。前述のHTMLとCSSを省略しても、JSだけの実行も可能 - preview
上述の内容を描画する領域
蛇足
- 表示と非表示を切り替える前後で境界線の位置は記憶していません
-
windowを伸縮させた時に境界線の位置がずれます - CodeMirror的なtokenの色分け表示は実装していません
- 構図変更機能は実装していません