Commit | Line | Data |
---|---|---|
1aac4625 | 1 | (function(angular, $, _) { |
9a78af90 | 2 | angular.module('crmMonaco', CRM.angRequires('crmMonaco')); |
1aac4625 | 3 | |
9a78af90 TO |
4 | // "crmMonaco" is a basic skeletal directive. |
5 | // Example usage: <div crm-monaco ng-model="my.content"></div> | |
f1291614 TO |
6 | // Example usage: <div crm-monaco="{readOnly: true}" ng-model="my.content"></div> |
7 | angular.module('crmMonaco').directive('crmMonaco', function($timeout, $parse) { | |
1aac4625 TO |
8 | return { |
9 | restrict: 'AE', | |
687bc834 | 10 | require: ['ngModel', 'crmMonaco'], |
9a78af90 | 11 | template: '<div class="crm-monaco-container"></div>', |
687bc834 TO |
12 | controller: function() { |
13 | this.editor = null; // Filled in by link(). | |
14 | }, | |
15 | link: function($scope, $el, $attr, controllers) { | |
16 | var ngModel = controllers[0], crmMonaco = controllers[1]; | |
6cb689b3 | 17 | var heightPct = 0.70; |
1aac4625 | 18 | var editor; |
9a78af90 | 19 | require.config({paths: CRM.crmMonaco.paths}); |
1aac4625 | 20 | require(['vs/editor/editor.main'], function() { |
f1291614 TO |
21 | var options = { |
22 | readOnly: false, | |
1aac4625 | 23 | language: 'html', |
6cb689b3 | 24 | // theme: 'vs-dark', |
f1291614 TO |
25 | theme: 'vs' |
26 | }; | |
27 | if ($attr.crmMonaco) { | |
28 | angular.extend(options, $parse($attr.crmMonaco)($scope)); | |
29 | } | |
30 | angular.extend(options, { | |
31 | value: ngModel.$modelValue, | |
1aac4625 TO |
32 | minimap: { |
33 | enabled: false | |
85933a02 | 34 | }, |
6cb689b3 | 35 | automaticLayout: true, |
85933a02 TO |
36 | scrollbar: { |
37 | useShadows: false, | |
38 | verticalHasArrows: true, | |
39 | horizontalHasArrows: true, | |
40 | vertical: 'visible', | |
41 | horizontal: 'visible', | |
42 | verticalScrollbarSize: 17, | |
43 | horizontalScrollbarSize: 17, | |
44 | arrowSize: 30 | |
1aac4625 TO |
45 | } |
46 | }); | |
47 | ||
64d0a548 TO |
48 | heightPct = options.crmHeightPct || heightPct; |
49 | delete options.crmHeightPct; | |
50 | ||
f1291614 TO |
51 | var editorEl = $el.find('.crm-monaco-container'); |
52 | editorEl.css({height: Math.round(heightPct * $(window).height())}); | |
53 | editor = monaco.editor.create(editorEl[0], options); | |
54 | ||
1aac4625 TO |
55 | editor.onDidChangeModelContent(_.debounce(function () { |
56 | $scope.$apply(function () { | |
57 | ngModel.$setViewValue(editor.getValue()); | |
58 | }); | |
59 | }, 150)); | |
60 | ||
61 | ngModel.$render = function() { | |
62 | if (editor) { | |
63 | editor.setValue(ngModel.$modelValue); | |
64 | } | |
65 | // FIXME: else: retry? | |
66 | }; | |
67 | ||
2a9c42ba TO |
68 | if ($attr.ngDisabled) { |
69 | $scope.$watch($parse($attr.ngDisabled), function(disabled){ | |
70 | editor.updateOptions({readOnly: disabled}); | |
71 | }); | |
72 | } | |
73 | ||
90cd1ece TO |
74 | // FIXME: This makes vertical scrolling much better, but horizontal is still weird. |
75 | var origOverflow; | |
76 | function bodyScrollSuspend() { | |
77 | if (origOverflow !== undefined) return; | |
78 | origOverflow = $('body').css('overflow'); | |
79 | $('body').css('overflow', 'hidden'); | |
80 | } | |
81 | function bodyScrollRestore() { | |
82 | if (origOverflow === undefined) return; | |
83 | $('body').css('overflow', origOverflow); | |
84 | origOverflow = undefined; | |
85 | } | |
86 | editorEl.on('mouseenter', bodyScrollSuspend); | |
87 | editorEl.on('mouseleave', bodyScrollRestore); | |
88 | editor.onDidFocusEditorWidget(bodyScrollSuspend); | |
89 | editor.onDidBlurEditorWidget(bodyScrollRestore); | |
90 | ||
687bc834 TO |
91 | crmMonaco.editor = editor; |
92 | ||
1aac4625 | 93 | $scope.$on('$destroy', function () { |
90cd1ece | 94 | bodyScrollRestore(); |
1aac4625 | 95 | if (editor) editor.dispose(); |
687bc834 | 96 | delete crmMonaco.editor; |
1aac4625 TO |
97 | }); |
98 | }); | |
99 | } | |
100 | }; | |
101 | }); | |
102 | ||
341a2441 TO |
103 | angular.module('crmMonaco').directive('crmMonacoInsertRx', function() { |
104 | return { | |
105 | require: 'crmMonaco', | |
106 | link: function(scope, element, attrs, crmMonaco) { | |
107 | scope.$on(attrs.crmMonacoInsertRx, function(e, tokenName) { | |
108 | var editor = crmMonaco.editor; | |
109 | var id = { major: 1, minor: 1 }; | |
110 | var op = {identifier: id, range: editor.getSelection(), text: tokenName, forceMoveMarkers: true}; | |
111 | editor.executeEdits("tokens", [op]); | |
112 | editor.focus(); | |
113 | }); | |
114 | } | |
115 | }; | |
116 | }); | |
117 | ||
1aac4625 | 118 | })(angular, CRM.$, CRM._); |