From d430c5575e2ac8d38239687c8309248e6f7f712b Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 19 May 2020 20:33:50 -0400
Subject: added nav buttons to webbox.  fixed drag/drop from bing (using
 UseCors)

---
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx      | 1 +
 1 file changed, 1 insertion(+)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index aeb0a5813..0751d749d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1341,6 +1341,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             onPointerDown={this.onPointerDown}
             onPointerMove={this.onCursorMove}
             onDrop={this.onExternalDrop.bind(this)}
+            onDragOver={e =>   e.preventDefault() }
             onContextMenu={this.onContextMenu}
             style={{
                 pointerEvents: this.backgroundEvents ? "all" : undefined,
-- 
cgit v1.2.3-70-g09d2


From 0b1039b75af01836082f9bb4613e66c6218a6117 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 20 May 2020 00:35:18 -0400
Subject: added link drag drop onto webBox url

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  4 +-
 src/client/views/nodes/WebBox.tsx                  | 54 ++++++++++++++++------
 src/server/server_Initialization.ts                | 28 ++++++-----
 3 files changed, 59 insertions(+), 27 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 0751d749d..c9b3519aa 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1341,7 +1341,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             onPointerDown={this.onPointerDown}
             onPointerMove={this.onCursorMove}
             onDrop={this.onExternalDrop.bind(this)}
-            onDragOver={e =>   e.preventDefault() }
+            onDragOver={e => {
+                e.preventDefault();
+            }}
             onContextMenu={this.onContextMenu}
             style={{
                 pointerEvents: this.backgroundEvents ? "all" : undefined,
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 63bdbdc5c..c1a585bca 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -116,6 +116,21 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
         this._url = e.target.value;
     }
 
+    onUrlDragover = (e: React.DragEvent) => {
+        e.preventDefault();
+    }
+    @action
+    onUrlDrop = (e: React.DragEvent) => {
+        const { dataTransfer } = e;
+        const html = dataTransfer.getData("text/html");
+        const uri = dataTransfer.getData("text/uri-list");
+        const url = uri || html || this._url;
+        this._url = url.startsWith(window.location.origin) ?
+            url.replace(window.location.origin, this._url.match(/http[s]?:\/\/[^\/]*/)?.[0] || "") : url;
+        this.submitURL();
+        e.stopPropagation();
+    }
+
     @action
     forward = () => {
         const future = Cast(this.dataDoc[this.fieldKey + "-future"], listSpec("string"), null);
@@ -140,21 +155,25 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
     @action
     submitURL = () => {
         if (!this._url.startsWith("http")) this._url = "http://" + this._url;
-        const future = Cast(this.dataDoc[this.fieldKey + "-future"], listSpec("string"), null);
-        const history = Cast(this.dataDoc[this.fieldKey + "-history"], listSpec("string"), null);
-        const url = Cast(this.dataDoc[this.fieldKey], WebField, null)?.url.toString();
-        if (url) {
-            if (history === undefined) {
-                this.dataDoc[this.fieldKey + "-history"] = new List<string>([url]);
-            } else {
-                history.push(url);
+        try {
+            const URLy = new URL(this._url);
+            const future = Cast(this.dataDoc[this.fieldKey + "-future"], listSpec("string"), null);
+            const history = Cast(this.dataDoc[this.fieldKey + "-history"], listSpec("string"), null);
+            const url = Cast(this.dataDoc[this.fieldKey], WebField, null)?.url.toString();
+            if (url) {
+                if (history === undefined) {
+                    this.dataDoc[this.fieldKey + "-history"] = new List<string>([url]);
+                } else {
+                    history.push(url);
+                }
+                future && (future.length = 0);
             }
-            future && (future.length = 0);
+            this.dataDoc[this.fieldKey] = new WebField(URLy);
+        } catch (e) {
+            console.log("Error in URL :" + this._url);
         }
-        this.dataDoc[this.fieldKey] = new WebField(new URL(this._url));
     }
 
-
     onValueKeyDown = async (e: React.KeyboardEvent) => {
         if (e.key === "Enter") {
             e.stopPropagation();
@@ -175,7 +194,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
 
     urlEditor() {
         return (
-            <div className="webBox-urlEditor" style={{ top: this._collapsed ? -70 : 0 }}>
+            <div className="webBox-urlEditor"
+                onDrop={this.onUrlDrop}
+                onDragOver={this.onUrlDragover} style={{ top: this._collapsed ? -70 : 0 }}>
                 <div className="urlEditor">
                     <div className="editorBase">
                         <button className="editor-collapse"
@@ -188,7 +209,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                             title="Collapse Url Editor" onClick={this.toggleCollapse}>
                             <FontAwesomeIcon icon="caret-up" size="2x" />
                         </button>
-                        <div className="webBox-buttons" style={{ display: this._collapsed ? "none" : "flex" }}>
+                        <div className="webBox-buttons"
+                            onDrop={this.onUrlDrop}
+                            onDragOver={this.onUrlDragover} style={{ display: this._collapsed ? "none" : "flex" }}>
                             <div className="webBox-freeze" title={"Annotate"} style={{ background: this.layoutDoc.isAnnotating ? "lightBlue" : "gray" }} onClick={this.toggleAnnotationMode} >
                                 <FontAwesomeIcon icon={faPen} size={"2x"} />
                             </div>
@@ -198,6 +221,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                             <input className="webpage-urlInput"
                                 placeholder="ENTER URL"
                                 value={this._url}
+                                onDrop={this.onUrlDrop}
+                                onDragOver={this.onUrlDragover}
                                 onChange={this.onURLChange}
                                 onKeyDown={this.onValueKeyDown}
                             />
@@ -207,7 +232,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                                 justifyContent: "space-between",
                                 maxWidth: "120px",
                             }}>
-                                <button className="submitUrl" onClick={this.submitURL}>
+                                <button className="submitUrl" onClick={this.submitURL}
+                                    onDragOver={this.onUrlDragover} onDrop={this.onUrlDrop}>
                                     GO
                                 </button>
                                 <button className="submitUrl" onClick={this.back}>
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts
index 14b8776d8..68954fa44 100644
--- a/src/server/server_Initialization.ts
+++ b/src/server/server_Initialization.ts
@@ -146,19 +146,23 @@ function registerCorsProxy(server: express.Express) {
             res.redirect(referer + (referer.endsWith("/") ? "" : "/") + requrl);
         }
         else {
-            req.pipe(request(requrl)).on("response", res => {
-                const headers = Object.keys(res.headers);
-                headers.forEach(headerName => {
-                    const header = res.headers[headerName];
-                    if (Array.isArray(header)) {
-                        res.headers[headerName] = header.filter(h => !headerCharRegex.test(h));
-                    } else if (header) {
-                        if (headerCharRegex.test(header as any)) {
-                            delete res.headers[headerName];
+            try {
+                req.pipe(request(requrl)).on("response", res => {
+                    const headers = Object.keys(res.headers);
+                    headers.forEach(headerName => {
+                        const header = res.headers[headerName];
+                        if (Array.isArray(header)) {
+                            res.headers[headerName] = header.filter(h => !headerCharRegex.test(h));
+                        } else if (header) {
+                            if (headerCharRegex.test(header as any)) {
+                                delete res.headers[headerName];
+                            }
                         }
-                    }
-                });
-            }).pipe(res);
+                    });
+                }).pipe(res);
+            } catch (e) {
+                console.log("problem with Cors URL: " + requrl);
+            }
         }
     });
 }
-- 
cgit v1.2.3-70-g09d2


From 8de8756e5fa8b7031092c870c84f5214e2a244c1 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 20 May 2020 12:16:56 -0400
Subject: fixed up interaction with web pages to allow horizontal scrolling.

---
 src/client/documents/Documents.ts                  |  4 +--
 src/client/views/collections/CollectionMapView.tsx |  4 +--
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 11 +++++--
 src/client/views/nodes/DocumentView.tsx            |  7 -----
 src/client/views/nodes/WebBox.tsx                  | 35 ++++++++++++----------
 src/client/views/pdf/PDFViewer.tsx                 |  1 -
 src/fields/documentSchemas.ts                      |  6 ++--
 7 files changed, 36 insertions(+), 32 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 18a0b43ff..b859086d5 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -112,7 +112,7 @@ export interface DocumentOptions {
     caption?: RichTextField;
     ignoreClick?: boolean;
     lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
-    lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
+    _lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
     isAnnotating?: boolean; // whether we web document is annotation mode where links can't be clicked to allow annotations to be created
     opacity?: number;
     defaultBackgroundColor?: string;
@@ -635,7 +635,7 @@ export namespace Docs {
         }
 
         export function WebDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(new URL(url)) : undefined, { _fitWidth: true, _chromeStatus: url ? "disabled" : "enabled", isAnnotating: true, lockedTransform: true, ...options });
+            return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(new URL(url)) : undefined, { _fitWidth: true, _chromeStatus: url ? "disabled" : "enabled", isAnnotating: true, _lockedTransform: true, ...options });
         }
 
         export function HtmlDocument(html: string, options: DocumentOptions = {}) {
diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx
index d91337ce9..a0b7cd8a8 100644
--- a/src/client/views/collections/CollectionMapView.tsx
+++ b/src/client/views/collections/CollectionMapView.tsx
@@ -226,7 +226,7 @@ class CollectionMapView extends CollectionSubView<MapSchema, Partial<IMapProps>
                     initialCenter={center}
                     center={center}
                     onIdle={(_props?: IMapProps, map?: google.maps.Map) => {
-                        if (this.layoutDoc.lockedTransform) {
+                        if (this.layoutDoc._lockedTransform) {
                             // reset zoom (ideally, we could probably can tell the map to disallow zooming somehow instead)
                             map?.setZoom(center?.zoom || 10);
                             map?.setCenter({ lat: center?.lat!, lng: center?.lng! });
@@ -238,7 +238,7 @@ class CollectionMapView extends CollectionSubView<MapSchema, Partial<IMapProps>
                         }
                     }}
                     onDragend={(_props?: IMapProps, map?: google.maps.Map) => {
-                        if (this.layoutDoc.lockedTransform) {
+                        if (this.layoutDoc._lockedTransform) {
                             // reset the drag (ideally, we could probably can tell the map to disallow dragging somehow instead)
                             map?.setCenter({ lat: center?.lat!, lng: center?.lng! });
                         } else {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c9b3519aa..972c09484 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -769,7 +769,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
 
     @action
     onPointerWheel = (e: React.WheelEvent): void => {
-        if (this.props.Document.lockedTransform || this.props.Document.inOverlay) return;
+        if (this.layoutDoc._lockedTransform || this.props.Document.inOverlay) return;
         if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) { // things that can scroll vertically should do that instead of zooming
             e.stopPropagation();
         }
@@ -805,7 +805,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 else if (ranges.yrange.max <= (panY - panelDim[1] / 2)) panY = ranges.yrange.min - panelDim[1] / 2;
             }
         }
-        if (!this.Document.lockedTransform || this.Document.inOverlay) {
+        if (!this.layoutDoc._lockedTransform || this.Document.inOverlay) {
             this.Document.panTransformType = panType;
             const scale = this.getLocalTransform().inverse().Scale;
             const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX));
@@ -1169,6 +1169,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth(), this.props.NativeHeight());
     }
 
+    @undoBatch
+    @action
+    toggleLockTransform = (): void => {
+        this.layoutDoc._lockedTransform = this.layoutDoc._lockedTransform ? undefined : true;
+    }
+
     private thumbIdentifier?: number;
 
     onContextMenu = (e: React.MouseEvent) => {
@@ -1189,6 +1195,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         optionItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
         optionItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" });
         this.props.ContainingCollectionView && optionItems.push({ description: "Promote Collection", event: this.promoteCollection, icon: "table" });
+        optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" });
         optionItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" });
         // layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" });
         optionItems.push({
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 34aabfe5e..8dbd0232b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -683,12 +683,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         this.Document.lockedPosition = this.Document.lockedPosition ? undefined : true;
     }
 
-    @undoBatch
-    @action
-    toggleLockTransform = (): void => {
-        this.Document.lockedTransform = this.Document.lockedTransform ? undefined : true;
-    }
-
     @action
     onContextMenu = async (e: React.MouseEvent | Touch): Promise<void> => {
         // the touch onContextMenu is button 0, the pointer onContextMenu is button 2
@@ -751,7 +745,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const moreItems: ContextMenuProps[] = more && "subitems" in more ? more.subitems : [];
         moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
         moreItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
-        moreItems.push({ description: this.Document.lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" });
         moreItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" });
 
         if (!ClientUtils.RELEASE) {
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index c1a585bca..1d242d958 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -59,14 +59,19 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
             iframe.contentDocument.addEventListener('scroll', this.iframeScrolled, false);
             this.layoutDoc.scrollHeight = iframe.contentDocument.children?.[0].scrollHeight || 1000;
             iframe.contentDocument.children[0].scrollTop = NumCast(this.layoutDoc.scrollTop);
+            iframe.contentDocument.children[0].scrollLeft = NumCast(this.layoutDoc.scrollLeft);
         }
         this._reactionDisposer?.();
-        this._reactionDisposer = reaction(() => this.layoutDoc.scrollY,
-            (scrollY) => {
-                if (scrollY !== undefined) {
-                    this._outerRef.current!.scrollTop = scrollY;
+        this._reactionDisposer = reaction(() => ({ y: this.layoutDoc.scrollY, x: this.layoutDoc.scrollX }),
+            ({ x, y }) => {
+                if (y !== undefined) {
+                    this._outerRef.current!.scrollTop = y;
                     this.layoutDoc.scrollY = undefined;
                 }
+                if (x !== undefined) {
+                    this._outerRef.current!.scrollLeft = x;
+                    this.layoutDoc.scrollX = undefined;
+                }
             },
             { fireImmediately: true }
         );
@@ -76,8 +81,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
         this._setPreviewCursor?.(e.screenX, e.screenY, false);
     }
     iframeScrolled = (e: any) => {
-        const scroll = e.target?.children?.[0].scrollTop;
-        this.layoutDoc.scrollTop = this._outerRef.current!.scrollTop = scroll;
+        const scrollTop = e.target?.children?.[0].scrollTop;
+        const scrollLeft = e.target?.children?.[0].scrollLeft;
+        this.layoutDoc.scrollTop = this._outerRef.current!.scrollTop = scrollTop;
+        this.layoutDoc.scrollLeft = this._outerRef.current!.scrollLeft = scrollLeft;
     }
     async componentDidMount() {
         const urlField = Cast(this.dataDoc[this.props.fieldKey], WebField);
@@ -182,14 +189,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
     }
 
     toggleAnnotationMode = () => {
-        if (!this.layoutDoc.isAnnotating) {
-            this.layoutDoc.lockedTransform = false;
-            this.layoutDoc.isAnnotating = true;
-        }
-        else {
-            this.layoutDoc.lockedTransform = true;
-            this.layoutDoc.isAnnotating = false;
-        }
+        this.layoutDoc.isAnnotating = !this.layoutDoc.isAnnotating;
     }
 
     urlEditor() {
@@ -427,7 +427,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
             {this.urlEditor()}
         </>);
     }
-    scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.props.Document.scrollTop));
+    scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc.scrollLeft), NumCast(this.layoutDoc.scrollTop));
     render() {
         return (<div className={`webBox-container`}
             style={{
@@ -449,10 +449,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                         if (iframe.children[0].scrollTop !== outerFrame.scrollTop) {
                             iframe.children[0].scrollTop = outerFrame.scrollTop;
                         }
+                        if (iframe.children[0].scrollLeft !== outerFrame.scrollLeft) {
+                            iframe.children[0].scrollLeft = outerFrame.scrollLeft;
+                        }
                     }
                     //this._outerRef.current!.scrollTop !== this._scrollTop && (this._outerRef.current!.scrollTop = this._scrollTop)
                 }}>
-                <div className={"webBox-innerContent"} style={{ height: NumCast(this.layoutDoc.scrollHeight) }}>
+                <div className={"webBox-innerContent"} style={{ height: NumCast(this.layoutDoc.scrollHeight), width: 4000 }}>
                     <CollectionFreeFormView {...this.props}
                         PanelHeight={this.props.PanelHeight}
                         PanelWidth={this.props.PanelWidth}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index c50969493..810ce5aea 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -125,7 +125,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
 
     _lastSearch: string = "";
     componentDidMount = async () => {
-        !this.props.Document.lockedTransform && (this.props.Document.lockedTransform = true);
         // change the address to be the file address of the PNG version of each page
         // file address of the pdf
         const { url: { href } } = Cast(this.dataDoc[this.props.fieldKey], PdfField)!;
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index cacba43b6..142f7e079 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -20,7 +20,9 @@ export const documentSchema = createSchema({
     z: "number",                // z "coordinate" - non-zero specifies the overlay layer of a freeformview
     zIndex: "number",           // zIndex of a document in a freeform view
     scrollY: "number",          // "command" to scroll a document to a position on load (the value will be reset to 0 after that )
+    scrollX: "number",          // "command" to scroll a document to a position on load (the value will be reset to 0 after that )
     scrollTop: "number",        // scroll position of a scrollable document (pdf, text, web)
+    scrollLeft: "number",        // scroll position of a scrollable document (pdf, text, web)
 
     // appearance properties on the layout
     _autoHeight: "boolean",     // whether the height of the document should be computed automatically based on its contents
@@ -74,8 +76,8 @@ export const documentSchema = createSchema({
     isLinkButton: "boolean",    // whether document functions as a link follow button to follow the first link on the document when clicked   
     isBackground: "boolean",    // whether document is a background element and ignores input events (can only select with marquee)
     lockedPosition: "boolean",  // whether the document can be moved (dragged)
-    lockedTransform: "boolean", // whether the document can be panned/zoomed
-
+    _lockedTransform: "boolean",// whether a freeformview can pan/zoom
+    
     // drag drop properties
     dragFactory: Doc,           // the document that serves as the "template" for the onDragStart script.  ie, to drag out copies of the dragFactory document.
     dropAction: "string",       // override specifying what should happen when this document is dropped (can be "alias", "copy", "move")
-- 
cgit v1.2.3-70-g09d2

