-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
304 lines (259 loc) · 10.7 KB
/
Copy pathscript.js
File metadata and controls
304 lines (259 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/* ============================================
Terminal Portfolio — JavaScript
============================================ */
document.addEventListener('DOMContentLoaded', () => {
// ===== Boot Sequence & Audio =====
const bootScreen = document.getElementById('boot-screen');
const bootText = document.getElementById('boot-text');
const bootPrompt = document.getElementById('boot-prompt');
const bgMusic = document.getElementById('bg-music');
const bootSequence = [
"Initializing core system...",
"Loading kernel modules................... [OK]",
"Mounting virtual filesystems............. [OK]",
"Starting networking protocols............ [OK]",
"Bypassing external firewalls............. [OK]",
"Establishing secure connection........... [OK]",
"Booting complete. Waiting for interaction..."
];
if (bootScreen && bootText) {
let delay = 0;
bootSequence.forEach((line, index) => {
setTimeout(() => {
const p = document.createElement('div');
p.className = 'boot-line';
p.innerText = line;
bootText.appendChild(p);
if (index === bootSequence.length - 1) {
setTimeout(() => {
bootPrompt.style.display = 'block';
}, 400);
}
}, delay);
delay += Math.random() * 300 + 250; // Random delay
});
const startSystem = () => {
// Play music
if (bgMusic) {
bgMusic.volume = 0.5;
bgMusic.play().catch(e => console.log("Audio play blocked", e));
}
// Fade out boot screen
bootScreen.style.opacity = '0';
setTimeout(() => {
bootScreen.style.display = 'none';
startInitialAnimations();
}, 800);
// Remove event listeners
document.removeEventListener('keydown', handleKey);
bootScreen.removeEventListener('click', startSystem);
};
const handleKey = (e) => {
if (e.key === 'Enter') {
startSystem();
}
};
document.addEventListener('keydown', handleKey);
bootScreen.addEventListener('click', startSystem);
} else {
// Fallback if boot screen not present
setTimeout(startInitialAnimations, 100);
}
// ===== ASCII Art for Neofetch =====
// Avatar image is now used instead of ASCII art
// ===== Tab Switching =====
const tabs = document.querySelectorAll('.tab');
const tabContents = document.querySelectorAll('.tab-content');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const target = tab.dataset.tab;
// Update active tab
tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
// Update active content
tabContents.forEach(content => {
content.classList.remove('active');
});
const targetContent = document.getElementById(`tab-${target}`);
if (targetContent) {
targetContent.classList.add('active');
// Trigger skill bar animation when skills tab is opened
if (target === 'skills') {
animateSkillBars();
}
}
});
});
// ===== Uptime Counter =====
const startTime = Date.now();
const uptimeEl = document.getElementById('uptime');
function updateUptime() {
const elapsed = Date.now() - startTime;
const minutes = Math.floor(elapsed / 60000);
const seconds = Math.floor((elapsed % 60000) / 1000);
if (uptimeEl) {
uptimeEl.textContent = `${minutes}m ${seconds}s`;
}
}
setInterval(updateUptime, 1000);
updateUptime();
// ===== Skill Bar Animation =====
function animateSkillBars() {
const fills = document.querySelectorAll('.skill-fill');
fills.forEach((fill, i) => {
const percent = fill.dataset.percent;
// Reset
fill.style.width = '0%';
// Animate with stagger
setTimeout(() => {
fill.style.width = percent + '%';
fill.classList.add('animated');
}, i * 100 + 50);
});
}
// ===== Interactive Command Input =====
const commandInput = document.getElementById('command-input');
const commands = {
help: () => {
return `Available commands:
help — show this help message
about — switch to about tab
projects — switch to projects tab
skills — switch to skills tab
experience — switch to experience tab
contact — switch to contact tab
whoami — who are you?
clear — clear the screen
date — show current date
echo [msg] — echo a message
sudo — try your luck
neofetch — display system info
nmap — scan something
man life — read the manual`;
},
about: () => { switchTab('about'); return 'Switching to about.sh...'; },
projects: () => { switchTab('projects'); return 'Switching to projects.ls...'; },
skills: () => { switchTab('skills'); return 'Switching to skills.yaml...'; },
experience: () => { switchTab('experience'); return 'Switching to experience.log...'; },
contact: () => { switchTab('contact'); return 'Switching to contact.md...'; },
whoami: () => 'visitor — unauthorized user detected. Access logged.',
clear: () => { clearOutput(); return null; },
date: () => new Date().toString(),
sudo: () => '🚫 Access denied. Incident reported to SOC. Your IP has been logged.',
neofetch: () => { switchTab('about'); return 'Displaying system info...'; },
nmap: () => `Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for visitor (127.0.0.1)
Host is up (0.00012s latency).
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
8080/tcp open http-proxy
Nmap done: 1 IP address (1 host up) scanned in 0.42 seconds
⚠ Nice try, but this portfolio is hardened. 😎`,
'man life': () => `
LIFE(1) General Commands Manual LIFE(1)
NAME
life - a brief, unpredictable process
SYNOPSIS
life [--hack] [--secure] [--repeat]
DESCRIPTION
Life is a non-deterministic process with a single-threaded
execution model. Side effects include finding CVEs,
patching vulnerabilities, and a growing collection of
cybersecurity certifications.
BUGS
Plenty in production systems. Report to /dev/soc.`,
};
if (commandInput) {
commandInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
const raw = commandInput.value.trim();
if (!raw) return;
const lower = raw.toLowerCase();
let result;
if (lower.startsWith('echo ')) {
result = raw.substring(5);
} else if (commands[lower]) {
result = commands[lower]();
} else {
result = `bash: ${raw}: command not found. Type 'help' for available commands.`;
}
if (result !== null) {
showCommandOutput(raw, result);
}
commandInput.value = '';
}
});
}
function switchTab(tabName) {
const tab = document.querySelector(`.tab[data-tab="${tabName}"]`);
if (tab) tab.click();
}
function showCommandOutput(cmd, output) {
// Create a temporary output block above the prompt
const activeContent = document.querySelector('.tab-content.active');
const prompt = document.querySelector('.interactive-prompt');
if (!activeContent || !prompt) return;
const block = document.createElement('div');
block.className = 'command-output-anim';
block.style.marginBottom = '0.5rem';
block.style.fontSize = '0.82rem';
block.innerHTML = `
<div class="command-line" style="margin-bottom:0.3rem;">
<span class="prompt"><span class="prompt-user">visitor@portfolio</span> <span class="prompt-separator">:</span> <span class="prompt-path">~</span> <span class="prompt-dollar">$</span></span>
<span class="command-text">${escapeHtml(cmd)}</span>
</div>
<pre style="color: var(--text-secondary); white-space: pre-wrap; margin-left: 0; font-family: var(--font-mono); font-size: 0.8rem; line-height: 1.5;">${escapeHtml(output)}</pre>
`;
// Insert before the interactive prompt
const contentArea = prompt.parentElement;
contentArea.insertBefore(block, prompt);
// Scroll to bottom
const termContent = document.querySelector('.terminal-content');
if (termContent) {
termContent.scrollTop = termContent.scrollHeight;
}
}
function clearOutput() {
// Remove all dynamically added command outputs
const outputs = document.querySelectorAll('.command-output-anim');
outputs.forEach(el => el.remove());
}
function escapeHtml(text) {
const div = document.createElement('div');
div.innerText = text;
return div.innerHTML;
}
// ===== Contact Form =====
const contactForm = document.getElementById('contact-form');
if (contactForm) {
contactForm.addEventListener('submit', (e) => {
e.preventDefault();
const btn = contactForm.querySelector('.submit-btn');
btn.textContent = '✓ Message sent!';
btn.style.borderColor = 'var(--accent-green)';
btn.style.color = 'var(--accent-green)';
setTimeout(() => {
btn.textContent = '$ send_message --now';
contactForm.reset();
}, 3000);
});
}
// ===== Initial animations =====
function startInitialAnimations() {
// Animate the about tab content on load
const aboutContent = document.getElementById('tab-about');
if (aboutContent) {
aboutContent.querySelectorAll('.command-line, .neofetch-output, .file-output').forEach((el, i) => {
el.style.opacity = '0';
el.style.transform = 'translateY(8px)';
setTimeout(() => {
el.style.transition = 'opacity 0.4s ease, transform 0.4s ease';
el.style.opacity = '1';
el.style.transform = 'translateY(0)';
}, i * 200 + 100);
});
}
}
});