【Handsontable】セル内にプログレスバー(Progress)の表示


はじめに

IE 11 のサポート終了が2022年6月15日と決まりました。Delphi 5で作成されたWebアプリケーションがあり、Active Xのグリッドを使用しています。Microsoft EdgeのIEモードで動作するとはいえ、IE対応は流石にやめたいです。

WebアプリケーションをASP.NETで作り替えようとしているのですが、Active Xのグリッドにはパーセント表示の際に進捗バーが表示されています。
移植する上で、Handsontableでプログレスバー(Progress)の表示に挑戦してみました。

環境

HandsontableはMITライセンス版のバージョン 6.2.2を使用しています。

Handsontableフォーラムのサンプル

Handsontableフォーラムの質問者の回答に答える形で、JsFiddleにサンプルが作成されています。

.process {
  height: 5px;
  widths: 10px;
  border-radius: 2px;
  margin-top: 10px;
  background: green;
}
function myRenderer(instance, td, row, col, prop, value, cellProperties) {
    Handsontable.renderers.TextRenderer.apply(this, arguments);
    td.innerHTML = '';
    var div = document.createElement('DIV');
    div.className = 'process';
    div.style.width = value + 'px';
    td.appendChild(div);
  }

Boostrap 4によるプログレスバー

Handsontableフォーラムのサンプルにより作り方が分かりました。ただ、数値の同時表示も実現したいのです。
そこでネットでプログレスバーで検索すると、Boostrapを使用したサンプルが見つかったので採用してみました。
バーの表示をストライプとかにすれば、よりオシャレになりそうです。

See the Pen Handsontable ProgressBar by やじゅ (@yaju-the-encoder) on CodePen.

CSS部分は、Boostrap 4側に定義されています。

function progressRenderer(instance, td, row, col, prop, value, cellProperties) {
  Handsontable.renderers.TextRenderer.apply(this, arguments);
  if (value === null) value = 0;

  let str = '<div class="progress">';
  str = str + '<div class="progress-bar bg-danger" role="progressbar" aria-valuenow="{0}" ';
  str = str + 'aria-valuemin="0" aria-valuemax="100" style="width: {0}%;">{0}%</div>';
  str = str + '</div>';
  str = str.replace(/\{0\}/g, value);
  td.innerHTML = str;
}

オリジナルのプログレスバー

Boostrap 4によるプログレスバーは悪くないのですが、数値の表示が進捗の位置に左右されるので数値が小さいと数字が見切れてしまうのです。そうするとセルの幅を広げる必要が出てきてしまいます。

ActiveX版のグリッドのパーセント表示の際に進捗バーの見た目とBoostrap 4によるプログレスバーの見た目を活かしてみました。
プログレスバーはグラデーションしています。グラデーションには下記ツールを使用しました。

See the Pen Handsontable ProgressBar by やじゅ (@yaju-the-encoder) on CodePen.

.progressBox {
  position: relative;
  width: 100%;
  height: 80%;
  font-size: 0.75rem;
  border: solid 1px silver;
  background-color: #e9ecef;
  border-radius: 0.25rem;
}

.progressBar {
  position: absolute;
  display: inline-block;
  top: 0px;
  left: 0px;
  height: 100%;
  background: rgb(255,0,0);
  background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,80,80,1) 30%, rgba(255,200,200,1) 100%);
}

.progressLabel {
  position: absolute;
  color: black;
  top: -1px;
}
function progressRenderer(instance, td, row, col, prop, value, cellProperties) {
  Handsontable.renderers.TextRenderer.apply(this, arguments);
  if (value === null) value = 0;

  let left = instance.getColWidth(col) / 22 * 10 - 5;
  let str = '<div class="progressBox">';
  str = str + '<div class="progressBar" style="width:{0}%"></div>'
  str = str + '<span class="progressLabel" style="left:' + (left - String(value).length * 3) + 'px;">{0}%</span></div>'
  str = str.replace(/\{0\}/g, value);
  td.innerHTML = str;
}

セル幅によって数値表示の中央位置を調整していますが、ズレている場合はleftの値を調整してみてください。

最後に

Handsontableのレンダラーを使いこなせれば何でも表示できてしまいますね。
Boostrapは、文字の大きさやボーターの角丸や背景色などのデザインを見習うところはあるので参考にしています。