HandsOntableとローカルストレージで偽EXCEL
HandsonTableでEXCELチックなものを作ろうとして
去年ごにょごにょしてたけど。まとまった時間がようやく取れたので
ひとまずのことはできるようにした。
特にセルに色を付けた状態を保存する箇所は何とか
実装させたくて色々と調べたものの分からず。強引な方法で
解決してます。
枠線とかメニューの日本語化はコンテキストメニュー周りで
問題が出てるみたいでへっぽこの自分では手に負えないので
断念。まぁそれ以外は何とか動くんでこれにて完成?ってことで
しかしVisualStudioCodeは結構軽くて便利だったりする。
そんな使いこなしていないけど
以下JSのソース、HTMLとCSSはまんま
去年ごにょごにょしてたけど。まとまった時間がようやく取れたので
ひとまずのことはできるようにした。
特にセルに色を付けた状態を保存する箇所は何とか
実装させたくて色々と調べたものの分からず。強引な方法で
解決してます。
枠線とかメニューの日本語化はコンテキストメニュー周りで
問題が出てるみたいでへっぽこの自分では手に負えないので
断念。まぁそれ以外は何とか動くんでこれにて完成?ってことで
しかしVisualStudioCodeは結構軽くて便利だったりする。
そんな使いこなしていないけど
以下JSのソース、HTMLとCSSはまんま
/*refer http://my-waking-dream.blogspot.jp/2013/12/live-search-filter-for-jquery.html http://ja.stackoverflow.com/questions/20343/handson-table%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%AE%E9%96%8B%E7%99%BA http://qiita.com/do_m_gatoru/items/b0f8d1d18b7037e5cba2 http://stackoverflow.com/questions/28309993/anyway-to-filter-rows-with-handsontable http://jsfiddle.net/awyjnbj6/ http://stackoverflow.com/questions/40552974/handsontable-header-search-input-text-is-cleared-intermittently-on-scroll http://stackoverflow.com/questions/33173850/how-do-i-format-the-column-headers-in-handsontable https://teratail.com/questions/36228 http://qiita.com/PianoScoreJP/items/be721f1b06745c2bbc39 http://qiita.com/opengl-8080/items/9d25e106ff48b66cb908 http://docs.handsontable.com/0.18.0/CommentEditor.html https://docs.handsontable.com/0.29.2/Comments.html http://qiita.com/mas0061/items/5ff36f63f39a6ada80d1 https://github.com/handsontable/handsontable/issues/3807 */ //HadsonTable用 var grid, hot, myData, myCells, styles ,resultRow; //ボタン設定 $(loaded); function loaded() { if (window.localStorage) { showContent(); SetProperty(); //保存している色を設定する //ローカルストレージ内データ削除ボタン挙動 $("#delData").click( function() { var myRet = confirm("PC内の投稿情報を全削除します。よろしいですか?"); if (myRet) { clearContent(); localStorage.clear(); } }); //保存ボタン挙動 $("#saveButton").click( function() { saveContent(); }); //クリアボタン挙動 $("#clearButton").click( function() { var myRet = confirm("全てのセルの内容をクリアします。よろしいですか?"); if (myRet) { clearContent(); } } ); } else { alert("未対応のブラウザです。ChromeもしくはFireFoxをご利用ください。"); } } // ローカルストレージに保存した値をテーブルに表示する function showContent() { //データ情報 var key, value = []; key = "gridData"; value = localStorage.getItem(key); if (value === "undefined") { myData = [ ["", "", "", ""] ]; } else { myData = JSON.parse(value); } //セルの色変更 var TableStyles = function(hot) { var self = this; var _cellStyles = []; var _createStyle = function(row, col, cellcolor, fontcolor) { var style = { row: row, col: col, renderer: function(instance, td, row, col, prop, value) { Handsontable.renderers.TextRenderer.apply(this, arguments); td.style.color = fontcolor; td.style.backgroundColor = cellcolor; }, }; return style; }; //セルのスタイルを返す self.getStyles = function() { return _cellStyles; }; //セルのスタイル設定 self.setCellStyle = function(row, col, cellcolor, fontcolor) { //, updateTable _cellStyles.push(_createStyle(row, col, cellcolor, fontcolor)); hot.updateSettings({ cell: self.getStyles() }); hot.render(); }; //選択範囲のセルに処理を行う。配列値が0開始なのでループ終了条件に+1している。 self.setCellsStyle = function(startrow, endrow, startcol, endcol, cellcolor, fontcolor) { for (var row = startrow; row < endrow + 1; row++) { for (var col = startcol; col < endcol + 1; col++) { self.setCellStyle(row, col, cellcolor, fontcolor); //, false } } }; }; //HandsonTable設定 grid = document.getElementById("grid"); var settings = { data: myData, //データ表示 // width: 500, //全体の横枠指定 height: 500, //全体の高さ指定 autoColumnSize: true, //カラム自動調整 startRows: 10, //初期表示行数 startCols: 5, //初期表示列数 autoRowSize: true, //行高さ自動調整 autoColumnSize: true, //列幅自動調整 rowHeaders: true, //行ヘッダー colHeaders: true, //列ヘッダー columnSorting: true, //ソート sortIndicator: true, //ソートの矢印 minSpareRows: 1, //1行だけの空白セル fillHandle: true, //possible values: true, false, "horizontal", "vertical" フィル有効 manualColumnMove: true, //ドラッグで移動(列) manualColumnResize: true, //ドラッグでサイズ調整(列) manualRowMove: true, //ドラッグで移動(行) manualRowResize: true, //ドラッグでサイズ調整(行) comments: true, //コメント(右クリックメニュー) mergeCells: true, //セル結合(右クリックメニュー) customBorders: true, //罫線(右クリックメニュー) renderAllRows: true, undo: true, //UNDO,REDO search: true, //検索有効 }; hot = new Handsontable(grid, settings); styles = new TableStyles(hot); //右クリックメニュー hot.updateSettings({ contextMenu: { //独自メニュー実装 callback: function(key, cell, e) { var sel = hot.getSelected(); var startRow = sel[0]; //開始行 var startCol = sel[1]; //開始列 var endRow = sel[2]; //終了行 var endCol = sel[3]; //終了列 var cellColor = document.getElementById("cellColorPicker").value; var fontColor = document.getElementById("fontColorPicker").value; // 独自メニューのクリック判定 switch (key) { case 'setColor': //色設定 styles.setCellsStyle(startRow, endRow, startCol, endCol, cellColor, fontColor); break; } }, //メニュー items: { row_above: { name: '上に行を挿入' }, row_below: { name: '下に行を挿入' }, col_left: { name: '左に列を挿入' }, col_right: { name: '右に列を挿入' }, remove_row: { name: '選択行を削除', disabled: function() { return $("#grid").handsontable('countRows') <= 2; } }, remove_col: { name: '選択列を削除', disabled: function() { return $("#grid").handsontable('countCols') <= 1; } }, 'setColor': { name: "色を変更" }, undo: { name: '元に戻す' }, redo: { name: 'やり直す' }, make_read_only: { name: 'セルを読取専用にする' }, mergeCells: { name: function() { var sel = this.getSelected(); var info = this.mergeCells.mergedCellInfoCollection.getInfo(sel[0], sel[1]); if (info) { return '結合を解除'; } else { return 'セルを結合'; } } }, alignment: { name: '文字位置指定' /* どうやらデフォルトのコンテキストメニューのサブメニューを日本語化しようとすると正常に動かない模様 submenu: { items: [ {key: 'alignment:left', name: '左寄'}, {key: 'alignment:center', name: '中央'}, {key: 'alignment:right', name: '右寄'}, {key: 'alignment:top', name: '上詰め'}, {key: 'alignment:middle', name: '中央揃え'}, {key: 'alignment:right', name: '下詰め'} ] } */ }, borders: { name: '枠線' /* submenu: { items: [ {key: 'borders:top', name: '上罫線'}, {key: 'borders:right', name: '右罫線'}, {key: 'borders:bottom', name: '下罫線'}, {key: 'borders:left', name: '左罫線'}, {key: 'alignment:remove border', name: '罫線を消す'} ] } */ }, commentsAddEdit: { name: 'コメントの挿入' }, commentsRemove: { name: 'コメントの削除' } } }, }); //検索結果合致の処理 var searchField = document.getElementById("searchField"); var resultCount = document.getElementById("resultCount"); Handsontable.Dom.addEvent(searchField, 'keyup', function(event) { filter(('' + this.value).toLowerCase()); resultRow = hot.countRows() - 1; //0で開始なので-1が必要 resultCount.innerText = "検索結果:" + resultRow.toString() + "行"; }); } // テーブルの内容をローカルストレージに保存する function saveContent() { var content = hot.getData(); var key = "gridData"; var val = JSON.stringify(content); //データ情報 localStorage.setItem(key, val); // セル情報 var rows = hot.countRows(); //行数 var cols = hot.countCols(); //列数 var i = 0; //セル取得用 var cellHeight; //行高 var cellWidth; //列幅 var styleColor; //文字色 var bgColor; //背景色 //コメント var comment; var commentsPlugin = hot.getPlugin('comments'); //ローカルストレージ保存用JSON var property = []; property ="["; //プロパティ情報取得(背景色やセルサイズ等) for (var row = 0; row < rows - 1; row++) { for (var col = 0; col < cols; col++) { cellHeight = hot.getRowHeight(row); //高さ cellWidth = hot.getColWidth(col); //幅 styleColor = $("td").eq(i).css("color"); //文字色 bgColor = $("td").eq(i).css("backgroundColor"); //背景色 value = hot.getDataAtCell(row, col); //データ comment = commentsPlugin.getCommentAtCell(row, col); //コメント(未実装の模様) var data = { "Row":row, "Col":col, "Height":cellHeight, "Width":cellWidth, "fontColor":styleColor, "BgColor":bgColor, "Value":value } //カンマの処理 if (col == 0 && row == 0){ property = property + JSON.stringify(data); }else{ property = property +"," + JSON.stringify(data); } i = ++i; } } property =property + "]"; var skey = "Setting"; var sval = property; localStorage.setItem(skey, sval); alert("データを保存しました。"); hot.render(); } //テーブルの内容をクリアする function clearContent() { hot.clear(); var background = 'white'; //色を初期化する $('td').css('background-color', 'transparent'); $('tr').css('background-color', background); } //プロパティ情報設定(背景色やセルサイズ等) function SetProperty(){ var key,value = []; var rows,cols; key = "Setting"; value = localStorage.getItem(key); var property = JSON.parse(value); if( !property ){ return; } var len = property.length; for(var i=0;i-1) { array.push(data[row]); break; } } } hot.loadData(array); }
コメント