前に公開したMarkdown Table Editorのソースコードを解説する回
まだまだ実用的ではないけど今後実装したい内容はこちら
- Markdown方式のテーブルをテキストにコピペしたらグリッドに反映される
- Markdown Table Editor用のオサレなページを作る(機能ではないので優先度は低めかな)
- あとは気になったこと少しづつ
早速ソースコードの解説と洒落込む
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.28.4/handsontable.full.min.js"></script> <link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.28.4/handsontable.full.min.css"> <!-- 追加削除ボタン --> <button id="add_row_btn">Add Row</button> <button id="del_row_btn">Delete Row</button> <br> <button id="add_col_btn">Add Column</button> <button id="del_col_btn">Delete Column</button> <!-- グリッド表示 --> <div id="grid" ></div> <!-- マークダウン表示 --> <div id="markdown" style="border:1px #ccc solid;" class="copy"></div> <script> var data = [ [ 'col1', 'col2', 'col3', 'col4', 'col5' ], [ '', '', '', '', '' ] ]; var markdown = {}; ( function() { "use strict"; var markdown_area = document.getElementById( 'markdown' ); markdown.setText = function() { var result = ''; $.each( data, function( i , value ) { if ( i == 1 ) { result += new Array( value.length + 1 ).join( ' --- | ' ); result = result.substr( 0, result.length - 2 ) + '<br>'; } result += value.join( ' | ' ); result = result.substr( 0, result.length ) + '<br>'; }); markdown_area.innerHTML = result; }; // コピペを簡単にする $( '#markdown' ).click( function() { var range = document.createRange(), selection = window.getSelection(); range.selectNodeContents( this ); selection.removeAllRanges(); selection.addRange( range ); }); })(); var grid = {}; ( function() { "use strict"; var container = document.getElementById( 'grid' ), addRowBtn = document.getElementById( 'add_row_btn' ), delRowBtn = document.getElementById( 'del_row_btn' ), addColBtn = document.getElementById( 'add_col_btn' ), delColBtn = document.getElementById( 'del_col_btn' ); // ヘッダカラムの表示を変更 function firstRowRenderer( instance, td, row, col, prop, value, cellProperties ) { Handsontable.renderers.TextRenderer.apply( this, arguments ); td.style.fontWeight = 'bold'; td.style.color = 'green'; td.style.background = '#CEC'; } // マイナスイメージのセルの表示設定 function negativeValueRenderer( instance, td, row, col, prop, value, cellProperties ) { Handsontable.renderers.TextRenderer.apply( this, arguments ); if ( parseInt( value, 10 ) < 0 ) { td.style.color = 'red'; } if ( !value || value === '' ) { td.style.background = '#EEE'; } } // グリッドのインスタンス生成 grid = new Handsontable( container, { // バインドされる値 data: data, // グリッドの更新後に実行されるやつ afterRender: function ( changes, source ) { markdown.setText(); }, cells: function ( row, col, prop ) { var cellProperties = {}; if ( row === 0 ) { // ヘッダカラムの設定 cellProperties.renderer = firstRowRenderer; } else { // マイナスイメージの設定 cellProperties.renderer = negativeValueRenderer; } return cellProperties; } }); // Add Row Handsontable.Dom.addEvent( addRowBtn, 'click', function () { grid.alter( 'insert_row', grid.countRows() ); }); // Delete Row Handsontable.Dom.addEvent(delRowBtn, 'click', function () { grid.countRows() > 1 ? grid.alter( 'remove_row', grid.countRows() - 1 ) : null; }); // Add Column Handsontable.Dom.addEvent( addColBtn, 'click', function () { grid.alter( 'insert_col', grid.countCols() ); }); // Delete Row Handsontable.Dom.addEvent( delColBtn, 'click', function () { grid.countCols() > 1 ? grid.alter( 'remove_col', grid.countCols() - 1 ) : null; }); })(); </script> |
またまたこれはindex.htmlにコピペすればそれだけで動くので試してみてください。
解説
1 2 3 |
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.28.4/handsontable.full.min.js"></script> <link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.28.4/handsontable.full.min.css"> |
この3つは今回使用するライブラリになります。
jqueryとhandsontableとhandsontableのCSSです。
handsontableとはjavascriptでExcelライクな操作で値の変更とかできるマジで変態なライブラリです。
範囲指定コピー貼り付けとかフィルコピーとかもできます。
ライセンスはMITライセンスのようです。
↓こんな感じです。
正直このライブラリを駆使するといろんなことができるようになるので
今後も使って何か作ろうかなと思ってます。
SFDCでExcelライクにデータの修正ができるとか夢が広がリングですね。
(インライン編集があるとか言わない)
1 2 3 4 5 6 |
<!-- 追加削除ボタン --> <button id="add_row_btn">Add Row</button> <button id="del_row_btn">Delete Row</button> <br> <button id="add_col_btn">Add Column</button> <button id="del_col_btn">Delete Column</button> |
グリッドの列と行の追加と削除するボタンです。
クリックすると列と行の最終行列が追加または削除されます。
指定した列と行に追加とかできるようにして欲しいですよね。これ。
もっと直感的な感じでできるように今後工夫して組み込んでみます。
もう少しお待ちくだされ。
1 2 3 4 5 |
<!-- グリッド表示 --> <div id="grid" ></div> <!-- マークダウン表示 --> <div id="markdown" style="border:1px #ccc solid;" class="copy"></div> |
ここにグリッドが表示されています。
マークダウンの表示もここでされています。
ここでテキストエリアになっててすでにあるマークダウンのテーブルを貼り付けたらグリッド反映されればいいのに。
文字列から配列にするのは簡単なんですがテーブルの表記揺れがあるので面倒なだけです。
git hub基準の最小テーブルを基準にしようかなと思ってます。(ダッシュ3つでヘッダを区切るとかの基準)
1 2 |
var data = [ [ 'col1', 'col2', 'col3', 'col4', 'col5' ], [ '', '', '', '', '' ] ]; |
このdataってやつにグリッドのデータがバインドされています。
なのでこのdataのArrayを変更した後にgrid.render()とかやるとgridに反映されます。
1 |
var markdown = {}; |
ここからマークダウンオブジェクトの宣言になるのですが
大したことしてないのではしょります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var grid = {}; ( function() { "use strict"; var container = document.getElementById( 'grid' ), addRowBtn = document.getElementById( 'add_row_btn' ), delRowBtn = document.getElementById( 'del_row_btn' ), addColBtn = document.getElementById( 'add_col_btn' ), delColBtn = document.getElementById( 'del_col_btn' ); |
グリッドオブジェクトの宣言に入ります。
最初は色々なエレメントの定義を宣言しちゃいます。
主に表示されているボタンとか。
1 2 3 4 5 6 7 8 9 10 |
// ヘッダカラムの表示を変更 function firstRowRenderer( instance, td, row, col, prop, value, cellProperties ) { Handsontable.renderers.TextRenderer.apply( this, arguments ); td.style.fontWeight = 'bold'; td.style.color = 'green'; td.style.background = '#CEC'; } |
ここは後ほど出てくるcellsというプロパティのfunctionで呼び出されるところで使用します。
ヘッダの表示を設定してます。
緑色にして目に優しくしてます。やさC。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// マイナスイメージのセルの表示設定 function negativeValueRenderer( instance, td, row, col, prop, value, cellProperties ) { Handsontable.renderers.TextRenderer.apply( this, arguments ); if ( parseInt( value, 10 ) < 0 ) { td.style.color = 'red'; } if ( !value || value === '' ) { td.style.background = '#EEE'; } } |
ここではセルに何もない場合はグレーに数値がマイナスの場合は赤くするなど設定してます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// グリッドのインスタンス生成 grid = new Handsontable( container, { // バインドされる値 data: data, // グリッドの更新後に実行されるやつ afterRender: function ( changes, source ) { markdown.setText(); }, cells: function ( row, col, prop ) { var cellProperties = {}; if ( row === 0 ) { // ヘッダカラムの設定 cellProperties.renderer = firstRowRenderer; } else { // マイナスイメージの設定 cellProperties.renderer = negativeValueRenderer; } return cellProperties; } }); |
今回の一番大切な箇所になります。
Handsontableのインスタンスを生成します。
dataは先ほど説明した表示用データです。
afterRenderは更新されるたびに実行されるイベントです。
イベントは引くほど多いので確認してみてください。引きますよ。
イベント一覧はこちら。
ちなみにbeforeもあります。
cellsとはセル一つ一つのオプションです。
文字列しか入らないとか文字を赤くするとか編集不可にするとか色々設定します。
今回はヘッダとマイナスイメージのセルにだけオプションつけてます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// Add Row Handsontable.Dom.addEvent( addRowBtn, 'click', function () { grid.alter( 'insert_row', grid.countRows() ); }); // Delete Row Handsontable.Dom.addEvent(delRowBtn, 'click', function () { grid.countRows() > 1 ? grid.alter( 'remove_row', grid.countRows() - 1 ) : null; }); // Add Column Handsontable.Dom.addEvent( addColBtn, 'click', function () { grid.alter( 'insert_col', grid.countCols() ); }); // Delete Row Handsontable.Dom.addEvent( delColBtn, 'click', function () { grid.countCols() > 1 ? grid.alter( 'remove_col', grid.countCols() - 1 ) : null; }); |
最後にボタンのイベントを追加してます。
みたとおりなのですが、別にjqueryのクリックイベントの追加でも構いません。
あとがき
このグリッドは色々代用できそうです。
例えばCSVの修正をWeb上でできたり、HTMLテーブルを修正できたり。
私はとにかくブログを書きやすくするという目的でサービスなどを作っていこうかなと思ってます。
3日坊主ですし簡単にブログ書けないとすぐやめちゃうので。
スポンサードリンク