tableのtr要素をドラッグ&ドロップで任意に入れ替え その2 ギブアップ!
せっかく、解説書がありながら、ギブアップ!
テーブルの範囲を選んだときに、rowSpan を見て、関連のある行を自動で選択できるようにするも、前方に検索するのは、あきらめました。view.getSelection で得た、range の扱いもゴタゴタ。
<!DOCTYPE html> <title></title> <style type="text/css"> table, th { border:1px #c88 outset; } td { border:1px #c88 inset; width :4em; text-align: right; } </style> <body> <table id="huga"> <thead> <tr> <th id="p">1 <th>2 <th>3 <th>4 <th>5 <th>6 <th>7 </thead> <tbody> <tr> <td>1 <td>2 <td>3 <td>4 <td>5 <td>6 <td>7 <tr> <td>1 <td>2 <td>3 <td>4 <td>5 <td>6 <td>7 <tr> <td>1 <td>2 <td>3 <td>4 <td>5 <td>6 <td>7 <tr> <td>2 <td rowspan="2">2 <td>3 <td>4 <td>5 <td>6 <td>7 <tr> <td>3 <td rowspan="2">3 <td>4 <td>5 <td>6 <td>7 <tr> <td>4 <td>2 <td rowspan="2">4 <td>5 <td>6 <td>7 <tr> <td>5 <td>2 <td>3 <td rowspan="2">5 <td>6 <td>7 <tr> <td>6 <td>2 <td>3 <td>4 <td rowspan="2">6 <td>7 <tr> <td>7 <td>2 <td>3 <td>4 <td>5 <td rowspan="2">7 <tr> <td>8 <td>2 <td>3 <td>4 <td>5 <td>6 <tr> <td>9 <td>2 <td>3 <td>4 <td>5 <td>6 <td>7 </tbody> </table> <p>abc</p> <script type="application/javascript; version=1.8"> (function () { const TableDrag = { table : [] }; //__________ // 目的の親を得る const getParent = (function (n, t, v) n ? (v == n[t]) ? n: arguments.callee (n.parentNode, t, v): null); // ノードが登録されたテーブルに含まれているか const hasInsideTable = (function (checker) (function (target) TableDrag.table.some (checker, target))) ((function (parent) !! (this.compareDocumentPosition (parent) & 8))); // 外部ファイルにしないと… // 指定行が、rowSpan で関連がある行番号の最大値を返す const getRowsRange = (function (getMax) (function (rowIndex) { var max = 0; var rowSpanMax; var row; var result = { min: rowIndex }; while (row = this[rowIndex]) { rowSpanMax = Math.max.apply (null, Array.map (row.cells, getMax)); if (max < rowSpanMax) max = rowSpanMax; max -= 1; if (1 > max) break; rowIndex += 1; } result.max = rowIndex; return result; })) ((function (cell) parseInt (cell.rowSpan, 10) || 1 )); // イベントハンドラ var onDrag = function (evt) { var target = evt.target; var doc = target.ownerDocument; var view = doc.defaultView; var selection = view.getSelection (); var table = getParent (target, 'nodeName', 'TABLE'); var dt = evt.dataTransfer; var row1 = getParent (target, 'nodeName', 'TR'); var row2; var no; if (! row1) return; switch (evt.type) { case 'dragstart': if (! hasInsideTable (target)) // 登録されていない return; if ('TBODY' === selection.anchorNode.nodeName) { dt.setData ('text/plain', selection.anchorOffset + '/' + selection.focusOffset); dt.effectAllowed = 'move'; } return; case 'drop': if ('TD' === row1.cells[0].nodeName) { no = dt.getData ('text/plain').split('/'); var rows = [], I = + no[1]; for (var i = +no[0]; i < I; i++) rows.push (table.rows[i]); rows.forEach (function (r) row1.parentNode.insertBefore (r, row1)); } break; default : } evt.preventDefault (); return; }; var onExtensionRowsRange = function (evt) { var node = evt.target; var doc = node.ownerDocument; var view = doc.defaultView; var selection = view.getSelection (); var range = doc.createRange (); var sNode = selection.anchorNode var eNode = selection.focusNode; var table; var sRange; var eRange; if (selection.isCollapsed) //選択範囲がない return; if (! hasInsideTable(sNode)) // 選択範囲の最初が登録されたテーブルか? return; if (! hasInsideTable(eNode)) // 選択範囲の最後が登録されたテーブルか? return; table = getParent (node, 'nodeName', 'TABLE'); //選択範囲のテーブルを取得 sNode = getParent (sNode, 'nodeName', 'TR'); //最初の行 eNode = getParent (eNode, 'nodeName', 'TR'); //最後の行 sRange = getRowsRange.call (table.rows, sNode.rowIndex); //rowSpanを探し出し、範囲を調べる eRange = getRowsRange.call (table.rows, eNode.rowIndex); selection.removeAllRanges (); // 選択範囲を削除 range.setStartBefore (table.rows[ Math.min (sRange.min, eRange.min)]); //選択範囲を設定する range.setEndAfter (table.rows[ Math.max (sRange.max, eRange.max)]); selection.addRange (range); // 選択範囲を追加 }; // 初期化(イベント設定) var init = function (view) { var win = view || window; var doc = win.document; doc.addEventListener ('dragstart', onDrag, false); doc.addEventListener ('dragover', onDrag, false); doc.addEventListener ('drop', onDrag, false); doc.addEventListener ('mouseup', onExtensionRowsRange, false); }; // テーブルの追加 const add = (function (hasArray) (function (target) (target instanceof HTMLTableElement) ? (! hasArray.call (TableDrag.table, target)) ? TableDrag.table.push (target) : null : null)) ((function (checker) (function (target) this.some (checker, target))) ((function (m) m == this))) //__________ TableDrag.add = add; TableDrag.init = init; //__________ this.TableDrag = TableDrag; })(); TableDrag.init (this); TableDrag.add (document.getElementById ('huga')); </script>