514 lines
20 KiB
HTML
514 lines
20 KiB
HTML
<span style='
|
|
font-family: system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "system-ui", "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif;
|
|
-webkit-font-smoothing: antialiased;
|
|
display: block; max-width: 720px; margin-left: auto; margin-right: auto;
|
|
'>
|
|
<span contenteditable autofocus onfocus="(function(){
|
|
document.title = 'OnlySpans.net';
|
|
[...document.getElementsByTagName('SPAN')].forEach(function(n) {
|
|
/* send a synthetic 'dblclick' event to each span */
|
|
var evt = document.createEvent('MouseEvents');
|
|
evt.initEvent('dblclick', true, true);
|
|
n.dispatchEvent(evt);
|
|
|
|
/* NOTE: styles and event handler can be added inline. These are added in
|
|
an event handler to demonstrate how to emulate CSS classes */
|
|
|
|
var S = n.style;
|
|
|
|
/* configure 'details' spans */
|
|
if(n.classList.contains('details')) {
|
|
/* styling */
|
|
S['font-weight'] = 700;
|
|
S['background-color'] = '#54c7ec26';
|
|
S['border-radius'] = '5px';
|
|
S['padding'] = '5px';
|
|
S['border'] = '1px solid #4cb3d4';
|
|
S['display'] = 'inline-block';
|
|
n.innerHTML = '▶ Code (click to show)';
|
|
/* click handler */
|
|
n.addEventListener('click', function(){
|
|
if(/click to hide/.test(n.innerText)) {
|
|
n.nextElementSibling.style.display = 'none';
|
|
n.innerHTML = '▶ Code (click to show)';
|
|
} else {
|
|
n.nextElementSibling.style.display = 'inline-block';
|
|
n.innerHTML = '▼ Code (click to hide)';
|
|
}
|
|
});
|
|
}
|
|
|
|
/* configure 'codeblock' spans */
|
|
if(n.classList.contains('codeblock')) {
|
|
S['padding'] = '5px';
|
|
S['font-family'] = 'monospace';
|
|
S['display'] = 'none';
|
|
S['background-color'] = '#efefef';
|
|
S['border-radius'] = '5px';
|
|
S['border'] = '1px solid #d4d5d8';
|
|
}
|
|
|
|
/* configure spans with 'href' attribute */
|
|
if(n.hasAttribute('href')) {
|
|
S['white-space'] = 'pre-wrap';
|
|
S['cursor'] = 'pointer';
|
|
S['color'] = 'blue';
|
|
n.addEventListener('click', function() {
|
|
window.location.href = n.getAttribute('href');
|
|
});
|
|
}
|
|
|
|
/* configure spans with 'heading' role */
|
|
if(n.hasAttribute('role')) {
|
|
switch(n.getAttribute('role')) {
|
|
case 'heading': switch(n.getAttribute('aria-level')) {
|
|
case '2': {
|
|
S['font-weight'] = '700';
|
|
S['font-size'] = '1.5rem';
|
|
} break;
|
|
case '3': {
|
|
S['font-weight'] = '700';
|
|
S['font-size'] = '1.25rem';
|
|
S['white-space'] = 'pre-wrap';
|
|
} break;
|
|
} break;
|
|
}
|
|
}
|
|
});
|
|
/* hide element (this probably should be removed) */
|
|
event.target.style.display = 'none';
|
|
})()"></span>
|
|
|
|
<span role="heading" aria-level="1" style="
|
|
white-space: pre;
|
|
font-weight: 700;
|
|
font-size: 2rem;
|
|
width: 100%;
|
|
text-align: center;
|
|
display: block;
|
|
">Only <SPAN>s</span>
|
|
|
|
<span style="
|
|
white-space: pre-wrap;
|
|
">
|
|
Each element on this page is a SPAN element. No elements are dynamically added to the page.
|
|
</span>
|
|
|
|
<span style="
|
|
white-space: pre-wrap;
|
|
">
|
|
<span><span role="heading" aria-level="2">Styles
|
|
</span>
|
|
<span>Each SPAN specifies styling properties through the `style` attribute.</span>
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
">This is <span style="font-weight: 700">bold</span>
|
|
This is <span style="font-style: italic">italicized</span>
|
|
<span style="text-decoration: line-through">These effects are impossible</span>
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
This is <span style="font-weight: 700">bold</span>
|
|
This is <span style="font-style: italic">italicized</span>
|
|
<span style="text-decoration: line-through">These effects are impossible</span>
|
|
```</span></span></span>
|
|
<span><span role="heading" aria-level="3">Line Breaks</span></span>
|
|
|
|
Newline characters are normally treated like spaces. They do not force a line break. `BR` elements force line breaks.
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
"><span style="white-space: normal;">Normally, newline characters
|
|
do not actually break lines. They
|
|
are treated like space characters.</span>
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span style="white-space: normal;">Normally, newline characters
|
|
do not actually break lines. They
|
|
are treated like space characters.</span>
|
|
```</span></span></span>
|
|
<span>When SPAN elements have the styling property <span style="font-family: monospace">white-space: pre-wrap</span>, newline characters in the HTML code are treated as line breaks.</span>
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
"><span style="white-space: pre-wrap;">With pre-wrap, newline characters
|
|
actually break lines and
|
|
are not treated like space characters</span>
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span style="white-space: pre-wrap;">With pre-wrap, newline characters
|
|
actually break lines and
|
|
are not treated like space characters</span>
|
|
```</span></span></span></span>
|
|
<span><span role="heading" aria-level="3">CSS Tables</span>
|
|
|
|
<span style="
|
|
white-space: pre-wrap;
|
|
">CSS Level 3 supports special values for the `display` styling property:</span>
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
"><span style="display: table">
|
|
<span style="display: table-row">
|
|
<span style="display: table-cell; padding: 3px;"><span style="font-weight: 700; text-align:center; display:inline-block; width: 100%">Value</span></span>
|
|
<span style="display: table-cell; padding: 3px;"><span style="font-weight: 700; text-align:center; display:inline-block; width: 100%">Behavior</span></span>
|
|
</span>
|
|
<span style="display: table-row">
|
|
<span style="display: table-cell; padding: 3px;"><span style="font-family:monospace; width: 100%">table</span></span>
|
|
<span style="display: table-cell; padding: 3px;"><span style="width: 100%">Acts like <span style="font-family:monospace">TABLE</span></span></span>
|
|
</span>
|
|
<span style="display: table-row">
|
|
<span style="display: table-cell; padding: 3px;"><span style="font-family:monospace; width: 100%">table-row</span></span>
|
|
<span style="display: table-cell; padding: 3px;"><span style="width: 100%">Acts like <span style="font-family:monospace">TR</span></span></span>
|
|
</span>
|
|
<span style="display: table-row">
|
|
<span style="display: table-cell; padding: 3px;"><span style="font-family:monospace; width: 100%">table-cell</span></span>
|
|
<span style="display: table-cell; padding: 3px;"><span style="width: 100%">Acts like <span style="font-family:monospace">TD</span></span></span>
|
|
</span>
|
|
</span>
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span style="display: table">
|
|
<span style="display: table-row">
|
|
<span style="display: table-cell">Value</span>
|
|
<span style="display: table-cell">Behavior</span>
|
|
</span>
|
|
<span style="display: table-row">
|
|
<span style="display: table-cell">table</span>
|
|
<span style="display: table-cell">Acts like TABLE</span>
|
|
</span>
|
|
</span>
|
|
```</span></span></span>
|
|
<span>Using these special style properties, SPAN elements can create simple table layouts. Unfortunately there is no equivalent of `colspan` and `rowspan` ("merge cells" in Excel parlance)
|
|
</span></span>
|
|
<span><span role="heading" aria-level="3">Images</span>
|
|
|
|
<span style="
|
|
white-space: pre-wrap;
|
|
">Images can be added to pages using the `background-image` inline style. To ensure spans are displayed, the `width`, `height` and `display` attributes are set:
|
|
</span>
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
"><span style="
|
|
width: 128px;
|
|
height: 128px;
|
|
background-image: url('https://sheetjs.com/sketch128.png');
|
|
display:inline-block;
|
|
"></span>
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span style="
|
|
width: 128px;
|
|
height: 128px;
|
|
background-image: url('https://sheetjs.com/sketch128.png');
|
|
display: inline-block;
|
|
"></span>
|
|
```</span></span></span>
|
|
</span></span>
|
|
|
|
<span style="
|
|
white-space: pre-wrap;
|
|
">
|
|
<span><span role="heading" aria-level="2">Dynamic Elements</span>
|
|
|
|
<span>Inline event handlers allow for some scripting without introducing explicit SCRIPT tags.</span>
|
|
|
|
<span>The following example uses the `onclick` inline event handler to increment a counter:</span>
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
">The blue span has been clicked <span style="
|
|
font-family: monospace;
|
|
font-weight:700;
|
|
background-color: #54c7ec26;
|
|
border-radius: 5px;
|
|
padding:5px; border: 1px solid #4cb3d4;
|
|
display: inline-block;
|
|
" onclick="(function() {
|
|
event.target.innerText = (+event.target.innerText) + 1;
|
|
})()">0</span> times
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span onclick="(function() {
|
|
event.target.innerText = (+event.target.innerText) + 1;
|
|
})()">0</span>
|
|
```</span></span></span>
|
|
<span><span role="heading" aria-level="3">Effectuating `onload`</span></span>
|
|
|
|
<span>SPAN elements do not receive a `load` event. Instead, this page uses a `contenteditable` SPAN with an `autofocus` attribute. This ensures the `onfocus` inline handler is called.</span>
|
|
|
|
<span>If multiple elements have the `autofocus` attribute, only the first element will receive focus.</span>
|
|
|
|
<span>To simplify the page, the `contenteditable autofocus` SPAN will send a synthetic double click (`dblclick`) event to each SPAN element on the page before hiding itself:</span>
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
">The relevant SPAN is at the top of the page (line 6 in the source). If it were placed here, the browser would scroll to this SPAN.
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span contenteditable autofocus onfocus="(function(){
|
|
[...document.getElementsByTagName('SPAN')].forEach(function(n) {
|
|
var evt = document.createEvent('MouseEvents');
|
|
evt.initEvent('dblclick', true, true);
|
|
n.dispatchEvent(evt);
|
|
});
|
|
event.target.style.visibility = 'hidden';
|
|
})()"></span>
|
|
```</span></span></span>
|
|
<span>Within the `ondblclick` inline handler, the SPAN DOM element can be referenced with the `<span style="font-family: monospace">target</span>` property of the `<span style="font-family: monospace">event</span>` global.</span>
|
|
|
|
<span>The following example shows the current time. The `ondblclick` event handler uses `setInterval` to set up a loop that updates the time. Clearing the `ondblclick` property ensures that a real double click will not invoke the original handler.</span>
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
">The time is now <span style="
|
|
font-family: monospace;
|
|
font-weight:700;
|
|
background-color: #efefef;
|
|
border-radius: 5px;
|
|
padding:5px; border: 1px solid #d4d5d8;
|
|
display: inline-block;
|
|
" ondblclick="(function() {
|
|
var last = new Date().toString(), tgt = event.target;
|
|
tgt.innerText = last;
|
|
setInterval(function() {
|
|
var cur = new Date().toString();
|
|
if(last != cur) tgt.innerText = last = cur;
|
|
}, 100);
|
|
tgt.ondblclick = null;
|
|
})()"></span>
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span style="font-family: monospace" ondblclick="(function() {
|
|
var last = new Date().toString(), tgt = event.target;
|
|
tgt.innerText = last;
|
|
setInterval(function() {
|
|
var cur = new Date().toString();
|
|
if(last != cur) tgt.innerText = last = cur;
|
|
}, 100);
|
|
tgt.ondblclick = null;
|
|
})()"></span>
|
|
```</span></span></span></span>
|
|
<span><span role="heading" aria-level="3">Emulating CSS Classes</span>
|
|
|
|
<span>Within the `onfocus` handler of the `autofocus` SPAN, every SPAN element on the page is visited. The `classList` property is a list of class names. Code can manually apply styling properties.</span>
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
">The code blocks that are displayed with the "Show Code" buttons use the `codeblock` class.
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span contenteditable autofocus onfocus="(function(){
|
|
[...document.getElementsByTagName('SPAN')].forEach(function(n) {
|
|
/* configure 'codeblock' spans */
|
|
if(n.classList.contains('codeblock')) {
|
|
var S = n.style;
|
|
S['font-family'] = 'monospace';
|
|
S['display'] = 'none';
|
|
}
|
|
})()"></span>
|
|
```</span></span></span></span>
|
|
<span><span role="heading" aria-level="3">Fetching Data</span>
|
|
|
|
<span>The `ondblclick` handler can fetch data. The following example fetches a text file:</span>
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
">The current version of <span href="https://sheetjs.com" role="link">SheetJS Community Edition</span> is <span style="
|
|
font-family: monospace;
|
|
font-weight:700;
|
|
background-color: #efefef;
|
|
border-radius: 5px;
|
|
padding:5px;
|
|
border: 1px solid #d4d5d8;
|
|
display: inline-block;
|
|
" ondblclick="(async function() {
|
|
const versions = await (await fetch('https://cdn.sheetjs.com/xlsx.lst')).text();
|
|
event.target.innerText = versions.trim().split('\n').reverse()[0];
|
|
})()"></span>
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span ondblclick="(async function() {
|
|
const versions = await (await fetch('https://cdn.sheetjs.com/xlsx.lst')).text();
|
|
event.target.innerText = versions.trim().split('\n').reverse()[0];
|
|
})()"></span>
|
|
```</span></span></span></span>
|
|
<span><span role="heading" aria-level="3">Editable Elements</span>
|
|
|
|
<span>The `contenteditable` attribute allows users to edit the content of SPAN elements. An `input` event is dispatched when the content has changed.</span>
|
|
|
|
<span>The following example includes one `contenteditable` SPAN and one non-editable SPAN. The `oninput` event handler of the first SPAN changes the `innerText` property of the second SPAN.
|
|
</span>
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
">Click the text span below and start typing:
|
|
|
|
<span contenteditable style="background-color: white; border-radius: 5px; padding:5px; border: 1px solid #009400; display: inline-block;" oninput="(function() {
|
|
/* output is the ID of the span that will be changed */
|
|
output.innerText = event.target.innerText||' ';
|
|
})()">Click here and start typing!</span>
|
|
|
|
The following span will update when the previous span is edited:
|
|
|
|
<span><span id="output" style="background-color: #efefef; border-radius: 5px; padding:5px; border: 1px solid #d4d5d8; display: inline-block;">Edit the previous span</span></span></span></span>
|
|
<span><span role="heading" aria-level="3">External Scripts</span>
|
|
|
|
<span>External scripts can be fetched and evaluated using `eval`.</span>
|
|
|
|
<span>The following example fetches the <span href="https://docs.sheetjs.com/docs/constellation/ssf" role="link">SheetJS SSF Library</span> and displays the version number.
|
|
</span>
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
">The current version of the SheetJS SSF number formatting library is <span style="
|
|
font-family: monospace; font-weight:700;
|
|
background-color: #efefef;
|
|
border-radius: 5px;
|
|
padding: 5px;
|
|
border: 1px solid #d4d5d8;
|
|
display: inline-block;
|
|
" ondblclick="(async function() {
|
|
const url = 'https://cdn.sheetjs.com/ssf-0.11.3/ssf.js';
|
|
const code = await (await fetch(url)).text();
|
|
eval(code);
|
|
window.SSF = SSF;
|
|
event.target.innerText = SSF.version;
|
|
})()"></span>
|
|
|
|
<span><span class="details">Show Code</span>
|
|
<span class="codeblock">```html
|
|
<span ondblclick="(async function() {
|
|
const url = 'https://cdn.sheetjs.com/ssf-0.11.3/ssf.js';
|
|
const code = await (await fetch(url)).text();
|
|
eval(ssf_text);
|
|
event.target.innerText = SSF.version;
|
|
})()"></span>
|
|
```</span></span></span>
|
|
<span>This example uses the <span href="https://docs.sheetjs.com/docs/constellation/ssf" role="link">SheetJS SSF Library</span> to format values. The SPAN elements with green borders are editable. When either SPAN is changed, the "Number Value" SPAN content is interpreted as a JS `Number` and formatted using the Format Code.</span>
|
|
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #efefef;
|
|
border-radius: 10px;
|
|
">The "Formatted Text" is automatically calculated from the "Format Code" and "Number Value". Try setting the "Format Code" to <span style="font-family: monospace; font-weight: 700">#,##0.00</span> and the value to <span style="font-family: monospace; font-weight: 700">314159.265</span>
|
|
|
|
<span style="display: table">
|
|
<span style="display: table-row">
|
|
<span style="display: table-cell; padding: 3px;"><span style="font-weight: 700; display:inline-block; width: 100%">Format Code</span></span>
|
|
<span style="display: table-cell; padding: 3px;"><span id="fmt" contenteditable style="font-family: monospace; width: 100%; background-color: white; border-radius: 5px; padding:5px; border: 1px solid #009400; display: inline-block; min-width: 11ch;" oninput="(function() {
|
|
var evt = document.createEvent('MouseEvents');
|
|
evt.initEvent('dblclick', true, true);
|
|
outssf.dispatchEvent(evt);
|
|
})()">$0.00</span></span>
|
|
</span>
|
|
<span style="display: table-row">
|
|
<span style="display: table-cell; padding: 3px;"><span style="font-weight: 700; display:inline-block; width: 100%">Number Value</span></span>
|
|
<span style="display: table-cell; padding: 3px;"><span id="val" contenteditable style="font-family: monospace; width: 100%; background-color: white; border-radius: 5px; padding:5px; border: 1px solid #009400; display: inline-block;" oninput="(function() {
|
|
var evt = document.createEvent('MouseEvents');
|
|
evt.initEvent('dblclick', true, true);
|
|
outssf.dispatchEvent(evt);
|
|
})()">3.5</span></span>
|
|
</span>
|
|
<span style="display: table-row"><span style="display: table-cell;"> </span></span>
|
|
<span style="display: table-row">
|
|
<span style="display: table-cell; padding: 3px;"><span style="font-weight: 700; display:inline-block; width: 100%">Formatted Text</span></span>
|
|
<span style="display: table-cell; padding: 3px;"><span id="outssf" style="font-family: monospace; font-weight: 700; width: 100%; background-color: #54c7ec26; border-radius: 5px; padding:5px; border: 1px solid #4cb3d4; display: inline-block;" ondblclick="(function() {
|
|
if(typeof SSF == 'undefined') return;
|
|
/* simple debounce wrapper */
|
|
function debounce(f) {
|
|
let id;
|
|
return function() {
|
|
if(id) window.cancelAnimationFrame(id);
|
|
id = window.requestAnimationFrame(() => f.call(this, ...arguments));
|
|
}
|
|
}
|
|
debounce(() => {
|
|
const v = Number(val.innerText), S = outssf.style;
|
|
try {
|
|
if(!isFinite(v)) throw 'Could not parse ' + val.innerText + ' as a finite number!';
|
|
outssf.innerText = SSF.format(fmt.innerText, Number(val.innerText));
|
|
S['background-color'] = '#54c7ec26';
|
|
S['border-color'] = '#4cb3d4';
|
|
} catch(e) {
|
|
outssf.innerText = 'ERROR: ' + (e && e.message || e);
|
|
S['background-color'] = '#fa383e26';
|
|
S['border-color'] = '#e13238';
|
|
}
|
|
})();
|
|
})()">$3.50</span></span>
|
|
</span>
|
|
</span></span></span>
|
|
</span>
|
|
|
|
<span style="
|
|
white-space: pre-wrap;
|
|
">
|
|
<span style="
|
|
margin: 5px;
|
|
padding: 15px;
|
|
display: block;
|
|
background-color: #e6f6e6;
|
|
border-radius: 10px;
|
|
"><span href="https://sheetjs.com" role="link">SheetJS LLC</span> has been "making sheet happen" with creative use of HTML, CSS and JS since 2012. If pushing the limits of the web tickles your fancy, <span href="https://sheetjs.com/careers" role="link">consider joining us!</span></span>
|
|
|
|
</span>
|
|
</span>
|