Blockly Menu作成(3)

# Blockly Menu作成(3)
前回に続けて、googleのガイドを参照して作成していこうと思います。
[Google for Education > Blockly > Guides > Get Started](https://developers.google.com/blockly/guides/get-started/web)

## 可変サイズ
googleのガイドを参照します。
[Resizable Workspace](https://developers.google.com/blockly/guides/configure/web/resizable)

on resizeイベント時にblocklyAreaに合わせてサイズを再計算することで実現しているようです。

```javascript
	var onresize = function (e) {
		// Compute the absolute coordinates and dimensions of blocklyArea.
		var element = blocklyArea;
		var x = 0;
		var y = 0;
		do {
			x += element.offsetLeft;
			y += element.offsetTop;
			element = element.offsetParent;
		} while (element);
		// Position blocklyDiv over blocklyArea.
		blocklyDiv.style.left = x + 'px';
		blocklyDiv.style.top = y + 'px';
		blocklyDiv.style.width = blocklyArea.offsetWidth + 'px';
		blocklyDiv.style.height = blocklyArea.offsetHeight + 'px';
		Blockly.svgResize(workspace);
	};
	window.addEventListener('resize', onresize, false);
	onresize();
```


## ファイル分割
今までindex.htmlの1ファイルだけで作成してきましたが、スクリプトとXMLを分割したいと思います。
スタイルシートの準備もします。


## まとめ


### HTML
表示サイズの計算のためにblocklyAreaを追加しています。



```html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
	<meta charset="utf-8">
	<title>Blockly Sample</title>
	<script src="../blockly/blockly_compressed.js"></script>
	<script src="../blockly/blocks_compressed.js"></script>
	<script src="../blockly/msg/js/en.js"></script>
	<link rel="stylesheet" href="./styles.css">
	<script src="./workspace.js"></script>
</head>

<body>
	<table>
		<tr>
			<td>
				<p>Blockly toolbox</p>
			</td>
    </tr>
    <tr>
      <td id="blocklyArea">
        Blockly will be positioned here.
      </td>
    </tr>
	</table>
	<div id="blocklyDiv"></div>
</body>

</html>
```


### スタイルシート

スタイルシートを分割します。

```scss:styles.css
html, body {
    height: 100%;
    margin: 0;
}

body {
    background-color: #fff;
    font-family: sans-serif;
    overflow: hidden;
}

h1 {
    font-weight: normal;
    font-size: 140%;
}

table {
    height: 100%;
    width: 100%;
}

#blocklyArea {
    height: 99%;
    background: #fc9;
    text-align: center;
}

#blocklyDiv
{
    position: absolute;
}
```

### XML

前回のカスタマイズしたメニューを別ファイルに分割します。

```xml:toolbox.xml
<xml id="toolbox" style="display: none">
    <category name="Control">
        <block type="controls_if"></block>
        <block type="controls_whileUntil"></block>
        <block type="controls_repeat_ext"></block>
    </category>
    <category name="Logic">
        <block type="logic_compare"></block>
        <block type="math_number"></block>
        <block type="math_arithmetic"></block>
    </category>
    <category name="Text">
        <block type="text"></block>
        <block type="text_print"></block>
    </category>
    <category name="Variables" custom="VARIABLE"></category>
    <category name="Functions" custom="PROCEDURE"></category>
</xml>
```

### JavaScript

Resizeするための処理を追加したスクリプトを別ファイルに準備します。


```javascript:workspace.js

Promise.all(
	["toolbox.xml"].map(async file => {
		return fetch(file).then(
			(res) => {
				return res.text();
			}
		);
	})
).then((xmls) => {
	xmls.forEach((xml) => {
		var parser = new DOMParser();
		var doc = parser.parseFromString(xml, "application/xml");
		document.body.appendChild(doc.documentElement);
	});
}).then(() => {
	var blocklyArea = document.getElementById('blocklyArea');
	var blocklyDiv = document.getElementById('blocklyDiv');
	var toolbox = document.getElementById("toolbox");

	var options = {
		toolbox: toolbox,
		scrollbars: true,
	};

	var blocklyDiv = document.getElementById('blocklyDiv');
	var workspace = Blockly.inject('blocklyDiv', options);

	var onresize = function (e) {
		// Compute the absolute coordinates and dimensions of blocklyArea.
		var element = blocklyArea;
		var x = 0;
		var y = 0;
		do {
			x += element.offsetLeft;
			y += element.offsetTop;
			element = element.offsetParent;
		} while (element);
		// Position blocklyDiv over blocklyArea.
		blocklyDiv.style.left = x + 'px';
		blocklyDiv.style.top = y + 'px';
		blocklyDiv.style.width = blocklyArea.offsetWidth + 'px';
		blocklyDiv.style.height = blocklyArea.offsetHeight + 'px';
		Blockly.svgResize(workspace);
	};
	window.addEventListener('resize', onresize, false);
	onresize();
	Blockly.svgResize(workspace);
});
```

Windowsサイズを変更すると、追従してサイズが変更するようになりました。