marty 8.5.0 → 9.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintignore +1 -0
  3. data/.eslintrc.js +26 -0
  4. data/.gitignore +3 -0
  5. data/.gitlab-ci.yml +7 -0
  6. data/.prettierignore +14 -0
  7. data/.rubocop_todo.yml +1 -1
  8. data/Dockerfile.dummy +3 -0
  9. data/Makefile +1 -0
  10. data/app/assets/javascripts/marty/cable.js +7 -3
  11. data/app/assets/javascripts/marty/extjs/extensions/datetime_field/component.js +401 -0
  12. data/app/assets/javascripts/marty/extjs/extensions/datetime_field/field.js +140 -0
  13. data/app/assets/javascripts/marty/extjs/extensions/marty.js +845 -781
  14. data/app/assets/stylesheets/marty/codemirror/codemirror.css +215 -77
  15. data/app/assets/stylesheets/marty/codemirror/delorean.css +2 -2
  16. data/app/assets/stylesheets/marty/dark_mode.css +13 -3
  17. data/app/components/marty/auth_app/client/auth_app.js +107 -102
  18. data/app/components/marty/base_rule_view/client/base_rule_view.js +10 -8
  19. data/app/components/marty/data_grid_view/client/data_grid_edit.js +534 -519
  20. data/app/components/marty/form/client/form.js +3 -3
  21. data/app/components/marty/grid/client/grid.js +110 -87
  22. data/app/components/marty/import_view/client/import_view.js +18 -18
  23. data/app/components/marty/live_search_grid_panel/client/live_search_grid_panel.js +14 -13
  24. data/app/components/marty/main_auth_app/client/main_auth_app.js +42 -42
  25. data/app/components/marty/mcfly_grid_panel/client/mcfly_grid_panel.js +27 -18
  26. data/app/components/marty/new_posting_form/client/new_posting_form.js +3 -3
  27. data/app/components/marty/panel/client/panel.js +3 -3
  28. data/app/components/marty/posting_grid/client/posting_grid.js +24 -18
  29. data/app/components/marty/promise_view/client/promise_view.css +12 -12
  30. data/app/components/marty/promise_view/client/promise_view.js +46 -38
  31. data/app/components/marty/report_form/client/report_form.js +30 -28
  32. data/app/components/marty/report_select/client/report_select.js +28 -23
  33. data/app/components/marty/reporting/client/reporting.js +3 -3
  34. data/app/components/marty/script_form/client/script_form.js +29 -23
  35. data/app/components/marty/script_tester/client/script_tester.js +4 -5
  36. data/app/components/marty/scripting/client/scripting.js +40 -36
  37. data/app/components/marty/simple_app/client/simple_app.js +33 -24
  38. data/app/components/marty/simple_app/client/statusbar_ext.js +1 -1
  39. data/app/controllers/marty/rpc_controller.rb +3 -0
  40. data/app/models/marty/promise.rb +10 -2
  41. data/app/services/marty/data_grid/constraint.rb +2 -1
  42. data/app/services/marty/jobs/schedule.rb +2 -2
  43. data/app/services/marty/promises/delorean/create.rb +9 -2
  44. data/app/services/marty/promises/ruby/create.rb +7 -2
  45. data/config/initializers/delayed_job_config.rb +1 -0
  46. data/delorean/blame_report.dl +50 -58
  47. data/delorean/enum_report.dl +2 -3
  48. data/delorean/{marty_fields.dl → fields.dl} +16 -0
  49. data/delorean/styles.dl +216 -0
  50. data/delorean/table_report.dl +4 -4
  51. data/lib/marty/monkey.rb +17 -0
  52. data/lib/marty/promise_job.rb +9 -0
  53. data/lib/marty/promise_ruby_job.rb +8 -0
  54. data/lib/marty/version.rb +1 -1
  55. data/make-lint.mk +19 -0
  56. data/package.json +16 -0
  57. data/prettier.config.js +6 -0
  58. data/spec/controllers/diagnostic/controller_spec.rb +0 -1
  59. data/spec/controllers/rpc_controller_spec.rb +21 -7
  60. data/spec/dummy/delorean/data_report.dl +4 -4
  61. data/spec/dummy/delorean/fields.dl +1 -0
  62. data/spec/features/data_grid_spec.rb +37 -1
  63. data/spec/job_helper.rb +6 -0
  64. data/spec/lib/data_blame_spec.rb +4 -4
  65. data/spec/lib/data_importer_spec.rb +6 -4
  66. data/spec/models/promise_spec.rb +31 -0
  67. data/spec/spec_helper.rb +8 -0
  68. data/spec/support/download_helper.rb +53 -49
  69. data/spec/support/json_helper.rb +11 -0
  70. data/spec/support/shared_connection_db_helpers.rb +1 -0
  71. data/spec/support/suite.rb +20 -14
  72. data/yarn.lock +967 -0
  73. metadata +16 -4
  74. data/spec/dummy/delorean/marty_fields.dl +0 -1
@@ -0,0 +1,140 @@
1
+ /*
2
+ * File: DateTimeField.js
3
+ *
4
+ * This file requires use of the Ext JS library, under independent license.
5
+ * This is part of the UX for DateTimeField developed by Guilherme Portela
6
+ */
7
+ Ext.define("Ext.ux.DateTimeField", {
8
+ extend: "Ext.form.field.Date",
9
+ alias: "widget.datetimefield",
10
+ requires: ["Ext.ux.DateTimePicker"],
11
+
12
+ //<locale>
13
+ /**
14
+ * @cfg {String} format
15
+ * The default date format string which can be overriden for localization support. The format must be valid
16
+ * according to {@link Ext.Date#parse}.
17
+ */
18
+ format: "m/d/Y H:i",
19
+ //</locale>
20
+ /**
21
+ * @cfg {String} altFormats
22
+ * Multiple date formats separated by "|" to try when parsing a user input value and it does not match the defined
23
+ * format.
24
+ */
25
+ altFormats: "m/d/Y H:i:s|c",
26
+ width: 270,
27
+
28
+ collapseIf(e) {
29
+ const me = this,
30
+ picker = me.picker;
31
+
32
+ if (picker.timePicker && !e.within(picker.timePicker.el, false, true)) {
33
+ me.callParent([e]);
34
+ }
35
+ },
36
+
37
+ createPicker() {
38
+ const me = this,
39
+ parentPicker = this.callParent(),
40
+ parentConfig = Ext.clone(parentPicker.initialConfig),
41
+ initialConfig = Ext.clone(me.initialConfig),
42
+ excludes = ["renderTo", "width", "height", "bind", "reference"];
43
+
44
+ // Avoiding duplicate ids error
45
+ parentPicker.destroy();
46
+
47
+ for (let i = 0; i < excludes.length; i++) {
48
+ if (initialConfig[excludes[i]] !== undefined) {
49
+ delete initialConfig[excludes[i]];
50
+ }
51
+ }
52
+
53
+ return Ext.create(
54
+ "Ext.ux.DateTimePicker",
55
+ Ext.merge(initialConfig, parentConfig)
56
+ );
57
+ },
58
+
59
+ getErrors(value) {
60
+ value =
61
+ arguments.length > 0
62
+ ? value
63
+ : this.formatDate(this.processRawValue(this.getRawValue()));
64
+
65
+ const me = this,
66
+ format = Ext.String.format,
67
+ errors = me.superclass.superclass.getErrors.apply(this, arguments),
68
+ disabledDays = me.disabledDays,
69
+ disabledDatesRE = me.disabledDatesRE,
70
+ minValue = me.minValue,
71
+ maxValue = me.maxValue,
72
+ len = disabledDays ? disabledDays.length : 0;
73
+
74
+ let i = 0,
75
+ day;
76
+
77
+ if (value === null || value.length < 1) {
78
+ // if it's blank and textfield didn't flag it then it's valid
79
+ return errors;
80
+ }
81
+
82
+ const svalue = value;
83
+ value = me.parseDate(value);
84
+ if (!value) {
85
+ errors.push(
86
+ format(me.invalidText, svalue, Ext.Date.unescapeFormat(me.format))
87
+ );
88
+ return errors;
89
+ }
90
+
91
+ const time = value.getTime();
92
+ if (minValue && time < minValue.getTime()) {
93
+ errors.push(format(me.minText, me.formatDate(minValue)));
94
+ }
95
+
96
+ if (maxValue && time > maxValue.getTime()) {
97
+ errors.push(format(me.maxText, me.formatDate(maxValue)));
98
+ }
99
+
100
+ if (disabledDays) {
101
+ day = value.getDay();
102
+
103
+ for (; i < len; i++) {
104
+ if (day === disabledDays[i]) {
105
+ errors.push(me.disabledDaysText);
106
+ break;
107
+ }
108
+ }
109
+ }
110
+
111
+ const fvalue = me.formatDate(value);
112
+ if (disabledDatesRE && disabledDatesRE.test(fvalue)) {
113
+ errors.push(format(me.disabledDatesText, fvalue));
114
+ }
115
+
116
+ return errors;
117
+ },
118
+
119
+ getRefItems() {
120
+ const me = this,
121
+ result = me.callParent();
122
+
123
+ if (me.picker && me.picker.timePicker) {
124
+ result.push(me.picker.timePicker);
125
+ }
126
+
127
+ return result;
128
+ },
129
+
130
+ onExpand() {
131
+ const me = this;
132
+
133
+ me.callParent();
134
+ const timePicker = me.picker && me.picker.timePicker;
135
+
136
+ if (timePicker) {
137
+ me.picker.alignTimePicker();
138
+ }
139
+ }
140
+ });
@@ -1,10 +1,10 @@
1
- Ext.define('Netzke.Grid.EventHandlers', {
2
- override: 'Netzke.Grid.EventHandlers',
3
- netzkeHandleItemdblclick: function(view, record) {
1
+ Ext.define("Netzke.Grid.EventHandlers", {
2
+ override: "Netzke.Grid.EventHandlers",
3
+ netzkeHandleItemdblclick(view, record) {
4
4
  if (this.editsInline) return; // inline editing is handled elsewhere
5
5
 
6
6
  // MONKEY: add view in form capability
7
- var has_perm = (this.permissions || {});
7
+ const has_perm = this.permissions || {};
8
8
  if (has_perm.read !== false && !has_perm.update) {
9
9
  this.doViewInForm(record);
10
10
  } else if (has_perm.update !== false) {
@@ -12,38 +12,40 @@ Ext.define('Netzke.Grid.EventHandlers', {
12
12
  }
13
13
  },
14
14
 
15
- netzkeReloadStore: function(opts={}) {
16
- var store = this.getStore();
15
+ netzkeReloadStore(opts = {}) {
16
+ const store = this.getStore();
17
17
 
18
18
  // MONKEY: add beforenetzkereload and netzkerevent on store
19
- store.fireEvent('beforenetzkereload');
20
- var callback = opts.callback;
19
+ store.fireEvent("beforenetzkereload");
20
+ const callback = opts.callback;
21
21
  opts.callback = function() {
22
- if (callback) { callback() }
23
- store.fireEvent('netzkereload');
24
- }
22
+ if (callback) {
23
+ callback();
24
+ }
25
+ store.fireEvent("netzkereload");
26
+ };
25
27
 
26
28
  // NETZKE'S HACK to work around buffered store's buggy reload()
27
29
  if (!store.lastRequestStart) {
28
30
  store.load(opts);
29
31
  } else store.reload(opts);
30
- },
32
+ }
31
33
  });
32
34
 
33
- Ext.define('Ext.toolbar.Paging', {
34
- override: 'Ext.toolbar.Paging',
35
+ Ext.define("Ext.toolbar.Paging", {
36
+ override: "Ext.toolbar.Paging",
35
37
 
36
38
  handleRefresh: Ext.emptyFn,
37
39
 
38
- doRefresh: function() {
39
- var me = this,
40
+ doRefresh() {
41
+ const me = this,
40
42
  current = me.store.currentPage;
41
43
 
42
44
  // MONKEY: add netzkerefresh to ExtJS paging toolbar refresh
43
45
  // as beforechange is too generic
44
- me.store.fireEvent('netzkerefresh', me);
46
+ me.store.fireEvent("netzkerefresh", me);
45
47
 
46
- if (me.fireEvent('beforechange', me, current) !== false) {
48
+ if (me.fireEvent("beforechange", me, current) !== false) {
47
49
  me.store.loadPage(current);
48
50
 
49
51
  me.handleRefresh();
@@ -51,33 +53,37 @@ Ext.define('Ext.toolbar.Paging', {
51
53
  }
52
54
  });
53
55
 
54
- Ext.define('Netzke.Grid.Columns', {
55
- override: 'Netzke.Grid.Columns',
56
- netzkeNormalizeAssociationRenderer: function(c) {
57
- var passedRenderer = c.renderer, // renderer we got from netzkeNormalizeRenderer
58
- assocValue;
56
+ Ext.define("Netzke.Grid.Columns", {
57
+ override: "Netzke.Grid.Columns",
58
+ netzkeNormalizeAssociationRenderer(c) {
59
+ const passedRenderer = c.renderer; // renderer we got from netzkeNormalizeRenderer
60
+ let assocValue;
59
61
  c.scope = this;
60
- c.renderer = function(value, a, r, ri, ci, store, view){
61
- var column = view.headerCt.items.getAt(ci),
62
- editor = column.getEditor && column.getEditor(),
63
-
64
- /* MONKEY: use findRecordByValue instead of findRecord to remedy inline editing temporarily
62
+ c.renderer = function(value, a, r, ri, ci, store, view) {
63
+ const column = view.headerCt.items.getAt(ci);
64
+ const editor = column.getEditor && column.getEditor();
65
+ /* MONKEY: use findRecordByValue instead of findRecord to remedy inline editing temporarily
65
66
  changing N/A columns to the recently changed value.
66
67
  */
67
- recordFromStore = editor && editor.isXType('combobox') && editor.findRecordByValue(value),
68
- renderedValue;
68
+ const recordFromStore =
69
+ editor && editor.isXType("combobox") && editor.findRecordByValue(value);
70
+ let renderedValue;
69
71
 
70
72
  if (recordFromStore) {
71
- renderedValue = recordFromStore.get('text');
72
- } else if ((assocValue = (r.get('association_values') || {})[c.name]) !== undefined) {
73
- renderedValue = (assocValue == undefined) ? c.emptyText : assocValue;
73
+ renderedValue = recordFromStore.get("text");
74
+ } else if (
75
+ (assocValue = (r.get("association_values") || {})[c.name]) !== undefined
76
+ ) {
77
+ renderedValue = assocValue == undefined ? c.emptyText : assocValue;
74
78
  } else {
75
79
  renderedValue = value;
76
80
  }
77
81
 
78
- return passedRenderer ? passedRenderer.call(this, renderedValue) : renderedValue;
82
+ return passedRenderer
83
+ ? passedRenderer.call(this, renderedValue)
84
+ : renderedValue;
79
85
  };
80
- },
86
+ }
81
87
  });
82
88
 
83
89
  /*
@@ -90,93 +96,93 @@ default.
90
96
  */
91
97
 
92
98
  /**
93
- * @private
94
- * @class Ext.ux.layout.component.field.CodeMirror
95
- * @extends Ext.layout.component.field.Field
96
- * @author Adrian Teodorescu (ateodorescu@gmail.com)
97
- *
98
- * Layout class for {@link Ext.ux.form.field.CodeMirror} fields. Handles sizing the codemirror field.
99
- */
100
- Ext.define('Ext.ux.layout.component.field.CodeMirror', {
101
- extend: 'Ext.layout.component.Auto',
102
- alias: ['layout.codemirror'],
103
-
104
- type: 'codemirror',
105
-
106
- beginLayout: function(ownerContext) {
107
- this.callParent(arguments);
108
-
109
- ownerContext.textAreaContext = ownerContext.getEl('textareaEl');
110
- ownerContext.editorContext = ownerContext.getEl('editorEl');
111
- },
99
+ * @private
100
+ * @class Ext.ux.layout.component.field.CodeMirror
101
+ * @extends Ext.layout.component.field.Field
102
+ * @author Adrian Teodorescu (ateodorescu@gmail.com)
103
+ *
104
+ * Layout class for {@link Ext.ux.form.field.CodeMirror} fields. Handles sizing the codemirror field.
105
+ */
106
+ Ext.define("Ext.ux.layout.component.field.CodeMirror", {
107
+ extend: "Ext.layout.component.Auto",
108
+ alias: ["layout.codemirror"],
109
+
110
+ type: "codemirror",
111
+
112
+ beginLayout(ownerContext) {
113
+ this.callParent(arguments);
114
+
115
+ ownerContext.textAreaContext = ownerContext.getEl("textareaEl");
116
+ ownerContext.editorContext = ownerContext.getEl("editorEl");
117
+ },
112
118
 
113
- renderItems: Ext.emptyFn,
119
+ renderItems: Ext.emptyFn,
114
120
 
115
- getRenderTarget: function() {
116
- return this.owner.bodyEl;
117
- },
121
+ getRenderTarget() {
122
+ return this.owner.bodyEl;
123
+ },
118
124
 
119
- publishInnerHeight: function (ownerContext, height) {
120
- var me = this,
121
- innerHeight = height - me.measureLabelErrorHeight(ownerContext) -
122
- ownerContext.bodyCellContext.getPaddingInfo().height;
123
- if (Ext.isNumber(innerHeight)) {
124
- ownerContext.textAreaContext.setHeight(innerHeight);
125
- ownerContext.editorContext.setHeight(innerHeight);
126
- } else {
127
- me.done = false;
128
- }
129
- },
125
+ publishInnerHeight(ownerContext, height) {
126
+ const me = this,
127
+ innerHeight =
128
+ height -
129
+ me.measureLabelErrorHeight(ownerContext) -
130
+ ownerContext.bodyCellContext.getPaddingInfo().height;
131
+ if (Ext.isNumber(innerHeight)) {
132
+ ownerContext.textAreaContext.setHeight(innerHeight);
133
+ ownerContext.editorContext.setHeight(innerHeight);
134
+ } else {
135
+ me.done = false;
136
+ }
137
+ },
130
138
 
131
- publishInnerWidth: function (ownerContext, width) {
132
- var me = this;
139
+ publishInnerWidth(ownerContext, width) {
140
+ const me = this;
133
141
 
134
- if (Ext.isNumber(width)) {
135
- ownerContext.textAreaContext.setWidth(width);
136
- ownerContext.editorContext.setWidth(width);
137
- } else {
138
- me.done = false;
139
- }
142
+ if (Ext.isNumber(width)) {
143
+ ownerContext.textAreaContext.setWidth(width);
144
+ ownerContext.editorContext.setWidth(width);
145
+ } else {
146
+ me.done = false;
140
147
  }
148
+ }
141
149
  });
142
150
 
143
- Ext.define('Ext.ux.form.field.CodeMirror', {
144
- extend: 'Ext.Component',
145
- mixins: {
146
- labelable: 'Ext.form.Labelable',
147
- field: 'Ext.form.field.Field'
148
- },
149
- alias: 'widget.codemirror',
150
- alternateClassName: 'Ext.form.CodeMirror',
151
- requires: [
152
- 'Ext.tip.QuickTipManager',
153
- 'Ext.util.Format',
154
- 'Ext.ux.layout.component.field.CodeMirror'
155
- ],
156
-
157
- childEls: [
158
- 'editorEl', 'textareaEl'
159
- ],
160
-
161
- fieldSubTpl: [
162
- '<textarea id="{cmpId}-textareaEl" name="{name}" tabIndex="-1" class="{textareaCls}" ',
163
- 'style="{size}" autocomplete="off"></textarea>',
164
- '<div id="{cmpId}-editorEl" class="{editorCls}" name="{editorName}" style="{size}"></div>',
165
- {
166
- disableFormats: true
167
- }
168
- ],
151
+ Ext.define("Ext.ux.form.field.CodeMirror", {
152
+ extend: "Ext.Component",
153
+ mixins: {
154
+ labelable: "Ext.form.Labelable",
155
+ field: "Ext.form.field.Field"
156
+ },
157
+ alias: "widget.codemirror",
158
+ alternateClassName: "Ext.form.CodeMirror",
159
+ requires: [
160
+ "Ext.tip.QuickTipManager",
161
+ "Ext.util.Format",
162
+ "Ext.ux.layout.component.field.CodeMirror"
163
+ ],
164
+
165
+ childEls: ["editorEl", "textareaEl"],
166
+
167
+ fieldSubTpl: [
168
+ '<textarea id="{cmpId}-textareaEl" name="{name}" tabIndex="-1" class="{textareaCls}" ',
169
+ 'style="{size}" autocomplete="off"></textarea>',
170
+ '<div id="{cmpId}-editorEl" class="{editorCls}" name="{editorName}" style="{size}"></div>',
171
+ {
172
+ disableFormats: true
173
+ }
174
+ ],
169
175
 
170
- // FIXME: the layout mechanism is currently busted
171
- // componentLayout: 'codemirror',
176
+ // FIXME: the layout mechanism is currently busted
177
+ // componentLayout: 'codemirror',
172
178
 
173
- editorWrapCls: Ext.baseCSSPrefix + 'html-editor-wrap',
179
+ editorWrapCls: Ext.baseCSSPrefix + "html-editor-wrap",
174
180
 
175
- maskOnDisable: true,
181
+ maskOnDisable: true,
176
182
 
177
- afterBodyEl: '</div>',
183
+ afterBodyEl: "</div>",
178
184
 
179
- /*
185
+ /*
180
186
  // map tabs to 4 spaces -- arman (doesn't work - may need new version)
181
187
  extraKeys: {
182
188
  "Tab": function() {
@@ -185,597 +191,643 @@ Ext.define('Ext.ux.form.field.CodeMirror', {
185
191
  },
186
192
  */
187
193
 
188
- /**
189
- * @cfg {String} mode The default mode to use when the editor is initialized. When not given, this will default to the first mode that was loaded.
190
- * It may be a string, which either simply names the mode or is a MIME type associated with the mode. Alternatively,
191
- * it may be an object containing configuration options for the mode, with a name property that names the mode
192
- * (for example {name: "javascript", json: true}). The demo pages for each mode contain information about what
193
- * configuration parameters the mode supports.
194
- */
195
- mode: 'text/plain',
196
-
197
- /**
198
- * @cfg {Boolean} showAutoIndent Enable auto indent button for indenting the selected range
199
- */
200
- showAutoIndent: true,
201
-
202
- /**
203
- * @cfg {Boolean} showLineNumbers Enable line numbers button in the toolbar.
204
- */
205
- showLineNumbers: true,
206
-
207
- /**
208
- * @cfg {Boolean} enableMatchBrackets Force matching-bracket-highlighting to happen
209
- */
210
- enableMatchBrackets: true,
211
-
212
- /**
213
- * @cfg {Boolean} enableElectricChars Configures whether the editor should re-indent the current line when a character is typed
214
- * that might change its proper indentation (only works if the mode supports indentation).
215
- */
216
- enableElectricChars: false,
217
-
218
- /**
219
- * @cfg {Boolean} enableIndentWithTabs Whether, when indenting, the first N*tabSize spaces should be replaced by N tabs.
220
- */
221
- enableIndentWithTabs: true,
222
-
223
- /**
224
- * @cfg {Boolean} enableSmartIndent Whether to use the context-sensitive indentation that the mode provides (or just indent the same as the line before).
225
- */
226
- enableSmartIndent: true,
227
-
228
- /**
229
- * @cfg {Boolean} enableLineWrapping Whether CodeMirror should scroll or wrap for long lines.
230
- */
231
- enableLineWrapping: false,
232
-
233
- /**
234
- * @cfg {Boolean} enableLineNumbers Whether to show line numbers to the left of the editor.
235
- */
236
- enableLineNumbers: true,
237
-
238
- /**
239
- * @cfg {Boolean} enableGutter Can be used to force a 'gutter' (empty space on the left of the editor) to be shown even
240
- * when no line numbers are active. This is useful for setting markers.
241
- */
242
- enableGutter: true,
243
-
244
- /**
245
- * @cfg {Boolean} enableFixedGutter When enabled (off by default), this will make the gutter stay visible when the
246
- * document is scrolled horizontally.
247
- */
248
- enableFixedGutter: false,
249
-
250
- /**
251
- * @cfg {Number} firstLineNumber At which number to start counting lines.
252
- */
253
- firstLineNumber: 1,
254
-
255
- /**
256
- * @cfg {Boolean} readOnly <tt>true</tt> to mark the field as readOnly.
257
- */
258
- readOnly : false,
259
-
260
- /**
261
- * @cfg {Number} pollInterval Indicates how quickly (miliseconds) CodeMirror should poll its input textarea for changes.
262
- * Most input is captured by events, but some things, like IME input on some browsers, doesn't generate events
263
- * that allow CodeMirror to properly detect it. Thus, it polls.
264
- */
265
- pollInterval: 100,
266
-
267
- /**
268
- * @cfg {Number} indentUnit How many spaces a block (whatever that means in the edited language) should be indented.
269
- */
270
- indentUnit: 4,
271
-
272
- /**
273
- * @cfg {Number} tabSize The width of a tab character.
274
- */
275
- tabSize: 4,
276
-
277
- /**
278
- * @cfg {String} theme The theme to style the editor with. You must make sure the CSS file defining the corresponding
279
- * .cm-s-[name] styles is loaded (see the theme directory in the distribution). The default is "default", for which
280
- * colors are included in codemirror.css. It is possible to use multiple theming classes at once—for example
281
- * "foo bar" will assign both the cm-s-foo and the cm-s-bar classes to the editor.
282
- */
283
- theme: 'default',
284
-
285
- /**
286
- * @property {String} pathModes Path to the modes folder to dinamically load the required scripts. You could also
287
- * include all your required modes in a big script file and this path will be ignored.
288
- * Do not fill in the trailing slash.
289
- */
290
- pathModes: 'mode',
291
-
292
- /**
293
- * @property {String} pathExtensions Path to the extensions folder to dinamically load the required scripts. You could also
294
- * include all your required extensions in a big script file and this path will be ignored.
295
- * Do not fill in the trailing slash.
296
- */
297
- pathExtensions: 'lib/util',
298
-
299
- /**
300
- * @property {Array} extensions Define here extensions script dependencies; This is used by toolbar buttons to automatically
301
- * load the scripts before using an extension.
302
- */
303
- extensions:{
304
- format: {
305
- dependencies: ['formatting.js']
306
- }
307
- },
194
+ /**
195
+ * @cfg {String} mode The default mode to use when the editor is initialized. When not given, this will default to the first mode that was loaded.
196
+ * It may be a string, which either simply names the mode or is a MIME type associated with the mode. Alternatively,
197
+ * it may be an object containing configuration options for the mode, with a name property that names the mode
198
+ * (for example {name: "javascript", json: true}). The demo pages for each mode contain information about what
199
+ * configuration parameters the mode supports.
200
+ */
201
+ mode: "text/plain",
202
+
203
+ /**
204
+ * @cfg {Boolean} showAutoIndent Enable auto indent button for indenting the selected range
205
+ */
206
+ showAutoIndent: true,
207
+
208
+ /**
209
+ * @cfg {Boolean} showLineNumbers Enable line numbers button in the toolbar.
210
+ */
211
+ showLineNumbers: true,
212
+
213
+ /**
214
+ * @cfg {Boolean} enableMatchBrackets Force matching-bracket-highlighting to happen
215
+ */
216
+ enableMatchBrackets: true,
217
+
218
+ /**
219
+ * @cfg {Boolean} enableElectricChars Configures whether the editor should re-indent the current line when a character is typed
220
+ * that might change its proper indentation (only works if the mode supports indentation).
221
+ */
222
+ enableElectricChars: false,
223
+
224
+ /**
225
+ * @cfg {Boolean} enableIndentWithTabs Whether, when indenting, the first N*tabSize spaces should be replaced by N tabs.
226
+ */
227
+ enableIndentWithTabs: true,
228
+
229
+ /**
230
+ * @cfg {Boolean} enableSmartIndent Whether to use the context-sensitive indentation that the mode provides (or just indent the same as the line before).
231
+ */
232
+ enableSmartIndent: true,
233
+
234
+ /**
235
+ * @cfg {Boolean} enableLineWrapping Whether CodeMirror should scroll or wrap for long lines.
236
+ */
237
+ enableLineWrapping: false,
238
+
239
+ /**
240
+ * @cfg {Boolean} enableLineNumbers Whether to show line numbers to the left of the editor.
241
+ */
242
+ enableLineNumbers: true,
243
+
244
+ /**
245
+ * @cfg {Boolean} enableGutter Can be used to force a 'gutter' (empty space on the left of the editor) to be shown even
246
+ * when no line numbers are active. This is useful for setting markers.
247
+ */
248
+ enableGutter: true,
249
+
250
+ /**
251
+ * @cfg {Boolean} enableFixedGutter When enabled (off by default), this will make the gutter stay visible when the
252
+ * document is scrolled horizontally.
253
+ */
254
+ enableFixedGutter: false,
255
+
256
+ /**
257
+ * @cfg {Number} firstLineNumber At which number to start counting lines.
258
+ */
259
+ firstLineNumber: 1,
260
+
261
+ /**
262
+ * @cfg {Boolean} readOnly <tt>true</tt> to mark the field as readOnly.
263
+ */
264
+ readOnly: false,
265
+
266
+ /**
267
+ * @cfg {Number} pollInterval Indicates how quickly (miliseconds) CodeMirror should poll its input textarea for changes.
268
+ * Most input is captured by events, but some things, like IME input on some browsers, doesn't generate events
269
+ * that allow CodeMirror to properly detect it. Thus, it polls.
270
+ */
271
+ pollInterval: 100,
272
+
273
+ /**
274
+ * @cfg {Number} indentUnit How many spaces a block (whatever that means in the edited language) should be indented.
275
+ */
276
+ indentUnit: 4,
277
+
278
+ /**
279
+ * @cfg {Number} tabSize The width of a tab character.
280
+ */
281
+ tabSize: 4,
282
+
283
+ /**
284
+ * @cfg {String} theme The theme to style the editor with. You must make sure the CSS file defining the corresponding
285
+ * .cm-s-[name] styles is loaded (see the theme directory in the distribution). The default is "default", for which
286
+ * colors are included in codemirror.css. It is possible to use multiple theming classes at once—for example
287
+ * "foo bar" will assign both the cm-s-foo and the cm-s-bar classes to the editor.
288
+ */
289
+ theme: "default",
290
+
291
+ /**
292
+ * @property {String} pathModes Path to the modes folder to dinamically load the required scripts. You could also
293
+ * include all your required modes in a big script file and this path will be ignored.
294
+ * Do not fill in the trailing slash.
295
+ */
296
+ pathModes: "mode",
297
+
298
+ /**
299
+ * @property {String} pathExtensions Path to the extensions folder to dinamically load the required scripts. You could also
300
+ * include all your required extensions in a big script file and this path will be ignored.
301
+ * Do not fill in the trailing slash.
302
+ */
303
+ pathExtensions: "lib/util",
304
+
305
+ /**
306
+ * @property {Array} extensions Define here extensions script dependencies; This is used by toolbar buttons to automatically
307
+ * load the scripts before using an extension.
308
+ */
309
+ extensions: {
310
+ format: {
311
+ dependencies: ["formatting.js"]
312
+ }
313
+ },
308
314
 
309
- scriptsLoaded: [],
310
- lastMode: '',
315
+ scriptsLoaded: [],
316
+ lastMode: "",
311
317
 
312
- initComponent : function(){
313
- var me = this;
318
+ initComponent() {
319
+ const me = this;
314
320
 
315
- me.callParent(arguments);
321
+ me.callParent(arguments);
316
322
 
317
- me.initLabelable();
318
- me.initField();
323
+ me.initLabelable();
324
+ me.initField();
319
325
 
320
- /*
326
+ /*
321
327
  Fix resize issues as suggested by user koblass on the Extjs forums
322
328
  http://www.sencha.com/forum/showthread.php?167047-Ext.ux.form.field.CodeMirror-for-Ext-4.x&p=860535&viewfull=1#post860535
323
329
  */
324
- me.on('resize', function() {
325
- if (me.editor) {
326
- me.editor.refresh();
327
- }
328
- }, me);
329
- },
330
-
331
- getMaskTarget: function(){
332
- return this.bodyEl;
333
- },
330
+ me.on(
331
+ "resize",
332
+ function() {
333
+ if (me.editor) {
334
+ me.editor.refresh();
335
+ }
336
+ },
337
+ me
338
+ );
339
+ },
334
340
 
335
- /**
336
- * @private override
337
- */
338
- getSubTplData: function() {
339
- var cssPrefix = Ext.baseCSSPrefix;
340
- return {
341
- $comp : this,
342
- cmpId : this.id,
343
- id : this.getInputId(),
344
- toolbarWrapCls : cssPrefix + 'html-editor-tb',
345
- textareaCls : cssPrefix + 'hidden',
346
- editorCls : cssPrefix + 'codemirror',
347
- editorName : Ext.id(),
348
- //size : 'height:100px;width:100%'
349
- // PennyMac: setting height to 100%.
350
- size : 'height:100%;width:100%',
351
- };
352
- },
341
+ getMaskTarget() {
342
+ return this.bodyEl;
343
+ },
353
344
 
354
- getSubTplMarkup: function() {
355
- return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
356
- },
345
+ /**
346
+ * @private override
347
+ */
348
+ getSubTplData() {
349
+ const cssPrefix = Ext.baseCSSPrefix;
350
+ return {
351
+ $comp: this,
352
+ cmpId: this.id,
353
+ id: this.getInputId(),
354
+ toolbarWrapCls: cssPrefix + "html-editor-tb",
355
+ textareaCls: cssPrefix + "hidden",
356
+ editorCls: cssPrefix + "codemirror",
357
+ editorName: Ext.id(),
358
+ //size : 'height:100px;width:100%'
359
+ // PennyMac: setting height to 100%.
360
+ size: "height:100%;width:100%"
361
+ };
362
+ },
357
363
 
358
- /**
359
- * @private override
360
- */
361
- onRender: function() {
362
- var me = this;
364
+ getSubTplMarkup() {
365
+ return this.getTpl("fieldSubTpl").apply(this.getSubTplData());
366
+ },
363
367
 
364
- me.callParent(arguments);
365
- me.editorEl = me.getEl('editorEl');
366
- me.bodyEl = me.getEl('bodyEl');
368
+ /**
369
+ * @private override
370
+ */
371
+ onRender() {
372
+ const me = this;
367
373
 
368
- me.disableItems(true);
369
- me.initEditor();
374
+ me.callParent(arguments);
375
+ me.editorEl = me.getEl("editorEl");
376
+ me.bodyEl = me.getEl("bodyEl");
370
377
 
371
- me.rendered = true;
372
- },
378
+ me.disableItems(true);
379
+ me.initEditor();
373
380
 
374
- initRenderData: function() {
375
- this.beforeSubTpl = '<div class="' + this.editorWrapCls + '">';
376
- return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
377
- },
381
+ me.rendered = true;
382
+ },
378
383
 
379
- /**
380
- * @private override
381
- */
382
- initEditor : function(){
383
- var me = this;
384
- var mode = me.mode;
385
-
386
- // if no mode is loaded we could get an error like "Object #<Object> has no method 'startState'"
387
- // search mime to find script dependencies
388
- var item = me.getMime(me.mode);
389
- if(item) {
390
- mode = me.getMimeMode(me.mode);
391
- if(!mode){
392
- mode = "text/x-delorean";
393
- }
394
- }
384
+ initRenderData() {
385
+ this.beforeSubTpl = '<div class="' + this.editorWrapCls + '">';
386
+ return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
387
+ },
395
388
 
396
- me.editor = CodeMirror(me.editorEl, {
397
- matchBrackets: me.enableMatchBrackets,
398
- electricChars: me.enableElectricChars,
399
- autoClearEmptyLines:true,
400
- value: me.rawValue || "",
401
- indentUnit: me.indentUnit,
402
- smartIndent: me.enableSmartIndent,
403
- indentWithTabs: me.indentWithTabs,
404
- pollInterval: me.pollInterval,
405
- lineNumbers: me.enableLineNumbers,
406
- lineWrapping: me.enableLineWrapping,
407
- firstLineNumber: me.firstLineNumber,
408
- tabSize: me.tabSize,
409
- gutter: me.enableGutter,
410
- fixedGutter: me.enableFixedGutter,
411
- theme: me.theme,
412
- mode: mode,
413
- onChange: function(editor, tc){
414
- me.checkChange();
415
- //me.fireEvent('change', me, tc.from, tc.to, tc.text, tc.next || null);
416
- },
417
- onCursorActivity: function(editor){
418
- me.fireEvent('cursoractivity', me);
419
- },
420
- onGutterClick: function(editor, line, event){
421
- me.fireEvent('gutterclick', me, line, event);
422
- },
423
- onFocus: function(editor){
424
- me.fireEvent('activate', me);
425
- },
426
- onBlur: function(editor){
427
- me.fireEvent('deactivate', me);
428
- },
429
- onScroll: function(editor){
430
- me.fireEvent('scroll', me);
431
- },
432
- onHighlightComplete: function(editor){
433
- me.fireEvent('highlightcomplete', me);
434
- },
435
- onUpdate: function(editor){
436
- me.fireEvent('update', me);
437
- },
438
- onKeyEvent: function(editor, event){
439
- event.cancelBubble = true; // fix suggested by koblass user on Sencha forums (http://www.sencha.com/forum/showthread.php?167047-Ext.ux.form.field.CodeMirror-for-Ext-4.x&p=862029&viewfull=1#post862029)
440
- me.fireEvent('keyevent', me, event);
441
- }
442
- });
443
- //me.editor.setValue(me.rawValue);
444
- me.setMode(me.mode);
445
- me.setReadOnly(me.readOnly);
446
- me.fireEvent('initialize', me);
447
-
448
- // change the codemirror css
449
- var css = Ext.util.CSS.getRule('.CodeMirror');
450
- if(css){
451
- css.style.height = '100%';
452
- css.style.position = 'relative';
453
- css.style.overflow = 'hidden';
454
- }
455
- var css = Ext.util.CSS.getRule('.CodeMirror-Scroll');
456
- if(css){
457
- css.style.height = '100%';
458
- }
389
+ /**
390
+ * @private override
391
+ */
392
+ initEditor() {
393
+ const me = this;
394
+ let mode = me.mode;
395
+
396
+ // if no mode is loaded we could get an error like "Object #<Object> has no method 'startState'"
397
+ // search mime to find script dependencies
398
+ const item = me.getMime(me.mode);
399
+ if (item) {
400
+ mode = me.getMimeMode(me.mode);
401
+ if (!mode) {
402
+ mode = "text/x-delorean";
403
+ }
404
+ }
459
405
 
460
- // PennyMac: align the body to the top. Otherwise it ends up
461
- // in the center of the enclosing table.
462
- var el = document.getElementById(me.bodyEl.id);
463
- el.setAttribute("valign", "top");
464
- },
406
+ me.editor = CodeMirror(me.editorEl, {
407
+ matchBrackets: me.enableMatchBrackets,
408
+ electricChars: me.enableElectricChars,
409
+ autoClearEmptyLines: true,
410
+ value: me.rawValue || "",
411
+ indentUnit: me.indentUnit,
412
+ smartIndent: me.enableSmartIndent,
413
+ indentWithTabs: me.indentWithTabs,
414
+ pollInterval: me.pollInterval,
415
+ lineNumbers: me.enableLineNumbers,
416
+ lineWrapping: me.enableLineWrapping,
417
+ firstLineNumber: me.firstLineNumber,
418
+ tabSize: me.tabSize,
419
+ gutter: me.enableGutter,
420
+ fixedGutter: me.enableFixedGutter,
421
+ theme: me.theme,
422
+ mode,
423
+ onChange() {
424
+ me.checkChange();
425
+ //me.fireEvent('change', me, tc.from, tc.to, tc.text, tc.next || null);
426
+ },
427
+ onCursorActivity() {
428
+ me.fireEvent("cursoractivity", me);
429
+ },
430
+ onGutterClick(editor, line, event) {
431
+ me.fireEvent("gutterclick", me, line, event);
432
+ },
433
+ onFocus() {
434
+ me.fireEvent("activate", me);
435
+ },
436
+ onBlur() {
437
+ me.fireEvent("deactivate", me);
438
+ },
439
+ onScroll() {
440
+ me.fireEvent("scroll", me);
441
+ },
442
+ onHighlightComplete() {
443
+ me.fireEvent("highlightcomplete", me);
444
+ },
445
+ onUpdate() {
446
+ me.fireEvent("update", me);
447
+ },
448
+ onKeyEvent(editor, event) {
449
+ event.cancelBubble = true; // fix suggested by koblass user on Sencha forums (http://www.sencha.com/forum/showthread.php?167047-Ext.ux.form.field.CodeMirror-for-Ext-4.x&p=862029&viewfull=1#post862029)
450
+ me.fireEvent("keyevent", me, event);
451
+ }
452
+ });
453
+ //me.editor.setValue(me.rawValue);
454
+ me.setMode(me.mode);
455
+ me.setReadOnly(me.readOnly);
456
+ me.fireEvent("initialize", me);
457
+
458
+ // change the codemirror css
459
+ const css1 = Ext.util.CSS.getRule(".CodeMirror");
460
+ if (css1) {
461
+ css1.style.height = "100%";
462
+ css1.style.position = "relative";
463
+ css1.style.overflow = "hidden";
464
+ }
465
465
 
466
- /**
467
- * @private
468
- */
469
- relayBtnCmd: function(btn){
470
- this.relayCmd(btn.getItemId());
471
- },
466
+ const css2 = Ext.util.CSS.getRule(".CodeMirror-Scroll");
467
+ if (css2) {
468
+ css2.style.height = "100%";
469
+ }
472
470
 
473
- /**
474
- * @private
475
- */
476
- relayCmd: function(cmd){
477
- Ext.defer(function() {
478
- var me = this;
479
- me.editor.focus();
480
- switch(cmd){
481
- // auto formatting
482
- case 'justifycenter':
483
- if(!CodeMirror.extensions.autoIndentRange){
484
- me.loadDependencies(me.extensions.format, me.pathExtensions, me.doIndentSelection, me);
485
- }else{
486
- me.doIndentSelection();
487
- }
488
- break;
489
-
490
- // line numbers
491
- case 'insertorderedlist':
492
- me.doChangeLineNumbers();
493
- break;
494
- }
495
- }, 10, this);
496
- },
471
+ // PennyMac: align the body to the top. Otherwise it ends up
472
+ // in the center of the enclosing table.
473
+ const el = document.getElementById(me.bodyEl.id);
474
+ el.setAttribute("valign", "top");
475
+ },
497
476
 
498
- /**
499
- * @private
500
- * Reload all CodeMirror extensions for the current instance;
501
- *
502
- */
503
- reloadExtentions: function(){
504
- var me = this;
477
+ /**
478
+ * @private
479
+ */
480
+ relayBtnCmd(btn) {
481
+ this.relayCmd(btn.getItemId());
482
+ },
505
483
 
506
- for (var ext in CodeMirror.extensions)
507
- if (CodeMirror.extensions.propertyIsEnumerable(ext) &&
508
- !me.editor.propertyIsEnumerable(ext))
509
- me.editor[ext] = CodeMirror.extensions[ext];
510
- },
484
+ /**
485
+ * @private
486
+ */
487
+ relayCmd(cmd) {
488
+ Ext.defer(
489
+ function() {
490
+ const me = this;
491
+ me.editor.focus();
492
+ switch (cmd) {
493
+ // auto formatting
494
+ case "justifycenter":
495
+ if (!CodeMirror.extensions.autoIndentRange) {
496
+ me.loadDependencies(
497
+ me.extensions.format,
498
+ me.pathExtensions,
499
+ me.doIndentSelection,
500
+ me
501
+ );
502
+ } else {
503
+ me.doIndentSelection();
504
+ }
505
+ break;
511
506
 
512
- doChangeLineNumbers: function(){
513
- var me = this;
507
+ // line numbers
508
+ case "insertorderedlist":
509
+ me.doChangeLineNumbers();
510
+ break;
511
+ }
512
+ },
513
+ 10,
514
+ this
515
+ );
516
+ },
514
517
 
515
- me.enableLineNumbers = !me.enableLineNumbers;
516
- me.editor.setOption('lineNumbers', me.enableLineNumbers);
517
- },
518
+ /**
519
+ * @private
520
+ * Reload all CodeMirror extensions for the current instance;
521
+ *
522
+ */
523
+ reloadExtentions() {
524
+ const me = this;
525
+
526
+ for (const ext in CodeMirror.extensions)
527
+ if (
528
+ Object.prototype.propertyIsEnumerable.call(
529
+ CodeMirror.extensions,
530
+ ext
531
+ ) &&
532
+ !Object.prototype.propertyIsEnumerable.call(me.editor, ext)
533
+ )
534
+ me.editor[ext] = CodeMirror.extensions[ext];
535
+ },
518
536
 
519
- /**
520
- * @private
521
- */
522
- doIndentSelection: function(){
523
- var me = this;
537
+ doChangeLineNumbers() {
538
+ const me = this;
524
539
 
525
- me.reloadExtentions();
540
+ me.enableLineNumbers = !me.enableLineNumbers;
541
+ me.editor.setOption("lineNumbers", me.enableLineNumbers);
542
+ },
526
543
 
527
- try{
528
- var range = { from: me.editor.getCursor(true), to: me.editor.getCursor(false) };
529
- me.editor.autoIndentRange(range.from, range.to);
530
- }catch(err){}
531
- },
544
+ /**
545
+ * @private
546
+ */
547
+ doIndentSelection() {
548
+ const me = this;
549
+
550
+ me.reloadExtentions();
551
+
552
+ try {
553
+ const range = {
554
+ from: me.editor.getCursor(true),
555
+ to: me.editor.getCursor(false)
556
+ };
557
+ me.editor.autoIndentRange(range.from, range.to);
558
+ } catch (err) {
559
+ // do nothing
560
+ }
561
+ },
532
562
 
533
- modes: [
534
- {
535
- mime: CodeMirror.mimeModes,
536
- dependencies: []
537
- },
538
- ],
563
+ modes: [
564
+ {
565
+ mime: CodeMirror.mimeModes,
566
+ dependencies: []
567
+ }
568
+ ],
569
+
570
+ /**
571
+ * @private
572
+ */
573
+ getMime(mime) {
574
+ const me = this;
575
+ let item,
576
+ found = false;
577
+
578
+ for (let i = 0; i < me.modes.length; i++) {
579
+ item = me.modes[i];
580
+ if (Ext.isArray(item.mime)) {
581
+ if (Ext.Array.contains(item.mime, mime)) {
582
+ found = true;
583
+ break;
584
+ }
585
+ } else {
586
+ if (item == mime) {
587
+ found = true;
588
+ break;
589
+ }
590
+ }
591
+ }
592
+ if (found) return item;
593
+ else return null;
594
+ },
539
595
 
540
- /**
541
- * @private
542
- */
543
- getMime: function(mime){
544
- var me = this, item, found = false;
545
-
546
- for(var i=0;i<me.modes.length;i++){
547
- item = me.modes[i];
548
- if(Ext.isArray(item.mime)){
549
- if(Ext.Array.contains(item.mime, mime)){
550
- found = true;
551
- break;
552
- }
553
- }else{
554
- if(item == mime){
555
- found = true;
556
- break;
596
+ /**
597
+ * @private
598
+ */
599
+ loadDependencies(item, path, handler, scope) {
600
+ const me = this;
601
+
602
+ me.scripts = [];
603
+ me.scriptIndex = -1;
604
+
605
+ // load the dependencies
606
+ for (let i = 0; i < item.dependencies.length; i++) {
607
+ if (
608
+ !Ext.Array.contains(me.scriptsLoaded, path + "/" + item.dependencies[i])
609
+ ) {
610
+ const options = {
611
+ url: path + "/" + item.dependencies[i],
612
+ index: ++me.scriptIndex,
613
+ onLoad() {
614
+ let ok = true;
615
+ for (let j = 0; j < me.scripts.length; j++) {
616
+ if (me.scripts[j].called) {
617
+ // this event could be raised before one script if fetched
618
+ ok = ok && me.scripts[j].success;
619
+ if (
620
+ me.scripts[j].success &&
621
+ !Ext.Array.contains(me.scriptsLoaded, me.scripts[j].url)
622
+ ) {
623
+ me.scriptsLoaded.push(me.scripts[j].url);
557
624
  }
625
+ } else {
626
+ ok = false;
627
+ }
558
628
  }
559
- }
560
- if(found)
561
- return item;
562
- else
563
- return null;
564
- },
565
-
566
- /**
567
- * @private
568
- */
569
- loadDependencies: function(item, path, handler, scope){
570
- var me = this;
571
-
572
- me.scripts = [];
573
- me.scriptIndex = -1;
574
-
575
- // load the dependencies
576
- for(var i=0; i < item.dependencies.length; i++){
577
- if(!Ext.Array.contains(me.scriptsLoaded, path + '/' + item.dependencies[i])){
578
- var options = {
579
- url: path + '/' + item.dependencies[i],
580
- index: ++me.scriptIndex,
581
- onLoad: function(options){
582
- var ok = true;
583
- for(j=0; j < me.scripts.length; j++){
584
- if(me.scripts[j].called) {// this event could be raised before one script if fetched
585
- ok = ok && me.scripts[j].success;
586
- if(me.scripts[j].success && !Ext.Array.contains(me.scriptsLoaded, me.scripts[j].url)){
587
- me.scriptsLoaded.push(me.scripts[j].url);
588
- }
589
- }else{
590
- ok = false;
591
- }
592
- }
593
- if(ok){
594
- handler.call(scope || me.editor);
595
- }
596
- }
597
- };
598
-
599
- me.scripts[me.scriptIndex] = {
600
- url: options.url,
601
- success: true,
602
- called: false,
603
- options: options,
604
- onLoad: options.onLoad || Ext.emptyFn,
605
- onError: options.onError || Ext.emptyFn
606
- };
629
+ if (ok) {
630
+ handler.call(scope || me.editor);
607
631
  }
608
- }
609
- for(var i=0; i < me.scripts.length; i++){
610
- me.loadScript(me.scripts[i].options);
611
- }
612
- },
632
+ }
633
+ };
613
634
 
614
- /**
615
- * @private
616
- */
617
- loadScript: function(options){
618
- var me = this;
619
- Ext.Ajax.request({
620
- url: options.url,
621
- scriptIndex: options.index,
622
- success: function(response, options) {
623
- var script = 'Ext.getCmp("' + this.id + '").scripts[' + options.scriptIndex + ']';
624
- window.setTimeout('try { ' + response.responseText + ' } catch(e) { '+script+'.success = false; '+script+'.onError('+script+'.options, e); }; ' + script + '.called = true; if ('+script+'.success) '+script+'.onLoad('+script+'.options);', 0);
625
- },
626
- failure: function(response, options) {
627
- var script = this.scripts[options.scriptIndex];
628
- script.success = false;
629
- script.called = true;
630
- script.onError(script.options, response.status);
631
- },
632
- scope: me
633
- });
634
- },
635
+ me.scripts[me.scriptIndex] = {
636
+ url: options.url,
637
+ success: true,
638
+ called: false,
639
+ options,
640
+ onLoad: options.onLoad || Ext.emptyFn,
641
+ onError: options.onError || Ext.emptyFn
642
+ };
643
+ }
644
+ }
635
645
 
636
- /**
637
- * @private
638
- * Return mode depending on the mime; If the mime is not loaded then return null
639
- *
640
- * @param mime
641
- */
642
- getMimeMode: function(mime){
643
- var mode = null;
644
- var mimes = CodeMirror.mimeModes;
645
- for(var i=0; i<mimes.length; i++){
646
- if(mimes[i].mime == mime){
647
- mode = mimes[i].mode;
648
- if(typeof mode == "object")
649
- mode = mode.name;
650
- break;
651
- }
652
- }
653
- return mode;
654
- },
646
+ for (let k = 0; k < me.scripts.length; k++) {
647
+ me.loadScript(me.scripts[k].options);
648
+ }
649
+ },
655
650
 
656
- /**
657
- * Change the CodeMirror mode to the specified mime.
658
- *
659
- * @param {String} mime The MIME value according to the CodeMirror documentation
660
- */
661
- setMode: function(mime){
662
- var me = this,
663
- found = false;
664
- // search mime to find script dependencies
665
- var item = me.getMime(mime);
666
-
667
- if(!item) {
668
- // mime not found
669
- return;
670
- }
651
+ /**
652
+ * @private
653
+ */
654
+ loadScript(options) {
655
+ const me = this;
656
+ Ext.Ajax.request({
657
+ url: options.url,
658
+ scriptIndex: options.index,
659
+ success(response, options) {
660
+ const script =
661
+ 'Ext.getCmp("' + this.id + '").scripts[' + options.scriptIndex + "]";
662
+ window.setTimeout(
663
+ "try { " +
664
+ response.responseText +
665
+ " } catch(e) { " +
666
+ script +
667
+ ".success = false; " +
668
+ script +
669
+ ".onError(" +
670
+ script +
671
+ ".options, e); }; " +
672
+ script +
673
+ ".called = true; if (" +
674
+ script +
675
+ ".success) " +
676
+ script +
677
+ ".onLoad(" +
678
+ script +
679
+ ".options);",
680
+ 0
681
+ );
682
+ },
683
+ failure(response, options) {
684
+ const script = this.scripts[options.scriptIndex];
685
+ script.success = false;
686
+ script.called = true;
687
+ script.onError(script.options, response.status);
688
+ },
689
+ scope: me
690
+ });
691
+ },
671
692
 
672
- var mode = me.getMimeMode(mime);
673
-
674
- if(!mode){
675
- me.loadDependencies(item, me.pathModes, function(){
676
- var mode = me.getMimeMode(mime);
677
- if(typeof mode == "string")
678
- me.editor.setOption('mode', mime);
679
- else
680
- me.editor.setOption('mode', mode);
681
- });
682
- }else{
683
- if(typeof mode == "string")
684
- me.editor.setOption('mode', mime);
685
- else
686
- me.editor.setOption('mode', mode);
687
- }
693
+ /**
694
+ * @private
695
+ * Return mode depending on the mime; If the mime is not loaded then return null
696
+ *
697
+ * @param mime
698
+ */
699
+ getMimeMode(mime) {
700
+ let mode = null;
701
+ const mimes = CodeMirror.mimeModes;
702
+ for (let i = 0; i < mimes.length; i++) {
703
+ if (mimes[i].mime == mime) {
704
+ mode = mimes[i].mode;
705
+ if (typeof mode == "object") mode = mode.name;
706
+ break;
707
+ }
708
+ }
709
+ return mode;
710
+ },
688
711
 
689
- if(me.modesSelect){
690
- me.modesSelect.dom.value = mime;
691
- }
692
- try{
693
- me.fireEvent('modechanged', me, mime, me.lastMode);
694
- me.lastMode = mime;
695
- }catch(err){}
696
- },
712
+ /**
713
+ * Change the CodeMirror mode to the specified mime.
714
+ *
715
+ * @param {String} mime The MIME value according to the CodeMirror documentation
716
+ */
717
+ setMode(mime) {
718
+ const me = this;
719
+ // found = false;
720
+ // search mime to find script dependencies
721
+ const item = me.getMime(mime);
722
+
723
+ if (!item) {
724
+ // mime not found
725
+ return;
726
+ }
697
727
 
698
- /**
699
- * Set the editor as read only
700
- *
701
- * @param {Boolean} readOnly
702
- */
703
- setReadOnly: function(readOnly) {
704
- var me = this;
728
+ const mode = me.getMimeMode(mime);
729
+
730
+ if (!mode) {
731
+ me.loadDependencies(item, me.pathModes, function() {
732
+ const mode = me.getMimeMode(mime);
733
+ if (typeof mode == "string") me.editor.setOption("mode", mime);
734
+ else me.editor.setOption("mode", mode);
735
+ });
736
+ } else {
737
+ if (typeof mode == "string") me.editor.setOption("mode", mime);
738
+ else me.editor.setOption("mode", mode);
739
+ }
705
740
 
706
- if(me.editor){
707
- me.editor.setOption('readOnly', readOnly);
708
- me.disableItems(readOnly);
709
- }
710
- },
741
+ if (me.modesSelect) {
742
+ me.modesSelect.dom.value = mime;
743
+ }
744
+ try {
745
+ me.fireEvent("modechanged", me, mime, me.lastMode);
746
+ me.lastMode = mime;
747
+ } catch (err) {
748
+ // do nothing
749
+ }
750
+ },
711
751
 
712
- onDisable: function() {
713
- this.bodyEl.mask();
714
- this.callParent(arguments);
715
- },
752
+ /**
753
+ * Set the editor as read only
754
+ *
755
+ * @param {Boolean} readOnly
756
+ */
757
+ setReadOnly(readOnly) {
758
+ const me = this;
759
+
760
+ if (me.editor) {
761
+ me.editor.setOption("readOnly", readOnly);
762
+ me.disableItems(readOnly);
763
+ }
764
+ },
716
765
 
717
- onEnable: function() {
718
- this.bodyEl.unmask();
719
- this.callParent(arguments);
720
- },
766
+ onDisable() {
767
+ this.bodyEl.mask();
768
+ this.callParent(arguments);
769
+ },
721
770
 
722
- disableItems: function(disabled) {
723
- },
771
+ onEnable() {
772
+ this.bodyEl.unmask();
773
+ this.callParent(arguments);
774
+ },
724
775
 
725
- /**
726
- * Sets a data value into the field and runs the change detection.
727
- * @param {Mixed} value The value to set
728
- * @return {Ext.ux.form.field.CodeMirror} this
729
- */
730
- setValue: function(value){
731
- var me = this;
732
-
733
- me.mixins.field.setValue.call(me, value);
734
- me.rawValue = value;
735
- if(me.editor)
736
- me.editor.setValue(value);
737
- return me;
738
- },
776
+ disableItems() {},
739
777
 
740
- /**
741
- * Return submit value to the owner form.
742
- * @return {Mixed} The field value
743
- */
744
- getSubmitValue: function(){
745
- var me = this;
746
- return me.getValue();
747
- },
778
+ /**
779
+ * Sets a data value into the field and runs the change detection.
780
+ * @param {Mixed} value The value to set
781
+ * @return {Ext.ux.form.field.CodeMirror} this
782
+ */
783
+ setValue(value) {
784
+ const me = this;
748
785
 
749
- /**
750
- * Return the value of the CodeMirror editor
751
- * @return {Mixed} The field value
752
- */
753
- getValue: function(){
754
- var me = this;
786
+ me.mixins.field.setValue.call(me, value);
787
+ me.rawValue = value;
788
+ if (me.editor) me.editor.setValue(value);
789
+ return me;
790
+ },
755
791
 
756
- if(me.editor)
757
- return me.editor.getValue();
758
- else
759
- return null;
760
- },
792
+ /**
793
+ * Return submit value to the owner form.
794
+ * @return {Mixed} The field value
795
+ */
796
+ getSubmitValue() {
797
+ const me = this;
798
+ return me.getValue();
799
+ },
761
800
 
762
- /**
763
- * @private
764
- */
765
- onDestroy: function(){
766
- var me = this;
767
- if(me.rendered){
768
- try {
769
- Ext.EventManager.removeAll(me.editor);
770
- for (prop in me.editor) {
771
- if (me.editor.hasOwnProperty(prop)) {
772
- delete me.editor[prop];
773
- }
774
- }
775
- }catch(e){}
801
+ /**
802
+ * Return the value of the CodeMirror editor
803
+ * @return {Mixed} The field value
804
+ */
805
+ getValue() {
806
+ const me = this;
807
+
808
+ if (me.editor) return me.editor.getValue();
809
+ else return null;
810
+ },
811
+
812
+ /**
813
+ * @private
814
+ */
815
+ onDestroy() {
816
+ const me = this;
817
+ if (me.rendered) {
818
+ try {
819
+ Ext.EventManager.removeAll(me.editor);
820
+ for (const prop in me.editor) {
821
+ if (Object.prototype.hasOwnProperty.call(me.editor, prop)) {
822
+ delete me.editor[prop];
823
+ }
776
824
  }
777
- me.callParent();
778
- },
825
+ } catch (e) {
826
+ // do nothing
827
+ }
828
+ }
829
+ me.callParent();
830
+ }
779
831
  });
780
832
 
781
833
  // There is an error with code tester. Sometimes the Ext app craches when you click test again after some time passed
@@ -788,144 +840,156 @@ Ext.define('Ext.ux.form.field.CodeMirror', {
788
840
  // check for outerCt.destroyed value. If it's destroyed then it's dom is gone and
789
841
  // and it's style and dimentions are not available
790
842
  // If it's not destroyed go with regular way
791
- Ext.define('Marty.layout.container.Auto', {
792
- override: 'Ext.layout.container.Auto',
793
-
794
- // Sometimes outerCt is already destroyed. in that case it's DOM is null and all methods
795
- // that call DOM should not be called
796
- beginLayoutCycle: function(ownerContext) {
797
- var me = this,
798
- outerCt = me.outerCt,
799
- lastOuterCtWidth = me.lastOuterCtWidth || '',
800
- lastOuterCtHeight = me.lastOuterCtHeight || '',
801
- lastOuterCtTableLayout = me.lastOuterCtTableLayout || '',
802
- state = ownerContext.state,
803
- overflowXStyle, outerCtWidth, outerCtHeight, outerCtTableLayout, inheritedStateInner;
804
-
805
- // FIX
806
- //- me.callParent(arguments);
807
- // If callParent would call overriden method, which leads to and exception
808
- // when outerCt is destroyed. In that case we use callSuper, which ignores overriden method.
809
- // If outerCt is not destroyed, then we call overriden method and exit the function. Fixes bellow are not needed
810
- if (outerCt.destroyed) {
811
- me.callSuper(arguments);
812
- } else {
813
- return me.callParent(arguments);
814
- }
815
-
816
- // Default to "shrink wrap styles".
817
- outerCtWidth = outerCtHeight = outerCtTableLayout = '';
818
- if (!ownerContext.widthModel.shrinkWrap) {
819
- // if we're not shrink wrapping width, we need to get the innerCt out of the
820
- // way to avoid any shrink wrapping effect on child items
821
- // fill the available width within the container
822
- outerCtWidth = '100%';
823
- inheritedStateInner = me.owner.inheritedStateInner;
824
- // expand no further than the available width, even if contents are wider
825
- // unless there is a potential for horizontal overflow, then allow
826
- // the outerCt to expand to the width of the contents
827
- overflowXStyle = me.getOverflowXStyle(ownerContext);
828
- outerCtTableLayout = (inheritedStateInner.inShrinkWrapTable || overflowXStyle === 'auto' || overflowXStyle === 'scroll') ? '' : 'fixed';
829
- }
830
- if (!ownerContext.heightModel.shrinkWrap && !Ext.supports.PercentageHeightOverflowBug) {
831
- // if we're not shrink wrapping height, we need to get the outerCt out of the
832
- // way so that percentage height children will be sized correctly. We do this
833
- // by giving the outerCt a height of '100%' unless the browser is affected by
834
- // the "percentage height overflow bug", in which case the outerCt will get a
835
- // pixel height set during the calculate phase after we know the targetEl size.
836
- outerCtHeight = '100%';
837
- }
838
- // if the outerCt width changed since last time (becuase of a widthModel change)
839
- // or if we set a pixel width on the outerCt last time to work around a browser-
840
- // specific bug, we need to set the width of the outerCt
841
- if ((outerCtWidth !== lastOuterCtWidth) || me.hasOuterCtPxWidth) {
842
- // FIX: Added check for !outerCt.destroyed
843
- if (!outerCt.destroyed) {
844
- outerCt.setStyle('width', outerCtWidth);
845
- }
846
- me.lastOuterCtWidth = outerCtWidth;
847
- me.hasOuterCtPxWidth = false;
848
- }
849
- // Set the outerCt table-layout property if different from last time.
850
- if (outerCtTableLayout !== lastOuterCtTableLayout) {
851
- outerCt.setStyle('table-layout', outerCtTableLayout);
852
- me.lastOuterCtTableLayout = outerCtTableLayout;
853
- }
854
- // if the outerCt height changed since last time (becuase of a heightModel change)
855
- // or if we set a pixel height on the outerCt last time to work around a browser-
856
- // specific bug, we need to set the height of the outerCt
857
- if ((outerCtHeight !== lastOuterCtHeight) || me.hasOuterCtPxHeight) {
858
- // FIX: Added check for !outerCt.destroyed
859
- if (!outerCt.destroyed) {
860
- outerCt.setStyle('height', outerCtHeight);
861
- }
862
- me.lastOuterCtHeight = outerCtHeight;
863
- me.hasOuterCtPxHeight = false;
864
- }
865
- if (me.hasInnerCtPxHeight) {
866
- // FIX: Added check for !innerCt.destroyed
867
- if (!me.innerCt.destroyed) {
868
- me.innerCt.setStyle('height', '');
869
- }
870
- me.hasInnerCtPxHeight = false;
871
- }
872
- // Begin with the scrollbar adjustment that we used last time - this is more likely
873
- // to be correct than beginning with no adjustment at all, but only if it is not
874
- // already defined - it may have already been set by invalidate()
875
- state.overflowAdjust = state.overflowAdjust || me.lastOverflowAdjust;
876
- },
843
+ Ext.define("Marty.layout.container.Auto", {
844
+ override: "Ext.layout.container.Auto",
845
+
846
+ // Sometimes outerCt is already destroyed. in that case it's DOM is null and all methods
847
+ // that call DOM should not be called
848
+ beginLayoutCycle(ownerContext) {
849
+ const me = this;
850
+ const outerCt = me.outerCt;
851
+ const lastOuterCtWidth = me.lastOuterCtWidth || "";
852
+ const lastOuterCtHeight = me.lastOuterCtHeight || "";
853
+ const lastOuterCtTableLayout = me.lastOuterCtTableLayout || "";
854
+ const state = ownerContext.state;
855
+ let overflowXStyle;
856
+ let outerCtWidth;
857
+ let outerCtHeight;
858
+ let outerCtTableLayout;
859
+ let inheritedStateInner;
860
+
861
+ // FIX
862
+ //- me.callParent(arguments);
863
+ // If callParent would call overriden method, which leads to and exception
864
+ // when outerCt is destroyed. In that case we use callSuper, which ignores overriden method.
865
+ // If outerCt is not destroyed, then we call overriden method and exit the function. Fixes bellow are not needed
866
+ if (outerCt.destroyed) {
867
+ me.callSuper(arguments);
868
+ } else {
869
+ return me.callParent(arguments);
870
+ }
877
871
 
878
- // The fix checks whether outerCt is destroyed or not
879
- // If it's destroyed, then the dom is gone and calling getHeight() would lead to exception
880
- // set contentHeight to 0 if outerCt is destroyed
881
- measureContentHeight: function(ownerContext) {
882
- // contentHeight includes padding, but not border, framing or margins
883
- // FIX
884
- // var contentHeight = this.outerCt.getHeight();
885
- var contentHeight = this.outerCt.destroyed ? 0 : this.outerCt.getHeight();
886
- // END FIX
887
- var target = ownerContext.target;
888
-
889
- if (this.managePadding && (target[target.contentPaddingProperty] === undefined)) {
890
- // if padding was not configured using the appropriate contentPaddingProperty
891
- // then the padding will not be on the paddingContext, and therfore not included
892
- // in the outerCt measurement, so we need to read the padding from the
893
- // targetContext
894
- contentHeight += ownerContext.targetContext.getPaddingInfo().height;
872
+ // Default to "shrink wrap styles".
873
+ outerCtWidth = outerCtHeight = outerCtTableLayout = "";
874
+ if (!ownerContext.widthModel.shrinkWrap) {
875
+ // if we're not shrink wrapping width, we need to get the innerCt out of the
876
+ // way to avoid any shrink wrapping effect on child items
877
+ // fill the available width within the container
878
+ outerCtWidth = "100%";
879
+ inheritedStateInner = me.owner.inheritedStateInner;
880
+ // expand no further than the available width, even if contents are wider
881
+ // unless there is a potential for horizontal overflow, then allow
882
+ // the outerCt to expand to the width of the contents
883
+ overflowXStyle = me.getOverflowXStyle(ownerContext);
884
+ outerCtTableLayout =
885
+ inheritedStateInner.inShrinkWrapTable ||
886
+ overflowXStyle === "auto" ||
887
+ overflowXStyle === "scroll"
888
+ ? ""
889
+ : "fixed";
890
+ }
891
+ if (
892
+ !ownerContext.heightModel.shrinkWrap &&
893
+ !Ext.supports.PercentageHeightOverflowBug
894
+ ) {
895
+ // if we're not shrink wrapping height, we need to get the outerCt out of the
896
+ // way so that percentage height children will be sized correctly. We do this
897
+ // by giving the outerCt a height of '100%' unless the browser is affected by
898
+ // the "percentage height overflow bug", in which case the outerCt will get a
899
+ // pixel height set during the calculate phase after we know the targetEl size.
900
+ outerCtHeight = "100%";
901
+ }
902
+ // if the outerCt width changed since last time (becuase of a widthModel change)
903
+ // or if we set a pixel width on the outerCt last time to work around a browser-
904
+ // specific bug, we need to set the width of the outerCt
905
+ if (outerCtWidth !== lastOuterCtWidth || me.hasOuterCtPxWidth) {
906
+ // FIX: Added check for !outerCt.destroyed
907
+ if (!outerCt.destroyed) {
908
+ outerCt.setStyle("width", outerCtWidth);
895
909
  }
896
- return contentHeight;
897
- },
910
+ me.lastOuterCtWidth = outerCtWidth;
911
+ me.hasOuterCtPxWidth = false;
912
+ }
913
+ // Set the outerCt table-layout property if different from last time.
914
+ if (outerCtTableLayout !== lastOuterCtTableLayout) {
915
+ outerCt.setStyle("table-layout", outerCtTableLayout);
916
+ me.lastOuterCtTableLayout = outerCtTableLayout;
917
+ }
918
+ // if the outerCt height changed since last time (becuase of a heightModel change)
919
+ // or if we set a pixel height on the outerCt last time to work around a browser-
920
+ // specific bug, we need to set the height of the outerCt
921
+ if (outerCtHeight !== lastOuterCtHeight || me.hasOuterCtPxHeight) {
922
+ // FIX: Added check for !outerCt.destroyed
923
+ if (!outerCt.destroyed) {
924
+ outerCt.setStyle("height", outerCtHeight);
925
+ }
926
+ me.lastOuterCtHeight = outerCtHeight;
927
+ me.hasOuterCtPxHeight = false;
928
+ }
929
+ if (me.hasInnerCtPxHeight) {
930
+ // FIX: Added check for !innerCt.destroyed
931
+ if (!me.innerCt.destroyed) {
932
+ me.innerCt.setStyle("height", "");
933
+ }
934
+ me.hasInnerCtPxHeight = false;
935
+ }
936
+ // Begin with the scrollbar adjustment that we used last time - this is more likely
937
+ // to be correct than beginning with no adjustment at all, but only if it is not
938
+ // already defined - it may have already been set by invalidate()
939
+ state.overflowAdjust = state.overflowAdjust || me.lastOverflowAdjust;
940
+ },
898
941
 
942
+ // The fix checks whether outerCt is destroyed or not
943
+ // If it's destroyed, then the dom is gone and calling getHeight() would lead to exception
944
+ // set contentHeight to 0 if outerCt is destroyed
945
+ measureContentHeight(ownerContext) {
946
+ // contentHeight includes padding, but not border, framing or margins
947
+ // FIX
948
+ // var contentHeight = this.outerCt.getHeight();
949
+ let contentHeight = this.outerCt.destroyed ? 0 : this.outerCt.getHeight();
950
+ // END FIX
951
+ const target = ownerContext.target;
952
+
953
+ if (
954
+ this.managePadding &&
955
+ target[target.contentPaddingProperty] === undefined
956
+ ) {
957
+ // if padding was not configured using the appropriate contentPaddingProperty
958
+ // then the padding will not be on the paddingContext, and therfore not included
959
+ // in the outerCt measurement, so we need to read the padding from the
960
+ // targetContext
961
+ contentHeight += ownerContext.targetContext.getPaddingInfo().height;
962
+ }
963
+ return contentHeight;
964
+ }
899
965
  });
900
966
 
901
- Ext.define('overrides.grid.column.Column', {
902
- override: 'Ext.grid.column.Column',
967
+ Ext.define("overrides.grid.column.Column", {
968
+ override: "Ext.grid.column.Column",
903
969
 
904
- initConfig: function(config) {
905
- if (!config.renderer && !this.updater) {
906
- config.formatter = 'htmlEncode'
907
- }
908
- return this.callParent(arguments)
970
+ initConfig(config) {
971
+ if (!config.renderer && !this.updater) {
972
+ config.formatter = "htmlEncode";
909
973
  }
974
+ return this.callParent(arguments);
910
975
  }
911
- );
912
-
913
- Ext.define('Ext.netzke.marty.MultiSelectCombo', {
914
- extend: 'Ext.form.ComboBox',
915
- alias: 'widget.multiselectcombo',
916
- separator: ",",
917
- multiSelect: true,
918
-
919
- setValue: function(v) {
920
- if (Ext.isString(v)) {
921
- var vArray = v.split(this.separator);
922
- this.callParent([vArray]);
923
- } else {
924
- this.callParent(arguments);
925
- }
926
- },
976
+ });
977
+
978
+ Ext.define("Ext.netzke.marty.MultiSelectCombo", {
979
+ extend: "Ext.form.ComboBox",
980
+ alias: "widget.multiselectcombo",
981
+ separator: ",",
982
+ multiSelect: true,
983
+
984
+ setValue(v) {
985
+ if (Ext.isString(v)) {
986
+ const vArray = v.split(this.separator);
987
+ this.callParent([vArray]);
988
+ } else {
989
+ this.callParent(arguments);
990
+ }
927
991
  }
928
- );
992
+ });
929
993
 
930
994
  // Fix component fetching in ExtJS 7
931
995
  // This flag was false by default in ExtJS 6