vanillajs-excelike-table
Version:
A user-friendly pure JavaScript table library with Excel-like features, preset configurations, and intuitive column helpers. Vanilla JS implementation - no frameworks required!
307 lines (277 loc) • 10.4 kB
HTML
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>🔧 タッチイベントデバッグ - ExceLikeTable</title>
<link rel="stylesheet" href="../dist/excelike-table.css">
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
margin: 0;
padding: 10px;
background: #f0f2f5;
overflow-x: hidden;
}
.debug-container {
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
margin-bottom: 16px;
}
.debug-header {
background: #1890ff;
color: white;
padding: 12px 16px;
border-radius: 8px 8px 0 0;
font-weight: 500;
}
.debug-content {
padding: 16px;
}
.table-container {
height: 300px;
border: 1px solid #d9d9d9;
border-radius: 6px;
margin: 16px 0;
}
.log-container {
background: #001529;
color: #ffffff;
padding: 12px;
border-radius: 6px;
font-family: 'Monaco', 'Courier New', monospace;
font-size: 11px;
line-height: 1.4;
height: 200px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-all;
}
.test-buttons {
display: flex;
gap: 8px;
margin: 12px 0;
flex-wrap: wrap;
}
.test-btn {
background: #1890ff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
min-height: 44px;
}
.test-btn:active {
background: #40a9ff;
}
.status-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
margin: 12px 0;
}
.status-item {
background: #f6f6f6;
padding: 8px;
border-radius: 4px;
text-align: center;
font-size: 12px;
}
.status-ok { background: #f6ffed; color: #52c41a; }
.status-error { background: #fff2f0; color: #ff4d4f; }
/* スライダーを大きく */
.range-thumb, .date-range-thumb {
width: 24px ;
height: 24px ;
border: 3px solid white ;
background: #1890ff ;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3) ;
}
.range-slider, .date-range-slider {
height: 8px ;
margin: 16px 0 ;
}
</style>
</head>
<body>
<div class="debug-container">
<div class="debug-header">
📱 タッチイベント デバッグコンソール
</div>
<div class="debug-content">
<div class="status-grid" id="status-grid">
<div class="status-item">Touch Events: <span id="touch-support">-</span></div>
<div class="status-item">Pointer Events: <span id="pointer-support">-</span></div>
<div class="status-item">画面サイズ: <span id="screen-size">-</span></div>
<div class="status-item">ビューポート: <span id="viewport-size">-</span></div>
</div>
<div class="test-buttons">
<button class="test-btn" onclick="clearLogs()">🗑️ ログクリア</button>
<button class="test-btn" onclick="testTouchEvents()">🧪 タッチテスト</button>
<button class="test-btn" onclick="toggleFullscreen()">📱 フルスクリーン</button>
</div>
</div>
</div>
<div class="debug-container">
<div class="debug-header">
📊 テスト用テーブル
</div>
<div class="debug-content">
<p style="margin: 0 0 8px 0; font-size: 14px; color: #666;">
給与・入社日列のフィルターでスライダーをテストしてください
</p>
<div class="table-container" id="table-container"></div>
</div>
</div>
<div class="debug-container">
<div class="debug-header">
🔧 リアルタイムログ
</div>
<div class="debug-content">
<div class="log-container" id="log-container">システム初期化中...</div>
</div>
</div>
<script src="../dist/excelike-table.js"></script>
<script>
let logContainer;
let logCount = 0;
function addLog(message, type = 'info') {
if (!logContainer) return;
const timestamp = new Date().toLocaleTimeString();
const prefix = type === 'error' ? '❌' : type === 'success' ? '✅' : type === 'touch' ? '👆' : 'ℹ️';
const logMessage = `[${timestamp}] ${prefix} ${message}\n`;
logContainer.textContent += logMessage;
logContainer.scrollTop = logContainer.scrollHeight;
logCount++;
if (logCount > 100) {
// ログが多すぎる場合は古いものを削除
const lines = logContainer.textContent.split('\n');
logContainer.textContent = lines.slice(-50).join('\n');
logCount = 50;
}
}
function clearLogs() {
if (logContainer) {
logContainer.textContent = '';
logCount = 0;
addLog('ログをクリアしました');
}
}
function testTouchEvents() {
addLog('タッチイベントテストを開始...');
const testElement = document.createElement('div');
testElement.style.cssText = 'position:fixed; top:50%; left:50%; width:100px; height:100px; background:#1890ff; border-radius:50%; transform:translate(-50%,-50%); z-index:10000; opacity:0.8;';
document.body.appendChild(testElement);
let touchCount = 0;
const handleTouch = (e) => {
touchCount++;
addLog(`タッチイベント ${touchCount}: ${e.type} (touches: ${e.touches ? e.touches.length : 0})`, 'touch');
if (touchCount >= 3) {
document.body.removeChild(testElement);
addLog('タッチテスト完了', 'success');
}
};
testElement.addEventListener('touchstart', handleTouch, { passive: false });
testElement.addEventListener('touchmove', handleTouch, { passive: false });
testElement.addEventListener('touchend', handleTouch, { passive: false });
addLog('青い円をタッチしてテストしてください');
setTimeout(() => {
if (document.body.contains(testElement)) {
document.body.removeChild(testElement);
addLog('タッチテストタイムアウト', 'error');
}
}, 10000);
}
function toggleFullscreen() {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen().then(() => {
addLog('フルスクリーンモードを開始');
}).catch(() => {
addLog('フルスクリーンモード失敗', 'error');
});
} else {
document.exitFullscreen().then(() => {
addLog('フルスクリーンモードを終了');
});
}
}
// オリジナルのconsole.logをオーバーライド
const originalLog = console.log;
console.log = function(...args) {
originalLog.apply(console, args);
if (args.length > 0 && typeof args[0] === 'string') {
const message = args.join(' ');
if (message.includes('👆') || message.includes('👉') || message.includes('📱')) {
addLog(message, 'touch');
} else if (message.includes('✅')) {
addLog(message, 'success');
} else if (message.includes('❌')) {
addLog(message, 'error');
} else {
addLog(message);
}
}
};
document.addEventListener('DOMContentLoaded', function() {
logContainer = document.getElementById('log-container');
// ステータス情報を更新
document.getElementById('touch-support').textContent = 'ontouchstart' in window ? '✅' : '❌';
document.getElementById('pointer-support').textContent = 'onpointerdown' in window ? '✅' : '❌';
document.getElementById('screen-size').textContent = `${screen.width}×${screen.height}`;
document.getElementById('viewport-size').textContent = `${window.innerWidth}×${window.innerHeight}`;
// ステータスの色を更新
const touchSupport = document.getElementById('touch-support').parentElement;
touchSupport.className = 'status-item ' + ('ontouchstart' in window ? 'status-ok' : 'status-error');
addLog('デバッグシステム初期化完了', 'success');
addLog(`デバイス: ${navigator.userAgent.includes('Mobile') ? 'モバイル' : 'デスクトップ'}`);
addLog(`ブラウザ: ${navigator.userAgent.split(' ').pop()}`);
// テストデータ
const testData = [
{ id: 1, name: '田中太郎', salary: 850000, joinDate: '2020-04-01' },
{ id: 2, name: '佐藤花子', salary: 720000, joinDate: '2021-07-15' },
{ id: 3, name: '鈴木次郎', salary: 680000, joinDate: '2022-01-20' },
{ id: 4, name: '高橋美咲', salary: 780000, joinDate: '2020-11-10' },
{ id: 5, name: '山田一郎', salary: 750000, joinDate: '2023-03-05' }
];
// シンプルな列定義
const columns = [
ColumnHelpers.text('name', '氏名', { width: 100 }),
ColumnHelpers.number('salary', '給与', {
width: 120,
currency: '¥',
filterable: true,
filterType: 'numeric'
}),
ColumnHelpers.date('joinDate', '入社日', {
width: 120,
filterable: true,
filterType: 'date-hierarchy'
})
];
// テーブル初期化
try {
const table = new ExceLikeTable('#table-container', {
preset: 'excel',
data: testData,
columns: columns,
rowKey: 'id',
tableId: 'touch-debug-table',
pagination: { pageSize: 10 },
persistSettings: false
});
addLog('テーブル初期化完了', 'success');
addLog('給与・入社日列のフィルターでスライダーをテストしてください');
} catch (error) {
addLog(`テーブル初期化エラー: ${error.message}`, 'error');
}
});
// ビューポートサイズ変更を監視
window.addEventListener('resize', () => {
document.getElementById('viewport-size').textContent = `${window.innerWidth}×${window.innerHeight}`;
});
</script>
</body>
</html>