Index: openacs-4/packages/xowf-monaco-plugin/tcl/form-field-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowf-monaco-plugin/tcl/form-field-procs.tcl,v diff -u -N -r1.1.1.1.2.5 -r1.1.1.1.2.6 --- openacs-4/packages/xowf-monaco-plugin/tcl/form-field-procs.tcl 2 Jul 2021 21:14:43 -0000 1.1.1.1.2.5 +++ openacs-4/packages/xowf-monaco-plugin/tcl/form-field-procs.tcl 3 Jul 2021 00:16:49 -0000 1.1.1.1.2.6 @@ -126,6 +126,90 @@ next } + ########################################################s### + # + # ::xowiki::formfield::html_sandbox + # + ########################################################### + + Class create html_sandbox -superclass monaco -ad_doc { + This class provides a HTML sandbox formfield powered by the Monaco + code editor set to HTML mode. The code inputed in the editor is + rendered as a standalone document inside an iframe. + + The formfield also supports live preview, updated whenever the + code has changed. + } -parameter { + {preview true} + } + + html_sandbox instproc initialize args { + set :language html + next + } + + html_sandbox ad_instproc render_input args { + Displays the editor. If user selected to have the preview, will + put editor and preview side by side using flexbox responsive + layout. The preview will update automatically whenever the code + changes. + } { + # No preview, just show the editor + if {!${:preview}} { + return [next] + } + + ::html::div -id ${:id}-container style "display:flex; flex-wrap:wrap;" { + ::html::div -id ${:id}-code { + next + } + ::html::div -id ${:id}-preview { + ::html::iframe -id ${:id}-iframe -style "width: ${:width}; height: ${:height};" + } + } + + # Find our Monaco editor instance, get its value and inject it + # into the preview iframe. Listen also to any change and update + # the preview on the fly. + template::add_body_handler -event load -script [subst -nocommands { + var iframe = document.getElementById('${:id}-iframe'); + for (var i = 0; i < xowf.monaco.editors.length ; i++) { + var e = xowf.monaco.editors[i]; + if (!e.getRawOptions()["readOnly"]) { + var hiddenId = e.getDomNode().parentNode.id + ".hidden"; + if (hiddenId === '${:id}.hidden') { + // This is our editor, set its value in the iframe + iframe.srcdoc = e.getValue(); + // Listen to changes and update the iframe + e.onDidChangeModelContent((event) => { + iframe.srcdoc = e.getValue(); + }); + } + } + } + }] + } + + html_sandbox ad_instproc pretty_value args { + Put the code (base64 encoded) in an invisible template element and + add an iframe. When the page loads, translate and put the code + inside the template element as the document of the iframe, so that + it is rendered. + + @return HTML + } { + template::add_body_handler -event load -script [subst -nocommands { + var srcDoc = document.getElementById('${:id}-srcdoc'); + var iframe = document.getElementById('${:id}-iframe'); + iframe.srcdoc = xowf.monaco.b64_to_utf8(srcDoc.innerHTML); + }] + set base64 [:value] + return [subst -nocommands { + + + }] + } + } # Local variables: