From 20dd1572d6d56cfe09f6488a890791f636d3e336 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 26 Apr 2020 22:41:10 -0400
Subject: from last

---
 src/client/views/nodes/DocumentContentsView.tsx | 57 ++++++++++++++-----------
 1 file changed, 33 insertions(+), 24 deletions(-)

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

diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 812b17d64..8582f92ed 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -58,35 +58,34 @@ const ObserverJsxParser: typeof JsxParser = ObserverJsxParser1 as any;
 
 interface HTMLtagProps {
     Document: Doc;
+    RootDoc: Doc;
     htmltag: string;
     onClick?: ScriptField;
+    onInput?: ScriptField;
 }
 //"<HTMLdiv borderRadius='100px' onClick={this.bannerColor=this.bannerColor==='red'?'green':'red'} width='100%' height='100%' transform='rotate({2*this.x+this.y}deg)'><ImageBox {...props} fieldKey={'data'}/><HTMLspan width='100%'  marginTop='50%'  height='10%'  position='absolute' backgroundColor='{this.bannerColor===`green`?`dark`:`light`}grey'>{this.title}</HTMLspan></HTMLdiv>"@observer
 @observer
 export class HTMLtag extends React.Component<HTMLtagProps> {
     click = (e: React.MouseEvent) => {
         const clickScript = (this.props as any).onClick as Opt<ScriptField>;
-        clickScript?.script.run({ this: this.props.Document });
+        clickScript?.script.run({ this: this.props.Document, self: this.props.RootDoc });
+    }
+    onInput = (e: React.FormEvent<HTMLDivElement>) => {
+        const onInputScript = (this.props as any).onInput as Opt<ScriptField>;
+        onInputScript?.script.run({ this: this.props.Document, self: this.props.RootDoc, value: (e.target as any).textContent });
     }
     render() {
         const style: { [key: string]: any } = {};
-        const divKeys = OmitKeys(this.props, ["children", "htmltag", "Document", "key", "onClick", "__proto__"]).omit;
+        const divKeys = OmitKeys(this.props, ["children", "htmltag", "RootDoc", "Document", "key", "onInput", "onClick", "__proto__"]).omit;
         Object.keys(divKeys).map((prop: string) => {
             let p = (this.props as any)[prop] as string;
-            const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: extend this to support expression -- is this really a script?
-                return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ this: this.props.Document }).result as string || "";
-            };
-            p = p?.replace(/{([^.'][^}']+)}/g, replacer);
-
-            const replacer2 = (match: any, key: string, offset: any, string: any) => { // bcz: extend this to support expression -- is this really a script?
-                const n = Cast(this.props.Document[key], "number", null);
-                return n ? n.toString() : StrCast(this.props.Document[key], p);
+            const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a propery expression string:  { script }  into a value
+                return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ self: this.props.RootDoc, this: this.props.Document }).result as string || "";
             };
-            style[prop] = p?.replace(/@([a-zA-Z0-9-_]+)/g, replacer2);
-
+            style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer);
         });
         const Tag = this.props.htmltag as keyof JSX.IntrinsicElements;
-        return <Tag style={style} onClick={this.click}>
+        return <Tag style={style} onClick={this.click} onInput={this.onInput as any}>
             {this.props.children}
         </Tag>;
     }
@@ -105,7 +104,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     @computed get layout(): string {
         TraceMobx();
         if (!this.layoutDoc) return "<p>awaiting layout</p>";
-        const layout = Cast(this.layoutDoc[StrCast(this.layoutDoc.layoutKey, this.layoutDoc === this.props.Document ? this.props.layoutKey : "layout")], "string");
+        // const layout = Cast(this.layoutDoc[StrCast(this.layoutDoc.layoutKey, this.layoutDoc === this.props.Document ? this.props.layoutKey : "layout")], "string");  // bcz: replaced this with below... is it right?
+        const layout = Cast(this.layoutDoc[this.layoutDoc === this.props.Document && this.props.layoutKey ? this.props.layoutKey : StrCast(this.layoutDoc.layoutKey, "layout")], "string");
         if (this.props.layoutKey === "layout_keyValue") {
             return StrCast(this.props.Document.layout_keyValue, KeyValueBox.LayoutString("data"));
         } else
@@ -129,15 +129,19 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         // bcz: replaced this with below : is it correct?  change was made to accommodate passing fieldKey's from a layout script
         // const template: Doc = this.props.LayoutDoc?.() || Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined);
         const template: Doc = this.props.LayoutDoc?.() ||
+            (this.props.layoutKey && StrCast(this.props.Document[this.props.layoutKey]) && this.props.Document) ||
+            Doc.Layout(this.props.Document, this.props.layoutKey ? Cast(this.props.Document[this.props.layoutKey], Doc, null) : undefined);
         return Doc.expandTemplateLayout(template, this.props.Document, params ? "(" + params + ")" : this.props.layoutKey);
     }
 
-    CreateBindings(onClick: Opt<ScriptField>): JsxBindings {
+    CreateBindings(onClick: Opt<ScriptField>, onInput: Opt<ScriptField>): JsxBindings {
         const list = {
             ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit,
+            RootDoc: Cast(this.layoutDoc?.rootDocument, Doc, null) || this.layoutDoc,
             Document: this.layoutDoc,
             DataDoc: this.dataDoc,
-            onClick: onClick
+            onClick: onClick,
+            onInput: onInput
         };
         return { props: list };
     }
@@ -154,7 +158,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
 
         // replace HTML<tag> with corresponding HTML tag as in:  <HTMLdiv> becomes  <HTMLtag Document={props.Document} htmltag='div'> 
         const replacer2 = (match: any, p1: string, offset: any, string: any) => {
-            return `<HTMLtag Document={props.Document} htmltag='${p1}'`;
+            return `<HTMLtag RootDoc={props.RootDoc} Document={props.Document} htmltag='${p1}'`;
         };
         layoutFrame = layoutFrame.replace(/<HTML([a-zA-Z0-9_-]+)/g, replacer2);
 
@@ -165,15 +169,20 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         layoutFrame = layoutFrame.replace(/<\/HTML([a-zA-Z0-9_-]+)/g, replacer3);
 
         // add onClick function to props
-        const splits = layoutFrame.split("onClick=");
-        let onClick: Opt<ScriptField>;
-        if (splits.length > 1) {
-            const code = XRegExp.matchRecursive(splits[1], "{", "}", "", { valueNames: ["between", "left", "match", "right", "between"] });
-            layoutFrame = splits[0] + " onClick={props.onClick} " + splits[1].substring(code[1].end + 1);
-            onClick = ScriptField.MakeScript(code[1].value, { this: Doc.name, self: Doc.name });
+        const makeFuncProp = (func: string) => {
+            const splits = layoutFrame.split(`func=`);
+            if (splits.length > 1) {
+                const code = XRegExp.matchRecursive(splits[1], "{", "}", "", { valueNames: ["between", "left", "match", "right", "between"] });
+                layoutFrame = splits[0] + ` ${func}={props.onClick} ` + splits[1].substring(code[1].end + 1);
+                return ScriptField.MakeScript(code[1].value, { this: Doc.name, self: Doc.name, value: "string" });
+            }
+            return undefined;
+            // add input function to props
         }
+        let onClick = makeFuncProp("onClick");
+        let onInput = makeFuncProp("onInput");
 
-        const bindings = this.CreateBindings(onClick);
+        const bindings = this.CreateBindings(onClick, onInput);
         //  layoutFrame = splits.length > 1 ? splits[0] + splits[1].replace(/{([^{}]|(?R))*}/, replacer4) : ""; // might have been more elegant if javascript supported recursive patterns
 
         return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc) ? (null) :
-- 
cgit v1.2.3-70-g09d2

