Add clusterize
This commit is contained in:
parent
7c562f6a59
commit
8767066e3e
27
index.html
27
index.html
@ -6,11 +6,19 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<title>Document</title>
|
<title>Document</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Tahoma';
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1>ReGrid</h1>
|
<h1>ReGrid</h1>
|
||||||
<section>
|
<button onclick="_regrid.render()">Refresh</button>
|
||||||
|
<section style="width: 60%;">
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<script src="./node_modules/jquery/dist/jquery.js"></script>
|
<script src="./node_modules/jquery/dist/jquery.js"></script>
|
||||||
@ -487,10 +495,27 @@
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
data.rows = data.rows.concat(data.rows);
|
||||||
|
data.rows = data.rows.concat(data.rows);
|
||||||
|
|
||||||
|
performance.mark("ReGrid-start");
|
||||||
var grid = new ReGrid({
|
var grid = new ReGrid({
|
||||||
wrapper: document.querySelector('section'),
|
wrapper: document.querySelector('section'),
|
||||||
|
addSerialNoColumn: true,
|
||||||
|
enableClusterize: true,
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
|
performance.mark("ReGrid-end");
|
||||||
|
|
||||||
|
performance.measure(
|
||||||
|
"ReGrid",
|
||||||
|
"ReGrid-start",
|
||||||
|
"ReGrid-end"
|
||||||
|
);
|
||||||
|
|
||||||
|
var measures = performance.getEntriesByName("ReGrid");
|
||||||
|
var measure = measures[0];
|
||||||
|
console.log(measure.duration);
|
||||||
|
|
||||||
window._regrid = grid;
|
window._regrid = grid;
|
||||||
})
|
})
|
||||||
|
|||||||
450
lib/ReGrid.js
450
lib/ReGrid.js
@ -112,6 +112,10 @@ var _jQuery = __webpack_require__(3);
|
|||||||
|
|
||||||
var _jQuery2 = _interopRequireDefault(_jQuery);
|
var _jQuery2 = _interopRequireDefault(_jQuery);
|
||||||
|
|
||||||
|
var _clusterize = __webpack_require__(9);
|
||||||
|
|
||||||
|
var _clusterize2 = _interopRequireDefault(_clusterize);
|
||||||
|
|
||||||
__webpack_require__(4);
|
__webpack_require__(4);
|
||||||
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
@ -122,12 +126,21 @@ var ReGrid = function () {
|
|||||||
function ReGrid(_ref) {
|
function ReGrid(_ref) {
|
||||||
var wrapper = _ref.wrapper,
|
var wrapper = _ref.wrapper,
|
||||||
events = _ref.events,
|
events = _ref.events,
|
||||||
data = _ref.data;
|
data = _ref.data,
|
||||||
|
addSerialNoColumn = _ref.addSerialNoColumn,
|
||||||
|
enableClusterize = _ref.enableClusterize;
|
||||||
|
|
||||||
_classCallCheck(this, ReGrid);
|
_classCallCheck(this, ReGrid);
|
||||||
|
|
||||||
this.wrapper = (0, _jQuery2.default)(wrapper);
|
this.wrapper = (0, _jQuery2.default)(wrapper);
|
||||||
this.events = events || {};
|
if (this.wrapper.length === 0) {
|
||||||
|
throw new Error('Invalid argument given for `wrapper`');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.events = (0, _utils.getDefault)(events, {});
|
||||||
|
this.addSerialNoColumn = (0, _utils.getDefault)(addSerialNoColumn, false);
|
||||||
|
this.enableClusterize = (0, _utils.getDefault)(enableClusterize, false);
|
||||||
|
|
||||||
this.makeDom();
|
this.makeDom();
|
||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -155,7 +168,11 @@ var ReGrid = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.renderHeader();
|
this.renderHeader();
|
||||||
this.renderBody();
|
if (this.enableClusterize) {
|
||||||
|
this.renderBodyWithClusterize();
|
||||||
|
} else {
|
||||||
|
this.renderBody();
|
||||||
|
}
|
||||||
this.setDimensions();
|
this.setDimensions();
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@ -170,6 +187,22 @@ var ReGrid = function () {
|
|||||||
// scrollable body
|
// scrollable body
|
||||||
this.bodyScrollable.html('\n <table class="data-table-body table table-bordered">\n ' + (0, _utils.getBodyHTML)(this.data.rows) + '\n </table>\n ');
|
this.bodyScrollable.html('\n <table class="data-table-body table table-bordered">\n ' + (0, _utils.getBodyHTML)(this.data.rows) + '\n </table>\n ');
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: 'renderBodyWithClusterize',
|
||||||
|
value: function renderBodyWithClusterize() {
|
||||||
|
// empty body
|
||||||
|
this.bodyScrollable.html('\n <table class="data-table-body table table-bordered">\n ' + (0, _utils.getBodyHTML)([]) + '\n </table>\n ');
|
||||||
|
|
||||||
|
var data = this.data.rows.map(function (row) {
|
||||||
|
return (0, _utils.getRowHTML)(row, { rowIndex: row[0].rowIndex });
|
||||||
|
});
|
||||||
|
|
||||||
|
this.clusterize = new _clusterize2.default({
|
||||||
|
rows: data,
|
||||||
|
scrollElem: this.bodyScrollable.get(0),
|
||||||
|
contentElem: this.bodyScrollable.find('tbody').get(0)
|
||||||
|
});
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'updateCell',
|
key: 'updateCell',
|
||||||
value: function updateCell(rowIndex, colIndex, value) {
|
value: function updateCell(rowIndex, colIndex, value) {
|
||||||
@ -202,6 +235,19 @@ var ReGrid = function () {
|
|||||||
var columns = data.columns,
|
var columns = data.columns,
|
||||||
rows = data.rows;
|
rows = data.rows;
|
||||||
|
|
||||||
|
|
||||||
|
if (this.addSerialNoColumn) {
|
||||||
|
var serialNoColumn = 'Sr. No';
|
||||||
|
|
||||||
|
columns = [serialNoColumn].concat(columns);
|
||||||
|
|
||||||
|
rows = rows.map(function (row, i) {
|
||||||
|
var val = i + 1 + "";
|
||||||
|
|
||||||
|
return [val].concat(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var _columns = (0, _utils.prepareRowHeader)(columns);
|
var _columns = (0, _utils.prepareRowHeader)(columns);
|
||||||
var _rows = (0, _utils.prepareRows)(rows);
|
var _rows = (0, _utils.prepareRows)(rows);
|
||||||
|
|
||||||
@ -264,6 +310,7 @@ var ReGrid = function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.setBodyWidth();
|
this.setBodyWidth();
|
||||||
|
this.setColumnWidths();
|
||||||
|
|
||||||
this.bodyScrollable.css({
|
this.bodyScrollable.css({
|
||||||
marginTop: this.header.height() + 1
|
marginTop: this.header.height() + 1
|
||||||
@ -344,9 +391,9 @@ var ReGrid = function () {
|
|||||||
|
|
||||||
(0, _jQuery2.default)('body').on('mousemove', function (e) {
|
(0, _jQuery2.default)('body').on('mousemove', function (e) {
|
||||||
if (!isDragging) return;
|
if (!isDragging) return;
|
||||||
var fwidth = startWidth + (e.pageX - startX);
|
var finalWidth = startWidth + (e.pageX - startX);
|
||||||
|
|
||||||
$currCell.find('.content').width(fwidth);
|
self.setColumnHeaderWidth($currCell, finalWidth);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@ -420,6 +467,48 @@ var ReGrid = function () {
|
|||||||
}
|
}
|
||||||
$el.css('width', width);
|
$el.css('width', width);
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: 'setColumnHeaderWidth',
|
||||||
|
value: function setColumnHeaderWidth(colIndex, width) {
|
||||||
|
var $cell = void 0;
|
||||||
|
|
||||||
|
if (typeof colIndex === 'number') {
|
||||||
|
$cell = this.getColumnHeaderElement(colIndex);
|
||||||
|
} else {
|
||||||
|
// directly element is passed
|
||||||
|
$cell = colIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cell.find('.content').width(width);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'setColumnWidths',
|
||||||
|
value: function setColumnWidths() {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
var availableWidth = this.wrapper.width();
|
||||||
|
var headerWidth = this.header.width();
|
||||||
|
|
||||||
|
if (headerWidth > availableWidth) {
|
||||||
|
// don't resize, horizontal scroll takes place
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var deltaWidth = (availableWidth - headerWidth) / this.data.columns.length;
|
||||||
|
|
||||||
|
this.data.columns.map(function (col) {
|
||||||
|
var width = _this.getColumnHeaderElement(col.colIndex).width();
|
||||||
|
var finalWidth = width + deltaWidth - 16;
|
||||||
|
|
||||||
|
if (_this.addSerialNoColumn && col.colIndex === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_this.setColumnHeaderWidth(col.colIndex, finalWidth);
|
||||||
|
_this.setColumnWidth(col.colIndex, finalWidth);
|
||||||
|
});
|
||||||
|
this.setBodyWidth();
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'setBodyWidth',
|
key: 'setBodyWidth',
|
||||||
value: function setBodyWidth() {
|
value: function setBodyWidth() {
|
||||||
@ -429,16 +518,22 @@ var ReGrid = function () {
|
|||||||
key: 'getColumn',
|
key: 'getColumn',
|
||||||
value: function getColumn(colIndex) {
|
value: function getColumn(colIndex) {
|
||||||
return this.data.columns.find(function (col) {
|
return this.data.columns.find(function (col) {
|
||||||
return col.col_index === colIndex;
|
return col.colIndex === colIndex;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: 'getRow',
|
key: 'getRow',
|
||||||
value: function getRow(rowIndex) {
|
value: function getRow(rowIndex) {
|
||||||
return this.data.rows.find(function (row) {
|
return this.data.rows.find(function (row) {
|
||||||
return row[0].row_index === rowIndex;
|
return row[0].rowIndex === rowIndex;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: 'getColumnHeaderElement',
|
||||||
|
value: function getColumnHeaderElement(colIndex) {
|
||||||
|
if (colIndex < 0) return null;
|
||||||
|
return this.wrapper.find('.data-table-col[data-is-header][data-col-index="' + colIndex + '"]');
|
||||||
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
return ReGrid;
|
return ReGrid;
|
||||||
@ -557,6 +652,10 @@ function prepareRows(rows) {
|
|||||||
return rows.map(prepareRow);
|
return rows.map(prepareRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDefault(a, b) {
|
||||||
|
return a !== undefined ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
exports.default = {
|
exports.default = {
|
||||||
getHeaderHTML: getHeaderHTML,
|
getHeaderHTML: getHeaderHTML,
|
||||||
getBodyHTML: getBodyHTML,
|
getBodyHTML: getBodyHTML,
|
||||||
@ -564,7 +663,8 @@ exports.default = {
|
|||||||
getColumnHTML: getColumnHTML,
|
getColumnHTML: getColumnHTML,
|
||||||
prepareRowHeader: prepareRowHeader,
|
prepareRowHeader: prepareRowHeader,
|
||||||
prepareRows: prepareRows,
|
prepareRows: prepareRows,
|
||||||
makeDataAttributeString: makeDataAttributeString
|
makeDataAttributeString: makeDataAttributeString,
|
||||||
|
getDefault: getDefault
|
||||||
};
|
};
|
||||||
module.exports = exports['default'];
|
module.exports = exports['default'];
|
||||||
|
|
||||||
@ -11409,6 +11509,340 @@ module.exports = function (css) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
/* 9 */
|
||||||
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
/*! Clusterize.js - v0.17.6 - 2017-03-05
|
||||||
|
* http://NeXTs.github.com/Clusterize.js/
|
||||||
|
* Copyright (c) 2015 Denis Lukov; Licensed GPLv3 */
|
||||||
|
|
||||||
|
;(function(name, definition) {
|
||||||
|
if (true) module.exports = definition();
|
||||||
|
else if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
|
||||||
|
else this[name] = definition();
|
||||||
|
}('Clusterize', function() {
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
// detect ie9 and lower
|
||||||
|
// https://gist.github.com/padolsey/527683#comment-786682
|
||||||
|
var ie = (function(){
|
||||||
|
for( var v = 3,
|
||||||
|
el = document.createElement('b'),
|
||||||
|
all = el.all || [];
|
||||||
|
el.innerHTML = '<!--[if gt IE ' + (++v) + ']><i><![endif]-->',
|
||||||
|
all[0];
|
||||||
|
){}
|
||||||
|
return v > 4 ? v : document.documentMode;
|
||||||
|
}()),
|
||||||
|
is_mac = navigator.platform.toLowerCase().indexOf('mac') + 1;
|
||||||
|
var Clusterize = function(data) {
|
||||||
|
if( ! (this instanceof Clusterize))
|
||||||
|
return new Clusterize(data);
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var defaults = {
|
||||||
|
rows_in_block: 50,
|
||||||
|
blocks_in_cluster: 4,
|
||||||
|
tag: null,
|
||||||
|
show_no_data_row: true,
|
||||||
|
no_data_class: 'clusterize-no-data',
|
||||||
|
no_data_text: 'No data',
|
||||||
|
keep_parity: true,
|
||||||
|
callbacks: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// public parameters
|
||||||
|
self.options = {};
|
||||||
|
var options = ['rows_in_block', 'blocks_in_cluster', 'show_no_data_row', 'no_data_class', 'no_data_text', 'keep_parity', 'tag', 'callbacks'];
|
||||||
|
for(var i = 0, option; option = options[i]; i++) {
|
||||||
|
self.options[option] = typeof data[option] != 'undefined' && data[option] != null
|
||||||
|
? data[option]
|
||||||
|
: defaults[option];
|
||||||
|
}
|
||||||
|
|
||||||
|
var elems = ['scroll', 'content'];
|
||||||
|
for(var i = 0, elem; elem = elems[i]; i++) {
|
||||||
|
self[elem + '_elem'] = data[elem + 'Id']
|
||||||
|
? document.getElementById(data[elem + 'Id'])
|
||||||
|
: data[elem + 'Elem'];
|
||||||
|
if( ! self[elem + '_elem'])
|
||||||
|
throw new Error("Error! Could not find " + elem + " element");
|
||||||
|
}
|
||||||
|
|
||||||
|
// tabindex forces the browser to keep focus on the scrolling list, fixes #11
|
||||||
|
if( ! self.content_elem.hasAttribute('tabindex'))
|
||||||
|
self.content_elem.setAttribute('tabindex', 0);
|
||||||
|
|
||||||
|
// private parameters
|
||||||
|
var rows = isArray(data.rows)
|
||||||
|
? data.rows
|
||||||
|
: self.fetchMarkup(),
|
||||||
|
cache = {},
|
||||||
|
scroll_top = self.scroll_elem.scrollTop;
|
||||||
|
|
||||||
|
// append initial data
|
||||||
|
self.insertToDOM(rows, cache);
|
||||||
|
|
||||||
|
// restore the scroll position
|
||||||
|
self.scroll_elem.scrollTop = scroll_top;
|
||||||
|
|
||||||
|
// adding scroll handler
|
||||||
|
var last_cluster = false,
|
||||||
|
scroll_debounce = 0,
|
||||||
|
pointer_events_set = false,
|
||||||
|
scrollEv = function() {
|
||||||
|
// fixes scrolling issue on Mac #3
|
||||||
|
if (is_mac) {
|
||||||
|
if( ! pointer_events_set) self.content_elem.style.pointerEvents = 'none';
|
||||||
|
pointer_events_set = true;
|
||||||
|
clearTimeout(scroll_debounce);
|
||||||
|
scroll_debounce = setTimeout(function () {
|
||||||
|
self.content_elem.style.pointerEvents = 'auto';
|
||||||
|
pointer_events_set = false;
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
if (last_cluster != (last_cluster = self.getClusterNum()))
|
||||||
|
self.insertToDOM(rows, cache);
|
||||||
|
if (self.options.callbacks.scrollingProgress)
|
||||||
|
self.options.callbacks.scrollingProgress(self.getScrollProgress());
|
||||||
|
},
|
||||||
|
resize_debounce = 0,
|
||||||
|
resizeEv = function() {
|
||||||
|
clearTimeout(resize_debounce);
|
||||||
|
resize_debounce = setTimeout(self.refresh, 100);
|
||||||
|
}
|
||||||
|
on('scroll', self.scroll_elem, scrollEv);
|
||||||
|
on('resize', window, resizeEv);
|
||||||
|
|
||||||
|
// public methods
|
||||||
|
self.destroy = function(clean) {
|
||||||
|
off('scroll', self.scroll_elem, scrollEv);
|
||||||
|
off('resize', window, resizeEv);
|
||||||
|
self.html((clean ? self.generateEmptyRow() : rows).join(''));
|
||||||
|
}
|
||||||
|
self.refresh = function(force) {
|
||||||
|
if(self.getRowsHeight(rows) || force) self.update(rows);
|
||||||
|
}
|
||||||
|
self.update = function(new_rows) {
|
||||||
|
rows = isArray(new_rows)
|
||||||
|
? new_rows
|
||||||
|
: [];
|
||||||
|
var scroll_top = self.scroll_elem.scrollTop;
|
||||||
|
// fixes #39
|
||||||
|
if(rows.length * self.options.item_height < scroll_top) {
|
||||||
|
self.scroll_elem.scrollTop = 0;
|
||||||
|
last_cluster = 0;
|
||||||
|
}
|
||||||
|
self.insertToDOM(rows, cache);
|
||||||
|
self.scroll_elem.scrollTop = scroll_top;
|
||||||
|
}
|
||||||
|
self.clear = function() {
|
||||||
|
self.update([]);
|
||||||
|
}
|
||||||
|
self.getRowsAmount = function() {
|
||||||
|
return rows.length;
|
||||||
|
}
|
||||||
|
self.getScrollProgress = function() {
|
||||||
|
return this.options.scroll_top / (rows.length * this.options.item_height) * 100 || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var add = function(where, _new_rows) {
|
||||||
|
var new_rows = isArray(_new_rows)
|
||||||
|
? _new_rows
|
||||||
|
: [];
|
||||||
|
if( ! new_rows.length) return;
|
||||||
|
rows = where == 'append'
|
||||||
|
? rows.concat(new_rows)
|
||||||
|
: new_rows.concat(rows);
|
||||||
|
self.insertToDOM(rows, cache);
|
||||||
|
}
|
||||||
|
self.append = function(rows) {
|
||||||
|
add('append', rows);
|
||||||
|
}
|
||||||
|
self.prepend = function(rows) {
|
||||||
|
add('prepend', rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Clusterize.prototype = {
|
||||||
|
constructor: Clusterize,
|
||||||
|
// fetch existing markup
|
||||||
|
fetchMarkup: function() {
|
||||||
|
var rows = [], rows_nodes = this.getChildNodes(this.content_elem);
|
||||||
|
while (rows_nodes.length) {
|
||||||
|
rows.push(rows_nodes.shift().outerHTML);
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
},
|
||||||
|
// get tag name, content tag name, tag height, calc cluster height
|
||||||
|
exploreEnvironment: function(rows, cache) {
|
||||||
|
var opts = this.options;
|
||||||
|
opts.content_tag = this.content_elem.tagName.toLowerCase();
|
||||||
|
if( ! rows.length) return;
|
||||||
|
if(ie && ie <= 9 && ! opts.tag) opts.tag = rows[0].match(/<([^>\s/]*)/)[1].toLowerCase();
|
||||||
|
if(this.content_elem.children.length <= 1) cache.data = this.html(rows[0] + rows[0] + rows[0]);
|
||||||
|
if( ! opts.tag) opts.tag = this.content_elem.children[0].tagName.toLowerCase();
|
||||||
|
this.getRowsHeight(rows);
|
||||||
|
},
|
||||||
|
getRowsHeight: function(rows) {
|
||||||
|
var opts = this.options,
|
||||||
|
prev_item_height = opts.item_height;
|
||||||
|
opts.cluster_height = 0;
|
||||||
|
if( ! rows.length) return;
|
||||||
|
var nodes = this.content_elem.children;
|
||||||
|
var node = nodes[Math.floor(nodes.length / 2)];
|
||||||
|
opts.item_height = node.offsetHeight;
|
||||||
|
// consider table's border-spacing
|
||||||
|
if(opts.tag == 'tr' && getStyle('borderCollapse', this.content_elem) != 'collapse')
|
||||||
|
opts.item_height += parseInt(getStyle('borderSpacing', this.content_elem), 10) || 0;
|
||||||
|
// consider margins (and margins collapsing)
|
||||||
|
if(opts.tag != 'tr') {
|
||||||
|
var marginTop = parseInt(getStyle('marginTop', node), 10) || 0;
|
||||||
|
var marginBottom = parseInt(getStyle('marginBottom', node), 10) || 0;
|
||||||
|
opts.item_height += Math.max(marginTop, marginBottom);
|
||||||
|
}
|
||||||
|
opts.block_height = opts.item_height * opts.rows_in_block;
|
||||||
|
opts.rows_in_cluster = opts.blocks_in_cluster * opts.rows_in_block;
|
||||||
|
opts.cluster_height = opts.blocks_in_cluster * opts.block_height;
|
||||||
|
return prev_item_height != opts.item_height;
|
||||||
|
},
|
||||||
|
// get current cluster number
|
||||||
|
getClusterNum: function () {
|
||||||
|
this.options.scroll_top = this.scroll_elem.scrollTop;
|
||||||
|
return Math.floor(this.options.scroll_top / (this.options.cluster_height - this.options.block_height)) || 0;
|
||||||
|
},
|
||||||
|
// generate empty row if no data provided
|
||||||
|
generateEmptyRow: function() {
|
||||||
|
var opts = this.options;
|
||||||
|
if( ! opts.tag || ! opts.show_no_data_row) return [];
|
||||||
|
var empty_row = document.createElement(opts.tag),
|
||||||
|
no_data_content = document.createTextNode(opts.no_data_text), td;
|
||||||
|
empty_row.className = opts.no_data_class;
|
||||||
|
if(opts.tag == 'tr') {
|
||||||
|
td = document.createElement('td');
|
||||||
|
// fixes #53
|
||||||
|
td.colSpan = 100;
|
||||||
|
td.appendChild(no_data_content);
|
||||||
|
}
|
||||||
|
empty_row.appendChild(td || no_data_content);
|
||||||
|
return [empty_row.outerHTML];
|
||||||
|
},
|
||||||
|
// generate cluster for current scroll position
|
||||||
|
generate: function (rows, cluster_num) {
|
||||||
|
var opts = this.options,
|
||||||
|
rows_len = rows.length;
|
||||||
|
if (rows_len < opts.rows_in_block) {
|
||||||
|
return {
|
||||||
|
top_offset: 0,
|
||||||
|
bottom_offset: 0,
|
||||||
|
rows_above: 0,
|
||||||
|
rows: rows_len ? rows : this.generateEmptyRow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var items_start = Math.max((opts.rows_in_cluster - opts.rows_in_block) * cluster_num, 0),
|
||||||
|
items_end = items_start + opts.rows_in_cluster,
|
||||||
|
top_offset = Math.max(items_start * opts.item_height, 0),
|
||||||
|
bottom_offset = Math.max((rows_len - items_end) * opts.item_height, 0),
|
||||||
|
this_cluster_rows = [],
|
||||||
|
rows_above = items_start;
|
||||||
|
if(top_offset < 1) {
|
||||||
|
rows_above++;
|
||||||
|
}
|
||||||
|
for (var i = items_start; i < items_end; i++) {
|
||||||
|
rows[i] && this_cluster_rows.push(rows[i]);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
top_offset: top_offset,
|
||||||
|
bottom_offset: bottom_offset,
|
||||||
|
rows_above: rows_above,
|
||||||
|
rows: this_cluster_rows
|
||||||
|
}
|
||||||
|
},
|
||||||
|
renderExtraTag: function(class_name, height) {
|
||||||
|
var tag = document.createElement(this.options.tag),
|
||||||
|
clusterize_prefix = 'clusterize-';
|
||||||
|
tag.className = [clusterize_prefix + 'extra-row', clusterize_prefix + class_name].join(' ');
|
||||||
|
height && (tag.style.height = height + 'px');
|
||||||
|
return tag.outerHTML;
|
||||||
|
},
|
||||||
|
// if necessary verify data changed and insert to DOM
|
||||||
|
insertToDOM: function(rows, cache) {
|
||||||
|
// explore row's height
|
||||||
|
if( ! this.options.cluster_height) {
|
||||||
|
this.exploreEnvironment(rows, cache);
|
||||||
|
}
|
||||||
|
var data = this.generate(rows, this.getClusterNum()),
|
||||||
|
this_cluster_rows = data.rows.join(''),
|
||||||
|
this_cluster_content_changed = this.checkChanges('data', this_cluster_rows, cache),
|
||||||
|
top_offset_changed = this.checkChanges('top', data.top_offset, cache),
|
||||||
|
only_bottom_offset_changed = this.checkChanges('bottom', data.bottom_offset, cache),
|
||||||
|
callbacks = this.options.callbacks,
|
||||||
|
layout = [];
|
||||||
|
|
||||||
|
if(this_cluster_content_changed || top_offset_changed) {
|
||||||
|
if(data.top_offset) {
|
||||||
|
this.options.keep_parity && layout.push(this.renderExtraTag('keep-parity'));
|
||||||
|
layout.push(this.renderExtraTag('top-space', data.top_offset));
|
||||||
|
}
|
||||||
|
layout.push(this_cluster_rows);
|
||||||
|
data.bottom_offset && layout.push(this.renderExtraTag('bottom-space', data.bottom_offset));
|
||||||
|
callbacks.clusterWillChange && callbacks.clusterWillChange();
|
||||||
|
this.html(layout.join(''));
|
||||||
|
this.options.content_tag == 'ol' && this.content_elem.setAttribute('start', data.rows_above);
|
||||||
|
callbacks.clusterChanged && callbacks.clusterChanged();
|
||||||
|
} else if(only_bottom_offset_changed) {
|
||||||
|
this.content_elem.lastChild.style.height = data.bottom_offset + 'px';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// unfortunately ie <= 9 does not allow to use innerHTML for table elements, so make a workaround
|
||||||
|
html: function(data) {
|
||||||
|
var content_elem = this.content_elem;
|
||||||
|
if(ie && ie <= 9 && this.options.tag == 'tr') {
|
||||||
|
var div = document.createElement('div'), last;
|
||||||
|
div.innerHTML = '<table><tbody>' + data + '</tbody></table>';
|
||||||
|
while((last = content_elem.lastChild)) {
|
||||||
|
content_elem.removeChild(last);
|
||||||
|
}
|
||||||
|
var rows_nodes = this.getChildNodes(div.firstChild.firstChild);
|
||||||
|
while (rows_nodes.length) {
|
||||||
|
content_elem.appendChild(rows_nodes.shift());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
content_elem.innerHTML = data;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getChildNodes: function(tag) {
|
||||||
|
var child_nodes = tag.children, nodes = [];
|
||||||
|
for (var i = 0, ii = child_nodes.length; i < ii; i++) {
|
||||||
|
nodes.push(child_nodes[i]);
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
},
|
||||||
|
checkChanges: function(type, value, cache) {
|
||||||
|
var changed = value != cache[type];
|
||||||
|
cache[type] = value;
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// support functions
|
||||||
|
function on(evt, element, fnc) {
|
||||||
|
return element.addEventListener ? element.addEventListener(evt, fnc, false) : element.attachEvent("on" + evt, fnc);
|
||||||
|
}
|
||||||
|
function off(evt, element, fnc) {
|
||||||
|
return element.removeEventListener ? element.removeEventListener(evt, fnc, false) : element.detachEvent("on" + evt, fnc);
|
||||||
|
}
|
||||||
|
function isArray(arr) {
|
||||||
|
return Object.prototype.toString.call(arr) === '[object Array]';
|
||||||
|
}
|
||||||
|
function getStyle(prop, elem) {
|
||||||
|
return window.getComputedStyle ? window.getComputedStyle(elem)[prop] : elem.currentStyle[prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Clusterize;
|
||||||
|
}));
|
||||||
|
|
||||||
/***/ })
|
/***/ })
|
||||||
/******/ ]);
|
/******/ ]);
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -48,6 +48,7 @@
|
|||||||
"homepage": "https://github.com/netchampfaris/regrid",
|
"homepage": "https://github.com/netchampfaris/regrid",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "^4.0.0-beta",
|
"bootstrap": "^4.0.0-beta",
|
||||||
|
"clusterize.js": "^0.17.6",
|
||||||
"popper.js": "^1.12.5"
|
"popper.js": "^1.12.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,27 @@
|
|||||||
import {
|
import {
|
||||||
getHeaderHTML,
|
getHeaderHTML,
|
||||||
getBodyHTML,
|
getBodyHTML,
|
||||||
|
getRowHTML,
|
||||||
getColumnHTML,
|
getColumnHTML,
|
||||||
prepareRowHeader,
|
prepareRowHeader,
|
||||||
prepareRows,
|
prepareRows,
|
||||||
getDefault
|
getDefault
|
||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
import $ from 'jQuery';
|
import $ from 'jQuery';
|
||||||
|
import Clusterize from 'clusterize.js';
|
||||||
|
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
export default class ReGrid {
|
export default class ReGrid {
|
||||||
constructor({ wrapper, events, data, addSerialNoColumn }) {
|
constructor({ wrapper, events, data, addSerialNoColumn, enableClusterize }) {
|
||||||
this.wrapper = $(wrapper);
|
this.wrapper = $(wrapper);
|
||||||
if (this.wrapper.length === 0) {
|
if (this.wrapper.length === 0) {
|
||||||
throw new Error('Invalid argument given for `wrapper`');
|
throw new Error('Invalid argument given for `wrapper`');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.events = getDefault(events, {});
|
this.events = getDefault(events, {});
|
||||||
this.addSerialNoColumn = getDefault(addSerialNoColumn, 0);
|
this.addSerialNoColumn = getDefault(addSerialNoColumn, false);
|
||||||
|
this.enableClusterize = getDefault(enableClusterize, false);
|
||||||
|
|
||||||
this.makeDom();
|
this.makeDom();
|
||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
@ -56,7 +59,11 @@ export default class ReGrid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.renderHeader();
|
this.renderHeader();
|
||||||
this.renderBody();
|
if (this.enableClusterize) {
|
||||||
|
this.renderBodyWithClusterize();
|
||||||
|
} else {
|
||||||
|
this.renderBody();
|
||||||
|
}
|
||||||
this.setDimensions();
|
this.setDimensions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,6 +81,25 @@ export default class ReGrid {
|
|||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderBodyWithClusterize() {
|
||||||
|
// empty body
|
||||||
|
this.bodyScrollable.html(`
|
||||||
|
<table class="data-table-body table table-bordered">
|
||||||
|
${getBodyHTML([])}
|
||||||
|
</table>
|
||||||
|
`);
|
||||||
|
|
||||||
|
const data = this.data.rows.map(
|
||||||
|
(row) => getRowHTML(row, { rowIndex: row[0].rowIndex })
|
||||||
|
);
|
||||||
|
|
||||||
|
this.clusterize = new Clusterize({
|
||||||
|
rows: data,
|
||||||
|
scrollElem: this.bodyScrollable.get(0),
|
||||||
|
contentElem: this.bodyScrollable.find('tbody').get(0)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
updateCell(rowIndex, colIndex, value) {
|
updateCell(rowIndex, colIndex, value) {
|
||||||
const row = this.getRow(rowIndex);
|
const row = this.getRow(rowIndex);
|
||||||
const cell = row.find(cell => cell.col_index === colIndex);
|
const cell = row.find(cell => cell.col_index === colIndex);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user