Skip to content

Commit

Permalink
Added more styling, functionality and major improving to the user exp…
Browse files Browse the repository at this point in the history
…erience
  • Loading branch information
mnestorov authored Aug 21, 2024
1 parent aff9714 commit 8ecb103
Show file tree
Hide file tree
Showing 4 changed files with 1,009 additions and 169 deletions.
52 changes: 43 additions & 9 deletions assets/css/app.css
Original file line number Diff line number Diff line change
@@ -1,26 +1,52 @@
body, html {
height: 100%;
margin: 0;
}

body {
background-color: #121212;
color: #ffffff;
}

.page-container {
display: flex;
flex-direction: column;
min-height: 100vh;
}

.content {
flex: 1;
border-radius: 10px;
}

header .container {
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}

footer .container {
margin-top: auto;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}

.container {
background-color: #1e1e1e;
padding: 20px;
border-radius: 8px;
}

.form-label, .form-select, .btn-primary {
background-color: #1e1e1e;
color: #ffffff;
.footer-sticky {
position: relative;
width: 100%;
}

.btn-primary {
border-color: #007bff;
.form-label, .form-select {
background-color: #1e1e1e;
color: #ffffff;
}

.btn-primary:hover {
background-color: #007bff;
color: #ffffff;
.text-bg-dark {
background-color: #121212 !important;
}

.alert-danger-custom {
Expand Down Expand Up @@ -48,4 +74,12 @@ input, select {

input:invalid, select:invalid {
border-color: red;
}

#actions .btn {
margin-right: 10px;
}

.bi {
margin-right: 5px;
}
105 changes: 99 additions & 6 deletions assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ function showPattern() {
const language = document.getElementById('programmingLanguage');
const regexDisplay = document.getElementById('regexDisplay');
const codeExampleDisplay = document.getElementById('codeExampleDisplay');
const exportButton = document.getElementById('exportButton');
const copyButton = document.getElementById('copyButton');
const explanationAccordion = document.getElementById('explanationAccordion');
const explanationBody = document.getElementById('explanationBody');

let hasError = false;

Expand Down Expand Up @@ -64,28 +68,59 @@ function showPattern() {
regexDisplay.classList.remove('alert-success', 'alert-danger-custom');
regexDisplay.classList.add('alert-danger');
codeExampleDisplay.style.display = 'none'; // Hide code example
exportButton.style.display = 'none'; // Hide export button
copyButton.style.display = 'none'; // Hide copy button
explanationAccordion.style.display = 'none'; // Hide explanation
return;
}

// Fetch data and show pattern
fetch('patterns.json')
.then(response => response.json())
.then(data => {
const selectedPattern = data.patterns[patternType.value][country.value];
const selectedData = data.patterns[patternType.value][country.value];

if (typeof selectedPattern === 'string' && selectedPattern.startsWith("Not applicable")) {
if (typeof selectedData === 'string') {
// If it's a special message, display it directly without showing a regex pattern
regexDisplay.innerHTML = `<strong>Notice:</strong> ${selectedPattern}`;
regexDisplay.innerHTML = `<strong>Notice:</strong> ${selectedData}`;
regexDisplay.classList.remove('alert-success');
regexDisplay.classList.add('alert-danger-custom');
codeExampleDisplay.style.display = 'none'; // Hide code example
exportButton.style.display = 'none'; // Hide export button
copyButton.style.display = 'none'; // Hide copy button
explanationAccordion.style.display = 'none'; // Hide explanation
} else {
// Otherwise, display the regex pattern and code example
regexDisplay.textContent = `Regex Pattern: ${selectedPattern}`;
const selectedPattern = selectedData.pattern;
regexDisplay.innerHTML = `<strong>Regex Pattern:</strong> ${selectedPattern}`;
regexDisplay.classList.remove('alert-danger', 'alert-danger-custom');
regexDisplay.classList.add('alert-success');
displayCodeExample(selectedPattern, language.value);
const codeExample = displayCodeExample(selectedPattern, language.value);
codeExampleDisplay.style.display = 'block'; // Show code example
exportButton.style.display = 'inline-block'; // Show export button
copyButton.style.display = 'inline-block'; // Show copy button

// Display the explanation
const explanation = selectedData.explanation;
explanationBody.innerHTML = ''; // Clear previous explanations
if (explanation) {
for (const [part, explanationText] of Object.entries(explanation)) {
explanationBody.innerHTML += `<strong class="text-warning">${part}:</strong> ${explanationText}<br>`;
}
explanationAccordion.style.display = 'block'; // Show explanation accordion
} else {
explanationAccordion.style.display = 'none'; // Hide explanation if not available
}

// Handle export button click
exportButton.onclick = function() {
exportToFile(selectedPattern, codeExample, language.value);
};

// Handle copy button click
copyButton.onclick = function() {
copyToClipboard(selectedPattern, codeExample);
};
}
})
.catch(error => {
Expand All @@ -94,9 +129,13 @@ function showPattern() {
regexDisplay.classList.add('alert-danger');
console.error('Error loading the patterns:', error);
codeExampleDisplay.style.display = 'none'; // Hide code example
exportButton.style.display = 'none'; // Hide export button
copyButton.style.display = 'none'; // Hide copy button
explanationAccordion.style.display = 'none'; // Hide explanation
});
}

// Function to return the code example string
function displayCodeExample(regex, language) {
const codeExamples = {
'PHP': `if (preg_match('/${regex}/', $input)) { echo 'Valid'; } else { echo 'Invalid'; }`,
Expand All @@ -109,5 +148,59 @@ function displayCodeExample(regex, language) {
'Swift': `import Foundation\nlet regex = try! NSRegularExpression(pattern: "${regex}")\nlet range = NSRange(location: 0, length: input.utf16.count)\nif regex.firstMatch(in: input, options: [], range: range) != nil { print("Valid") } else { print("Invalid") }`,
'Perl': `if ($input =~ /${regex}/) { print "Valid"; } else { print "Invalid"; }`
};
document.getElementById('codeExampleDisplay').innerHTML = `<strong>Code Example in ${language}:</strong> ${codeExamples[language]}`;
const codeExample = codeExamples[language];
document.getElementById('codeExampleDisplay').innerHTML = `<strong>Code Example in ${language}:</strong> ${codeExample}`;
return codeExample;
}

// Function to export the pattern and code example to a file
function exportToFile(pattern, codeExample, language) {
const content = `Regex Pattern:\n${pattern}\n\nCode Example in ${language}:\n${codeExample}`;
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);

const a = document.createElement('a');
a.href = url;
a.download = `regex-pattern.${language.toLowerCase()}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}

// Function to copy the pattern and code example to the clipboard
function copyToClipboard(pattern, codeExample) {
const content = `Regex Pattern:\n${pattern}\n\n${codeExample}`;

// Check if the Clipboard API is supported
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(content)
.then(() => {
alert('Pattern and code copied to clipboard!');
})
.catch(err => {
console.error('Failed to copy with Clipboard API:', err);
fallbackCopyToClipboard(content); // Use fallback
});
} else {
// Use fallback if Clipboard API is not supported
fallbackCopyToClipboard(content);
}
}

// Fallback method using document.execCommand('copy')
function fallbackCopyToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();

try {
document.execCommand('copy');
alert('Pattern and code copied to clipboard!');
} catch (err) {
console.error('Fallback: Unable to copy', err);
}

document.body.removeChild(textArea);
}
124 changes: 87 additions & 37 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,100 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Regex Viewer</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Regex Pattern Generator</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/app.css">
</head>
<body>
<div class="container py-5">
<h1 class="mb-3">Regex Pattern Viewer</h1>
<form>
<div class="mb-3">
<label for="patternType" class="form-label">Select Pattern Type:</label>
<select id="patternType" class="form-select" onchange="updateCountriesAndLabel()">
<option value="">Please select</option>
<option value="phoneNumbers">Phone Numbers</option>
<option value="postalCodes">Postal Codes</option>
<option value="VATNumbers">VAT Numbers</option>
<option value="commonPatterns">Common Patterns</option>
</select>
<div class="page-container">
<!-- Header -->
<header class="text-white mb-2 pb-2">
<div class="container d-flex justify-content-between align-items-center">
<h1 class="h3 mb-0">Regex Pattern Generator</h1>
<a href="https://github.com/mnestorov/regex-patterns" target="_blank" class="text-white">
<i class="bi bi-github" style="font-size: 1.5rem;"></i>
</a>
</div>
<div class="mb-3">
<label id="secondSelectLabel" for="country" class="form-label">Select Country:</label>
<select id="country" class="form-select">
<option value="">Please select</option>
</select>
</header>
<!-- Description Block -->
<div class="container content bg-transparent text-center">
<hr class="dotted">
<p class="lead">Designed to help developers easily generate and understand regular expressions for various use cases.</p>
<p class="">Select a pattern type, country, and programming language to see the corresponding regular expression and code example. You can also view a detailed explanation of how the regex works and export or copy the code for your project.</p>
<hr>
</div>
<div class="container py-5 mt-4 content">
<form>
<div class="mb-3">
<label for="patternType" class="form-label">Select Pattern Type:</label>
<select id="patternType" class="form-select" onchange="updateCountriesAndLabel()">
<option value="">Please select</option>
<option value="phoneNumbers">Phone Numbers</option>
<option value="postalCodes">Postal Codes</option>
<option value="VATNumbers">VAT Numbers</option>
<option value="commonPatterns">Common Patterns</option>
</select>
</div>
<div class="mb-3">
<label id="secondSelectLabel" for="country" class="form-label">Select Country:</label>
<select id="country" class="form-select">
<option value="">Please select</option>
</select>
</div>
<div class="mb-3">
<label for="programmingLanguage" class="form-label">Select Programming Language:</label>
<select id="programmingLanguage" class="form-select">
<option value="">Please select</option>
<option value="PHP">PHP</option>
<option value="JavaScript">JavaScript</option>
<option value="Python">Python</option>
<option value="C#">C#</option>
<option value="Java">Java</option>
<option value="Ruby">Ruby</option>
<option value="Go">Go</option>
<option value="Swift">Swift</option>
<option value="Perl">Perl</option>
</select>
</div>
<button type="button" onclick="showPattern()" class="btn btn-primary">
<i class="bi bi-eye"></i> Show Pattern and Code
</button>
</form>
<div id="regexDisplay" class="alert alert-success mt-3">Regex pattern will be displayed here.</div>
<div class="accordion mt-3" id="explanationAccordion" style="display: none;">
<div class="accordion-item border border-3 border-warning rounded">
<h2 class="accordion-header" id="headingExplanation">
<button class="accordion-button text-bg-warning shadow-none" type="button" data-bs-toggle="collapse" data-bs-target="#collapseExplanation" aria-expanded="true" aria-controls="collapseExplanation">
<strong><i class="bi bi-info-circle"></i> Explanation of Regex Pattern</strong>
</button>
</h2>
<div id="collapseExplanation" class="accordion-collapse collapse show" aria-labelledby="headingExplanation" data-bs-parent="#explanationAccordion">
<div class="accordion-body text-bg-dark" id="explanationBody">
<!-- Explanation content will be dynamically generated here -->
</div>
</div>
</div>
</div>
<div class="mb-3">
<label for="programmingLanguage" class="form-label">Select Programming Language:</label>
<select id="programmingLanguage" class="form-select">
<option value="">Please select</option>
<option value="PHP">PHP</option>
<option value="JavaScript">JavaScript</option>
<option value="Python">Python</option>
<option value="C#">C#</option>
<option value="Java">Java</option>
<option value="Ruby">Ruby</option>
<option value="Go">Go</option>
<option value="Swift">Swift</option>
<option value="Perl">Perl</option>
</select>
<div id="codeExampleDisplay" class="alert alert-info mt-3">Code example will be displayed here.</div>
<div id="actions" class="mt-3">
<button id="exportButton" type="button" class="btn btn-success" style="display: none;">
<i class="bi bi-download"></i> Export to File
</button>
<button id="copyButton" type="button" class="btn btn-success" style="display: none;">
<i class="bi bi-clipboard"></i> Copy to Clipboard
</button>
</div>
<button type="button" onclick="showPattern()" class="btn btn-primary">Show Pattern and Code</button>
</form>
<div id="regexDisplay" class="alert alert-success mt-3">Regex pattern will be displayed here.</div>
<div id="codeExampleDisplay" class="alert alert-info mt-3">Code example will be displayed here.</div>
</div>
<!-- Footer -->
<footer class="text-center mt-4 pt-4">
<div class="container">
<p class="my-3">&copy; 2024 - Developed by <a href="https://github.com/mnestorov/" target="_blank" class="text-decoration-none"><mark class="bg-primary text-white rounded">Martin Nestorov</mark></a></p>
<p><small>Contributions are welcome so feel free to fork the project on GitHub and submit a pull request. <br> Your help in improving this tool is greatly appreciated.</small></p>
</div>
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<script src="assets/js/app.js"></script>
</body>
</html>
Loading

0 comments on commit 8ecb103

Please sign in to comment.