From fee3821a95072ae31dbe7d79ef9e032040ef7738 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 4 Mar 2021 10:06:31 -0500
Subject: fixed dynamic updating of equations and functions when underlying
 data cahnges.

---
 src/client/views/nodes/FunctionPlotBox.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/nodes/FunctionPlotBox.tsx')

diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index f35677014..9094651f3 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -33,7 +33,7 @@ export class FunctionPlotBox extends ViewBoxBaseComponent<FieldViewProps, Equati
     }
     componentDidMount() {
         this.props.setContentView?.(this);
-        reaction(() => [DocListCast(this.dataDoc.data).lastElement()?.text, this.dataDoc.xRange, this.dataDoc.yRange],
+        reaction(() => [DocListCast(this.dataDoc.data).lastElement()?.text, this.layoutDoc.width, this.layoutDoc.height, this.dataDoc.xRange, this.dataDoc.yRange],
             () => this.createGraph());
     }
     getAnchor = () => {
-- 
cgit v1.2.3-70-g09d2


From 47e0c97b04a67b3bad1f2c789145a92ba7069f1e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 4 Mar 2021 20:22:00 -0500
Subject: fixed scrolling of web pages and fitwidth for web pages.

---
 src/Utils.ts                               |  24 +++++--
 src/client/views/nodes/EquationBox.tsx     |   1 -
 src/client/views/nodes/FunctionPlotBox.tsx |   1 -
 src/client/views/nodes/WebBox.tsx          | 101 ++++++++++++++++++++---------
 4 files changed, 88 insertions(+), 39 deletions(-)

(limited to 'src/client/views/nodes/FunctionPlotBox.tsx')

diff --git a/src/Utils.ts b/src/Utils.ts
index b6a59118a..f22df0da2 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -482,20 +482,30 @@ const easeInOutQuad = (currentTime: number, start: number, change: number, durat
     return (-change / 2) * (newCurrentTime * (newCurrentTime - 2) - 1) + start;
 };
 
-export function smoothScroll(duration: number, element: HTMLElement, to: number, finish?: () => void) {
-    const start = element.scrollTop;
-    const change = to - start;
-    const startDate = new Date().getTime();
+export function smoothScroll(duration: number, element: HTMLElement | HTMLElement[], to: number, finish?: () => void, reset?: { resetGoTo: { to: number, duration: number } | undefined }) {
+    const elements = (element instanceof HTMLElement ? [element] : element);
+    let starts = elements.map(element => element.scrollTop);
+    let startDate = new Date().getTime();
 
     const animateScroll = () => {
         const currentDate = new Date().getTime();
-        const currentTime = currentDate - startDate;
-        element.scrollTop = easeInOutQuad(currentTime, start, change, duration);
+        let currentTime = currentDate - startDate;
+        const resetParams = reset?.resetGoTo;
+        if (resetParams) {
+            reset!.resetGoTo = undefined;
+            const { to: newTo, duration: newDuration } = resetParams;
+            to = newTo;
+            starts = starts.map(start => easeInOutQuad(currentTime, start, to - start, duration));
+            startDate = currentDate;
+            duration = newDuration;
+            currentTime = currentDate - startDate;
+        }
+        elements.map((element, i) => element.scrollTop = easeInOutQuad(currentTime, starts[i], to - starts[i], duration));
 
         if (currentTime < duration) {
             requestAnimationFrame(animateScroll);
         } else {
-            element.scrollTop = to;
+            elements.forEach(element => element.scrollTop = to);
             finish?.();
         }
     };
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index a8c5430a9..64e1e9c72 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -84,7 +84,6 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps, EquationDo
     }
     render() {
         TraceMobx();
-        console.log("eqn" + this.dataDoc.text)
         return (<div onPointerDown={e => !e.ctrlKey && e.stopPropagation()}
             style={{
                 pointerEvents: !this.props.isSelected() ? "none" : undefined,
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index 9094651f3..e8bec9676 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -57,7 +57,6 @@ export class FunctionPlotBox extends ViewBoxBaseComponent<FieldViewProps, Equati
         const width = this.props.PanelWidth();
         const height = this.props.PanelHeight();
         const fn = StrCast(DocListCast(this.dataDoc.data).lastElement()?.text, "x^2").replace(/\\frac\{(.*)\}\{(.*)\}/, "($1/$2)");
-        console.log("Graphing:" + fn);
         try {
             this._plot = functionPlot({
                 target: "#" + this._plotEle.id,
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 0cf052501..156fe64c9 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -26,11 +26,11 @@ import { ViewBoxAnnotatableComponent } from "../DocComponent";
 import { DocumentDecorations } from "../DocumentDecorations";
 import { MarqueeAnnotator } from "../MarqueeAnnotator";
 import { Annotation } from "../pdf/Annotation";
-import { DocAfterFocusFunc } from "./DocumentView";
 import { FieldView, FieldViewProps } from './FieldView';
+import { LinkDocPreview } from "./LinkDocPreview";
 import "./WebBox.scss";
+import { DocumentType } from '../../documents/DocumentTypes';
 import React = require("react");
-import { LinkDocPreview } from "./LinkDocPreview";
 const htmlToText = require("html-to-text");
 
 type WebDocument = makeInterface<[typeof documentSchema]>;
@@ -47,7 +47,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
     private _iframeIndicatorRef = React.createRef<HTMLDivElement>();
     private _iframeDragRef = React.createRef<HTMLDivElement>();
     private _keyInput = React.createRef<HTMLInputElement>();
-    private _ignoreScroll = false;
+    private _ignoreScroll = "";
+    private _scrollTimer: any;
     private _initialScroll: Opt<number>;
     @observable private _marqueeing: number[] | undefined;
     @observable private _url: string = "hello";
@@ -90,41 +91,63 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                 }
             })));
             iframe.contentDocument.addEventListener('wheel', this.iframeWheel, false);
+            iframe.contentDocument.addEventListener('scroll', this.iframeScroll, false);
         }
     }
 
-    @action
-    onWheelScroll = (scrollTop: number) => {
-        if (this.webpage && this._outerRef.current) {
-            this.webpage.scrollLeft = 0;
-            this._outerRef.current.scrollTop = scrollTop;
-            this._outerRef.current.scrollLeft = 0;
-            this._ignoreScroll = true;
-            if (this.layoutDoc._scrollTop !== scrollTop) {
-                this.layoutDoc._scrollTop = scrollTop;
-            }
-            this._ignoreScroll = false;
-        }
+    resetIgnoreScroll = () => {
+        this._scrollTimer && clearTimeout(this._scrollTimer);
+        this._scrollTimer = setTimeout(() => {
+            this._scrollTimer = undefined;
+            this._ignoreScroll = "";
+        }, 250);
+        this._outerRef.current && (this._outerRef.current.scrollLeft = 0);
+    }
+    iframeWheel = (e: any) => {
+        this._ignoreScroll = "iframe";
+        this.resetIgnoreScroll();
+        e.stopPropagation();
+    }
+    onWebWheel = (e: React.WheelEvent) => {
+        this._ignoreScroll = "iframe";
+        this.goTo(Math.max(0, (this.webpage?.scrollTop || 0) + (this._accumulatedGoTo + 1) * e.deltaY), 100);
+        this.resetIgnoreScroll();
+        e.stopPropagation();
     }
-    iframeWheel = (e: any) => this.webpage && e.target?.children && this.onWheelScroll(this.webpage.scrollTop);
     onWheel = (e: React.WheelEvent) => {
-        this._outerRef.current && this.onWheelScroll(this._outerRef.current.scrollTop);
+        this._ignoreScroll = "outer";
+        this.resetIgnoreScroll();
         e.stopPropagation();
     }
-
-    getAnchor = () => this.rootDoc;
+    iframeScroll = (e: any) => {
+        if (!this._ignoreScroll.includes("outer") && this._outerRef.current) {
+            this._outerRef.current.scrollTop = this.webpage?.scrollTop || 0;
+            this.layoutDoc._scrollTop = this.webpage?.scrollTop;
+        }
+    }
+    onScroll = (e: any) => {
+        if (!this._ignoreScroll.includes("iframe") && this.webpage) {
+            this.webpage.scrollTop = this._outerRef.current?.scrollTop || 0;
+            this.layoutDoc._scrollTop = this._outerRef.current?.scrollTop;
+        }
+    }
     scrollFocus = (doc: Doc, smooth: boolean) => {
         let focusSpeed: Opt<number>;
         if (doc !== this.rootDoc && this.webpage && this._outerRef.current) {
-            const scrollTo = Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.layoutDoc._scrollTop), this.props.PanelHeight() / (this.props.scaling?.() || 1));
+            const scrollTo = doc.type === DocumentType.TEXTANCHOR ? NumCast(doc.y) : Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.layoutDoc._scrollTop), this.props.PanelHeight() / (this.props.scaling?.() || 1));
             if (scrollTo !== undefined) {
                 this._initialScroll !== undefined && (this._initialScroll = scrollTo);
-                this._ignoreScroll = true;
-                this.goTo(scrollTo, focusSpeed = smooth ? 500 : 0);
                 if (!LinkDocPreview.LinkInfo) {
+                    this._ignoreScroll = "iframe|outer";
                     this.layoutDoc._scrollTop = scrollTo;
+                    this._ignoreScroll = "";
                 }
-                this._ignoreScroll = false;
+                this._ignoreScroll = "iframe|outer";
+                this.goTo(scrollTo, focusSpeed = smooth ? 500 : 0);
+                setTimeout(() => {
+                    this._scrollTimer = undefined;
+                    this._ignoreScroll = "";
+                }, focusSpeed);
             }
         } else {
             this._initialScroll = NumCast(doc.y);
@@ -133,6 +156,18 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
         return focusSpeed;
     }
 
+    getAnchor = () => {
+        const anchor = Docs.Create.TextanchorDocument({
+            title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop),
+            useLinkSmallAnchor: true,
+            hideLinkButton: true,
+            annotationOn: this.rootDoc,
+            y: NumCast(this.layoutDoc._scrollTop),
+        });
+        this.addDocument(anchor);
+        return anchor;
+    }
+
     async componentDidMount() {
         this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document.  this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
 
@@ -172,7 +207,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                 if (quickScroll) {
                     this._initialScroll = scrollTop;
                 }
-                else if (!this._ignoreScroll) {
+                else {
                     const viewTrans = StrCast(this.Document._viewTransition);
                     const durationMiliStr = viewTrans.match(/([0-9]*)ms/);
                     const durationSecStr = viewTrans.match(/([0-9.]*)s/);
@@ -185,11 +220,16 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
         quickScroll = false;
     }
 
+    _accumulatedGoTo = 0;
+    _resetGoTo: { resetGoTo: { to: number, duration: number } | undefined } = { resetGoTo: undefined };
     goTo = (scrollTop: number, duration: number) => {
         if (this._outerRef.current && this.webpage) {
             if (duration) {
-                smoothScroll(duration, this.webpage as any as HTMLElement, scrollTop);
-                smoothScroll(duration, this._outerRef.current, scrollTop);
+                if (this._accumulatedGoTo++) {
+                    this._resetGoTo.resetGoTo = { to: scrollTop, duration };
+                } else {
+                    smoothScroll(duration, [this.webpage as any as HTMLElement, this._outerRef.current], scrollTop, () => this._accumulatedGoTo = 0, this._resetGoTo);
+                }
             } else {
                 this.webpage.scrollTop = scrollTop;
                 this._outerRef.current.scrollTop = scrollTop;
@@ -202,6 +242,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
         document.removeEventListener("pointerup", this.onLongPressUp);
         document.removeEventListener("pointermove", this.onLongPressMove);
         this._iframe?.removeEventListener('wheel', this.iframeWheel);
+        this._iframe?.removeEventListener('scroll', this.iframeScroll);
     }
 
     @action
@@ -497,17 +538,18 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
         return (<div className="webBox" ref={this._mainCont} >
             <div className={`webBox-container`}
                 style={{ pointerEvents: inactiveLayer ? "none" : undefined }}
+                onWheel={this.onWebWheel}
                 onContextMenu={this.specificContextMenu}>
                 <base target="_blank" />
                 {this.content}
                 <div className={"webBox-outerContent"} ref={this._outerRef}
                     style={{
                         width: `${100 / scale}%`, height: `${100 / scale}%`, transform: `scale(${scale})`,
-                        pointerEvents: this.layoutDoc.isAnnotating && !inactiveLayer ? "all" : "none"
+                        pointerEvents: !this.layoutDoc.isAnnotating || inactiveLayer ? "none" : "all"
                     }}
                     onWheel={this.onWheel}
                     onPointerDown={this.onMarqueeDown}
-                    onScroll={e => e.stopPropagation()}
+                    onScroll={this.onScroll}
                 >
                     <div className={"webBox-innerContent"} style={{
                         height: NumCast(this.scrollHeight, 50),
@@ -527,8 +569,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                             addDocument={this.addDocument}
                             select={emptyFunction}
                             active={this.active}
-                            whenActiveChanged={this.whenActiveChanged}>
-                        </CollectionFreeFormView>
+                            whenActiveChanged={this.whenActiveChanged} />
                     </div>
                 </div>
                 {this.annotationLayer}
-- 
cgit v1.2.3-70-g09d2

