diff --git a/assets/css/app.css b/assets/css/app.css
index f535571..47fd7b6 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -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 {
@@ -48,4 +74,12 @@ input, select {
input:invalid, select:invalid {
border-color: red;
+}
+
+#actions .btn {
+ margin-right: 10px;
+}
+
+.bi {
+ margin-right: 5px;
}
\ No newline at end of file
diff --git a/assets/js/app.js b/assets/js/app.js
index 298306a..de1b490 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -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;
@@ -64,6 +68,9 @@ 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;
}
@@ -71,21 +78,49 @@ function showPattern() {
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 = `Notice: ${selectedPattern}`;
+ regexDisplay.innerHTML = `Notice: ${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 = `Regex Pattern: ${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 += `${part}: ${explanationText}
`;
+ }
+ 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 => {
@@ -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'; }`,
@@ -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 = `Code Example in ${language}: ${codeExamples[language]}`;
+ const codeExample = codeExamples[language];
+ document.getElementById('codeExampleDisplay').innerHTML = `Code Example in ${language}: ${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);
+}
\ No newline at end of file
diff --git a/index.html b/index.html
index ce8f898..9062d42 100644
--- a/index.html
+++ b/index.html
@@ -3,50 +3,100 @@