Skip to content

Commit af62faf

Browse files
anuragteapotlaoneo
authored andcommitted
[4.0] Fix Codemirror as a custom elements (#20684)
* codemirror fix * eslit style * eslint code style * await * some more hound issues * fix
1 parent 89f1cd6 commit af62faf

File tree

7 files changed

+533
-511
lines changed

7 files changed

+533
-511
lines changed

administrator/language/en-GB/en-GB.plg_editors_codemirror.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,5 @@ PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_SIMPLE="Simple"
3434
PLG_CODEMIRROR_FIELD_VIM_KEYBINDING_LABEL="Vim Keybinding"
3535
PLG_CODEMIRROR_FIELDSET_APPEARANCE_OPTIONS_LABEL="Appearance Options"
3636
PLG_CODEMIRROR_FIELDSET_TOOLBAR_OPTIONS_LABEL="Toolbar Options"
37-
PLG_CODEMIRROR_TOGGLE_FULL_SCREEN="Press %1$s %2$s to toggle Full Screen editing."
3837
PLG_CODEMIRROR_XML_DESCRIPTION="This plugin loads the CodeMirror editor."
3938
PLG_EDITORS_CODEMIRROR="Editor - CodeMirror"
Lines changed: 151 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -1,147 +1,153 @@
1-
21
customElements.define('joomla-editor-codemirror', class extends HTMLElement {
3-
static get observedAttributes() {
4-
return ['options'];
5-
}
6-
7-
get options() { return JSON.parse(this.getAttribute('options')); }
8-
set options(value) { this.setAttribute('options', value); }
9-
10-
attributeChangedCallback(attr, oldValue, newValue) {
11-
switch (attr) {
12-
case 'options':
13-
if (oldValue && newValue !== oldValue) {
14-
this.refresh(this.element);
15-
}
16-
17-
break;
18-
}
19-
}
20-
21-
constructor() {
22-
super();
23-
24-
this.instance = '';
25-
this.cm = '';
26-
this.file = document.currentScript;
27-
this.element = this.querySelector('textarea');
28-
this.host = window.location.origin;
29-
30-
// Append the editor script
31-
if (!document.head.querySelector('#cm-editor')) {
32-
const cmPath = this.getAttribute('editor');
33-
const script1 = document.createElement('script');
34-
35-
script1.src = `${this.host}/${cmPath}`;
36-
script1.id = 'cm-editor';
37-
script1.setAttribute('async', false);
38-
document.head.insertBefore(script1, this.file);
39-
}
40-
41-
this.toggleFullScreen = this.toggleFullScreen.bind(this);
42-
this.closeFullScreen = this.closeFullScreen.bind(this);
43-
}
44-
45-
connectedCallback() {
46-
const buttons = [].slice.call(this.querySelectorAll('.editor-xtd-buttons .xtd-button'));
47-
this.checkElement('CodeMirror')
48-
.then(() => {
49-
// Append the addons script
50-
if (!document.head.querySelector('#cm-addons')) {
51-
const addonsPath = this.getAttribute('addons');
52-
const script2 = document.createElement('script');
53-
54-
script2.src = `${this.host}/${addonsPath}`;
55-
script2.id = 'cm-addons';
56-
script2.setAttribute('async', false);
57-
document.head.insertBefore(script2, this.file)
58-
}
59-
60-
this.checkElement('CodeMirror', 'findModeByName')
61-
.then(() => {
62-
window.CodeMirror.keyMap.default["Ctrl-Q"] = this.toggleFullScreen;
63-
window.CodeMirror.keyMap.default[this.getAttribute('fs-combo')] = this.toggleFullScreen;
64-
window.CodeMirror.keyMap.default["Esc"] = this.closeFullScreen;
65-
66-
// For mode autoloading.
67-
window.CodeMirror.modeURL = this.getAttribute('mod-path');
68-
69-
// Fire this function any time an editor is created.
70-
window.CodeMirror.defineInitHook((editor) => {
71-
// Try to set up the mode
72-
const mode = window.CodeMirror.findModeByName(editor.options.mode || '');
73-
74-
if (mode) {
75-
window.CodeMirror.autoLoadMode(editor, mode.mode);
76-
editor.setOption('mode', mode.mime);
77-
} else {
78-
window.CodeMirror.autoLoadMode(editor, editor.options.mode);
79-
}
80-
81-
// Handle gutter clicks (place or remove a marker).
82-
editor.on("gutterClick", function (ed, n, gutter) {
83-
if (gutter !== "CodeMirror-markergutter") {
84-
return;
85-
}
86-
87-
const info = ed.lineInfo(n);
88-
const hasMarker = !!info.gutterMarkers && !!info.gutterMarkers["CodeMirror-markergutter"];
89-
ed.setGutterMarker(n, "CodeMirror-markergutter", hasMarker ? null : this.makeMarker());
90-
});
91-
92-
// Some browsers do something weird with the fieldset which doesn't work well with CodeMirror. Fix it.
93-
if (this.parentNode.tagName.toLowerCase() === 'fieldset') {
94-
this.parentNode.style.minWidth = 0;
95-
}
96-
});
97-
98-
/** Register Editor */
99-
this.instance = window.CodeMirror.fromTextArea(this.element, this.options);
100-
Joomla.editors.instances[this.element.id] = this.instance;
101-
});
102-
});
103-
}
104-
105-
disconnectedCallback() {
106-
// Remove from the Joomla API
107-
delete Joomla.editors.instances[this.element.id];
108-
}
109-
110-
refresh(element) {
111-
this.instance = window.CodeMirror.fromTextArea(element, this.options);
112-
}
113-
114-
rafAsync() {
115-
return new Promise(resolve => {
116-
requestAnimationFrame(resolve);
117-
});
118-
}
119-
120-
async checkElement(string1, string2) {
121-
if (string2) {
122-
while (typeof window[string1][string2] !== 'function') {
123-
await this.rafAsync()
124-
}
125-
} else {
126-
while (typeof window[string1] !== 'function') {
127-
await this.rafAsync()
128-
}
129-
}
130-
131-
return true;
132-
}
133-
134-
toggleFullScreen() {
135-
this.instance.setOption("fullScreen", !this.instance.getOption("fullScreen"));
136-
}
137-
138-
closeFullScreen() {
139-
this.instance.getOption("fullScreen") && this.instance.setOption("fullScreen", false);
140-
}
141-
142-
makeMarker() {
143-
const marker = document.createElement("div");
144-
marker.className = "CodeMirror-markergutter-mark";
145-
return marker;
146-
}
2+
constructor() {
3+
super();
4+
5+
this.instance = '';
6+
this.cm = '';
7+
this.host = window.location.origin;
8+
this.element = this.querySelector('textarea');
9+
this.refresh = this.refresh.bind(this);
10+
this.toggleFullScreen = this.toggleFullScreen.bind(this);
11+
this.closeFullScreen = this.closeFullScreen.bind(this);
12+
13+
// Append the editor script
14+
if (!document.head.querySelector('#cm-editor')) {
15+
const cmPath = this.getAttribute('editor');
16+
const script1 = document.createElement('script');
17+
18+
script1.src = `${this.host}/${cmPath}`;
19+
script1.id = 'cm-editor';
20+
script1.setAttribute('async', false);
21+
document.head.insertBefore(script1, this.file);
22+
}
23+
}
24+
25+
static get observedAttributes() {
26+
return ['options'];
27+
}
28+
29+
get options() { return JSON.parse(this.getAttribute('options')); }
30+
set options(value) { this.setAttribute('options', value); }
31+
32+
attributeChangedCallback(attr, oldValue, newValue) {
33+
switch (attr) {
34+
case 'options':
35+
if (oldValue && newValue !== oldValue) {
36+
this.refresh(this.element);
37+
}
38+
break;
39+
default:
40+
// Do nothing
41+
}
42+
}
43+
44+
connectedCallback() {
45+
const that = this;
46+
this.checkElement('CodeMirror')
47+
.then(() => {
48+
// Append the addons script
49+
if (!document.head.querySelector('#cm-addons')) {
50+
const addonsPath = this.getAttribute('addons');
51+
const script2 = document.createElement('script');
52+
53+
script2.src = `${this.host}/${addonsPath}`;
54+
script2.id = 'cm-addons';
55+
script2.setAttribute('async', false);
56+
document.head.insertBefore(script2, this.file);
57+
}
58+
59+
this.checkElement('CodeMirror', 'findModeByName')
60+
.then(() => {
61+
// For mode autoloading.
62+
window.CodeMirror.modeURL = this.getAttribute('mod-path');
63+
64+
// Fire this function any time an editor is created.
65+
window.CodeMirror.defineInitHook((editor) => {
66+
// Try to set up the mode
67+
const mode = window.CodeMirror.findModeByName(editor.options.mode || '') ||
68+
window.CodeMirror.findModeByName(editor.options.mode || '') ||
69+
window.CodeMirror.findModeByExtension(editor.options.mode || '');
70+
71+
window.CodeMirror.autoLoadMode(editor, mode ? mode.mode : editor.options.mode);
72+
73+
if (mode) {
74+
editor.setOption('mode', mode.mode);
75+
}
76+
77+
const map = {
78+
'Ctrl-Q': that.toggleFullScreen,
79+
[that.getAttribute('fs-combo')]: that.toggleFullScreen,
80+
Esc: that.closeFullScreen,
81+
};
82+
83+
editor.addKeyMap(map);
84+
85+
// Handle gutter clicks (place or remove a marker).
86+
editor.on('gutterClick', (ed, n, gutter) => {
87+
if (gutter !== 'CodeMirror-markergutter') {
88+
return;
89+
}
90+
91+
const info = ed.lineInfo(n);
92+
const hasMarker = !!info.gutterMarkers && !!info.gutterMarkers['CodeMirror-markergutter'];
93+
ed.setGutterMarker(n, 'CodeMirror-markergutter', hasMarker ? null : this.makeMarker());
94+
});
95+
96+
/* Some browsers do something weird with the fieldset which doesn't
97+
work well with CodeMirror. Fix it. */
98+
if (this.parentNode.tagName.toLowerCase() === 'fieldset') {
99+
this.parentNode.style.minWidth = 0;
100+
}
101+
});
102+
103+
// Register Editor
104+
this.instance = window.CodeMirror.fromTextArea(this.element, this.options);
105+
Joomla.editors.instances[this.element.id] = this.instance;
106+
});
107+
});
108+
}
109+
110+
disconnectedCallback() {
111+
// Remove from the Joomla API
112+
delete Joomla.editors.instances[this.element.id];
113+
}
114+
115+
refresh(element) {
116+
this.instance = window.CodeMirror.fromTextArea(element, this.options);
117+
}
118+
119+
/* eslint-disable */
120+
rafAsync() {
121+
return new Promise(resolve => requestAnimationFrame(resolve));
122+
}
123+
124+
async checkElement(string1, string2) {
125+
if (string2) {
126+
while (typeof window[string1][string2] !== 'function') {
127+
await this.rafAsync();
128+
}
129+
} else {
130+
while (typeof window[string1] !== 'function') {
131+
await this.rafAsync();
132+
}
133+
}
134+
135+
return true;
136+
}
137+
138+
/* eslint-enable */
139+
toggleFullScreen() {
140+
this.instance.setOption('fullScreen', !this.instance.getOption('fullScreen'));
141+
}
142+
143+
closeFullScreen() {
144+
this.instance.getOption('fullScreen');
145+
this.instance.setOption('fullScreen', false);
146+
}
147+
148+
static makeMarker() {
149+
const marker = document.createElement('div');
150+
marker.className = 'CodeMirror-markergutter-mark';
151+
return marker;
152+
}
147153
});

0 commit comments

Comments
 (0)