Skip to content

Commit 59933c5

Browse files
author
WebCoder49
committed
Fix TODO comments and loading
1 parent 0cd6f1f commit 59933c5

8 files changed

+61
-41
lines changed

code-input.d.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ export as namespace codeInput;
55
* provide custom extra functionality to code-input elements.
66
*/
77
export abstract class Plugin {
8-
constructor()
8+
/**
9+
* Create a Plugin
10+
*
11+
* @param {Array<string>} observedAttributes - The HTML attributes to watch for this plugin, and report any
12+
* modifications to the `codeInput.Plugin.attributeChanged` method.
13+
*/
14+
constructor(observedAttributes: Array<string>)
915
/**
1016
* Runs before code is highlighted.
1117
* @param {codeInput.CodeInput} codeInput - The codeInput element

code-input.js

+43-26
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* **<https://github.com/WebCoder49/code-input>**
77
*/
88

9-
// TODO: Stop annoying "glitch" with delaying until load?; Fix input evtListener
109

1110
var codeInput = {
1211
/**
@@ -30,7 +29,7 @@ var codeInput = {
3029
* code-input element.
3130
*/
3231
textareaSyncAttributes: [
33-
"aria-*", // TODO: Check this with PR comment
32+
"aria-*",
3433
"value",
3534
"name",
3635
// Form validation - https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation#using_built-in_form_validation
@@ -108,7 +107,7 @@ var codeInput = {
108107
for (let i in codeInput.templateNotYetRegisteredQueue[templateName]) {
109108
elem = codeInput.templateNotYetRegisteredQueue[templateName][i];
110109
elem.template = template;
111-
codeInput.runOnceLoaded(() => { elem.setup(); }, elem); // So innerHTML can be read
110+
codeInput.runOnceWindowLoaded(() => { elem.setup(); }, elem); // So innerHTML can be read
112111
}
113112
console.log(`code-input: template: Added existing elements with template ${templateName}`);
114113
}
@@ -119,7 +118,7 @@ var codeInput = {
119118
for (let i in codeInput.templateNotYetRegisteredQueue[undefined]) {
120119
elem = codeInput.templateNotYetRegisteredQueue[undefined][i];
121120
elem.template = template;
122-
codeInput.runOnceLoaded(() => { elem.setup(); }, elem); // So innerHTML can be read
121+
codeInput.runOnceWindowLoaded(() => { elem.setup(); }, elem); // So innerHTML can be read
123122
}
124123
}
125124
console.log(`code-input: template: Set template ${templateName} as default`);
@@ -344,17 +343,23 @@ var codeInput = {
344343
* provide custom extra functionality to code-input elements.
345344
*/
346345
Plugin: class {
347-
constructor() {
346+
/**
347+
* Create a Plugin
348+
*
349+
* @param {Array<string>} observedAttributes - The HTML attributes to watch for this plugin, and report any
350+
* modifications to the `codeInput.Plugin.attributeChanged` method.
351+
*/
352+
constructor(observedAttributes) {
348353
console.log("code-input: plugin: Created plugin");
349354

350-
codeInput.observedAttributes.forEach((attribute) => {
355+
observedAttributes.forEach((attribute) => {
351356
// Move plugin attribute to codeInput observed attributes
352357
let regexFromWildcard = codeInput.wildcard2regex(attribute);
353358
if(regexFromWildcard == null) {
354359
// Not a wildcard
355360
codeInput.observedAttributes.push(attribute);
356361
} else {
357-
codeInput.observedAttributes.regex.push(regexFromWildcard);
362+
codeInput.observedAttributes.regexp.push(regexFromWildcard);
358363
}
359364
});
360365
}
@@ -387,11 +392,6 @@ var codeInput = {
387392
* @param {string} newValue - The value of the attribute after it is changed
388393
*/
389394
attributeChanged(codeInput, name, oldValue, newValue) { }
390-
/**
391-
* The HTML attributes to watch for this plugin, and report any
392-
* modifications to the `codeInput.Plugin.attributeChanged` method.
393-
*/
394-
observedAttributes = []
395395
},
396396

397397
/* ------------------------------------
@@ -468,8 +468,14 @@ var codeInput = {
468468

469469
/** Update the text value to the result element, after the textarea contents have changed.
470470
* @param {string} value - The text value of the code-input element
471+
* @param {boolean} originalUpdate - Whether this update originates from the textarea's content; if so, run it first so custom updates override it.
471472
*/
472473
update(value) {
474+
if(this.textareaElement == null) {
475+
this.addEventListener("code-input_load", () => { this.update(value) }); // Only run when fully loaded
476+
return;
477+
}
478+
473479
// Prevent this from running multiple times on the same input when "value" attribute is changed,
474480
// by not running when value is already equal to the input of this (implying update has already
475481
// been run). Thank you to peterprvy for this.
@@ -623,6 +629,8 @@ var codeInput = {
623629
this.pluginEvt("afterElementsAdded");
624630

625631
this.update(value);
632+
633+
this.dispatchEvent(new CustomEvent("code-input_load"));
626634
}
627635

628636
/**
@@ -661,7 +669,7 @@ var codeInput = {
661669
this.template = this.getTemplate();
662670
if (this.template != undefined) {
663671
this.classList.add("code-input_registered");
664-
codeInput.runOnceLoaded(() => {
672+
codeInput.runOnceWindowLoaded(() => {
665673
this.setup();
666674
this.classList.add("code-input_loaded");
667675
}, this);
@@ -678,6 +686,14 @@ var codeInput = {
678686
if (mutation.type !== 'attributes')
679687
continue;
680688

689+
/* Check regular attributes */
690+
for(let i = 0; i < codeInput.observedAttributes.length; i++) {
691+
if (mutation.attributeName == codeInput.observedAttributes[i]) {
692+
return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
693+
}
694+
}
695+
696+
/* Check wildcard attributes */
681697
for(let i = 0; i < codeInput.observedAttributes.regexp.length; i++) {
682698
const reg = codeInput.observedAttributes.regexp[i];
683699
if (mutation.attributeName.match(reg)) {
@@ -692,16 +708,8 @@ var codeInput = {
692708
}
693709

694710
/**
695-
* Get the HTML attributes that need to be monitored and reported
696-
* to `codeInput.CodeInput.attributeChangedCallback` when modified.
697-
*/
698-
static get observedAttributes() {
699-
return codeInput.observedAttributes.concat(codeInput.textareaSyncAttributes);
700-
}
701-
702-
/**
703-
* Triggered when an HTML attribute in `codeInput.CodeInput.observedAttributes`
704-
* has been modified.
711+
* Triggered when an observed HTML attribute
712+
* has been modified (called from `mutationObserverCallback`).
705713
* @param {string} name - The name of the attribute
706714
* @param {string} oldValue - The value of the attribute before it was changed
707715
* @param {string} newValue - The value of the attribute after it is changed
@@ -798,9 +806,17 @@ var codeInput = {
798806

799807
if (codeInput.textareaSyncEvents.includes(type)) {
800808
if (options === undefined) {
801-
codeInput.runOnceLoaded(() => { this.textareaElement.addEventListener(type, boundCallback); }, this);
809+
if(this.textareaElement == null) {
810+
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback); });
811+
} else {
812+
this.textareaElement.addEventListener(type, boundCallback);
813+
}
802814
} else {
803-
codeInput.runOnceLoaded(() => { this.textareaElement.addEventListener(type, boundCallback, options); }, this);
815+
if(this.textareaElement == null) {
816+
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback, options); });
817+
} else {
818+
this.textareaElement.addEventListener(type, boundCallback, options);
819+
}
804820
}
805821
} else {
806822
if (options === undefined) {
@@ -847,6 +863,7 @@ var codeInput = {
847863
if (val === null || val === undefined) {
848864
val = "";
849865
}
866+
this._value = val;
850867
this.update(val);
851868
return val;
852869
}
@@ -978,7 +995,7 @@ var codeInput = {
978995
* To ensure the DOM is ready, run this callback after the window
979996
* has loaded (or now if it has already loaded)
980997
*/
981-
runOnceLoaded(callback, codeInputElem) {
998+
runOnceWindowLoaded(callback, codeInputElem) {
982999
if(codeInputElem.textareaElement != null) {
9831000
callback(); // Fully loaded
9841001
} else {

plugins/autocomplete.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ codeInput.plugins.Autocomplete = class extends codeInput.Plugin {
88
* @param {function} updatePopupCallback a function to display the popup that takes in (popup element, textarea, textarea.selectionEnd).
99
*/
1010
constructor(updatePopupCallback) {
11-
super();
11+
super([]); // No observed attributes
1212
this.updatePopupCallback = updatePopupCallback;
1313
}
1414
/* When a key is pressed, or scrolling occurs, update the autocomplete */
@@ -75,6 +75,5 @@ codeInput.plugins.Autocomplete = class extends codeInput.Plugin {
7575
}
7676
return {"top": afterSpan.offsetTop - textarea.scrollTop, "left": afterSpan.offsetLeft - textarea.scrollLeft};
7777
}
78-
observedAttributes = [];
7978
updatePopupCallback = function() {};
8079
}

plugins/autodetect.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
codeInput.plugins.Autodetect = class extends codeInput.Plugin {
77
constructor() {
8-
super();
8+
super([]); // No observed attributes
99
}
1010
/* Remove previous language class */
1111
beforeHighlight(codeInput) {
@@ -25,5 +25,4 @@ codeInput.plugins.Autodetect = class extends codeInput.Plugin {
2525
codeInput.setAttribute("lang", lang);
2626
}
2727
}
28-
observedAttributes = []
2928
}

plugins/debounce-update.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ codeInput.plugins.DebounceUpdate = class extends codeInput.Plugin {
99
* @param {Number} delayMs Delay, in ms, to wait until updating the syntax highlighting
1010
*/
1111
constructor(delayMs) {
12-
super();
12+
super([]); // No observed attributes
1313
this.delayMs = delayMs;
1414
}
1515
/* Runs before elements are added into a `code-input`; Params: codeInput element) */

plugins/indent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
codeInput.plugins.Indent = class extends codeInput.Plugin {
77
constructor() {
8-
super();
8+
super([]); // No observed attributes
99
}
1010

1111
/* Add keystroke events */

plugins/special-chars.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
1818
* @param {RegExp} specialCharRegExp The regular expression which matches special characters
1919
*/
2020
constructor(colorInSpecialChars = false, inheritTextColor = false, specialCharRegExp = /(?!\n)(?!\t)[\u{0000}-\u{001F}]|[\u{007F}-\u{009F}]|[\u{0200}-\u{FFFF}]/ug) { // By default, covers many non-renderable ASCII characters
21-
super();
21+
super([]); // No observed attributes
2222

2323
this.specialCharRegExp = specialCharRegExp;
2424
this.colorInSpecialChars = colorInSpecialChars;
@@ -152,7 +152,7 @@ codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
152152
}
153153
}
154154

155-
getCharacterWidth(codeInput, char) { // TODO: Check StackOverflow question
155+
getCharacterWidth(codeInput, char) {
156156
// Force zero-width characters
157157
if(new RegExp("\u00AD|\u02de|[\u0300-\u036F]|[\u0483-\u0489]|\u200b").test(char) ) { return 0 }
158158
// Non-renderable ASCII characters should all be rendered at same size

plugins/test.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
*/
1111
codeInput.plugins.Test = class extends codeInput.Plugin {
1212
constructor() {
13-
super();
13+
super(["testattr", "test-*"]);
14+
// Array of observed attributes as parameter
15+
// Wildcard "*" matches any text
1416
}
1517
/* Runs before code is highlighted; Params: codeInput element) */
1618
beforeHighlight(codeInput) {
@@ -28,11 +30,8 @@ codeInput.plugins.Test = class extends codeInput.Plugin {
2830
afterElementsAdded(codeInput) {
2931
console.log(codeInput, "after elements added");
3032
}
31-
/* Runs when an attribute of a `code-input` is changed (you must add the attribute name to observedAttributes); Params: codeInput element, name attribute name, oldValue previous value of attribute, newValue changed value of attribute) */
33+
/* Runs when an observed attribute of a `code-input` is changed (you must add the attribute name in the constructor); Params: codeInput element, name attribute name, oldValue previous value of attribute, newValue changed value of attribute) */
3234
attributeChanged(codeInput, name, oldValue, newValue) {
33-
if(name == "testattr") {
34-
console.log(codeInput, "testattr:", oldValue, ">", newValue);
35-
}
35+
console.log(codeInput, name, ":", oldValue, ">", newValue);
3636
}
37-
observedAttributes = ["testattr"]
3837
}

0 commit comments

Comments
 (0)