stefans
committed
on 28 Jan 20
Render embedding editor more robust when multiple editors are present, fix readyOnly mode
openacs-4/.../tcl/form-field-procs.tcl (+26 -17)
22 22     {height 600px}
23 23     {minimap true}
24 24     {CSSclass xowf-monaco-container}
25 25   }
26 26
27 27   # TODO: Provide for switching between debug (dev) and production (min) mode
28 28   monaco instproc initialize {} {
29 29     if {![info exists :__initialized]} {
30 30       # TODO: Provide for setting data attributes (data-name) on link
31 31       # tags via template::head::add_link
32 32       ::xo::Page requireJS urn:ad:js:jquery
33 33       ::xo::Page requireJS {
34 34         $("<link/>", {
35 35           rel: "stylesheet",
36 36           type: "text/css"
37 37         }).attr("data-name", "vs/editor/editor.main")
38 38         .attr("href","/resources/xowf-monaco-plugin/monaco-editor/dev/vs/editor/editor.main.css")
39 39         .appendTo("head");
40 40       }
41 41       ::xo::Page requireCSS "/resources/xowf-monaco-plugin/plugin.css"
  42       ::xo::Page requireJS "/resources/xowf-monaco-plugin/plugin.js"
42 43      
43 44       append :style "width: ${:width};" "height: ${:height};"
44 45       set :__initialized 1
45 46     }
46 47   }
47 48
48 49   monaco instproc fromBase64 {encValue} {
49 50     # this is the equivalent to b64_to_utf8 at the client side
50 51     if {$encValue ne ""} {
51 52       return [encoding convertfrom utf-8 [binary decode base64 $encValue]]
52 53     }
53 54   }
54 55
55 56   monaco instproc pretty_value {} {
56 57     return [:fromBase64 [:value]]
57 58   }
58 59
59 60   monaco instproc render_input {} {
60 61     # TODO: Find the appropriate CSP escapes for monaco
61 62     security::csp::require script-src 'unsafe-inline'
62 63    
63 64     # TODO: In disabled mode, one could also use
64 65     # monaco.editor.colorizeElement on a pre element holding the code
65 66     # value
66 67     set readOnly [:is_disabled]
67 68    
68 69     ::html::div [:get_attributes id style {CSSclass class}] {}
69       ::html::input -type hidden -name ${:name} -id ${:id}.hidden
  70    
70 71     # TODO: URNs
71 72     template::add_body_script -script {var require = { paths: { 'vs': '/resources/xowf-monaco-plugin/monaco-editor/min/vs' } };}
72 73     template::add_body_script -src  "/resources/xowf-monaco-plugin/monaco-editor/min/vs/loader.js"
73 74     template::add_body_script -src  "/resources/xowf-monaco-plugin/monaco-editor/min/vs/editor/editor.main.nls.js"
74 75     template::add_body_script -src  "/resources/xowf-monaco-plugin/monaco-editor/min/vs/editor/editor.main.js"
75 76     # TODO: Use ids accepted by JQuery
76 77     # regsub -all {[.:]} ${:id} "" id
77 78     set currentValue [:value]
78 79     # ns_log notice currentValue=>[:fromBase64 $currentValue]
79 80     template::add_body_script -script [subst -nocommands {
80         function utf8_to_b64(str) {
81           return window.btoa(unescape(encodeURIComponent(str)));
82         }
83 81      
84         function b64_to_utf8(str) {
85           return decodeURIComponent(escape(window.atob(str)));
86         }
87        
88         var editor = monaco.editor.create(document.getElementById('${:id}'), {
  82       xowf.monaco.editors.push(monaco.editor.create(document.getElementById('${:id}'), {
89 83         language: '${:language}', minimap: {enabled: ${:minimap}}, readOnly: $readOnly, theme: '${:theme}'
  84       }));
  85       xowf.monaco.editors[xowf.monaco.editors.length-1].setValue(xowf.monaco.b64_to_utf8('$currentValue'));
  86     }]
  87
  88
  89     if {!$readOnly} {
  90       ::html::input -type hidden -name ${:name} -id ${:id}.hidden
  91       template::add_body_script -script {
  92         $(document).ready(function(){
  93           $("form").submit(function(event) {
  94             for (var i = 0; i < xowf.monaco.editors.length ; i++)  {
  95                var e = xowf.monaco.editors[i];
  96                if (!e.getRawOptions()["readOnly"]) {
  97                  var hiddenId = e.getDomNode().parentNode.id + ".hidden";
  98                  var hiddenEl = document.getElementById(hiddenId);
  99                  if (hiddenEl != null) {
  100                    hiddenEl.value = xowf.monaco.utf8_to_b64(e.getValue());
  101                  }
  102               }                            
  103             }
90 104           });
91         editor.setValue(b64_to_utf8('$currentValue'));
92         \$(document).ready(function(){
93           \$("form").submit(function(event){
94             // alert(utf8_to_b64(editor.getValue()));
95             document.getElementById('${:id}.hidden').value = utf8_to_b64(editor.getValue());
96 105       });
97         });
98       }]
99 106       }
  107     }
  108   }
100 109
101 110   monaco instproc set_feedback {feedback_mode} {
102 111     next
103 112   }
104 113
105 114 }
106 115
107 116 # Local variables:
108 117 #    mode: tcl
109 118 #    tcl-indent-level: 2
110 119 #    indent-tabs-mode: nil
111 120 # End: