I’m trying to create a sliding menu for my web application that contains several buttons which should slide in from the right when a menu icon is clicked. I’ve attempted to use CSS for the sliding effect and JavaScript to handle the toggle functionality, but I’m encountering issues with the elements not behaving as expected.
Here’s a simplified version of the code I’m working with:
body, html {
height: 100%;
margin: 0;
font-family: Arial, sans-serif;
background-color: #333;
color: white;
}
header {
background-color: #222;
padding: 10px 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
nav h1 {
margin: 0;
}
nav ul {
list-style: none;
padding: 0;
display: flex;
gap: 10px;
}
nav ul li button {
background-color: #555;
border: none;
padding: 10px 20px;
color: white;
cursor: pointer;
}
nav ul li button:hover {
background-color: #666;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Taskboard</title>
<link rel="stylesheet" href="/static/styling/home.css">
</head>
<body>
<header>
<nav>
<h1>My New Taskboard</h1>
<ul>
<li>
<button id="update-button">Update</button>
</li>
<li><button id="edit-button">Edit</button></li>
<li><button id="open-button">Open</button></li>
<li><button id="new-button">New</button></li>
<li><button id="settings-button">Settings</button></li>
</ul>
</nav>
</header>
<main>
<section class="taskboard-grid" id="taskboard-grid">
<!-- Task cards will be dynamically added here -->
</section>
<!-- Hidden form for creating a new taskboard -->
<div id="new-taskboard-form" style="display: none;">
<input type="text" id="new-taskboard-name" placeholder="Enter Taskboard Name">
<input type="file" id="new-taskboard-file" accept=".xlsx">
<button id="submit-new-taskboard">Create Taskboard</button>
</div>
</main>
<script>
document.getElementById('settings-button').addEventListener('click', function() {
// To open in the same tab:
window.location.href = 'settings';
});
// Global variable to keep track of the currently selected taskboard
let currentTaskboard = null;
document.getElementById('update-button').addEventListener('click', function() {
if (!currentTaskboard) {
alert('Please select a taskboard first.');
return;
}
var fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.xlsx';
fileInput.addEventListener('change', function(event) {
var file = event.target.files[0];
var formData = new FormData();
formData.append('file', file);
formData.append('name', currentTaskboard); // Use the current taskboard
fetch('/upload/', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
// If the upload is successful, fetch and display the updated data
fetchTaskboardData(currentTaskboard);
})
.catch(error => {
console.error('Error:', error);
});
});
fileInput.click();
});
document.getElementById('open-button').addEventListener('click', function() {
fetch('/list/')
.then(response => response.json())
.then(taskboards => {
showTaskboardSelector(Object.values(taskboards));
})
.catch(error => {
console.error('Error fetching taskboards:', error);
});
});
function showTaskboardSelector(taskboards) {
var selector = document.createElement('select');
selector.id = 'taskboard-selector';
taskboards.forEach(taskboard => {
var option = document.createElement('option');
option.value = taskboard;
option.textContent = taskboard;
selector.appendChild(option);
});
document.body.appendChild(selector);
selector.addEventListener('change', function() {
currentTaskboard = this.value; // Update the current taskboard
fetchTaskboardData(currentTaskboard);
});
}
function fetchTaskboardData(taskboardName) {
fetch(`/get/?name=${encodeURIComponent(taskboardName)}`)
.then(response => response.json())
.then(data => {
var taskboardGrid = document.getElementById('taskboard-grid');
taskboardGrid.innerHTML = ''; // Clear existing content
// Check if data is an array and handle accordingly
if (Array.isArray(data)) {
data.forEach(createCard);
} else if (typeof data === 'object') {
// If data is an object, iterate over its values
Object.values(data).forEach(createCard);
}
})
.catch(error => {
console.error('Error fetching taskboard data:', error);
});
}
function createCard(row) {
var card = document.createElement('div');
card.className = 'task-card';
Object.keys(row).forEach(key => {
if (row[key] !== null && row[key] !== undefined) { // Check for non-null and non-undefined values
var p = document.createElement('p');
p.textContent = `${key}: ${row[key]}`;
card.appendChild(p);
}
});
document.getElementById('taskboard-grid').appendChild(card);
}
// function createCard(row) {
// var card = document.createElement('div');
//card.className = 'task-card';
// Object.keys(row).forEach(key => {
//var p = document.createElement('p');
// p.textContent = `${key}: ${row[key]}`;
// card.appendChild(p);
// });
// document.getElementById('taskboard-grid').appendChild(card);
// }
// Event listener for the 'Edit' button
document.getElementById('edit-button').addEventListener('click', function() {
if (!currentTaskboard) {
alert('Please select a taskboard first.');
return;
}
// Change the window location to your edit page and pass the taskboard name as a query parameter
window.location.href = `/edit?name=${encodeURIComponent(currentTaskboard)}`;
});
// New functionality for the 'New' button
document.getElementById('new-button').addEventListener('click', function() {
document.getElementById('new-taskboard-form').style.display = 'block';
});
document.getElementById('submit-new-taskboard').addEventListener('click', function() {
var taskboardName = document.getElementById('new-taskboard-name').value;
var fileInput = document.getElementById('new-taskboard-file');
var file = fileInput.files[0];
if (!taskboardName || !file) {
alert('Please enter a taskboard name and select a file.');
return;
}
var formData = new FormData();
formData.append('name', taskboardName);
formData.append('file', file);
fetch('/create', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
console.log('Taskboard created:', data);
// Hide the form and clear inputs after successful creation
document.getElementById('new-taskboard-form').style.display = 'none';
document.getElementById('new-taskboard-name').value = '';
fileInput.value = '';
})
.catch(error => {
console.error('Error:', error);
});
});
document.addEventListener('DOMContentLoaded', function() {
const urlParams = new URLSearchParams(window.location.search);
const taskboardName = urlParams.get('name');
if (taskboardName) {
// Code to open the specified taskboard
// For example, if you have a function to load a taskboard by name, call it here
openTaskboard(taskboardName);
}
});
function openTaskboard(taskboardName) {
// Implement the logic to open and display the taskboard by its name
// This might involve setting the 'currentTaskboard' variable and calling a function to fetch and display its data
currentTaskboard = taskboardName;
fetchTaskboardData(taskboardName);
}
</script>
</body>
</html>
The expected behavior is that when the menu icon is clicked, the menu should slide in from the right with a smooth transition, and clicking the icon again should hide the menu with a similar sliding effect.
Actually, right now it is static as you can see at the picture below.
Here is how it looks now, it is static:
Here is how it should look like, this is when the buttons are expanded, please pay attention only to the header with the buttons:
This is when the buttons are not expanded:
Could someone help me understand what I’m doing wrong and how to achieve the sliding menu effect properly?
2
Answers
You seem to have no onClick method on the buttons.
And to get the sliding effect, you will need @keyframes in the CSS.
Edit
Read this: https://www.joshwcomeau.com/animation/keyframe-animations/
You can use translate() function this way. I will also start by removing the buttons. You will also need to add onclick listener to slide back the non-clicked elements