aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/components/helpers
diff options
context:
space:
mode:
authorJason <jason.daurus@gmail.com>2016-03-10 21:40:07 +0800
committerJason <jason.daurus@gmail.com>2016-03-10 21:40:07 +0800
commit1c0496e051d8b1af297138732475b1689ada5eb8 (patch)
tree7a2134ac48cce29694313e5a5b3105f2cf7e93ff /web/src/js/components/helpers
parentb413a052f96896d387f58e903203cf2e29c6f1f6 (diff)
downloadmitmproxy-1c0496e051d8b1af297138732475b1689ada5eb8.tar.gz
mitmproxy-1c0496e051d8b1af297138732475b1689ada5eb8.tar.bz2
mitmproxy-1c0496e051d8b1af297138732475b1689ada5eb8.zip
[web] VirtualScroll and AutoScroll helper
Diffstat (limited to 'web/src/js/components/helpers')
-rw-r--r--web/src/js/components/helpers/AutoScroll.js25
-rw-r--r--web/src/js/components/helpers/VirtualScroll.js70
2 files changed, 95 insertions, 0 deletions
diff --git a/web/src/js/components/helpers/AutoScroll.js b/web/src/js/components/helpers/AutoScroll.js
new file mode 100644
index 00000000..d37b9f37
--- /dev/null
+++ b/web/src/js/components/helpers/AutoScroll.js
@@ -0,0 +1,25 @@
+import React from "react";
+import ReactDOM from "react-dom";
+
+const symShouldStick = Symbol("shouldStick");
+const isAtBottom = v => v.scrollTop + v.clientHeight === v.scrollHeight;
+
+export default Component => Object.assign(class AutoScrollWrapper extends Component {
+
+ static displayName = Component.name;
+
+ componentWillUpdate() {
+ const viewport = ReactDOM.findDOMNode(this);
+ this[symShouldStick] = viewport.scrollTop && isAtBottom(viewport);
+ super.componentWillUpdate && super.componentWillUpdate();
+ }
+
+ componentDidUpdate() {
+ const viewport = ReactDOM.findDOMNode(this);
+ if (this[symShouldStick] && !isAtBottom(viewport)) {
+ viewport.scrollTop = viewport.scrollHeight;
+ }
+ super.componentDidUpdate && super.componentDidUpdate();
+ }
+
+}, Component);
diff --git a/web/src/js/components/helpers/VirtualScroll.js b/web/src/js/components/helpers/VirtualScroll.js
new file mode 100644
index 00000000..5d4cf796
--- /dev/null
+++ b/web/src/js/components/helpers/VirtualScroll.js
@@ -0,0 +1,70 @@
+/**
+ * Calculate virtual scroll stuffs
+ *
+ * @param {?Object} opts Options for calculation
+ *
+ * @returns {Object} result
+ *
+ * __opts__ should have following properties:
+ * - {number} itemCount
+ * - {number} rowHeight
+ * - {number} viewportTop
+ * - {number} viewportHeight
+ * - {Array<?number>} [itemHeights]
+ *
+ * __result__ have following properties:
+ * - {number} start
+ * - {number} end
+ * - {number} paddingTop
+ * - {number} paddingBottom
+ */
+export function calcVScroll(opts) {
+ if (!opts) {
+ return { start: 0, end: 0, paddingTop: 0, paddingBottom: 0 };
+ }
+
+ const { itemCount, rowHeight, viewportTop, viewportHeight, itemHeights } = opts;
+ const viewportBottom = viewportTop + viewportHeight;
+
+ let start = 0;
+ let end = 0;
+
+ let paddingTop = 0;
+ let paddingBottom = 0;
+
+ if (itemHeights) {
+
+ for (let i = 0, pos = 0; i < itemCount; i++) {
+ const height = itemHeights[i] || rowHeight;
+
+ if (pos <= viewportTop && i % 2 === 0) {
+ paddingTop = pos;
+ start = i;
+ }
+
+ if (pos <= viewportBottom) {
+ end = i + 1;
+ } else {
+ paddingBottom += height;
+ }
+
+ pos += height;
+ }
+
+ } else {
+
+ // Make sure that we start at an even row so that CSS `:nth-child(even)` is preserved
+ start = Math.max(0, Math.floor(viewportTop / rowHeight) - 1) & ~1;
+ end = Math.min(
+ itemCount,
+ start + Math.ceil(viewportHeight / rowHeight) + 1
+ );
+
+ // 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.
+ paddingTop = Math.min(start, itemCount) * rowHeight;
+ paddingBottom = Math.max(0, itemCount - end) * rowHeight;
+ }
+
+ return { start, end, paddingTop, paddingBottom };
+}