您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
見出し列をAlt+左クリック/Alt+右クリック:並べ替え
当前为
// ==UserScript== // @name Tableの表をソート // @description 見出し列をAlt+左クリック/Alt+右クリック:並べ替え // @match *://*/* // @version 0.1.1 // @run-at document-idle // @namespace https://greasyfork.org/users/181558 // ==/UserScript== (function() { const SORT_ASCENDING_ACTION = "Alt+0"; // Shift+ Alt+ Ctrl+ 0:左ボタン 1:中ボタン 2:右ボタン 3:X1ボタン 4:X2ボタン const SORT_DESCENDING_ACTION = "Alt+2"; document.body.addEventListener("mousedown", e => { let key = (e?.shiftKey ? "Shift+" : "") + (e?.altKey ? "Alt+" : "") + (e?.ctrlKey ? "Ctrl+" : "") + e?.button; if (key == SORT_ASCENDING_ACTION || key == SORT_DESCENDING_ACTION) { //if (e?.target?.matches('table th,table thead td,table>tbody>tr:first-child>td')) { if (e?.target?.matches('table th,table td')) { let th = e?.target //?.closest('table th,table thead td,table tr:first-child td') let table = e?.target?.closest("table"); if (!table.querySelector('[rowspan],[colspan]')) { let body = table?.querySelector('tbody') let column = th?.cellIndex; [...table.querySelectorAll('td')].forEach(e => e.asnum = parseFloat(e?.textContent?.trim()?.replace(/(\d)\,(\d)/gm, "$1$2"))); // ^1,000$などの数値に関しては,を除去 [...table.querySelectorAll('td')].forEach(e => { // セル内文字列が「abc100」「100」「100abc」のどれかなら数値が主体のデータだろうと判断し数値データとして見る。「abc100abc」なら文字列と判断。,は無視。 if (e?.textContent?.trim()?.match(/^[0-9\,\.\–\-]+\D+$|^[0-9\,\.\-\–]+$|^\D+[0-9\,\.\-\–]+$/gm)) { e.asnum = parseFloat(e?.textContent?.trim()?.replace(/–/gm, "-")?.replace(/^[^0-9\.\,\-\–]*([0-9\,\.\-\–])/, "$1")?.replace(/(\d)\,(\d)/g, "$1$2")) // なぜか「–」ダッシュをマイナスとして使うサイトもあるのでマイナスに置き換える } }) let startrow = Array.from(table.rows).findIndex(r => r.contains(e.target)); //alert(startrow) let rows = Array.from(table.rows).slice(0, startrow).concat( key == SORT_ASCENDING_ACTION ? Array.from(table.rows).slice(startrow).sort((a, b) => a?.cells?.[column]?.asnum && b?.cells?.[column]?.asnum ? a?.cells?.[column]?.asnum == b?.cells?.[column]?.asnum ? 0 : a?.cells?.[column]?.asnum - b?.cells?.[column]?.asnum : new Intl.Collator("ja", { numeric: true, sensitivity: 'base' }).compare(a?.cells?.[column]?.textContent?.trim(), b?.cells?.[column]?.textContent?.trim())) : Array.from(table.rows).slice(startrow).sort((a, b) => a?.cells?.[column]?.asnum && b?.cells?.[column]?.asnum ? a?.cells?.[column]?.asnum == b?.cells?.[column]?.asnum ? 0 : b?.cells?.[column]?.asnum - a?.cells?.[column]?.asnum : new Intl.Collator("ja", { numeric: true, sensitivity: 'base' }).compare(b?.cells?.[column]?.textContent?.trim(), a?.cells?.[column]?.textContent?.trim())) ) let fragment = new DocumentFragment(); // prependを使っても順番を維持するためにDocumentFragmentを使う rows.forEach(tr => fragment.appendChild(tr)) body.prepend(fragment) } else { [...table.querySelectorAll('[colspan]')].forEach(e => { let c = e.getAttribute("colspan"); e.removeAttribute("colspan"); e.insertAdjacentHTML("afterend", "<td></td>".repeat(c - 1)) }); [...table.querySelectorAll('[rowspan]')].forEach(e => { e.removeAttribute("rowspan"); }); [...table.querySelectorAll('tr')].filter(e => !e.hasChildNodes()).forEach(e => e.remove()); } } } }) function sani(s) { return s?.replace(/&/g, "&")?.replace(/"/g, """)?.replace(/'/g, "'")?.replace(/`/g, '`')?.replace(/</g, "<")?.replace(/>/g, ">") || "" } })();