Merge pull request #24063 from eileenmcnaughton/msg_breakdown
[civicrm-core.git] / ang / crmMonaco.js
1 (function(angular, $, _) {
2 angular.module('crmMonaco', CRM.angRequires('crmMonaco'));
3
4 // "crmMonaco" is a basic skeletal directive.
5 // Example usage: <div crm-monaco ng-model="my.content"></div>
6 // Example usage: <div crm-monaco="{readOnly: true}" ng-model="my.content"></div>
7 angular.module('crmMonaco').directive('crmMonaco', function($timeout, $parse) {
8 return {
9 restrict: 'AE',
10 require: ['ngModel', 'crmMonaco'],
11 template: '<div class="crm-monaco-container"></div>',
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];
17 var heightPct = 0.70;
18 var editor;
19 require.config({paths: CRM.crmMonaco.paths});
20 require(['vs/editor/editor.main'], function() {
21 var options = {
22 readOnly: false,
23 language: 'html',
24 // theme: 'vs-dark',
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,
32 minimap: {
33 enabled: false
34 },
35 automaticLayout: true,
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
45 }
46 });
47
48 heightPct = options.crmHeightPct || heightPct;
49 delete options.crmHeightPct;
50
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
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
68 if ($attr.ngDisabled) {
69 $scope.$watch($parse($attr.ngDisabled), function(disabled){
70 editor.updateOptions({readOnly: disabled});
71 });
72 }
73
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
91 crmMonaco.editor = editor;
92
93 $scope.$on('$destroy', function () {
94 bodyScrollRestore();
95 if (editor) editor.dispose();
96 delete crmMonaco.editor;
97 });
98 });
99 }
100 };
101 });
102
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
118 })(angular, CRM.$, CRM._);