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);
}
コメント