Design and code update, fixed IE8 compat, use new clipboard API when available.
This commit is contained in:
parent
3d6d5b87ab
commit
c491d967ba
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2020-2023, flashwave <me@flash.moe>
|
Copyright (c) 2020-2024, flashwave <me@flash.moe>
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
|
|
@ -3,37 +3,32 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Your IP Addresses</title>
|
<title>Your IP Addresses</title>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link href="/style.css" type="text/css" rel="stylesheet">
|
<link rel="preconnect" href="//fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="//fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="/style.css" rel="stylesheet">
|
||||||
|
<link href="//fonts.googleapis.com/css2?family=Electrolize&family=Victor+Mono:ital,wght@0,100..700;1,100..700&family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0&display=swap" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<div class="background-gradient-top"></div>
|
||||||
<div class="fullscreen-overlay">
|
<div class="background-gradient-bottom"></div>
|
||||||
<div class="ipbox nojs">
|
<div class="container">
|
||||||
<div class="ipbox-background"></div>
|
<div class="addrbox addrbox-v4 js-address" data-subdomain="ipv4">
|
||||||
<div class="ipbox-content">
|
<div class="addrbox-label">Your IPv4 address is</div>
|
||||||
<div class="ipbox-title">This Website</div>
|
<div class="addrbox-value">
|
||||||
<div class="ipbox-address">needs javascript</div>
|
<span class="js-address-value"><noscript><a class="addrbox-noscript" href="//ipv4.flash.moe">ipv4.flash.moe</a></noscript></span>
|
||||||
|
<a class="addrbox-copy material-symbols-outlined js-address-copy" href="javascript:void(0);"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="addrbox addrbox-v6 js-address" data-subdomain="ipv6">
|
||||||
|
<div class="addrbox-label">Your IPv6 address is</div>
|
||||||
|
<div class="addrbox-value">
|
||||||
|
<span class="js-address-value"><noscript><a class="addrbox-noscript" href="//ipv6.flash.moe">ipv6.flash.moe</a></noscript></span>
|
||||||
|
<a class="addrbox-copy material-symbols-outlined js-address-copy" href="javascript:void(0);"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</noscript>
|
<script src="/script.js"></script>
|
||||||
<div class="boxgrid">
|
|
||||||
<div class="ipbox ipv4" id="ipv4-click">
|
|
||||||
<div class="ipbox-background"></div>
|
|
||||||
<div class="ipbox-content">
|
|
||||||
<div class="ipbox-title">Your IPv4 address is</div>
|
|
||||||
<div class="ipbox-address" id="ipv4">loading...</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ipbox ipv6" id="ipv6-click">
|
|
||||||
<div class="ipbox-background"></div>
|
|
||||||
<div class="ipbox-content">
|
|
||||||
<div class="ipbox-title">Your IPv6 address is</div>
|
|
||||||
<div class="ipbox-address" id="ipv6">loading...</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script src="/script.js" type="text/javascript" charset="utf-8"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -14,10 +14,11 @@ var createXHR = function() {
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
throw 'no impl';
|
||||||
}
|
}
|
||||||
|
|
||||||
var getRemoteString = function(url, callback) {
|
var getRemoteString = function(url, callback) {
|
||||||
|
try {
|
||||||
var xhr = createXHR();
|
var xhr = createXHR();
|
||||||
xhr.onload = function(ev) {
|
xhr.onload = function(ev) {
|
||||||
callback({ success: true, info: ev, text: xhr.responseText });
|
callback({ success: true, info: ev, text: xhr.responseText });
|
||||||
|
@ -27,64 +28,75 @@ var getRemoteString = function(url, callback) {
|
||||||
};
|
};
|
||||||
xhr.open('GET', url);
|
xhr.open('GET', url);
|
||||||
xhr.send();
|
xhr.send();
|
||||||
|
} catch(ex) {
|
||||||
|
callback({ success: false, info: ex });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var selectTextInElement = function(target) {
|
var copyTextInElement = function(target, skipClipboardAPI) {
|
||||||
// MSIE
|
if(!skipClipboardAPI && 'clipboard' in navigator) {
|
||||||
if(document.body.createTextRange) {
|
// for some reason I'm supporting IE8 with this and it gets mad over the catch keyword...
|
||||||
|
navigator.clipboard.writeText(target.textContent)['catch'](function(ex) {
|
||||||
|
copyTextInElement(target, true);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if('execCommand' in document) {
|
||||||
|
if('createTextRange' in document.body) { // MSIE
|
||||||
var range = document.body.createTextRange();
|
var range = document.body.createTextRange();
|
||||||
range.moveToElementText(target);
|
range.moveToElementText(target);
|
||||||
range.select();
|
range.select();
|
||||||
return;
|
} else if('getSelection' in window) { // Mozilla
|
||||||
}
|
var select = window.getSelection();
|
||||||
|
var range = document.createRange();
|
||||||
// Mozilla
|
|
||||||
if(window.getSelection) {
|
|
||||||
var select = window.getSelection(),
|
|
||||||
range = document.createRange();
|
|
||||||
range.selectNodeContents(target);
|
range.selectNodeContents(target);
|
||||||
select.removeAllRanges();
|
select.removeAllRanges();
|
||||||
select.addRange(range);
|
select.addRange(range);
|
||||||
return;
|
} else return;
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var copySelectedText = function() {
|
|
||||||
if(document.execCommand) {
|
|
||||||
document.execCommand('copy');
|
document.execCommand('copy');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var fields = [
|
var fields = document.querySelectorAll('.js-address');
|
||||||
{ target: 'ipv4', ext: 'v4', clickTarget: 'ipv4-click' },
|
|
||||||
{ target: 'ipv6', ext: 'v6', clickTarget: 'ipv6-click' },
|
|
||||||
];
|
|
||||||
|
|
||||||
for(var i in fields)
|
for(var i = 0; i < fields.length; ++i)
|
||||||
(function(field) {
|
(function(field) {
|
||||||
|
var valueField = field.querySelector('.js-address-value');
|
||||||
|
if(valueField === null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var setValueField = function(text) {
|
||||||
|
valueField['textContent' in valueField ? 'textContent' : 'innerText'] = text;
|
||||||
|
};
|
||||||
|
|
||||||
|
setValueField('loading...');
|
||||||
|
|
||||||
|
var subdomain = field.getAttribute('data-subdomain');
|
||||||
|
if(typeof subdomain !== 'string')
|
||||||
|
return;
|
||||||
|
|
||||||
|
var copyButton = field.querySelector('.js-address-copy');
|
||||||
|
|
||||||
var host = location.host.split('.');
|
var host = location.host.split('.');
|
||||||
host[0] += field.ext;
|
host[0] = subdomain;
|
||||||
|
|
||||||
var url = location.protocol + '//' + host.join('.') + '/';
|
var url = location.protocol + '//' + host.join('.') + '/';
|
||||||
|
|
||||||
getRemoteString(url, function(info) {
|
getRemoteString(url, function(info) {
|
||||||
var target = document.getElementById(field.target),
|
|
||||||
prop = 'textContent' in target ? 'textContent' : 'innerText';
|
|
||||||
|
|
||||||
if(info.success) {
|
if(!info.success) {
|
||||||
target[prop] = info.text;
|
setValueField('not available');
|
||||||
|
return;
|
||||||
if(field.clickTarget) {
|
|
||||||
var clickTarget = document.getElementById(field.clickTarget);
|
|
||||||
if(clickTarget)
|
|
||||||
clickTarget.onclick = function() {
|
|
||||||
selectTextInElement(target);
|
|
||||||
copySelectedText();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
target[prop] = 'not available';
|
setValueField(info.text);
|
||||||
|
|
||||||
|
if(copyButton)
|
||||||
|
copyButton.onclick = function() { copyTextInElement(valueField); };
|
||||||
});
|
});
|
||||||
})(fields[i]);
|
})(fields[i]);
|
||||||
})();
|
})();
|
||||||
|
|
145
public/style.css
145
public/style.css
|
@ -3,91 +3,110 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
position: relative;
|
position: relative;
|
||||||
outline-style: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html,
|
html, body {
|
||||||
body {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font: 12px/20px Tahoma, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif;
|
font-size: 16px;
|
||||||
background-color: #111;
|
line-height: 25px;
|
||||||
color: #fff;
|
font-family: 'Electrolize', Verdana, 'Dejavu Sans', sans-serif;
|
||||||
|
color: #000;
|
||||||
|
background-color: #ff9290;
|
||||||
|
padding: 114px 10px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
.background-gradient-top {
|
||||||
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fullscreen-overlay {
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 25%;
|
||||||
|
z-index: 1;
|
||||||
|
background: -moz-linear-gradient(top, #db5176 0%, #ff9290 100%);
|
||||||
|
background: -webkit-linear-gradient(top, #db5176 0%, #ff9290 100%);
|
||||||
|
background: linear-gradient(to bottom, #db5176 0%, #ff9290 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#db5176', endColorstr='#ff9290', GradientType=0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.background-gradient-bottom {
|
||||||
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background-color: #000;
|
height: 25%;
|
||||||
background-image: repeating-linear-gradient(-45deg, #440, #440 10px, #000 10px, #000 20px);
|
z-index: 1;
|
||||||
z-index: 20001;
|
background: -moz-linear-gradient(top, #ff9290 0%, #4c8999 100%);
|
||||||
display: flex;
|
background: -webkit-linear-gradient(top, #ff9290 0%, #4c8999 100%);
|
||||||
justify-content: center;
|
background: linear-gradient(to bottom, #ff9290 0%, #4c8999 100%);
|
||||||
align-items: center;
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff9290', endColorstr='#4c8999', GradientType=0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ipv4 { --ipv-colour: #437675; margin-left: 22px !important; }
|
.container {
|
||||||
.ipv6 { --ipv-colour: #66678d; margin-left: -22px !important; }
|
z-index: 2;
|
||||||
|
background: #fff;
|
||||||
.ipbox {
|
margin: 0 auto;
|
||||||
max-width: 600px;
|
max-width: 850px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 8px 0;
|
|
||||||
cursor: pointer;
|
|
||||||
filter: drop-shadow(0 1px 5px #000);
|
|
||||||
}
|
|
||||||
.ipbox-content {
|
|
||||||
padding: 5px 25px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.ipbox-title {
|
|
||||||
font-size: 1.4em;
|
|
||||||
line-height: 1.5em;
|
|
||||||
}
|
|
||||||
.ipbox-address {
|
|
||||||
font-size: 2em;
|
|
||||||
line-height: 1.3em;
|
|
||||||
font-family: 'Electrolize', Verdana, 'Dejavu Sans', Arial, Helvetica, sans-serif;
|
|
||||||
user-select: text;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
.ipbox-background {
|
|
||||||
position: absolute;
|
@media (prefers-color-scheme: dark) {
|
||||||
top: 0;
|
body { color: #fff; }
|
||||||
left: 0;
|
.container { background: #000; }
|
||||||
width: calc(100% - 20px);
|
|
||||||
height: 100%;
|
|
||||||
background-image: linear-gradient(0deg, #1118 0%, #2228 50%, #3338 50%, #5558 100%);
|
|
||||||
transform: skew(-15deg);
|
|
||||||
background-color: var(--ipv-colour);
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
.ipbox:not(.nojs):active .ipbox-background {
|
|
||||||
background-image: linear-gradient(0deg, #1118 0%, #2228 50%, #3338 50%, #3338 100%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.boxgrid {
|
.addrbox {
|
||||||
display: flex;
|
padding: 4px 8px;
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
margin: 0 15px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nojs {
|
.addrbox-v4 .addrbox-label,
|
||||||
--ipv-colour: #933;
|
.addrbox-v4 .addrbox-copy {
|
||||||
cursor: not-allowed;
|
color: #59a063;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addrbox-v6 .addrbox-label,
|
||||||
|
.addrbox-v6 .addrbox-copy {
|
||||||
|
color: #fe6c7e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addrbox-label {
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addrbox-value {
|
||||||
|
font-family: 'Victor Mono', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
||||||
|
font-size: 2em;
|
||||||
|
line-height: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addrbox-noscript {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: underline dashed;
|
||||||
|
}
|
||||||
|
.addrbox-noscript:hover,
|
||||||
|
.addrbox-noscript:focus {
|
||||||
|
text-decoration-style: solid;
|
||||||
|
}
|
||||||
|
.addrbox-noscript:active {
|
||||||
|
text-decoration-style: dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addrbox-copy {
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
.addrbox-copy:hover,
|
||||||
|
.addrbox-copy:focus {
|
||||||
|
border-style: dashed;
|
||||||
|
border-color: currentColor;
|
||||||
|
}
|
||||||
|
.addrbox-copy:active {
|
||||||
|
border-style: dotted;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue