flash.moe/public/ascii.php

421 lines
15 KiB
PHP
Raw Normal View History

2020-08-20 00:02:37 +00:00
<?php
$table = [
// Control characters
['Null character', 'NUL'],
['Start of heading', 'SOH'],
['Start of text', 'STX'],
['End of text', 'ETX'],
['End of transmission', 'EOT'],
['Enquiry', 'ENQ'],
['Acknowledgement', 'ACK'],
['Bell', 'BEL'],
['Backspace', 'BS' ],
['Horizontal tab', 'HT' ],
['Line feed', 'LF' ],
['Vertical tab', 'VT' ],
['Form feed', 'FF' ],
['Carriage return', 'CR' ],
['Shift out/X-On', 'SO' ],
['Shift in/X-Off', 'SI' ],
['Delta line escape', 'DLE'],
['Device control 1 (often XON)', 'DC1'],
['Device control 2', 'DC2'],
['Device control 3 (often XOFF)', 'DC3'],
['Device control 4', 'DC4'],
['Negative acknowledgement', 'NAK'],
['Synchronous idle', 'SYN'],
['End of transmit block', 'ETB'],
['Cancel', 'CAN'],
['End of medium', 'EM' ],
['Substitute', 'SUB'],
['Escape', 'ESC'],
['File separator', 'FS' ],
['Group separator', 'GS' ],
['Record separator', 'RS' ],
['Unit separator', 'US' ],
// Printable characters
['Space'],
['Excalamation mark'],
['Double quotes', 'quot'],
['Hash'],
['Dollar'],
['Percent'],
['Ampersand', 'amp'],
['Single quote'],
['Open parenthesis'],
['Close parenthesis'],
['Asterisk'],
['Plus'],
['Comma'],
['Hyphen'],
['Period'],
['Slash'],
['Zero'],
['One'],
['Two'],
['Three'],
['Four'],
['Five'],
['Six'],
['Seven'],
['Eight'],
['Nine'],
['Colon'],
['Semicolon'],
['Less than', 'lt'],
['Equals'],
['Greater than', 'gt'],
['Question mark'],
['At symbol'],
['Uppercase A'],
['Uppercase B'],
['Uppercase C'],
['Uppercase D'],
['Uppercase E'],
['Uppercase F'],
['Uppercase G'],
['Uppercase H'],
['Uppercase I'],
['Uppercase J'],
['Uppercase K'],
['Uppercase L'],
['Uppercase M'],
['Uppercase N'],
['Uppercase O'],
['Uppercase P'],
['Uppercase Q'],
['Uppercase R'],
['Uppercase S'],
['Uppercase T'],
['Uppercase U'],
['Uppercase V'],
['Uppercase W'],
['Uppercase X'],
['Uppercase Y'],
['Uppercase Z'],
['Opening bracket'],
['Backslash'],
['Closing bracket'],
['Caret'],
['Underscore'],
['Accent grave'],
['Lowercase a'],
['Lowercase b'],
['Lowercase c'],
['Lowercase d'],
['Lowercase e'],
['Lowercase f'],
['Lowercase g'],
['Lowercase h'],
['Lowercase i'],
['Lowercase j'],
['Lowercase k'],
['Lowercase l'],
['Lowercase m'],
['Lowercase n'],
['Lowercase o'],
['Lowercase p'],
['Lowercase q'],
['Lowercase r'],
['Lowercase s'],
['Lowercase t'],
['Lowercase u'],
['Lowercase v'],
['Lowercase w'],
['Lowercase x'],
['Lowercase y'],
['Lowercase z'],
['Opening curly brace'],
['Vertical bar'],
['Closing curly brace'],
['Tilde'],
// Delete
['Delete', 'DEL'],
];
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>US-ASCII Table</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
box-sizing: border-box;
position: relative;
outline-style: none !important;
}
html, body {
width: 100%;
height: 100%;
}
body {
font: 12px/20px Tahoma, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif;
background-color: #ddd;
color: #000;
}
pre, code {
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
}
.wrap {
margin-bottom: calc(100vh - 70px);
}
.hidden {
display: none !important;
visibility: hidden !important;
}
.invisible {
opacity: 0;
}
.chars {
text-align: center;
max-width: 1200px;
margin: 0 auto;
}
.char {
display: inline-flex;
flex-direction: column;
border: 2px solid #000;
border-radius: 5px;
overflow: hidden;
width: 200px;
text-align: left;
margin: 2px;
background-color: #eee;
cursor: pointer !important;
transition: background-color .1s;
}
.char:hover,
.char:focus {
background-color: #fff;
}
.char:active {
background-color: #ddd;
}
.char-print {
white-space: pre;
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
font-size: 2.5em;
text-align: center;
padding: 10px;
pointer-events: none;
}
.char-desc {
text-align: center;
font-size: 1.2em;
padding: 0 5px 5px;
pointer-events: none;
}
.char-misc {
display: flex;
justify-content: space-evenly;
border-top: 1px solid #111;
}
.char-misc-item {
flex: 1 1 auto;
padding: 2px 5px;
transition: background-color .1s;
background-color: #eee;
}
.char-misc-item:not(:last-child) {
border-right: 1px solid #111;
}
.char-misc-item:hover,
.char-misc-item:focus {
background-color: #fff;
}
.char-misc-item:active {
background-color: #ddd;
}
.char-misc-item-head {
font-variant: small-caps;
}
.char-misc-item-value {
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
text-align: right;
}
.search {
margin: 0 auto;
padding-top: 10px;
max-width: 1200px;
position: sticky;
top: 0;
z-index: 1000;
background-image: linear-gradient(180deg, #ddd 51px, transparent);
}
.search-box {
border: 1px solid #000;
border-radius: 5px;
overflow: hidden;
}
.search-box input {
border-width: 0;
background-color: #fff;
color: #000;
width: 100%;
height: 100%;
font-size: 2em;
padding: 5px;
}
.search-hint {
font-size: .9em;
padding: 0 5px;
transition: opacity .2s;
}
</style>
<script type="text/javascript">
var _paq = window._paq || [];
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
_paq.push(['setTrackerUrl', '//uiharu.railgun.sh/mtm']);
_paq.push(['setSiteId', 'w4PqjBGmOL5l']);
var g = document.createElement('script');
g.type = 'text/javascript'; g.async = true;
g.defer = true; g.src = '//uiharu.railgun.sh/mtm.js';
document.head.appendChild(g);
})();
</script>
</head>
<body>
<div class="wrap">
<div class="search">
<div class="search-box">
<input type="search" id="search" placeholder="Filter..." autocomplete="off"/>
</div>
<div class="search-hint js-invisible-on-scroll">
Type <em><code>printable</code></em> for all printable characters, or <em><code>control</code></em> for all control characters.
</div>
</div>
<div class="chars"><?php
foreach($table as $code => $info):
$isPrintable = ($code > 31 && $code < 127);
$print = $isPrintable ? chr($code) : $info[1];
$attrs = ['data-key-code' => $code, 'data-key-desc' => $info[0], 'data-key-print' => $print, 'data-copy' => $print];
$attrStr = '';
if($isPrintable && isset($info[1]))
$attrs['data-key-html'] = $info[1];
foreach($attrs as $name => $value)
$attrStr .= $name . '="' . htmlentities($value) . '" ';
?><div class="char" <?=trim($attrStr);?>>
<div class="char-print"><?=$print;?></div>
<div class="char-desc"><?=$info[0];?></div>
<div class="char-misc">
<div class="char-misc-item" data-copy="<?=$code;?>">
<div class="char-misc-item-head">Decimal</div>
<div class="char-misc-item-value"><?=$code;?></div>
</div>
<div class="char-misc-item" data-copy="<?=decoct($code);?>">
<div class="char-misc-item-head">Octal</div>
<div class="char-misc-item-value"><?=decoct($code);?></div>
</div>
<div class="char-misc-item" data-copy="<?=dechex($code);?>">
<div class="char-misc-item-head">Hex</div>
<div class="char-misc-item-value"><?=dechex($code);?></div>
</div>
<?php if(isset($attrs['data-key-html'])): ?>
<div class="char-misc-item" data-copy="&amp;<?=$attrs['data-key-html'];?>;">
<div class="char-misc-item-head">HTML</div>
<div class="char-misc-item-value">&amp;<?=$attrs['data-key-html'];?>;</div>
</div>
<?php endif; ?>
</div>
</div><?php endforeach; ?></div>
</div>
<script type="text/javascript">
var chars = document.getElementsByClassName('char'),
search = document.getElementById('search');
function charsFilter(filter) {
if(!filter) {
for(var i = 0; i < chars.length; ++i)
chars[i].classList.remove('hidden');
return;
}
filter = filter.toLowerCase();
for(var i = 0; i < chars.length; ++i) {
var chr = chars[i],
code = (chr.dataset.keyCode || 0).toString().toLowerCase(),
print = (chr.dataset.keyPrint || "\0").toString().toLowerCase(),
desc = (chr.dataset.keyDesc || '').toString().toLowerCase(),
html = (chr.dataset.keyHtml || "\0").toString().toLowerCase(),
codeInt = parseInt(code),
isMatch = (filter === 'printable' && (codeInt > 31 && codeInt < 127))
|| (filter === 'control' && (codeInt < 32 || codeInt === 127))
|| code == filter || print == filter
|| html == filter || desc.indexOf(filter) >= 0;
chr.classList[isMatch ? 'remove' : 'add']('hidden');
}
};
window.addEventListener('scroll', function() {
var hidden = document.getElementsByClassName('js-hidden-on-scroll'),
invisible = document.getElementsByClassName('js-invisible-on-scroll'),
atTop = window.scrollY === 0;
for(var i = 0; i < hidden.length; ++i)
hidden[i].classList[atTop ? 'remove' : 'add']('hidden');
for(var i = 0; i < invisible.length; ++i)
invisible[i].classList[atTop ? 'remove' : 'add']('invisible');
});
search.addEventListener('keyup', function() {
location.hash = search.value.trim();
});
window.addEventListener('hashchange', function() {
charsFilter(decodeURIComponent((location.hash || '#').substring(1)));
});
if(location.hash.length > 0) {
search.value = location.hash.substring(1).trim();
charsFilter(search.value);
}
for(var i = 0; i < chars.length; ++i) {
chars[i].addEventListener('click', function(ev) {
var target = ev.target;
while(target !== null && typeof target.dataset.copy === 'undefined') {
target = target.parentNode || null;
if(target.classList.contains('char'))
break;
}
if(target === null || typeof target.dataset.copy === 'undefined')
return;
// Clipboard interactions are fucking horrendous
/*if(document.execCommand) {
/*var clipfriend = document.createElement('input');
clipfriend.type = 'text';
clipfriend.value = target.dataset.copy;
clipfriend.className = 'hidden';
document.body.appendChild(clipfriend);
clipfriend.select();
clipfriend.setSelectionRange(0, clipfriend.value.length);
document.execCommand('copy');
document.body.removeChild(clipfriend);
} else {*/
var doCopy = function() { navigator.clipboard.writeText(target.dataset.copy); };
if(typeof window.mozInnerScreenX !== 'undefined')
doCopy();
else
navigator.permissions.query({name: 'clipboard-write'}).then(function(res) {
if(res.state === 'granted' || res.state === 'prompt')
doCopy();
});
//}
});
}
</script>
</body>
</html>