サイトアイコン わんすけに聞いてみる

HTMLのtableをExcelみたいに編集可能にしてみる。

jqueryの勉強してて、例えばHTMLのtableをExcelみたいにしてみたらどうだろうと思った。

まずは、Tableを編集可能にしてみるところから作ってみました。

editable-table.csseditable-table.jsを参照に追加して、

編集可能にしたい既存のTableタグにclass="editable-table"を追加するだけで

tdタグの内容を変更可能なTableになるっていうスクリプトです。

必要な設定は、これだけ↓↓↓

<table class="editable-table">

このスクリプトはjqueryを使っています。

 

逆に、表中のtdタグで編集されたくないところには、lock属性を追加すれば編集不可にできます。

<td lock>おれ</td>

こんなバルーンがでて編集モードにはなりません。

 

これをベースにして、本物のExcelみたいに関数とか使えるようにして

画面上のテーブル使って簡単な集計処理とかできたら便利そーだなーとか思ったり。

これから徐々に機能拡張していこうかなと考えてます。

 

次回は、選択中のセルを方向キーで移動できるようにして、F2で編集っていうのも足してみよう。

 

サンプルHTML
<html>
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="editable-table.js"></script>
<link href="editable-table.css" rel="stylesheet">
</head>
<body>

<table class="editable-table">
	<tr><th>#</th><th>name</th><th>status</th></tr>
	<tr><th>1</th><td lock>おれ</td><td>元気</td></tr>
	<tr><th>2</th><td>おまえ</td><td>超元気</td></tr>
</table>

<hr>

<table class="editable-table">
	<tr><th>#</th><th>name</th><th>status</th></tr>
	<tr><th>10</th><td>キサマ</td><td lock>千鳥</td></tr>
	<tr><th>11</th><td>おぬし</td><td>武士</td></tr>
</table>

</body>
</html>
editable-table.css
.editable-table,.editable-table th,td{
	border: 1px solid darkgray;
	border-collapse: collapse;
}
.editable-table th { background-color: paleturquoise; }
.editable-table td.selected { border: 2px solid black;}
textarea.cell-edit {
	display: block;
	padding: 6px 24px;
	height: 100%; width: 100%;
  -webkit-box-sizing: border-box;
   -khtml-box-sizing: border-box;
     -moz-box-sizing: border-box;
      -ms-box-sizing: border-box;
  box-sizing: border-box;}
span.tooltip {
  position:absolute;
  z-index:9999;
  display:block;
  color:#0000ff;
  font-size:14px;
  line-height:1.2;
}
span.tooltip__body {
  position:relative;
  top:-15px;
  padding:10px;
  background:#f0e68c;
  -webkit-border-radius:3px;
     -moz-border-radius:3px;
      -ms-border-radius:3px;
          border-radius:3px;
  -webkit-box-shadow:0 2px 4px rgba(0, 0, 0, .4);
     -moz-box-shadow:0 2px 4px rgba(0, 0, 0, .4);
      -ms-box-shadow:0 2px 4px rgba(0, 0, 0, .4);
          box-shadow:0 2px 4px rgba(0, 0, 0, .4);
}
span.tooltip__body:after {
  content:"";
  position:absolute;
  bottom:-5px;
  left:50%;
  display:block;
  width:0;
  height:0;
  margin-left:-5px;
  border-width:5px 5px 0 5px;
  border-style:solid;
  border-color:#f0e68c transparent transparent transparent;
}
editable-table.js
$(function (){
  editable_table.Initalize();
});

var editable_table_val = {};
var editable_table = {
  Initalize: function () {
    $('.editable-table').find('td').each(function(){
      var $td = $(this);
      var tr = $(this).parent();
      var row = $('.editable-table').find('tr').index(tr);
      var col = $(tr).find('td').index(this);
      var idx = "$"+col+"_"+row;
      $(this).attr("data-address", idx);
      editable_table_val[idx] = $td.html();

      $td.click(function () {
        editable_table.ClearSelectionCells();
        $(this).toggleClass("selected", true);
      });
      $td.dblclick(function () {
        var $this = $(this);
        if ($this.hasClass("editing")) { return }
        if ($this.attr("lock") != undefined) { editable_table.CellLock(this); return }
        var adrs = $this.attr("data-address");
        var cell_val = editable_table_val[adrs];
        editable_table.ClearSelectionCells();
        var input = $("<textarea />").attr("id", "edit_target").attr("data-address", adrs).addClass("cell-edit").text(cell_val);
        $this.toggleClass("selected",true).html("").append(input);
        $this.addClass("editing");
        $("#edit_target").focus().blur(function (){
           var adrs = $(this).attr("data-address");
           var edit_val = $(this).text().toString();
           var rollback = editable_table_val[adrs];
           editable_table_val[adrs] = edit_val;

           $(this).remove();
           $("td[data-address='" + adrs + "']").toggleClass("editing", false);
           editable_table.Recalculation();
         });
      });
      $(document).keydown(function(e){
        // Esc キー
        if (e.keyCode == 27) {
          var adrs = $("#edit_target").attr("data-address");
          if (adrs == undefined) { return }
          $("#edit_target").remove();
          $("td[data-address='" + adrs + "']").toggleClass("editing", false);
          editable_table.Recalculation();
        }
      });
    });
  },
  ClearSelectionCells: function () {
    $('.editable-table').find('td').each(function(){
      $(this).toggleClass("selected", false);
    });
  },
  Recalculation: function() {
    for (idx in editable_table_val) {
      $("td[data-address='" + idx + "']").html(editable_table_val[idx]);
    }
  },
  CellLock: function(cell) {
    var msg = "このセルは変更できません。";
    var $tooltip = $("<span />").addClass("tooltip").append($("<span />").addClass("tooltip__body").text(msg));
    $('body').append($tooltip);
    var $cell = $(cell);
    var cell_offset = $cell.offset();
    var cell_size = { width: $cell.outerWidth(), height: $cell.outerHeight() };
    var tip_size = { width: $tooltip.outerWidth(), height: $tooltip.outerHeight() };
    $tooltip.css({ top: cell_offset.top - tip_size.height,
                  left: cell_offset.left + cell_size.width / 2 - tip_size.width / 2});
    $cell.mouseout(function (){ $('.tooltip').fadeOut("slow", function() {$(this).remove(); })});
  }
}

 

モバイルバージョンを終了