[0.2.0] - 2026-09-24 #1
@@ -3,4 +3,5 @@
|
||||
### 🚀 Features
|
||||
|
||||
- Added changelog
|
||||
- Added Themes
|
||||
## [0.1.0] - 2026-09-23
|
||||
|
||||
+85
-18
@@ -39,12 +39,18 @@ var theme = (() => {
|
||||
return { init };
|
||||
})();
|
||||
const table = (() => {
|
||||
var dirty = false;
|
||||
var flushTimer = null;
|
||||
var ipIndex = {};
|
||||
let data = [];
|
||||
let filtered = [];
|
||||
let sortKey = 'ip';
|
||||
let sortDir = 'asc';
|
||||
let filterText = '';
|
||||
let checkedIps = new Set();
|
||||
var ROW_HEIGHT = 32;
|
||||
var BUFFER_ROWS = 20;
|
||||
var scrollContainer = null;
|
||||
|
||||
function ipToNum(ip) {
|
||||
const parts = String(ip).split('.');
|
||||
@@ -193,20 +199,61 @@ const table = (() => {
|
||||
}
|
||||
|
||||
function render() {
|
||||
const tbody = document.getElementById('results-body');
|
||||
const count = document.getElementById('host-count');
|
||||
var tbody = document.getElementById('results-body');
|
||||
var count = document.getElementById('host-count');
|
||||
if (!tbody) return;
|
||||
|
||||
expandedIp = null;
|
||||
|
||||
const rows = filtered.map((host) => {
|
||||
const ip = host.ip;
|
||||
const status = host.status || 'Unknown';
|
||||
const cls = 'status-' + status.toLowerCase();
|
||||
const rtt = host.ping ? host.ping.rtt_ms.toFixed(1) : '-';
|
||||
const hostname = host.hostname || '-';
|
||||
if (!scrollContainer) {
|
||||
scrollContainer = document.getElementById('results-table-container');
|
||||
scrollContainer.addEventListener('scroll', onScroll);
|
||||
}
|
||||
|
||||
const isChecked = checkedIps.has(ip) ? 'checked' : '';
|
||||
return '<tr data-ip="' + ip + '">'
|
||||
renderVisible();
|
||||
|
||||
if (count) {
|
||||
var up = data.filter(function (h) { return h.status === 'Up'; }).length;
|
||||
count.textContent = up + ' up / ' + data.length + ' total';
|
||||
}
|
||||
|
||||
if (columns && columns.apply) columns.apply();
|
||||
}
|
||||
|
||||
function renderVisible() {
|
||||
var tbody = document.getElementById('results-body');
|
||||
if (!tbody || !scrollContainer) return;
|
||||
|
||||
var totalRows = filtered.length;
|
||||
var viewHeight = scrollContainer.clientHeight;
|
||||
var scrollTop = scrollContainer.scrollTop;
|
||||
var headerHeight = 36;
|
||||
|
||||
var startIdx = Math.max(0, Math.floor((scrollTop - headerHeight) / ROW_HEIGHT) - BUFFER_ROWS);
|
||||
var visibleCount = Math.ceil(viewHeight / ROW_HEIGHT) + (BUFFER_ROWS * 2);
|
||||
var endIdx = Math.min(totalRows, startIdx + visibleCount);
|
||||
|
||||
var topSpace = startIdx * ROW_HEIGHT;
|
||||
var bottomSpace = (totalRows - endIdx) * ROW_HEIGHT;
|
||||
|
||||
var colCount = document.querySelectorAll('#results-table th').length;
|
||||
|
||||
var html = '';
|
||||
|
||||
if (topSpace > 0) {
|
||||
html += '<tr class="virtual-spacer"><td colspan="' + colCount + '" style="height:' + topSpace + 'px"></td></tr>';
|
||||
}
|
||||
|
||||
for (var i = startIdx; i < endIdx; i++) {
|
||||
var host = filtered[i];
|
||||
var ip = host.ip;
|
||||
var status = host.status || 'Unknown';
|
||||
var cls = 'status-' + status.toLowerCase();
|
||||
var rtt = host.ping ? host.ping.rtt_ms.toFixed(1) : '-';
|
||||
var hostname = host.hostname || '-';
|
||||
var isChecked = checkedIps.has(ip) ? 'checked' : '';
|
||||
|
||||
html += '<tr data-ip="' + ip + '">'
|
||||
+ '<td class="col-check"><input type="checkbox" class="row-check" ' + isChecked + ' /></td>'
|
||||
+ '<td>' + ip + '</td>'
|
||||
+ '<td class="' + cls + '">' + status + '</td>'
|
||||
@@ -214,24 +261,43 @@ const table = (() => {
|
||||
+ '<td>' + hostname + '</td>'
|
||||
+ '<td class="ports-cell">' + formatPorts(host) + '</td>'
|
||||
+ '</tr>';
|
||||
});
|
||||
|
||||
tbody.innerHTML = rows.join('');
|
||||
|
||||
if (count) {
|
||||
const up = data.filter((h) => h.status === 'Up').length;
|
||||
count.textContent = up + ' up / ' + data.length + ' total';
|
||||
}
|
||||
|
||||
if (bottomSpace > 0) {
|
||||
html += '<tr class="virtual-spacer"><td colspan="' + colCount + '" style="height:' + bottomSpace + 'px"></td></tr>';
|
||||
}
|
||||
|
||||
tbody.innerHTML = html;
|
||||
}
|
||||
|
||||
var scrollTimeout = null;
|
||||
function onScroll() {
|
||||
if (scrollTimeout) return;
|
||||
scrollTimeout = requestAnimationFrame(function () {
|
||||
scrollTimeout = null;
|
||||
renderVisible();
|
||||
if (columns && columns.apply) columns.apply();
|
||||
});
|
||||
}
|
||||
|
||||
function upsert(host) {
|
||||
const idx = data.findIndex((h) => h.ip === host.ip);
|
||||
var idx = data.findIndex(function (h) { return h.ip === host.ip; });
|
||||
if (idx >= 0) {
|
||||
data[idx] = host;
|
||||
} else {
|
||||
ipIndex[host.ip] = data.length;
|
||||
data.push(host);
|
||||
}
|
||||
dirty = true;
|
||||
if (!flushTimer) {
|
||||
flushTimer = setTimeout(flush, 200);
|
||||
}
|
||||
}
|
||||
|
||||
function flush() {
|
||||
flushTimer = null;
|
||||
if (!dirty) return;
|
||||
dirty = false;
|
||||
refresh();
|
||||
}
|
||||
|
||||
@@ -239,6 +305,7 @@ const table = (() => {
|
||||
data = [];
|
||||
filtered = [];
|
||||
checkedIps.clear();
|
||||
ipIndex = {};
|
||||
document.getElementById('check-all').checked = false;
|
||||
refresh();
|
||||
}
|
||||
|
||||
@@ -409,6 +409,7 @@ body {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
#results-table tbody tr {
|
||||
@@ -428,6 +429,15 @@ body {
|
||||
box-shadow: inset 3px 0 0 var(--cyan);
|
||||
}
|
||||
|
||||
.virtual-spacer {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.virtual-spacer td {
|
||||
padding: 0 !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
/* ===== Status Colors ===== */
|
||||
|
||||
.status-up {
|
||||
@@ -1322,6 +1332,7 @@ body {
|
||||
.changelog-content a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.theme-picker {
|
||||
padding: 1px 6px;
|
||||
font-size: 11px;
|
||||
@@ -1345,6 +1356,7 @@ body {
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* ===== Theme: Midnight ===== */
|
||||
|
||||
:root[data-theme="midnight"] {
|
||||
|
||||
Reference in New Issue
Block a user