Skip to content

Commit e5ef6ef

Browse files
authored
Merge pull request #17 from STICKnoLOGIC/main
Add Search Bar
2 parents 9895fe4 + 776ad53 commit e5ef6ef

File tree

3 files changed

+198
-2
lines changed

3 files changed

+198
-2
lines changed

index.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,23 @@ <h3>Grab your own sweet-looking <span>.is-a.dev</span> subdomain.</h3>
6060
src="//cdn.carbonads.com/carbon.js?serve=CW7DE2JU&placement=is-adev&format=cover"
6161
id="_carbonads_js"></script>
6262

63+
<h2>Check Subdomain Availability</h2>
64+
<div class="search-cntnr">
65+
<input id="search-domain" disabled type="text">
66+
</div>
67+
<div>
68+
<div id="result-card" class="hidden result-card">
69+
<div class="user-infos">
70+
<img id="user-avatar" class="user-avatar" alt="user-avatar" href="https://github.com/github.png?size=64" draggable="false">
71+
<span>This subdomain is owned by <a id="user-gh" target="_blank"><span id="user-gh-name" class="font-semibold"></span></a>.</span>
72+
</div>
73+
</div>
74+
75+
<p id="result-none" class="hidden">That subdomain is available, <a alt="register-docs" target="_blank" href="https://docs.is-a.dev">click here</a> to learn how to register it!</p>
76+
<p id="result-error" class="hidden">An error occurred whilst processing your request, please try again.</p>
77+
<p id="result-reserved" class="hidden">Unfortunately the subdomain you have searched for is reserved, please try a different subdomain.</p>
78+
</div>
79+
6380
<h2>Important Links</h2>
6481
<ul>
6582
<li><a href="https://docs.is-a.dev">Documentation</a></li>
@@ -88,5 +105,7 @@ <h2>Donations</h2>
88105
A project by <a href="https://wdh.gg">William Harrison</a>.
89106
</p>
90107
</main>
108+
109+
<script src="scripts/subdomain-availability.js"></script>
91110
</body>
92111
</html>

scripts/subdomain-availability.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
let isSearching = false;
2+
let reservedDomains;
3+
let searchTimeout;
4+
const DOMAIN_PATTERN = /^[a-zA-Z0-9_][a-zA-Z0-9.-]*/;
5+
6+
const searchDomain = document.getElementById("search-domain");
7+
const resultCard = document.getElementById("result-card");
8+
const resultNone = document.getElementById("result-none");
9+
const resultError = document.getElementById("result-error");
10+
const resultReserved = document.getElementById("result-reserved");
11+
const userAvatar = document.getElementById("user-avatar");
12+
const userGitHubLink = document.getElementById("user-gh");
13+
const userGitHubName = document.getElementById("user-gh-name");
14+
15+
async function fetchReservedDomains() {
16+
try {
17+
if (!reservedDomains) {
18+
const response = await fetch("https://raw.githubusercontent.com/is-a-dev/register/main/util/reserved.json");
19+
if (!response.ok) throw new Error(`Failed to fetch reserved domains: ${response.statusText}`);
20+
reservedDomains = await response.json();
21+
searchDomain.disabled = false;
22+
searchDomain.placeholder = "e.g. william";
23+
}
24+
} catch (error) {
25+
console.error(error.message);
26+
}
27+
}
28+
29+
function hideResults() {
30+
[resultCard, resultNone, resultError, resultReserved].forEach((el) => el.classList.add("hidden"));
31+
}
32+
33+
function isReserved(domain) {
34+
return (
35+
reservedDomains?.includes(domain) ||
36+
reservedDomains?.some((pattern) => /\[/.test(pattern) && new RegExp(pattern).test(domain))
37+
);
38+
}
39+
40+
async function check() {
41+
const search = searchDomain.value.trim().replace(/\s/g, "-").toLowerCase();
42+
if (!search || isSearching) return;
43+
44+
hideResults();
45+
46+
if (isReserved(search)) {
47+
resultReserved.classList.remove("hidden");
48+
return;
49+
}
50+
51+
isSearching = true;
52+
try {
53+
const response = await fetch(`https://raw.githubusercontent.com/is-a-dev/register/main/domains/${search}.json`);
54+
if (!response.ok && response.status !== 404) throw new Error("Something went wrong");
55+
56+
const data = response.ok ? await response.json() : null;
57+
if (data) {
58+
propagateResult(data, search);
59+
} else {
60+
resultNone.classList.remove("hidden");
61+
}
62+
} catch (error) {
63+
console.error(error.message);
64+
resultError.classList.remove("hidden");
65+
} finally {
66+
isSearching = false;
67+
}
68+
}
69+
70+
function propagateResult(data, search) {
71+
resultCard.classList.remove("hidden");
72+
const githubURL = `https://github.com/${data.owner.username}`;
73+
userAvatar.src = `${githubURL}.png?size=64`;
74+
userGitHubLink.href = githubURL;
75+
userGitHubName.textContent = data.owner.username;
76+
}
77+
78+
searchDomain.addEventListener("input", function () {
79+
const inputValue = this.value.trim();
80+
81+
if (!inputValue) {
82+
clearTimeout(searchTimeout);
83+
hideResults();
84+
return;
85+
}
86+
87+
const matchedValue = inputValue.match(DOMAIN_PATTERN);
88+
if (matchedValue) {
89+
searchDomain.value = matchedValue[0];
90+
}
91+
92+
clearTimeout(searchTimeout);
93+
searchTimeout = setTimeout(check, 1000);
94+
});
95+
96+
fetchReservedDomains();

styles/main.css

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
html,
22
body {
3-
--header-bg: linear-gradient(90deg, #1a1331, #4e3aa3);
3+
--header-bg: linear-gradient(90deg, #1a1331, var(--hover-bg));
44
--accent: #7041ff;
55
--body-fg: #d1c4ff;
66
--hover-bg: #4e3aa3;
77
--hover-accent: #9b7dff;
8-
8+
--styled-border: conic-gradient(#0f0c19 0 0) padding-box,linear-gradient(to right,#1a1331 20%,#4e3aa3 80%) border-box;
9+
910
margin: 0;
1011
padding: 0;
1112
background-color: #0f0c19;
@@ -119,6 +120,86 @@ a:hover {
119120
background-color: transparent; /* No background change */
120121
}
121122

123+
/* Search */
124+
input {
125+
font-family: "Ubuntu Mono Regular";
126+
width: 100%;
127+
color: var(--body-fg);
128+
font-size: 1.2rem;
129+
padding: 8px;
130+
border-width: 1px;
131+
border-radius: 4px;
132+
border: 4px solid #0000;
133+
background: var(--styled-border);
134+
135+
}
136+
137+
input:focus {
138+
outline-style: none
139+
}
140+
141+
input::placeholder {
142+
color: var(--body-fg);
143+
opacity: 0.8;
144+
}
145+
146+
.search-cntnr {
147+
font-family: "Ubuntu Mono Regular";
148+
display: flex;
149+
flex-direction: column;
150+
justify-content: center;
151+
align-items: stretch;
152+
align-self: center;
153+
}
154+
155+
.search-keyword {
156+
font-size: 1rem;
157+
opacity: 0.5;
158+
line-height: 1.2rem;
159+
padding-left: 8px;
160+
font-style: italic;
161+
-webkit-user-select: none;
162+
-moz-user-select: none;
163+
-ms-user-select: none;
164+
user-select: none;
165+
}
166+
167+
.result-card {
168+
padding: 0.5rem;
169+
border: 5px solid #0000;
170+
background: var(--styled-border);
171+
border-style: solid;
172+
border-width: 4px;
173+
border-radius: 4px;
174+
margin-top: 1rem
175+
}
176+
177+
.user-infos {
178+
display: flex;
179+
align-items: center;
180+
justify-content: start;
181+
gap: .5rem;
182+
width: 100%
183+
}
184+
185+
.user-avatar {
186+
border-radius: 50%;
187+
background-color: var(--hover-bg);
188+
width: 64px;
189+
height: 64px
190+
}
191+
192+
.hidden{
193+
display: none;
194+
}
195+
196+
/* adjust body padding when using mobile devices */
197+
@media (max-width: 480px) {
198+
body{
199+
padding: 0;
200+
}
201+
}
202+
122203
/* Carbon Ads */
123204
#carbonads {
124205
padding-top: 20px;

0 commit comments

Comments
 (0)