Skip to content

Commit 96a0f80

Browse files
committed
Add no-JavaScript fallback (Fixes #134)
1 parent 57b4b16 commit 96a0f80

File tree

6 files changed

+76
-35
lines changed

6 files changed

+76
-35
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,13 @@ The next step is to set up a `template` to link `code-input` to your syntax-high
122122
To see a full list of plugins and their functions, please see [plugins/README.md](./plugins/README.md).
123123

124124
### 4. Using the component
125-
Now that you have registered a template, you can use the custom `<code-input>` element in HTML. If you have more than one template registered, you need to add the template name as the `template` attribute. With the element, using the `language` attribute will add a `language-{value}` class to the `pre code` block. You can now use HTML attributes and events, as well as CSS styles, to make your element as simple or interactive as you like, as if it were a `textarea` element!
125+
Now that you have registered a template, you can use the custom `<code-input>` element in HTML. I recommend it surrounds a fallback `<textarea code-input-fallback>` element which will be used instead when JavaScript support is absent, and will pass its attributes to the `<code-input>` element otherwise, as shown below. If you have more than one template registered, you need to add the template name as the `template` attribute. With the element, using the `language` attribute will add a `language-{value}` class to the `pre code` block. You can now use HTML attributes and events, as well as CSS styles, to make your element as simple or interactive as you like, as if it were a `textarea` element!
126126
```HTML
127-
<code-input language="HTML"></code-input>
127+
<code-input language="HTML"><textarea code-input-fallback></textarea></code-input>
128128
```
129129
*or*
130130
```HTML
131-
<code-input language="HTML" placeholder="Type code here" template="syntax-highlighted" onchange="console.log('Your code is', this.value)">&lt; href='https://github.com/WebCoder49/code-input'>code-input&lt;/a></code-input>
131+
<code-input language="HTML" template="syntax-highlighted" onchange="console.log('Your code is', this.value)"><textarea code-input-fallback placeholder="Type code here">&lt; href='https://github.com/WebCoder49/code-input'>code-input&lt;/a></textarea></code-input>
132132
```
133133

134134
> ⚠️ At the moment, you need to set the `--padding` property rather than `padding` for a `code-input` element's CSS. All other properties should work as normal.

code-input.css

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ code-input {
1212
top: 0;
1313
left: 0;
1414

15+
color: black;
16+
background-color: white;
17+
1518
/* Normal inline styles */
1619
margin: 8px;
1720
--padding: 16px;
@@ -90,7 +93,7 @@ code-input textarea, code-input pre {
9093

9194
/* Move the textarea in front of the result */
9295

93-
code-input textarea {
96+
code-input textarea:not([code-input-fallback]) {
9497
z-index: 1;
9598
}
9699
code-input pre {
@@ -99,7 +102,7 @@ code-input pre {
99102

100103
/* Make textarea almost completely transparent, except for caret and placeholder */
101104

102-
code-input textarea {
105+
code-input textarea:not([code-input-fallback]) {
103106
color: transparent;
104107
background: transparent;
105108
caret-color: inherit!important; /* Or choose your favourite color */
@@ -122,7 +125,7 @@ code-input textarea {
122125
outline: none!important;
123126
}
124127
code-input:has(textarea:focus):not(.code-input_mouse-focused) {
125-
outline: 2px solid black;
128+
outline: 2px solid currentColor;
126129
}
127130

128131
/* Before registering give a hint about how to register. */
@@ -134,19 +137,30 @@ code-input:not(.code-input_registered) {
134137

135138
code-input:not(.code-input_registered)::after {
136139
/* Display message to register */
137-
content: "Use codeInput.registerTemplate to set up.";
140+
content: "No-JavaScript fallback. For highlighting and plugins: as a user use a newer browser/enable JavaScript support; as a developer use codeInput.registerTemplate.";
138141
display: block;
139142
position: absolute;
140-
bottom: var(--padding, 16px);
143+
bottom: 0;
141144
left: var(--padding, 16px);
142145
width: calc(100% - 2 * var(--padding, 16px));
146+
overflow-x: auto;
143147

144-
border-top: 1px solid grey;
145-
outline: var(--padding, 16px) solid white;
146-
background-color: white;
148+
border-top: 1px solid currentColor;
149+
outline-top: 0;
150+
background-color: inherit;
151+
color: inherit;
152+
153+
margin: 0;
154+
padding: 0;
155+
height: 2em;
156+
}
157+
158+
code-input:not(.code-input_registered) textarea {
159+
/* Don't overlap with message */
160+
min-height: calc(100% - var(--padding, 16px) * 2 - 2em);
147161
}
148162

149-
code-input:not(.code-input_loaded) pre, code-input:not(.code-input_loaded) textarea {
163+
code-input:not(.code-input_loaded) pre, code-input:not(.code-input_loaded) textarea:not([code-input-fallback]) {
150164
opacity: 0;
151165
}
152166

@@ -203,19 +217,28 @@ code-input:has(pre[dir=rtl]) .code-input_dialog-container .code-input_keyboard-n
203217
right: 0;
204218
}
205219

206-
code-input:not(:has(textarea:focus)) .code-input_dialog-container .code-input_keyboard-navigation-instructions,
220+
code-input:not(:has(textarea:not([code-input-fallback]):focus)) .code-input_dialog-container .code-input_keyboard-navigation-instructions,
207221
code-input.code-input_mouse-focused .code-input_dialog-container .code-input_keyboard-navigation-instructions,
208222
code-input .code-input_dialog-container .code-input_keyboard-navigation-instructions:empty {
209223
/* When not keyboard-focused / no instructions don't show instructions */
210224
display: none;
211225
}
212226

213227
/* Things with padding when instructions are present */
214-
code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:focus):not(.code-input_mouse-focused) textarea,
215-
code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:focus):not(.code-input_mouse-focused):not(.code-input_pre-element-styled) pre code,
216-
code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:focus):not(.code-input_mouse-focused).code-input_pre-element-styled pre {
228+
code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([code-input-fallback]):focus):not(.code-input_mouse-focused) textarea,
229+
code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([code-input-fallback]):focus):not(.code-input_mouse-focused):not(.code-input_pre-element-styled) pre code,
230+
code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([code-input-fallback]):focus):not(.code-input_mouse-focused).code-input_pre-element-styled pre {
217231
padding-top: calc(var(--padding, 16px) + 3em)!important;
218232
}
219-
code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:focus):not(.code-input_mouse-focused) textarea, code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:focus):not(.code-input_mouse-focused):not(.code-input_pre-element-styled) pre code, code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:focus):not(.code-input_mouse-focused).code-input_pre-element-styled pre {
233+
code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([code-input-fallback]):focus):not(.code-input_mouse-focused) textarea, code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([code-input-fallback]):focus):not(.code-input_mouse-focused):not(.code-input_pre-element-styled) pre code, code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([code-input-fallback]):focus):not(.code-input_mouse-focused).code-input_pre-element-styled pre {
220234
min-height: calc(100% - var(--padding, 16px) * 2 - 3em);
221235
}
236+
237+
/* No JavaScript fallback - styles to override all previous */
238+
239+
code-input textarea[code-input-fallback] {
240+
overflow: auto;
241+
background-color: inherit;
242+
color: inherit;
243+
height: max-content;
244+
}

code-input.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -605,16 +605,34 @@ var codeInput = {
605605

606606
this.pluginEvt("beforeElementsAdded");
607607

608+
const fallbackTextarea = this.querySelector("textarea[code-input-fallback]");
609+
let value;
610+
if(fallbackTextarea) {
611+
// Fallback textarea exists
612+
// Sync attributes; existing code-input attributes take priority
613+
let textareaAttributeNames = fallbackTextarea.getAttributeNames();
614+
for(let i = 0; i < textareaAttributeNames.length; i++) {
615+
const attr = textareaAttributeNames[i];
616+
if(!this.hasAttribute(attr)) {
617+
this.setAttribute(attr, fallbackTextarea.getAttribute(attr));
618+
}
619+
}
620+
// Sync value
621+
value = fallbackTextarea.value;
622+
} else {
623+
value = this.unescapeHtml(this.innerHTML);
624+
}
625+
value = value || this.getAttribute("value") || "";
626+
608627
// First-time attribute sync
609-
let lang = this.getAttribute("language") || this.getAttribute("lang");
610-
let placeholder = this.getAttribute("placeholder") || this.getAttribute("language") || this.getAttribute("lang") || "";
611-
let value = this.unescapeHtml(this.innerHTML) || this.getAttribute("value") || "";
612-
// Value attribute deprecated, but included for compatibility
628+
const lang = this.getAttribute("language") || this.getAttribute("lang");
629+
const placeholder = this.getAttribute("placeholder") || lang || "";
630+
613631

614632
this.initialValue = value; // For form reset
615633

616634
// Create textarea
617-
let textarea = document.createElement("textarea");
635+
const textarea = document.createElement("textarea");
618636
textarea.placeholder = placeholder;
619637
if(value != "") {
620638
textarea.value = value;

tests/hljs.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ <h4><a href="prism.html">Test for Prism.js</a></h4>
4242

4343
<details id="collapse-results"><summary>Test Results (Click to Open)</summary><pre id="test-results"></pre></details>
4444
<form method="GET" action="https://google.com/search" target="_blank">
45-
<code-input name="q">console.log("Hello, World!");
45+
<code-input><textarea code-input-fallback name="q">console.log("Hello, World!");
4646
// A second line
47-
// A third line with &lt;html> tags</code-input>
47+
// A third line with &lt;html> tags</textarea></code-input>
4848
<input type="submit" value="Search Google For Code"/>
4949
</form>
5050

5151
<script>
5252
beginTest(true);
5353
</script>
5454
</body>
55-
</html>
55+
</html>

tests/i18n.html

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@
4848
<body>
4949
<textarea dir="rtl" placeholder="textarea rtl"></textarea>
5050
<textarea dir="ltr" placeholder="textarea ltr"></textarea>
51-
<code-input dir="rtl" template="prism" language="markdown" placeholder="prism rtl"></code-input>
52-
<code-input dir="ltr" template="prism" language="markdown" placeholder="prism ltr"></code-input>
53-
<code-input dir="rtl" template="hljs" language="markdown" placeholder="hljs rtl"></code-input>
54-
<code-input dir="ltr" template="hljs" language="markdown" placeholder="hljs ltr"></code-input>
55-
<code-input dir="rtl" template="prism+" language="markdown" placeholder="prism rtl" class="line-numbers"></code-input>
56-
<code-input dir="ltr" template="prism+" language="markdown" placeholder="prism ltr" class="line-numbers"></code-input>
57-
<code-input dir="rtl" template="hljs+" language="markdown" placeholder="hljs rtl"></code-input>
58-
<code-input dir="ltr" template="hljs+" language="markdown" placeholder="hljs ltr"></code-input>
51+
<code-input dir="rtl" template="prism" language="markdown"><textarea code-input-fallback placeholder="prism rtl"></textarea></code-input>
52+
<code-input dir="ltr" template="prism" language="markdown"><textarea code-input-fallback placeholder="prism ltr"></textarea></code-input>
53+
<code-input dir="rtl" template="hljs" language="markdown"><textarea code-input-fallback placeholder="hljs rtl"></textarea></code-input>
54+
<code-input dir="ltr" template="hljs" language="markdown"><textarea code-input-fallback placeholder="hljs ltr"></textarea></code-input>
55+
<code-input dir="rtl" template="prism+" language="markdown" class="line-numbers"><textarea code-input-fallback placeholder="prism rtl"></textarea></code-input>
56+
<code-input dir="ltr" template="prism+" language="markdown" class="line-numbers"><textarea code-input-fallback placeholder="prism ltr"></textarea></code-input>
57+
<code-input dir="rtl" template="hljs+" language="markdown"><textarea code-input-fallback placeholder="hljs rtl"></textarea></code-input>
58+
<code-input dir="ltr" template="hljs+" language="markdown"><textarea code-input-fallback placeholder="hljs ltr"></textarea></code-input>
5959

6060
<script>
6161
codeInput.registerTemplate("hljs", codeInput.templates.hljs(hljs, []));

tests/prism.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ <h4><a href="hljs.html">Test for highlight.js</a></h4>
4141

4242
<details id="collapse-results"><summary>Test Results (Click to Open)</summary><pre id="test-results"></pre></details>
4343
<form method="GET" class="match-braces line-numbers" action="https://google.com/search" target="_blank">
44-
<code-input name="q">console.log("Hello, World!");
44+
<code-input><textarea code-input-fallback name="q">console.log("Hello, World!");
4545
// A second line
46-
// A third line with &lt;html> tags</code-input>
46+
// A third line with &lt;html> tags</textarea></code-input>
4747
<input type="submit" value="Search Google For Code"/>
4848
</form>
4949

0 commit comments

Comments
 (0)