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', | |
10 | require: 'ngModel', | |
9a78af90 | 11 | template: '<div class="crm-monaco-container"></div>', |
1aac4625 | 12 | link: function($scope, $el, $attr, ngModel) { |
6cb689b3 | 13 | var heightPct = 0.70; |
1aac4625 | 14 | var editor; |
9a78af90 | 15 | require.config({paths: CRM.crmMonaco.paths}); |
1aac4625 | 16 | require(['vs/editor/editor.main'], function() { |
f1291614 TO |
17 | var options = { |
18 | readOnly: false, | |
1aac4625 | 19 | language: 'html', |
6cb689b3 | 20 | // theme: 'vs-dark', |
f1291614 TO |
21 | theme: 'vs' |
22 | }; | |
23 | if ($attr.crmMonaco) { | |
24 | angular.extend(options, $parse($attr.crmMonaco)($scope)); | |
25 | } | |
26 | angular.extend(options, { | |
27 | value: ngModel.$modelValue, | |
1aac4625 TO |
28 | minimap: { |
29 | enabled: false | |
85933a02 | 30 | }, |
6cb689b3 | 31 | automaticLayout: true, |
85933a02 TO |
32 | scrollbar: { |
33 | useShadows: false, | |
34 | verticalHasArrows: true, | |
35 | horizontalHasArrows: true, | |
36 | vertical: 'visible', | |
37 | horizontal: 'visible', | |
38 | verticalScrollbarSize: 17, | |
39 | horizontalScrollbarSize: 17, | |
40 | arrowSize: 30 | |
1aac4625 TO |
41 | } |
42 | }); | |
43 | ||
f1291614 TO |
44 | var editorEl = $el.find('.crm-monaco-container'); |
45 | editorEl.css({height: Math.round(heightPct * $(window).height())}); | |
46 | editor = monaco.editor.create(editorEl[0], options); | |
47 | ||
1aac4625 TO |
48 | editor.onDidChangeModelContent(_.debounce(function () { |
49 | $scope.$apply(function () { | |
50 | ngModel.$setViewValue(editor.getValue()); | |
51 | }); | |
52 | }, 150)); | |
53 | ||
54 | ngModel.$render = function() { | |
55 | if (editor) { | |
56 | editor.setValue(ngModel.$modelValue); | |
57 | } | |
58 | // FIXME: else: retry? | |
59 | }; | |
60 | ||
90cd1ece TO |
61 | // FIXME: This makes vertical scrolling much better, but horizontal is still weird. |
62 | var origOverflow; | |
63 | function bodyScrollSuspend() { | |
64 | if (origOverflow !== undefined) return; | |
65 | origOverflow = $('body').css('overflow'); | |
66 | $('body').css('overflow', 'hidden'); | |
67 | } | |
68 | function bodyScrollRestore() { | |
69 | if (origOverflow === undefined) return; | |
70 | $('body').css('overflow', origOverflow); | |
71 | origOverflow = undefined; | |
72 | } | |
73 | editorEl.on('mouseenter', bodyScrollSuspend); | |
74 | editorEl.on('mouseleave', bodyScrollRestore); | |
75 | editor.onDidFocusEditorWidget(bodyScrollSuspend); | |
76 | editor.onDidBlurEditorWidget(bodyScrollRestore); | |
77 | ||
1aac4625 | 78 | $scope.$on('$destroy', function () { |
90cd1ece | 79 | bodyScrollRestore(); |
1aac4625 TO |
80 | if (editor) editor.dispose(); |
81 | }); | |
82 | }); | |
83 | } | |
84 | }; | |
85 | }); | |
86 | ||
87 | })(angular, CRM.$, CRM._); |