aboutsummaryrefslogtreecommitdiffstats
path: root/mitmproxy/web/src/js/components/virtualscroll.js
diff options
context:
space:
mode:
Diffstat (limited to 'mitmproxy/web/src/js/components/virtualscroll.js')
-rw-r--r--mitmproxy/web/src/js/components/virtualscroll.js85
1 files changed, 85 insertions, 0 deletions
diff --git a/mitmproxy/web/src/js/components/virtualscroll.js b/mitmproxy/web/src/js/components/virtualscroll.js
new file mode 100644
index 00000000..956e1a0b
--- /dev/null
+++ b/mitmproxy/web/src/js/components/virtualscroll.js
@@ -0,0 +1,85 @@
+var React = require("react");
+
+var VirtualScrollMixin = {
+ getInitialState: function () {
+ return {
+ start: 0,
+ stop: 0
+ };
+ },
+ componentWillMount: function () {
+ if (!this.props.rowHeight) {
+ console.warn("VirtualScrollMixin: No rowHeight specified", this);
+ }
+ },
+ getPlaceholderTop: function (total) {
+ var Tag = this.props.placeholderTagName || "tr";
+ // When a large trunk of elements is removed from the button, start may be far off the viewport.
+ // To make this issue less severe, limit the top placeholder to the total number of rows.
+ var style = {
+ height: Math.min(this.state.start, total) * this.props.rowHeight
+ };
+ var spacer = <Tag key="placeholder-top" style={style}></Tag>;
+
+ if (this.state.start % 2 === 1) {
+ // fix even/odd rows
+ return [spacer, <Tag key="placeholder-top-2"></Tag>];
+ } else {
+ return spacer;
+ }
+ },
+ getPlaceholderBottom: function (total) {
+ var Tag = this.props.placeholderTagName || "tr";
+ var style = {
+ height: Math.max(0, total - this.state.stop) * this.props.rowHeight
+ };
+ return <Tag key="placeholder-bottom" style={style}></Tag>;
+ },
+ componentDidMount: function () {
+ this.onScroll();
+ window.addEventListener('resize', this.onScroll);
+ },
+ componentWillUnmount: function(){
+ window.removeEventListener('resize', this.onScroll);
+ },
+ onScroll: function () {
+ var viewport = this.getDOMNode();
+ var top = viewport.scrollTop;
+ var height = viewport.offsetHeight;
+ var start = Math.floor(top / this.props.rowHeight);
+ var stop = start + Math.ceil(height / (this.props.rowHeightMin || this.props.rowHeight));
+
+ this.setState({
+ start: start,
+ stop: stop
+ });
+ },
+ renderRows: function (elems) {
+ var rows = [];
+ var max = Math.min(elems.length, this.state.stop);
+
+ for (var i = this.state.start; i < max; i++) {
+ var elem = elems[i];
+ rows.push(this.renderRow(elem));
+ }
+ return rows;
+ },
+ scrollRowIntoView: function (index, head_height) {
+
+ var row_top = (index * this.props.rowHeight) + head_height;
+ var row_bottom = row_top + this.props.rowHeight;
+
+ var viewport = this.getDOMNode();
+ var viewport_top = viewport.scrollTop;
+ var viewport_bottom = viewport_top + viewport.offsetHeight;
+
+ // Account for pinned thead
+ if (row_top - head_height < viewport_top) {
+ viewport.scrollTop = row_top - head_height;
+ } else if (row_bottom > viewport_bottom) {
+ viewport.scrollTop = row_bottom - viewport.offsetHeight;
+ }
+ },
+};
+
+module.exports = VirtualScrollMixin; \ No newline at end of file