昨日に引き続き、なでしこ3のテーブル部品に、なでしこ1のグリッド部品で出来る機能を色々追加しようと頑張る話。
編集機能については昨日の記事をご覧下さい。
行選択機能を追加
v1のグリッドは、「行選択」がオンになっていると、クリックした行の色が変わり、どの行を選択しているのか見やすくなります。
なでしこさんのテーブルでは、「DOM部品オプション」の「テーブル背景色」で[ヘッダ色,偶数行色,奇数行色]の配列を指定して、テーブル作成時「tr」の背景色にその色がスタイル設定されています。
クリックした時にその行のtrの背景色を変更してやるだけで出来そうですね。
クリックした位置の色を変える
クリックした位置と書いてきましたが、クリックだと押して離すがセットなので、色が変わるのはマウスを離した時。
押した時すぐに色が変わってくれた方が気分がいいので、「マウス押した時」のイベントを使うことにします。
マウスのイベントは、行(tr)に設定してもテーブルそのものに設定しても発生するのですが、どこに設定してもイベントが発生した時に対象に入るのはセル(td)です。
セルの親部品(parentNode)であるtrが、色を変えるべきtrということになります。
テストデータ=「名前,ふりがな,点数
太郎,たろう,55
花子,はなこ,100
一郎,いちろう,80」をCSV取得。
テストテーブル=テストデータのテーブル作成。
テストテーブルをマウス押した時には、:
もし、対象.nodeName=「TD」ならば、:
クリック行=対象.parentNode。
クリック行の「背景色」に「#CCF」をDOMスタイル設定。
DOM部品はこのように親要素や子要素の参照がプロパティに入っているので、ずっと辿って行くことが出来るんですよ✨
前にクリックした行の色を戻す
一回目はコレだけで良いのですが、また別の行をクリックした時には、前にクリックしていた行の色を元に戻してやらないと、どんどん選択行色が増えていってしまいますよね💦
ということは前の位置を覚えておかなきゃならない。
とりあえず、グローバルに「前クリックセル」変数を作っておき、行色変更が発生したらその時クリックしたセルの参照を入れておくことにします。
そしてその行数が奇数か偶数かで、DOM部品オプションのテーブル背景色を参照して塗り分けます。
もし、前クリックセルが空でなければ、:
変数 前クリック行=前クリックセル.parentNode。
変数 前行数=前クリック行.rowIndex。
変数 行色情報=DOM部品オプション.テーブル背景色。
変数 前背景色=行色情報[前行数%2+1]。
前クリック行の「背景色」に前背景色をDOMスタイル設定。
「%」は割った余りを求める演算子です。
行数を2で割った余りが0なら偶数、1なら奇数。
テーブル背景色は、偶数行の色が[1]に、奇数行の色が[2]に入っているので+1してやれば取得できるって寸法です。
オブジェクトプロパティ構文
配列の中身は直接参照できないっぽい
オブジェクトプロパティ構文、途中で内容が配列だったりするとうまく行きませんでした。
配列の前で一旦変数に入れるか、オブジェクトプロパティ構文を使わず[" "]を使えば大丈夫デス。
前背景色=DOM部品オプション.テーブル背景色[0]。 # できない
前背景色=DOM部品オプション["テーブル背景色"][0]。# できる
テーブル背景色=DOM部品オプション["テーブル背景色"]
前背景色=テーブル背景色[0] # できる
テーブルのナゾ(?)
実は、クリック行の背景色をオブジェクトプロパティ構文で指定してみようとしたら、出来ませんでした。
テストテーブルをマウス押した時には、:
もし、対象.nodeName=「TD」ならば、:
クリック行=対象.parentNode。
クリック行.背景色=「#CCF」 # できない!?
//クリック行の「背景色」に「#CCF」をDOMスタイル設定。 # できる
ちゅーとりあるを見ても、背景色の設定はこれであってるはずなのに、ナゼ~。
parentNodeの参照だから? とか、イベントの中だから? とかとか色々なやむワケですけど、DOM部品作成でいっこいっこ作っていった場合には、イベントの中だろうがparentNodeだろうが、ちゃんと出来たんです。
#できる
A=「table」のDOM部品作成。
AにDOM親部品設定。
「tr」のDOM部品作成。
それ$背景色=DOM部品オプション["テーブル背景色"][0]。
それにDOM親部品設定。
「th」のDOM部品作成。
それに1をテキスト設定。
「th」のDOM部品作成。
それに2をテキスト設定。
AにDOM親部品設定。
「tr」のDOM部品作成。
それ$背景色=DOM部品オプション["テーブル背景色"][2]。
それにDOM親部品設定。
「td」のDOM部品作成。
それに「あいう」をテキスト設定。
「td」のDOM部品作成。
それに「えお」をテキスト設定。
Aをクリックした時には
対象を表示。
対象.parentNodeを表示。
対象$背景色=緑色。# できる
対象.parentNode$背景色=水色。# できる
ここまで。
長っ💦
テーブル作成のありがたみを感じますねw
でも、同じことがテーブル作成ではできないのねん。
#できない
A=「1,2
あいう,えお」のテーブル作成。
Aをクリックした時には
対象を表示。
対象$parentNodeを表示。
対象$背景色=緑色。# できない
対象$parentNode$背景色=水色。# できない
ここまで。
ナゾだわ~。
さっぱり分からにゃいのでもうフツーにDOMスタイル設定😅
行選択できました
それはさておき、できました。
こんな感じ?
テストデータ=「名前,ふりがな,点数
太郎,たろう,55
花子,はなこ,100
一郎,いちろう,80」をCSV取得。
テストテーブル=テストデータのテーブル作成。
選択行色=「#CCF」
前クリックセル=空。
テストテーブルをマウス押した時には、:
もし、対象.nodeName=「TD」ならば、:
変数 クリック行=対象.parentNode。
もし、前クリックセルが空でなければ、:
変数 前行数=前クリックセルのセル行番号。
変数 前クリック行=前クリックセル.parentNode。
変数 行色情報=DOM部品オプション.テーブル背景色。
変数 前背景色=行色情報[前行数%2+1]。
前クリック行の「背景色」に前背景色をDOMスタイル設定。
クリック行の「背景色」に選択行色をDOMスタイル設定。
前クリックセル=対象。
●(セルの)セル行番号
セル.parentNode.rowIndexを戻す。
ここまで。
行選択のサンプルです👇
クリックしたらその行の色が変わります。そんだけ!
自動ソート機能を追加
自動と言っても本当の自動ではなく、ヘッダ部分をクリックすることでソートが行われる機能です。
なでしこさんには「表ソート」という命令があり、二次元配列の列番号を指定することで、その列をキーにソートしてくれます。
クリックしたセルの列番号を取得して、元データを表ソートし、そのデータでテーブル更新すれば良いだけ!
編集の時とは逆に、まずデータの方に変更を加え、テーブルに反映させる形です。
同様にしてサーチ機能なども実装できるはずです(今回はやりません)
注意点としては、テーブル作成は一番最初の行がタイトル行(ヘッダ)になっているので、それをソートに含めてはいけないので、データの0行目を一度切り取って待避し、ソート後また戻しています。
テストデータ=「名前,ふりがな,点数
太郎,たろう,55
花子,はなこ,100
一郎,いちろう,80」をCSV取得。
テストテーブル=テストデータのテーブル作成。
昇順=はい。
テストテーブルをクリックした時には、
もし、対象.nodeName=「TH」ならば、:
ヘッダ=テストデータの0を配列切り取り。
列=対象のセル列番号。
テストデータの列を表ソート。
もし、昇順=はいでなければ、テストデータを配列逆順。
昇順=昇順*-1。
テストデータの0へヘッダを配列挿入。
テストテーブルをテストデータにテーブル更新。
ここまで。
●(セルの)セル列番号
セル.cellIndexを戻す。
ここまで。
できました!
表ソートと表数値ソート
表ソートは文字列順、表数値ソートは数値順ということなので、数値だけの列は表数値ソートになるようにしなきゃダメかな? と思ったのですが、あれれ~? 表ソートのままでも数値の列もいい感じにソートされてるっぽい?
v1のグリッドでは「55,100,80」などを自動ソートすると、「100,55,80」とかになっちゃうんです。数字の大小ではなく文字として、1は5の前ということですよねー。
v1にも表数値ソートはあるので、数値の列でソートしたい場合は自分で何とかする必要がありました。
でも、なでしこ3の表ソートではちゃんと「55,80,100」になりますよ。
とりあえずこのままでいいかも?
ソート記号をつける
v1のグリッドでは、どの列でソート中なのか、昇順なのか降順なのかが分かるよう、ヘッダに「▲」「▼」の記号が付きます。
なんかCSSで上下に三角の矢印出すなどもあったのですが、むじゅかしくてよく分かんなかったので、フツーに昇順降順で「▲」か「▼」の文字を表示させることにしとく。
テストテーブルをクリックした時には、
# 三角のラベルをクリックした時も動くようにする
もし、(対象.nodeName=「TH」)または(対象.nodeName=「SPAN」)ならば、:
セル=対象。
もし、(対象.nodeName=「SPAN」)ならば、セル=対象.parentNode。
ソート列=セルのセル列番号。
ヘッダ=テストデータの0を配列切り取り。
テストデータのソート列を表ソート。
もし、昇順=はいでなければ、テストデータを配列逆順。
昇順=昇順*-1。
テストデータの0へヘッダを配列挿入。
テストテーブルをテストデータにテーブル更新。
記号=「▲」
もし、昇順=はいならば、記号=「▼」
ソート列に記号のソート記号追加。
ここまで。
●(列に記号の)ソート記号追加
変数 全ヘッダ=テストテーブルの「th」をDOM子要素全取得。
母艦=DOM親要素。
全ヘッダを反復:
対象にDOM親部品設定。
もし、対象キー=列ならば、:
記号のラベル作成。
それに{
"margin-left":"0.5em",
"vertical-align":"middle",
"font-size":"0.7em",
"色":灰色
}をDOMスタイル一括設定。
母艦にDOM親部品設定。
ここまで。
できました! いい感じ?
セル幅の変更
v1のグリッドでは、ヘッダ部分をドラッグしてセル幅を変更できます。
テーブル部品のセル幅は内容に応じて自動的に良きように調整されるので、あんまりいらないかもと思いましたが、勝手に調整されない設定にしたい場合もあるかもしれないし、何より出来るとかっこいいw
CSSで出来そうかなと思って調べたら、resize
というスタイルがありました‼️
マウスを動かしたイベントやら位置や移動量なんて一切考える必要なさそうです。
値は、both
で縦横可変、horizontal
幅だけ、vertical
高さだけ。不可はnone
。
今回はセルの幅だけ変えられたら良いので、全てのヘッダ(th)の「resize」に「horizontal」をDOMスタイル設定すれば良いはず。
変数 全ヘッダ=テストテーブルの「th」をDOM子要素全取得。
全ヘッダを反復:
対象の「resize」に「horizontal」をDOMスタイル設定。
でも出来ない!
さらに調べると、overflow
がvisible
になっているとresize
が働かないということで、hidden
に設定。
でもでも出来ない!!
さらにさらに調べると、Chromeはこれだけで出来るのですが(できた!)Firefoxの場合は出来ず、thの中にdivを入れて、そのdivにこの設定を付けてやらなければいけないとのこと。にゃにぃ~💧
テストテーブル=「名前,ふりがな,点数
太郎,たろう,55
花子,はなこ,100
一郎,いちろう,80」のテーブル作成。
# ヘッダの設定
変数 全ヘッダ=テストテーブルの「th」をDOM子要素全取得。
全ヘッダを反復:
# ヘッダのテキストを新しく作ったdivの中にうつす
テキスト=対象のテキスト取得。
対象に空をテキスト設定。
対象にDOM親部品設定。
「div」のDOM部品作成。
それにテキストをテキスト設定。
# リサイズの設定。horizontalが横幅。
# overflowがvisibleになっているとresizeが効かない
# white-space:nowrapで狭くした時に文字が折り返すのを止める。
それに{
"resize":"horizontal",
"overflow":"hidden",
"white-space":"nowrap"
}をDOMスタイル一括設定。
できました!
でもthに余白がついているために、見た目がビミョーなことになっています💧
thの余白は0にして、セルの余白はdivの方に付ける必要がありそうです・・・が! 元々thに付いている余白のサイズは一体どうやって取得したらいいんだ。
DOMスタイル取得では、要素自体にスタイルが設定されている場合しか取得できません。試しにやってみると、空が返ってきました。
貯蔵庫のスタイルシートで0.4emが付いてることは分かってるんだけどさー。ソレを決め打ちするっていうのはアレですよね? ある種負けみたいなw
調査のレイアウトで見れるんだから、なんかかんか取得する手立てがありそうなもんだ。
getComputedStyleを知る‼️
WINDOW
オブジェクトにgetComputedStyle()
というメソッドがあって、引数にDOM要素を与えると、CSSプロパティ情報をオブジェクトとして取得することが出来るラシイ。
早速やってみます!
WINDOWの「getComputedStyle」を対象でJSメソッド実行。
それ.paddingを表示。
6.4pxと出ました。合っています! すばらしい。
しかもemで付けられていてもpxに換算されて出てくるようです。
これをdivのほうに付けてやり、ヘッダの余白は0とすれば、ヘッダの枠とdivがピッタリ重なりいい感じ🎶
ちなみにこれは「それ.余白」にはできませんでした。
なお今回はスタイルの内容をそっくりdivに移すのが目的なので良いですが、単位付きでの取得となるので数値が欲しい場合は単位を削除する必要があります。
またpaddingは上右下左をまとめて設定出来るヤツなので、設定によっては「1px 2px 4px 2px」などと取得されますので注意が必要です。
おっと、もちろんwidthも取得出来ますよ。
すごく狭くした時文字が折り返されてヘッダの高さが伸びてしまうのイヤンなので、
white-space:nowrap
など付けてみていましたが、むしろもうdivの最小サイズを親要素のヘッダの幅に設定してやればよいのでは?!
# ヘッダの設定
変数 全ヘッダ=テストテーブルの「th」をDOM子要素全取得。
全ヘッダを反復:
# ヘッダの余白サイズを調べ、ヘッダの余白は0にする。
WINDOWの「getComputedStyle」を対象でJSメソッド実行。
余白サイズ=それ.padding。
最小幅=それ.width。
対象.余白=0。
# ヘッダのテキストを新しく作ったdivの中にうつす
テキスト=対象のテキスト取得。
対象に空をテキスト設定。
対象にDOM親部品設定。
「div」のDOM部品作成。
それにテキストをテキスト設定。
# リサイズの設定。horizontalが横幅。
# overflowがvisibleになっているとresizeが効かない
# min-widthでヘッダの幅より小さくならないようにする。
# ヘッダの余白をうつす
それに{
"resize":"horizontal",
"overflow":"hidden",
"min-width":最小幅,
"余白":余白サイズ
}をDOMスタイル一括設定。
できました✨
続くかも知れないし続かないかも知れない
ユキノはgetComputedStyleのじゅもんをおぼえた!
これでグリッド部品の、あると良さそうな機能はだいたい出来たかなあと思います。
他にまだナニカあるでしょうか。
ワタクシ一回しかグリッド部品使ったことなかったものですから~😅
今回はバラバラの状態でそれぞれお試ししましたが、全部おまとめしてグリッド部品のようにしたら良いのかなあとか、そーゆうのはよく出来たライブラリにおまかせして、テーブル部品に欲しい機能をチョコッと追加出来るようになっていると良いのかなぁとかとか色々考えるわけですが、知恵と時間が追い付かず文字数も結構なものになりましたので、一通りできたよ! というところでひとまず終了です。
しかし、相変わらず書くこと無くてピンチなので、なんかかんか考えて続く可能性も無くはありません。
アドベントカレンダー、後半はまだまだいっぱい空いています。
ぜひぜひご参加下さいませ~🙇♀️