dポイントプレゼントキャンペーン実施中!

掲載画像のように

ドラッグ&ドロップしたらその範囲が一つの範囲になるようにしたい
セル結合しているのかboderを消しているのかわからないのですが
色付けしたいです。

セル結合をやってみましたが難しいです。もっと汎用的にしたいです。
ソースとかの具体例をいただけると助かります。

<html>
<head>
<title>テーブルのセルを結合したり分割したりする</title>
<script type="text/javascript">
var colflag = 1;
var rowflag = 1;
function colspanTest()
{
var table = document.getElementById("table1")
var tr = table.getElementsByTagName("tr")[0]
var td1 = tr.getElementsByTagName("td")[0]
var td2 = tr.getElementsByTagName("td")[1]
if (colflag % 2 == 1) {
var td3 = tr.getElementsByTagName("td")[2]
}

if (colflag % 2 == 1) {
tr.removeChild(td3)
td1.colSpan = "2"
} else {
var td3 = document.createElement("td")
td3.innerHTML = "3"
tr.appendChild(td3)
td1.colSpan = "1"
}
return colflag = colflag + 1;
}

function rowspanTest()
{
var table = document.getElementById("table2")
var tr1 = table.getElementsByTagName("tr")[0]
var tr2 = table.getElementsByTagName("tr")[1]
var td1 = tr1.getElementsByTagName("td")[0]
if (rowflag % 2 == 1) {
var td2 = tr2.getElementsByTagName("td")[0]
}

if (rowflag % 2 == 1) {
tr2.removeChild(td2)
td1.rowSpan = "2"
} else {
var td2 = document.createElement("td")
td2.innerHTML = "3"
tr2.appendChild(td2)
td1.rowSpan = "1"
}
rowflag = rowflag + 1;
}
</script>
</head>
<body>

<table id="table1" border="1">
<tr><td colspan="1">1</td><td>2</td><td>3</td></tr>
<tr><td>1</td><td>2</td><td>3</td></tr>
</table>

<table id="table2" border="1">
<tr><td colspan="1">1</td><td>2</td><td>3</td></tr>
<tr><td>1</td><td>2</td><td>3</td></tr>
</table>

<input type="button" value="button" onclick="colspanTest();" />
<input type="button" value="button" onclick="rowspanTest();" />

</body>
</html>

「ドラッグ&ドロップしたらその範囲が一つの」の質問画像

A 回答 (3件)

No2です



>今のままだと色だけ変わってセルの内容が1つづつ記載となりますよね
>これをまとめて1行にしたいんです。
No1に記しましたが、何をしたいのかわからないので、テキトーに設定しています。
ご質問文からは、色が変わればよいものと解釈しましたので。

>だからセル結合かなと思ったのですが。
結合したいのなら、セル範囲はわかっているので、その範囲を結合すれば宜しいでしょう。
一方で、
>まとめて1行にしたい
って、他のセルも1行に纏めるってことでしょうか?
それとも、ご提示の図(よく見えないけれど)では、1行の中で色が変わっているようなので、そもそもが1行内で処理できればいいのかな・・・
>もっと汎用的にしたいです。
とは、方向性が異なるようにも思いますけれど。


どうやら「結合」にこだわりがあるようなので・・・
「ダブルクリックしたら、1行内でテキトーに結合する」例を。
No1にも記したように、質問文に無い(質問様の頭の中にある)ことはわかりませんし、漠とした説明しかないので、テキトーに考えることしかできません。
禅問答を繰り返すつもりもありませんので、あとはよしなに。

<!DOCTYPE HTML>
<html lang="ja">
<head><title>Sample</title>
<style>
#testTable { border-collapse: collapse; font-size: 12px; font-weight: bold; }
#testTable td { padding: 0.3em; border: 1px solid gray; text-align: center; min-width:3em; }

#testTable tr:nth-child(3n) td[colspan] { background-color: palegreen; }
#testTable tr:nth-child(3n+1) td[colspan] { background-color: bisque; }
#testTable tr:nth-child(3n+2) td[colspan] { background-color: silver; }
</style>
</head>
<body>

<table id="testTable"></table>

<script>
// ** テスト用テーブル作成 **
let
tbl = document.getElementById('testTable'),
col = 'colspan', num = 1,
f = document.createDocumentFragment(),
tr = document.createElement('tr'),
td = document.createElement('td');
td.textContent = "…";
for(let i = 0; i<20; i++) tr.appendChild(td.cloneNode(true));
for(let i = 0; i<20; i++) f.appendChild(tr.cloneNode(true));
document.getElementById('testTable').appendChild(f);

// ** イベント処理 **
tbl.addEventListener('dblclick', e =>{
let t = e.target;
if(t.nodeName != 'TD') return;
let i, cells = t.parentNode.cells;
let n = t.cellIndex, c = (t.getAttribute(col) || 1) | 0;
c = Math.min(cells.length - n, c + (Math.random()*6 | 0) + 1);
for(i=1; i<c; i++) if(cells[n+i].getAttribute(col)) break;
c = c>i?i:c;
t.setAttribute(col, c);
t.textContent = '備考' + num++;
for(i=1; i<c; i++) cells[n+i].style.display = 'none';
});
</script>
</body>
</html>
    • good
    • 0

No1です。



No1のスクリプト部分のみ、追加での投稿になります。


<script>
window.addEventListener('DOMContentLoaded', e => {

// ** テスト用テーブル作成 **
for(let r = 0; r<20; r++){
let tr = document.createElement('tr')
for(let c = 0; c<25; c++){
let td = document.createElement('td');
td.textContent = (r+1) + "-" + (c+1);
tr.appendChild(td);
}
document.getElementById('testTable').appendChild(tr);
}
document.body.insertAdjacentHTML('beforeend', '<div id="selectMarker"></div>');



// ** 初期設定 **
const
tbl = document.getElementById('testTable'),
marker = {
elm: document.getElementById('selectMarker'),
flag: false,

clear: function(){
this.elm.style.display = 'none';
this.flag = false;
this.cell1 = this.cell2 = null;
},

set: function(t){
this.cell2 = t;
let
rec1 = this.cell1.getBoundingClientRect(),
rec2 = t.getBoundingClientRect(),
top = Math.min(rec1.top, rec2.top),
left = Math.min(rec1.left, rec2.left),
styl = this.elm.style;
styl.width = (Math.max(rec1.right, rec2.right) - left) + 'px';
styl.height = (Math.max(rec1.bottom, rec2.bottom) - top) + 'px';
styl.left = (left + window.scrollX) + 'px';
styl.top = (top + window.scrollY) + 'px';
styl.display = 'block';
},

areaIndex: function(){
let
r1 = this.cell1.parentNode.rowIndex,
r2 = this.cell2.parentNode.rowIndex,
c1 = this.cell1.cellIndex,
c2 = this.cell2.cellIndex;
if(r1>r2) [r1, r2] = [r2, r1];
if(c1>c2) [c1, c2] = [c2, c1];
return { r1: r1, c1: c1, r2: r2, c2: c2 };
},

check: function(){
return (this.flag || !this.cell1 || !this.cell2);
}
},

getPos = (elm, tag, d, L1, L2) =>{
let r, elms = elm.querySelectorAll(tag);
for( let i=0; i<elms.length; i++){
let rec = elms[i].getBoundingClientRect();
if(rec[L1] < d && d <= rec[L2]){ r = elms[i]; break; }
}
return r;
},

getCell = e => {
let r, t = e.target;
if(t.nodeName == 'TD' || t.id == 'selectMarker') {
let x = e.pageX - window.scrollX;
let y = e.pageY - window.scrollY;
r = getPos(tbl, 'tr', y, 'top', 'bottom');
if(r) r = getPos(r, 'td', x, 'left', 'right');
}
return r;
},

// ** イベント処理 **
mouseClick = e =>{
let t = getCell(e);
if(!t) { marker.clear(); return; }
if(!marker.flag) marker.cell1= t;
marker.flag = !marker.flag;
marker.set(t);
},

mouseMove = e => {
if(!marker.flag) return;
let t = getCell(e);
if(t) marker.set(t);
},

setColor = e => {
let elms = document.querySelectorAll('#colorTable td');
let n =elms[ [...elms].indexOf(e.target)];
if(!n || marker.check()) return;
let a = marker.areaIndex();
let color = n.style.backgroundColor;
let bcolor = color=='transparent'?'gray':color;

for(let r = a.r1; r<=a.r2; r++){
let tds = tbl.rows[r].querySelectorAll('td');
for(let c = a.c1; c<=a.c2; c++){
tds[c].style.backgroundColor = color;
tds[c].style.borderColor = bcolor;
}
}
marker.clear();
},

setEvent = (elm, evt, func) =>{
elm.addEventListener(evt, e =>{ func(e); });
};


setEvent( document, 'click', mouseClick);
setEvent( document, 'mousemove', mouseMove);
setEvent(document.getElementById('colorTable'), 'click', setColor);

});
</script>
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
作成していただいたコードですがイメージとしてはいいのですが
色を付けた部分を1行として備考を記載したいんですよね
今のままだと色だけ変わってセルの内容が1つづつ記載となりますよね
これをまとめて1行にしたいんです。
だからセル結合かなと思ったのですが。
ありがとうございました。
もし、上記もヒントやコード載せていただけれるようでしたお願いします。

お礼日時:2021/04/10 02:22

こんばんは



>もっと汎用的にしたいです。
汎用化するのは良いですが、結合した際の他のデータはどうなるのでしょうか?
ご提示のサンプルでは分離すると復活するみたいですけれど、そうなるとバックグラウンドでテーブルをもう一つ持っておく必要がありそうな・・・
あるいは、結合セルを含む範囲を選択する場合には、包含矩形となるのかそうでないのかなど、起こり得るいろいろなケースに対して仕様を決めておく必要がありそうです。

一方で、
>セル結合しているのかboderを消しているのか
>わからないのですが色付けしたいです。
から推測して、同じ色のエリアになればよいものと解釈しました。

また、
>ドラッグ&ドロップしたらその範囲が~~
通常のブラウザの動作だと、表上でドラッグすると表示文字が選択されますが、その際カーソルをドラッグで上下移動すると、選択対象は行全体になってしまい、大変紛らわしいことになるような気がします。
まぁ、デフォルトの動作をキャンセルすればよいのかもしれませんが、「マウスダウン-ドラッグ-マウスアップ」ではなく、「クリック-ムーブ-クリック」の操作に変更して考えています。

>ソースとかの具体例をいただけると助かります。
色の指定方法が不明なので、ひとまず、テキトーなカラーテーブルを作り、「セルを選択した状態でカラーをクリックすると、選択範囲がその色になる」という単純な例として作成しています。
とは言っても、スクリプトの考え方は十人十色なので、UIは多少の参考にはなるかもしれませんが、スクリプトはあまり参考にはならないと思います。
(思い付きのまま記述しているので、整理されていませんし、必ずしも読みやすいとも思えませんので)

以下のように、勝手に読み替えています。
・click-move-clickでセル範囲を選択してから、色を指定すると該当範囲がその色になる
・セルの単位はそのままで、結合などはしない。(表示内容もそのまま)
・罫線は、まとめて背景色と同色にしています。
 (外枠だけは元の色を残すようにしたほうが、効果的かもしれません)

※ 通常ならイベント発生要素からセル位置を簡単に特定できますが、選択範囲を示すdivを表示している関係で、その範囲内の(下にある)セルは同じ方法では特定できません。
ですので、全体に、セルを特定する方法としてマウス座標から計算する方法をとっています。

※ 何かの足しにでもなれば。
(全体をまとめると文字数オーバーになるため、スクリプト部分は分けて別投稿にしました。)
Chromeとfxでテストしています。

<!DOCTYPE HTML>
<html lang="ja">
<head><title>Sample</title>
<style>
#testTable { border-collapse: collapse; font-size: 10px; }
#testTable td { padding: 0.3em; border: 1px solid gray; text-align: center; min-width:4em; }

#colorTable { border-collapse: separate; border-spacing: 2px; margin: 1em; }
#colorTable, #colorTable td { border: 1px solid gray; }
#colorTable td { width: 1.5em; height:1.5em; text-align: center; }

#selectMarker {
position: absolute; box-sizing: border-box;
background-color: rgba(0, 0, 255, .05);
border: 2px dashed blue;
z-index: 10; display: none;
}
</style>

<script>
// *** この部分は別投稿になります。
</script>
</head>
<body>

<table id="colorTable"><tr>
<td style="background-color: transparent;">無</td>
<td style="background-color: silver;"></td>
<td style="background-color: pink;"></td>
<td style="background-color: bisque;"></td>
<td style="background-color: lightyellow;"></td>
<td style="background-color: yellow;"></td>
<td style="background-color: palegreen;"></td>
<td style="background-color: aquamarine;"></td>
<td style="background-color: aqua;"></td>
<td style="background-color: turquoise;"></td>
<td style="background-color: skyblue;"></td>
<td style="background-color: cornflowerblue;"></td>
<td style="background-color: plum;"></td>
<td style="background-color: hotpink;"></td>
</tr></table>

<table id="testTable"></table>

</body>
</html>
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!