Skip to content

Instantly share code, notes, and snippets.

@fumokmm
Last active August 30, 2015 13:25
Show Gist options
  • Save fumokmm/302869f3e8df666b5518 to your computer and use it in GitHub Desktop.
Save fumokmm/302869f3e8df666b5518 to your computer and use it in GitHub Desktop.
jQueryで大量データを扱うテーブルのサンプル
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>jQueryで大量データテーブル</title>
<style type="text/css">
.viewport {
position: relative;
background: blue;
overflow: auto;
width: 300px;
height: 600px;
border: solid 1px orange;
}
.canvas {
background: yellow;
}
.row {
position: absolute;
display: block;
background: lime;
padding: 2px;
border: 1px solid green;
}
.cell {
display: inline-block;
padding: 2px;
border: 1px solid silver;
}
#indicator {
position: fixed;
top: 10px;
left: 320px;
border-radius: 5px;
border: 1px solid silver;
}
</style>
</head>
<body>
<div class="viewport">
<div class="canvas">
</div>
</div>
<div id="indicator"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script>
$(function(){
var DATA_SIZE = 40000;
var DATA_HEIGHT = 40;
var DATA_CACHE_RATE = 1.2;
var CANVAS_HEIGHT = DATA_SIZE * DATA_HEIGHT;
var $viewport = $( '.viewport' );
var $canvas = $( '.canvas' );
$canvas.height(CANVAS_HEIGHT);
// スクロールバーの高さを取得
var SCROLL_BAR_HEIGHT = (function(){
var max = $viewport.scrollTop(DATA_SIZE * DATA_HEIGHT)
.scrollTop();
$viewport.scrollTop(0);
return DATA_SIZE * DATA_HEIGHT - max;
})();
var VIEWPORT_HEIGHT = $viewport.height();
console.log('スクロールバーの高さ=' + SCROLL_BAR_HEIGHT);
console.log('viewportの高さ=' + VIEWPORT_HEIGHT);
// 初期の要素を作成
var firstCreateSize = Math.min(Math.floor(VIEWPORT_HEIGHT / DATA_HEIGHT * DATA_CACHE_RATE), DATA_SIZE);
console.log('first create size is ' + firstCreateSize);
for (var i = 0; i < firstCreateSize; i++) {
$canvas.append(makeRow(i));
}
function makeRow(rowNo) {
var height = DATA_HEIGHT * rowNo;
var no = rowNo + 1;
var html = '';
html += '<div class="row" id="row' + rowNo + '" style="top: ' + height + 'px;">';
html += '<div class="cell">' + no + '</div>';
html += '<div class="cell">aaa' + no + '</div>';
html += '<div class="cell">bbb' + no + '</div>';
html += '</div>';
return html;
}
// スクロールイベント
$viewport.on('scroll', (function(){
var _prevScrollTop = 0; // 前回の位置
return function(e) {
var scrollTop = $viewport.scrollTop();
var scrollBottom = scrollTop + (VIEWPORT_HEIGHT * DATA_CACHE_RATE);
$('#indicator').text(scrollTop);
console.log('scroll to ' + scrollTop);
var poses = [];
for (var pos = scrollTop; pos < Math.min(scrollBottom, CANVAS_HEIGHT); pos += DATA_HEIGHT) {
poses.push(pos);
}
// 上方向へ向かってスクロールしている場合、逆転させる
if (_prevScrollTop < scrollTop) {
poses.reverse();
}
for (var i = 0, len = poses.length; i < len; i++) {
var rowNo = Math.floor(poses[i] / DATA_HEIGHT);
var rowId = '#row' + rowNo
$row = $(rowId);
if ($row.size() > 0) {
// 存在する場合、入れ替える
$canvas.append($row);
} else {
// 下に追加して、一番上を削除
$canvas.append(makeRow(rowNo));
var $removeData = $canvas.children(':first');
console.log(' ' + rowId + ' added. ' + $removeData.find('div:first').text() + ' removed. current data count is ' + $canvas.children().size());
$removeData.remove();
}
}
_prevScrollTop = scrollTop; // 前回の位置を保持
}
})());
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment