001 - Blocklyを使ったオリジナルVisual Programming Editorを作ってみる

## とりあえず動かしてみる
[前回](http://qiita.com/heyhachi/items/f422ffefd959a673ca7b)開発環境は整えました。今回はとりあえず動かしてみます。

## Blocklyの表示エリアを作る
まずはBlocklyを埋め込むHTMLを用意しなければなりません。公式のドキュメントによると、ウィンドウのサイズが変更されてもサイズの変わらない方法と、ウィンドウサイズに合わせてリサイズさせる2通りの埋め込み方があるようです。今回はウィンドウに合わせてリサイズさせるようにします。

## Blocklyモジュールを読み込む
googleディレクトリにindex.htmlを作り、[こちらのチュートリアル](https://developers.google.com/blockly/installation/injecting-fixed-size)参考に各モジュールを読み込みます。今回は本体とブロックモジュール以外はとりあえず適当に読み込みました。

```html
<!DOCTYPE html>
<head>
  <!--本体モジュール-->
  <script src="blockly/blockly_compressed.js"></script>
  <!--Blockモジュール-->
  <script src="blockly/blocks_compressed.js"></script>
  <!--Block定義モジュール-->
  <script src="blockly/blocks/logic.js"></script>
  <script src="blockly/blocks/math.js"></script>
  <script src="blockly/blocks/lists.js"></script>
  <!--ソースコードジェネレーターモジュール-->
  <script src="blockly/generators/javascript/logic.js"></script>
  <script src="blockly/generators/javascript/math.js"></script>
  <script src="blockly/generators/javascript/lists.js"></script>
  <!--翻訳-->
  <script src="blockly/msg/js/ja.js"></script>
</head>
<body>
</body>
```

## ツールボックスの表示
次にツールボックスを埋め込みます。ツールボックスはXMLで定義します。bodyタグ内に以下のように定義します。

```xml
<xml id="toolbox" style="display: none">
  <category name="コントロール">
    <block type="controls_if"></block>
    <block type="controls_repeat_ext"></block>
  </category>
  <category name="ロジック">
    <block type="logic_compare"></block>
  </category>
  <category name="数学">
    <block type="math_number"></block>
    <block type="math_arithmetic"></block>
  </category>
  <category name="テキスト">
    <block type="text"></block>
    <block type="text_print"></block>
  </category>
</xml>
```

## Blockly用のdiv要素を定義
そして、Blocklyを埋め込むdiv要素を定義します。idをblocklyDivにしてあげる必要があります。

```html
<!--Blockly埋め込み位置-->
<div id="blocklyDiv" style="position: absolute;"></div>
```  

## リサイズに対応させたエリアを用意
公式のドキュメントによると、HTMLのtableタグ、もしくはdiv+cssでウィンドウのリサイズに対応した領域を用意する必要があるようです。そしてその要素のidはblocklyAreaとするみたいです。とりあえずtableタグを使って以下のようにしました。

```html
<table>
  <tbody>
    <tr>
      <h1>おれおれエディター</h1>
    </tr>
    <tr>
      <td id="blocklyArea">Workspace</td>
    </tr>
  </tbody>
</table>
```

## 最後はスクリプト
あとはJavaScriptでゴニョゴニョしてやれば良いようです。bloclyDivにBlocklyを注入し、リサイズ時にはblocklyAreaプロパティから情報を取得してblocklyDivの位置、座標を書き換えるだけのようです。

```javascript
var blocklyArea = document.getElementById("blocklyArea");
var blocklyDiv = document.getElementById("blocklyDiv");
// blocklyDivにツールボックスなどを注入
var workspace = Blockly.inject(blocklyDiv,
  {toolbox: document.getElementById('toolbox'),
  grid: // グリッドを表示させる
    {spacing: 20, // グリッドのスペース
    length: 3, // グリッドのラインの長さ
    colour: '#ccc', // グリッドの色
    snap: true}, // グリッドに吸い付かせるかどうか
  trashcan: true}); // ゴミ箱を表示する

// リサイズ時の処理は公式ドキュメントそのまま  
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';
};
window.addEventListener('resize', onResize, false);
onResize();
```

## 最後に
ちょこっとスタイルの定義を追加したここまでのHTMLの全容です。

```html
<!DOCTYPE html>
<head>
	<style>
    html, body {
      height: 100%;
      margin: 0;
    }
    
    table {
      height: 100%;
      width: 100%;
    }
    
    #blocklyArea {
      height: 99%;
      background: #888888;
      text-align: center;
    }
  </style>
  
  <!--本体モジュール-->
  <script src="blockly/blockly_compressed.js"></script>
  <!--Blockモジュール-->
  <script src="blockly/blocks_compressed.js"></script>
  <!--Block定義モジュール-->
  <script src="blockly/blocks/logic.js"></script>
  <script src="blockly/blocks/math.js"></script>
  <script src="blockly/blocks/lists.js"></script>
  <!--ソースコードジェネレーターモジュール-->
  <script src="blockly/generators/javascript/logic.js"></script>
  <script src="blockly/generators/javascript/math.js"></script>
  <script src="blockly/generators/javascript/lists.js"></script>
  <!--翻訳-->
  <script src="blockly/msg/js/ja.js"></script>
</head>
<body>
  <!--Blockly埋め込みエリア-->
  <table>
    <tbody>
    <tr>
      <h1>おれおれエディター</h1>
    </tr>
    <tr>
      <td id="blocklyArea">Workspace</td>
    </tr>
    </tbody>
  </table>
  
  <div id="blocklyDiv" style="position: absolute;"></div>
  <!--ツールボックス-->
  <xml id="toolbox" style="display: none">
    <category name="コントロール">
      <block type="controls_if"></block>
      <block type="controls_repeat_ext"></block>
    </category>
    <category name="ロジック">
      <block type="logic_compare"></block>
    </category>
    <category name="数学">
      <block type="math_number"></block>
      <block type="math_arithmetic"></block>
    </category>
    <category name="テキスト">
      <block type="text"></block>
      <block type="text_print"></block>
    </category>
  </xml>
  
  <script>
    var blocklyArea = document.getElementById("blocklyArea");
    var blocklyDiv = document.getElementById("blocklyDiv");
    var workspace = Blockly.inject(blocklyDiv,
      {toolbox: document.getElementById('toolbox'),
      grid:
        {spacing: 20,
        length: 3,
        colour: '#ccc',
        snap: true},
      trashcan: true});
    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';
    };
    window.addEventListener('resize', onResize, false);
    onResize();
  </script>
</body>
```

あとはindex.htmlを開くだけで、とりえずブロック並べたり、削除したりが動作するはずです。まだ、Webサーバーは特に必要ありません。次回はソースコードの出力を試したいと思います。