【Javascript】リアルタイムプレビュー付き簡易htmlエディタ

今回はJavascriptを使ってhtml作成をある程度楽にする簡易エディタをつくりたいと思います。
似たようなhtmlファイルを大量につくりたいならいいかも

<font color="lightgray">内容をゴリゴリ書くなら然程労力は変わらないと思う…</font>

#プレビュー
![qiita_js003.gif](https://qiita-image-store.s3.amazonaws.com/0/139165/1e5907c6-02cc-07c6-1bd6-83d9bdaf2227.gif)
必要最低限の機能しか実装してないけどちょっと工夫すれば
そこそこ実用的なものが作れるかと思います。そして楽！

[クリックでデモページのzipファイルダウンロード](http://sometrouble.net/tekitou/qiita_js003.zip)
Win,MacのChromeでのみ動作確認済みです
<font color="lightgray">10/17 リンク間違ってました…ごめんなさい</font>

#ソースコード
```qiita_js003.html
<html>
	<head>
		<title>qiita_js003</title>

		<meta charset="utf-8">
		<meta name="viewport" content="width=320, minimum-scale=1.0, maximum-scale=2.0">

		<style type="text/css">
		
			*{
				font-family: Meiryo;
				text-align: center;
				margin: 0;
				padding: 0;
			}
			
			#liveeditor{
				margin: 10px;
			}
			
			.bottomspace{
				margin-bottom: 20px;
			}
			
			.editorwrapper{
				
			}
			
			.editor{
				float: left;
				width: 50%;
				height: 70%;
				
			}
			
			.preview{
				float: right;
				width: 50%;
				height: 70%;
				background-color: DDDDDD;
				
			}
			
			.procedure{
				background-color: white;
				min-height: 100%;
				clear: both;
			}
			
			.button{
				border: 1px solid plum;
				color: black;
				line-height: 50px;
				width: 200px;
				margin: 20px;
				background-color: aliceblue;
				padding: 5px 10px 5px 10px;
				transition: 0.3s;
			}
			
			.button:hover{
				border: 1px solid mediumpurple;
				color: white;
				transition: 0.3s;
				background-color: mediumpurple;
			}
			
			.footer{
				font-size:6px;
				font-weight: 100;
				position: fixed;
				color: white;
				background-color: #444444;
				width: 100%;
				padding: 5px 10px 5px 10px;
				bottom: 0;
			}
		</style>
		
		<script src="http://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.slim.min.js"></script>
		<script>
			$(function() {
				$('body').keyup(function() {
					$('#livepreview').html($('#liveeditor').val());
				});
			});
		</script>
		
	</head>

	<body>
		<div style="editorwrapper">
			<div class="editor">
				<p style="background-color:Black; color:white;">Editor</p>
				<form name="js">
					<p>ページタイトル(ファイル名にも適用されます)</p>
					<input class="bottomspace" type="text" name="title" value="index"><br>
					
					<p>ページの内容(htmlタグが使えます)</p>
					<textarea id="liveeditor" name="htmlbody" rows="10" cols="80"></textarea>
				</form>
			</div>

			<div class="preview">
				<p style="background-color:Black; color:white;">Preview</p>
				<div id="livepreview"></div>
			</div>

			<div class="procedure">
				<p style="background-color:Black; color:white;">Procedure</p>
				<button class="button" onclick="openmanual()">How to Use</button>
				<button class="button" onclick="downloadfile()">Download</button>
			</div>
		</div>
		
		<div class="footer">
				Copyright &#169; 2016 Trouble_SUM All Rights Reserved.
		</div>
		
		<script type="text/javascript">
			function downloadfile(){
				//BOM
                var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
				
				//各フォームの値を取得
                var title = document.js.title.value;
				var htmlbody = document.js.htmlbody.value;
				
				//htmlの内容を変数に格納
				var html ="<html><head><title>" + title + "</title></head><body>" + htmlbody + "</body></html>"
				
				//blobとしてhtmlファイルを生成
				var blob = new Blob([bom, html],{type: "text/html;"})
				
				//a要素を作成してクリックイベント実行
				var a = document.createElement("a");
				a.href = URL.createObjectURL(blob);
				a.target = '_blank';
				a.download = title + '.html';
				a.click();
			}
			
			function openmanual(){
				window.open('manual.html','_blank','top=50,left=50,width=500,height=500,scrollbars=1,location=0,menubar=0,toolbar=0,status=1,directories=0,resizable=1');
				return false;
				}
		</script>
	</body>
</html>
```

一見長いがCSS部分（ちょっと凝ってしまった）を取り除けばかなり単純な構造
大事っぽいところを順に解説していきます。

#解説
```js
<script>
	$(function() {
		$('body').keyup(function() {
			$('#livepreview').html($('#liveeditor').val());
		});
	});
</script>
```
jQueryをちょびっと使ってキー入力が終わった瞬間にliveeditorの値をlivepreview側に反映してるだけ

```html
<div style="editorwrapper">
	<div class="editor">
		<p style="background-color:Black; color:white;">Editor</p>
		<form name="js">
			<p>ページタイトル(ファイル名にも適用されます)</p>
			<input class="bottomspace" type="text" name="title" value="index"><br>

			<p>ページの内容(htmlタグが使えます)</p>
			<textarea id="liveeditor" name="htmlbody" rows="10" cols="80"></textarea>
		</form>
	</div>

	<div class="preview">
		<p style="background-color:Black; color:white;">Preview</p>
		<div id="livepreview"></div>
	</div>

	<div class="procedure">
		<p style="background-color:Black; color:white;">Procedure</p>
		<button class="button" onclick="openmanual()">How to Use</button>
		<button class="button" onclick="downloadfile()">Download</button>
	</div>
</div>
```
フォーム。特別変わったことはしていないと思う

```js
function downloadfile(){
	//BOM
	var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);

	//各フォームの値を取得
	var title = document.js.title.value;
	var htmlbody = document.js.htmlbody.value;

	//htmlの内容を変数に格納
	var html ="<html><head><title>" + title + "</title></head><body>" + htmlbody + "</body></html>"

	//blobとしてhtmlファイルを生成
	var blob = new Blob([bom, html],{type: "text/html;"})

	//a要素を作成してクリックイベントを発火させる
	var a = document.createElement("a");
	a.href = URL.createObjectURL(blob);
	a.target = '_blank';
	a.download = title + '.html';
	a.click();
}
```
これが今回のメイン処理。
htmlファイルをそのまま生成したら文字化けしてしまったのでBOMをつけたら直った。
MacでもWinでも一応文字化けせずにファイル生成できたから大丈夫だと思うけど、
もしもうまくいかないようなら文字コードをUTF-16あたりにすると治るかも？<font color="lightgray">（試してないけど）</font>

あとはフォームからタイトルと本文をぶっこ抜いてタグと結合して変数に格納。
blobとしてhtmlファイルをつくる

そのあとにa要素を生成、クリックイベントを発火させてhtmlファイルを直でダウンロードするようにしてます。

#問題点
言わずともわかると思うけどこれをそのまま使ったらXSSの餌食です。
よくわからない人は試しにテキストエリアに

```js
<script>alert('uoaaaa!!!!!');</script>
```

とかコピペしてみよう。

ローカルで使うならまだしも自分のサーバ上で公開するならタグとか特殊文字のエスケープ処理を加える必要があると思う。
これをこのまま使う人はいないと思うので参考程度に見てネ

#参考にさせていただいた記事
>JavaScriptでファイルダウンロード処理を実現する
http://qiita.com/wadahiro/items/eb50ac6bbe2e18cf8813

BOMを変数に格納するところそのままもらいました