Features Implemented
-
Modern UI Design:
-
Clean, responsive layout with card-based design
-
Smooth animations and transitions
-
Mobile-friendly
-
-
URL Shortening:
-
Input validation for URLs
-
Option to add a custom alias
-
Simulated API call with loading state
-
-
Copy to Clipboard:
-
One-click copy button
-
Visual notification when copied
-
Uses modern Clipboard API
-
-
Social Media Sharing:
-
Twitter, Facebook, LinkedIn, and WhatsApp buttons
-
Opens share dialogs in new windows
-
-
Additional Features:
-
Feature cards highlighting service benefits
-
Error handling and user feedback
-
Responsive design for all screen sizes
-
How to Use
-
Save the three files (index.html, styles.css, script.js) in the same directory
-
Open index.html in a web browser
-
Paste a long URL and click "Shorten"
-
Copy the shortened URL or share it on social media
Notes
-
This is a frontend-only implementation. In a production environment, you would need:
-
A backend service to actually shorten and store the URLs
-
A database to persist the URL mappings
-
Analytics tracking for the shortened URLs
-
-
The current implementation simulates the shortening process with random strings for demonstration purposes.
-
For a complete solution, you would need to implement server-side code (Node.js, PHP, Python, etc.) to handle the actual URL shortening and redirection.
:root {
--primary-color: #4361ee;
--secondary-color: #3f37c9;
--accent-color: #4895ef;
--light-color: #f8f9fa;
--dark-color: #212529;
--success-color: #4bb543;
--error-color: #ff3333;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: #f5f7ff;
color: var(--dark-color);
line-height: 1.6;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
header {
text-align: center;
margin-bottom: 2rem;
}
header h1 {
font-size: 2.5rem;
color: var(--primary-color);
margin-bottom: 0.5rem;
}
header p {
color: #666;
font-size: 1.1rem;
}
.url-form {
background: white;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
margin-bottom: 2rem;
}
.url-form input[type="url"] {
width: 100%;
padding: 1rem;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 1rem;
margin-bottom: 1rem;
transition: border 0.3s;
}
.url-form input[type="url"]:focus {
border-color: var(--primary-color);
outline: none;
}
.url-form button {
background-color: var(--primary-color);
color: white;
border: none;
padding: 1rem 2rem;
border-radius: 5px;
font-size: 1rem;
cursor: pointer;
width: 100%;
font-weight: bold;
transition: background-color 0.3s;
}
.url-form button:hover {
background-color: var(--secondary-color);
}
.custom-option {
display: flex;
align-items: center;
margin-top: 1rem;
gap: 0.5rem;
}
.custom-option input[type="checkbox"] {
width: auto;
}
.custom-option label {
font-size: 0.9rem;
color: #666;
}
.custom-option input[type="text"] {
flex: 1;
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 0.9rem;
}
.result-container {
background: white;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
margin-bottom: 2rem;
transition: all 0.3s ease;
}
.result-box {
display: flex;
flex-direction: column;
gap: 1rem;
}
.original-url, .shortened-url {
padding: 1rem;
background: #f8f9fa;
border-radius: 5px;
word-break: break-all;
}
.shortened-url {
display: flex;
justify-content: space-between;
align-items: center;
background: #e9f5ff;
}
.shortened-url span {
color: var(--primary-color);
font-weight: bold;
}
#copy-btn {
background-color: var(--accent-color);
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 5px;
font-size: 0.9rem;
cursor: pointer;
transition: background-color 0.3s;
display: flex;
align-items: center;
gap: 0.5rem;
}
#copy-btn:hover {
background-color: var(--secondary-color);
}
.share-options {
margin-top: 1rem;
}
.share-options p {
margin-bottom: 0.5rem;
font-size: 0.9rem;
color: #666;
}
.social-icons {
display: flex;
gap: 0.5rem;
}
.social-btn {
width: 40px;
height: 40px;
border-radius: 50%;
border: none;
color: white;
font-size: 1rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.3s;
}
.social-btn:hover {
transform: translateY(-3px);
}
.twitter {
background-color: #1DA1F2;
}
.facebook {
background-color: #4267B2;
}
.linkedin {
background-color: #0077B5;
}
.whatsapp {
background-color: #25D366;
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.feature-card {
background: white;
padding: 1.5rem;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
text-align: center;
transition: transform 0.3s;
}
.feature-card:hover {
transform: translateY(-5px);
}
.feature-card i {
font-size: 2rem;
color: var(--primary-color);
margin-bottom: 1rem;
}
.feature-card h3 {
margin-bottom: 0.5rem;
color: var(--dark-color);
}
.feature-card p {
color: #666;
font-size: 0.9rem;
}
footer {
text-align: center;
color: #666;
font-size: 0.9rem;
padding-top: 2rem;
border-top: 1px solid #eee;
}
.notification {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background-color: var(--success-color);
color: white;
padding: 1rem 2rem;
border-radius: 5px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
z-index: 1000;
opacity: 0;
transition: opacity 0.3s;
}
.notification.show {
opacity: 1;
}
.hidden {
display: none;
}
@media (max-width: 600px) {
.container {
padding: 1rem;
}
header h1 {
font-size: 2rem;
}
.url-form, .result-container {
padding: 1.5rem;
}
.features {
grid-template-columns: 1fr;
}
}
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const originalUrlInput = document.getElementById('original-url');
const shortenBtn = document.getElementById('shorten-btn');
const customToggle = document.getElementById('custom-toggle');
const customAliasInput = document.getElementById('custom-alias');
const resultContainer = document.querySelector('.result-container');
const displayOriginal = document.getElementById('display-original');
const displayShortened = document.getElementById('display-shortened');
const copyBtn = document.getElementById('copy-btn');
const notification = document.querySelector('.notification');
const socialButtons = document.querySelectorAll('.social-btn');
// Toggle custom alias input
customToggle.addEventListener('change', function() {
customAliasInput.disabled = !this.checked;
if (!this.checked) {
customAliasInput.value = '';
}
});
// Shorten URL
shortenBtn.addEventListener('click', function() {
const originalUrl = originalUrlInput.value.trim();
const customAlias = customAliasInput.value.trim();
if (!originalUrl) {
showError('Please enter a URL to shorten');
return;
}
// Validate URL format
try {
new URL(originalUrl);
} catch (e) {
showError('Please enter a valid URL (include http:// or https://)');
return;
}
// Validate custom alias if provided
if (customToggle.checked && customAlias) {
if (!/^[a-zA-Z0-9_-]+$/.test(customAlias)) {
showError('Custom alias can only contain letters, numbers, hyphens, and underscores');
return;
}
if (customAlias.length > 20) {
showError('Custom alias must be 20 characters or less');
return;
}
}
// In a real app, you would send this to your backend API
// For this demo, we'll simulate a response
simulateShortenUrl(originalUrl, customAlias);
});
// Simulate URL shortening (in a real app, this would be an API call)
function simulateShortenUrl(originalUrl, customAlias) {
// Show loading state
shortenBtn.disabled = true;
shortenBtn.textContent = 'Shortening...';
// Simulate API delay
setTimeout(() => {
// Generate a random short code or use custom alias
const shortCode = customAlias || generateRandomString(6);
const shortenedUrl = `https://snipurl.com/${shortCode}`;
// Display results
displayOriginal.textContent = originalUrl;
displayShortened.textContent = shortenedUrl;
resultContainer.classList.remove('hidden');
// Reset form
shortenBtn.disabled = false;
shortenBtn.textContent = 'Shorten';
// Scroll to results
resultContainer.scrollIntoView({ behavior: 'smooth' });
}, 800);
}
// Generate random string for short URL
function generateRandomString(length) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
// Copy to clipboard
copyBtn.addEventListener('click', function() {
const shortenedUrl = displayShortened.textContent;
navigator.clipboard.writeText(shortenedUrl).then(() => {
showNotification('URL copied to clipboard!');
}).catch(err => {
console.error('Failed to copy: ', err);
showNotification('Failed to copy URL');
});
});
// Show notification
function showNotification(message) {
const notificationText = document.querySelector('.notification-text');
notificationText.textContent = message;
notification.classList.add('show');
setTimeout(() => {
notification.classList.remove('show');
}, 3000);
}
// Show error (simple version for this demo)
function showError(message) {
showNotification(message);
}
// Social sharing
socialButtons.forEach(button => {
button.addEventListener('click', function() {
const platform = this.classList.contains('twitter') ? 'twitter' :
this.classList.contains('facebook') ? 'facebook' :
this.classList.contains('linkedin') ? 'linkedin' : 'whatsapp';
const shortenedUrl = displayShortened.textContent;
let shareUrl = '';
switch (platform) {
case 'twitter':
shareUrl = `https://twitter.com/intent/tweet?text=Check%20this%20link&url=${encodeURIComponent(shortenedUrl)}`;
break;
case 'facebook':
shareUrl = `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(shortenedUrl)}`;
break;
case 'linkedin':
shareUrl = `https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(shortenedUrl)}`;
break;
case 'whatsapp':
shareUrl = `https://wa.me/?text=${encodeURIComponent(`Check this link: ${shortenedUrl}`)}`;
break;
}
window.open(shareUrl, '_blank', 'width=600,height=400');
});
});
// Allow pressing Enter in the URL input to submit
originalUrlInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
shortenBtn.click();
}
});
});
إرسال تعليق
Thank you
Learning robo team