Flask repeating function by keep pressing a button - javascript

today I've been trying to resolve this problem, but I can't figure it out how to "fix".
I'm creating a website using Flask, and when I'm clicking a button placed in a post form, I'd like to keep an action doing; to be more accurate, when I click the button, an action should be performed, but I'd like this action to be performed more times if I keep pressing the button. This is the structure of my layout and code.
Here is the python code
from flask import (
Blueprint, render_template, request
)
from webapp.Utilities.utilities import SerialHandler
from webapp.blueprints.decorators import login_required
bp = Blueprint('main', __name__)
serial_scheduler = SerialHandler()
#bp.route('/', methods=('GET', 'POST'))
#login_required
def index():
if request.method == 'POST':
button = request.form['press_to_run']
foo()
return render_template('index.html', title="Index")
And here the HTML structure
{% extends "layout.html" %}
{% block stylesheet %}
<link rel="stylesheet" href="{{ url_for('static', filename='index.css') }}">
{% endblock %}
{% block content %}
<div class="container new_container">
<div class="card" style="width: 18rem;">
<div class="card-header">
Featured
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
</div>
</div>
<div class="container">
<img src="{{ url_for('video.video') }}" alt="">
</div>
<form class="" method="post">
<div class="btn-group" style="width:100%">
<button style="width:33.3%">Apple</button>
<button style="width:33.3%">Samsung</button>
<button style="width:33.3%">Sony</button>
</div>
</form>
<div class="container new_container">
<div class="col-md-12 text-center">
<button onclick="switch_theme()" class="btn btn-light shadow-none" id="switch_button" style="width: 15%;">Dark Mode</button>
</div>
</div>
<script>
function switch_theme() {
const theme = document.getElementById('switch_theme').className;
if(theme === "dark-theme") {
document.getElementById('switch_theme').className = "light-theme";
document.getElementById('switch_button').className = "btn btn-dark shadow-none";
document.getElementById('switch_button').innerHTML = "Light Mode";
} else {
document.getElementById('switch_theme').className = "dark-theme";
document.getElementById('switch_button').className = "btn btn-light shadow-none";
document.getElementById('switch_button').innerHTML = "Dark Mode";
}
}
</script>
{% endblock %}
To conclude I say that I don't necessarily need a solution with python, but I would also be fine with a solution that include maybe a javascript function that runs the python function of my SerialHandler object.
Thanks in advance for the answers.

The code you provided doesn't help much. From what I understood you want to call your flask API endpoint (that will call the python function) repeatedly if someone keeps pressing a button inside a form element. This can be done in the front end with JavaScript itself. Something like -
<form method="POST">
<button id="formbutton">Click me!</button>
</form>
<script>
// grab the button
formBtn = document.querySelector('#formbutton')
let isMouseDown = false
// don't send the form automatically
formBtn.addEventListener('click', function(e) {
e.preventDefault()
})
// keep track of isMouseDown
formBtn.addEventListener('mousedown', function(e) {
isMouseDown = true
})
formBtn.addEventListener('mouseup', function(e) {
isMouseDown = false
})
// how many times to call the backend
setInterval(function() {
if(isMouseDown) {
// can also use axios & pass custom data
fetch('http://your.server/end/point', {
method: 'POST'
}).then(res => console.log(resres))
}
}, 200)
</script>
This may not be the best way to do it but will get the job done. If there are multiple buttons just add them in an array & add event listeners on them in a loop.

Related

How to change contents on clicking the selected div using Javascript?

I am new to Javascript. I wish to change the contents of div on selecting a particular div element.
If I select a div, the text associated with that div contents only should display. I am using a loop to display the contents. It's like a chat application. If a user clicks on a contact the messages associated with that user should display. I am using a loop to display messages and users.
What I have tried is:
Twig code:
{% set msg = query().from('messages').get() %}
{% set to_add =to_name %}
{% set to_details = query().from('users_users').where('id', to_add).get() %}
<div class="container">
<h3 class=" text-center">Messaging</h3>
<div class="messaging">
<div class="inbox_msg">
<div class="inbox_people">
<div class="headind_srch">
<div class="recent_heading">
<h4>{{auth_user().first_name}}</h4>
</div>
<div class="srch_bar">
<div class="stylish-input-group">
<input type="text" class="search-bar" placeholder="Search" >
<span class="input-group-addon">
<button type="button"> <i class="fa fa-search" aria-hidden="true"></i> </button>
</span> </div>
</div>
</div>
<div class="inbox_chat">
{% set newArray = [] %}
{% for msg in msg_details %}
{% if msg.to_name not in newArray %}
<div class="chat_list active_chat" onclick=viewMessage(this)>
<div class="chat_people">
<div class="chat_img"> <img src="https://ptetutorials.com/images/user-profile.png" alt="sunil"> </div>
<div class="chat_ib">
<h5>{{msg.to_name}} <span class="chat_date">{{msg.time}}</span></h5>
</div>
</div>
</div>
{% set newArray = newArray|merge([msg.to_name]) %}
{% endif %}
{% endfor %}
</div>
</div>
<div class="mesgs">
<div class="msg_history">
<div class="incoming_msg">
<div class="incoming_msg_img">
<img src="https://ptetutorials.com/images/user-profile.png" alt="sunil">
</div>
<div class="received_msg">
<div class="received_withd_msg">
<p>{{msg.message}}</p>
<span class="time_date">{{msg.time}}</span></div>
</div>
</div>
<div class="outgoing_msg">
<div class="sent_msg">
<p></p>
<span class="time_date"></span> </div>
</div>
</div>
</div>
</div>
</div></div>
Javascript code:
<script>
function copyText(elementId){
var x = document.getElementById(elementId).textContent;
if(document.getElementById('select-text').value.length == 0)
{
document.getElementById("btn").disabled = false;
document.getElementById(elementId).style.backgroundColor = "lightblue";
document.getElementById('select-text').focus();
document.getElementById('select-text').value += x;
}
else{
document.getElementById('select-text').readOnly = true;
}
}
</script>
What my output looks like
Output
My output shows all the messages, I want to show only the particular user message. How to do so?
What my table looks like:
Table
First of all you have to fetch the data from your table using a query something like to ensure you will get one record from each from_id.
SELECT * FROM msg GROUP BY from_id;
Then you can loop in twig to create the left side elements like,
{% for distinctMsg in distinctMsgs %}
<div class="chat_list active_chat" data-userId="{{ distinctMsg.fromId }}">
<div class="chat_people">
<div class="chat_img"> <img src="https://ptetutorials.com/images/user-profile.png" alt="sunil"> </div>
<div class="chat_ib">
<h5>{{distinctMsg.to_name}} <span class="chat_date">{{distinctMsg.time}}</span></h5>
</div>
</div>
</div>
{% endfor %}
Then in your javascript:-
$(".chat_list").on("click", function(){
// have a look here https://stackoverflow.com/questions/5309926/how-can-i-get-the-data-id-attribute
var userId = $(this).data( "userId" );
// Maybe display a loading icon in the right side div
$.ajax({
type: "POST",
url: "/api/msg/user/history", // your controller url
dataType: 'json',
headers: {
// if you have any headers to set
"Authorization": "Bearer {{ token }}"
},
data:{
"userId" : userId
}
})
.done(function (response) {
// stop displaying the loading icon
// process the response and display message history in right side
})
.fail(function (xhr, status, error) {
// show proper error message
});
});
NOTE: You will have to have jQuery in your page for Ajax functions to work.

Django AJAX Infinite Scroll Error on page reload

I'm trying to implement infinite scroll with django and jquery(Waypoint).
I have a ListView with a pagination of 5, but when waypoint loads second page, AJAX requests are no longer performed so I added the AJAX function on the onAfterPageLoad which helps bring back AJAX function to the newly loaded page.
That's fine, but then it introduces a bug to my code making the page loaded initially (First Page) no longer perform AJAX functions very well. It makes AJAX on the first page run 3 times if I just loaded a third page and makes AJAX on the second page run twice and so on depending on the number of pages loaded already.
I don't know if there are any cool ways to achieve this because I tried using just jquery without waypoint, but still get same errors as I get when using just waypoint making it an error. This is kinda tricky so far.
{% extends "base.html" %}
{% block content %}
{% load static %}
<div class="container" style="max-width:700px">
<div class="px-3 pt-md-5 pb-md-4 mx-auto text-center">
<h1 class="display-4">All Groups</h1>
<p class="lead">List of groups</p>
</div>
<div class="">
<div class="row infinite-container">
{% for group in groups %}
<div class="col-md-12 infinite-item">
<!-- <img class="img-fluid" src="https://picsum.photos/700"> -->
<a class="text-dark" href="{{ group.get_absolute_url }}">
<div class="card mb-4 box-shadow">
<div class="card-body">
<h2 style="font-size:18px;font-weight:bold;min-height:42px;">
{{group.name|truncatechars:50}}</h2>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">{{group.owner}}</small>
<small class="text-muted">{{group.date_created}}</small>
</div>
<p><a class='follow-btn' data-href='{{ group.get_group_follow_api_url }}'
data-likes='{{ page.likes.count }}'
href='{{ group.get_group_follow_url }}'>{{ group.follows.count }}
{% if request.user.profile in group.follows.all %}
Unfollow
{% else %}
Follow
{% endif %}
</a></p>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
<!-- Comment for loading spinner -->
{% comment %}
<div class="d-flex d-none position-fixed" style="top:35vh;left:46vw">
<button class="btn btn-primary loading">
<span class="spinner-border spinner-border-sm"></span>
Loading...
</button>
</div>
{% endcomment %}
<!-- End of comment for loading spinner -->
<div class="row">
<div class="col-12">
{% if page_obj.has_next %}
<a class="infinite-more-link" href="?page={{ page_obj.next_page_number }}"></a>
{% endif %}
</span>
</div>
</div>
</div>
</div>
<script src="{% static "js/jquery.waypoints.min.js" %}"></script>
<script src="/static/js/infinite.min.js"></script>
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0],
offset: 'bottom-in-view',
onBeforePageLoad: function () {
$('.loading').show();
},
onAfterPageLoad: function () {
$('.loading').hide();
$(document).ready(function(){
function updateText(btn, newCount, verb){
btn.text(newCount + " " + verb)
}
$(".follow-btn").click(function(e){
e.preventDefault()
var this_ = $(this)
var badge = this_.find('.unlike-update')
var followUrl = this_.attr("data-href")
var followCount = parseInt(this_.attr("data-follows")) | 0
var addFollow = followCount + 1
var removeFollow = followCount - 1
if (followUrl){
$.ajax({
url: followUrl,
method: "GET",
data: {},
success: function(data){
console.log(data)
var newFollows;
if (data.followed){
// updateText(this_, addLike, "Unlike")
// updateText(this_, data.likescount, badge)
updateText(this_, data.followscount, "Unfollow")
} else {
// updateText(this_, removeLike, "Like")
updateText(this_, data.followscount, "Follow")
// remove one like
}
}, error: function(error){
console.log(error)
console.log("error")
}
})
}
})
})
}})
</script>
{% include 'group/snippets/group_follow.html' %}
{% endblock %}
class GroupListView(LoginRequiredMixin, ListView):
model = Group
paginate_by = 5
context_object_name = 'groups'
template_name = 'group/group_list.html'
ordering = ['-date_created']

Cannot Update Bootstrap Modal Forms

I have a CRUD reminder app, and when users right click on a reminder, a context menu pops up. Options include edit, delete, etc. Each reminder has an id, and the context menu button updates based on the reminders id, and passes it to a bootstrap modal form:
JS:
//part of the context menu script
//this function is called when the user right clicks inside of any element with class task
function toggleMenuOn(e) {
if ( menuState !== 1 ) {
menuState = 1;
menu.classList.add( contextMenuActive );
}
let reminder_id = e.target.id
$.ajax({
url: '/ajax/get_reminder/',
data: {
'reminder_id': reminder_id
},
dataType: 'json',
success: function (data) {
let context_btn1 = document.getElementById("context_menu_btn1");
let reminder_pk = data.serialized_reminder.toString();
let reminder_url = "{% url 'update-reminder' 0 %}".replace(/0/, reminder_pk)
context_btn1.className = "update-reminder context-menu__link btn btn-light";
context_btn1.setAttribute('data-id', reminder_url);
change_var(reminder_url)
}
});
}
let context_btn_id = "/update_reminder/0/";
function change_var(new_name) {
context_btn_id = new_name;
}
$(document).ready(function() {
$("#context_menu_btn1").click(function () {
$(this).modalForm({formURL: context_btn_id});
});
});
HTML:
<nav id="context-menu" class="context-menu">
<ul class="context-menu__items">
<li class="context-menu__item">
<button type="button" class="context-menu__link btn btn-light" id="context_menu_btn1" data-id=""><i class="fa fa-edit"></i> Edit</button>
</li>
<li class="context-menu__item">
<button type="button" class="context-menu__link btn btn-light" id="context_menu_btn2" data-id=""><i class="fa fa-times"></i> Delete</button>
</li>
<li class="context-menu__item">
<button type="button"class="context-menu__link btn btn-light" id="context_menu_btn3" data-id=""><i class="fa fa-eye"></i> Share</button>
</li>
</ul>
</nav>
Reminder HTML:
<div>
<h3 class="ml-4">Long-Term Assignments:</h3>
<div class="events-content-section ml-4 mr-3">
{% get_reminder_id user.username as id_reminders %}
{% for reminder_id, long_term_reminder in id_reminders.items %}
<div class="task mb-2" style="display: flex;">
<button type="button" class="view-reminder btn btn-light" data-id="{% url 'view-reminder' long_term_reminder.pk %}" id="{{ reminder_id }}" style="width: 100%;">
<h4 style="float: left;">{{ long_term_reminder.title }}</h4>
</button>
</div>
{% endfor %}
</div>
</div>
As you can see, I have one navigation menu and have buttons that change data-id every time it is shown. The code works the first time, but when I go to edit another reminder it just brings up the modal form for the first reminder. For example, if I were to update a reminder named Test1, and then try to edit Test2, it would bring up the edit form form for Test1.
I think it has something to do with the code not creating a new modalForm every time context_btn_id is updated. As a reference, the code below works, but an individual button is created for each reminder.
$(".view-reminder").each(function () {
$(this).modalForm({formURL: $(this).data('id')});
});
How would I solve this issue? Any help would be appreciated!
You can add a data-id attribute for each reminder in reminders list or table and on navigation click you can get the selected reminder id.

Django App Not Communicating with JavaScript Code Block

I have a Django application that accepts an Elasticsearch query in a form and produces a downloadable report. An earlier iteration worked great, but we decided to add a component that checks every ten seconds if the report is done being created. Our ultimate goal is to have it check repeatedly for the completed report (and tell the user the report is still processing if not complete), and then either add a button to download the report or just have it automatically begin downloading.
However, my application doesn't seem to be calling on the javascript block I have in my form.html. When I run this, it says {"file_created": False} until I manually refresh myself, then it switches to True. I tried the code commented out in check_progress (which is basically what my code in form.html does...) but it returned an error.
How do I make them communicate? What am I missing?
views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
import os
import threading
from .forms import QueryForm
from .models import *
#login_required
def get_query(request):
if request.method == 'POST':
form = QueryForm(request.POST)
if form.is_valid():
query = form.cleaned_data["query"]
t = threading.Thread(target=generate_doc, args=(query,))
t.start()
return HttpResponseRedirect('/check_progress/')
else:
return HttpResponse("Your query does not appear to be valid. Please enter a valid query and try again.")
else:
form = QueryForm()
return render(request, 'audit_tool/form.html', {'form': form})
#login_required
def check_progress(request):
"""
Returns whether document generation is complete or in progress
"""
# check if file exists, return response as a JSON
# how to integrate with js code in html to continuously check and refresh
# only shows true when refreshed; how to talk to html??
file = "/report.docx"
data = {
"file_created": os.path.exists(file)
}
# if os.path.exists(file):
# response = generate_doc(query)
# return response
# else:
# return HttpResponseRedirect('/check_progress/')
# this does not work, "10.168.83.100 redirected you too many times.
# Try clearing your cookies.
# ERR_TOO_MANY_REDIRECTS"
return JsonResponse(data)
#login_required
def return_doc(request):
"""
Returns file response upon user request, or error message if something goes wrong
"""
response = generate_doc(query)
return response
form.html
<!-- templates/django_audit/form.html -->
{% extends 'base_login.html' %}
{% block javascript %}
<script>
var checkInterval = setInterval(isFileComplete, 10000); //10000 is 10 seconds
function isFileComplete() {
$.ajax({
url: '/check_progress/',
type: 'GET',
data: {
'file_created': 'True'
},
dataType: 'json',
success: function (data) {
if (data.exists) {
alert("Your file is ready to download!");
clearInterval(checkInterval);
} else {
alert("Your report is still being created, please hold.");
}
}
});
}
</script>
{% endblock %}
{% block title %}Form{% endblock %}
{% block content %}
<p><br></p>
<p><br></p>
<div class="alert alert-primary" role="alert">
<b>Instruction:</b>
{% load crispy_forms_tags %}
<!-- form action="/report/" method="post" onsubmit="this.submit(); this.reset(); return false; -->
<form action="/report/" method="post" onsubmit="this.submit(); this.reset(); return false;">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="Submit">
</form>
</div>
{% endblock %}
core/urls.py
from django.contrib import admin
from django.urls import include, path
from django.views.generic.base import TemplateView
from django.conf import settings
from django.conf.urls.static import static
from audit_tool import views
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('form/', include('audit_tool.urls')),
path('report/', include('audit_tool.urls')),
path('check_progress/', views.check_progress, name='check_progress'),
path('', TemplateView.as_view(template_name='home.html'), name='home'),
] + static(settings.STATIC_URL, document_root=settings.STAT)
audit_tool/urls.py
from django.urls import path
from . import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', views.get_query, name='form'),
] + static(settings.STATIC_URL, document_root=settings.STAT)
base_login.html
<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<html lang="en">
{% load static %}
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<link rel="shortcut icon" href="link/to/company/iconicon.ico" type="image/vnd.microsoft.icon" />
<title>Audit Report Tool</title>
</head>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">Dept</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="../">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../admin">Admin</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<div class="row justify-content-center">
<div class="col-8">
<hr class="mt-0 mb-4">
<img src="{% static "logo.png" %}" alt="Company Logo" align="left"></img>
<img src="{% static "logo.png" %}" alt="Dept Logo" align="right" width="140" height="140"></img>
<h1 align="center"><font size="6"> Audit Report Tool</font></h1>
</div>
</div>
</div>
<body>
<main>
{% block content %}
{% endblock %}
</main>
</body>
</html>
Your key is data.file_created, not data.exists in if (data.exists) { line. And that sending of data: {'file_created': 'True'}, get rid of that in your javascript - you're not querying request for anything in your view, as, for example, the name of the file, so you don't need to fill that data.
Also the following:
file = "/report.docx"
data = {
"file_created": os.path.exists(file)
}
It implies that report.docx is going to be saved in the root of the filesystem, that's not going to happen. Use something like
from django.conf import settings
os.path.join(settings.BASE_DIR, "../upload/", "report.docx")
Also ,you may provide the part of base_login.html where that {% block javascript %} is placed.

flask just refresh templated portion of page

I have a simple flask app that uses templates.
Every time I click somewhere on the navigation (in the base.html) it refreshes the entire page, I'd rather it just refresh inside the template because I have collapsable elements in the navbar that go back to being collapsed when the entire page is reloaded.
How do I just reload the new template I want to render and not the nav bar when I click on a link in the nav bar?
for reference here's some code:
base.html
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
<script>
// Hide submenus
$('#body-row .collapse').collapse('hide');
// Collapse/Expand icon
$('#collapse-icon').addClass('fa-angle-double-left');
// Collapse click
$('[data-toggle=sidebar-colapse]').click(function() {
SidebarCollapse();
});
function SidebarCollapse () {
$('.menu-collapsed').toggleClass('d-none');
$('.sidebar-submenu').toggleClass('d-none');
$('.submenu-icon').toggleClass('d-none');
$('#sidebar-container').toggleClass('sidebar-expanded sidebar-collapsed');
// Treating d-flex/d-none on separators with title
var SeparatorTitle = $('.sidebar-separator-title');
if ( SeparatorTitle.hasClass('d-flex') ) {
SeparatorTitle.removeClass('d-flex');
} else {
SeparatorTitle.addClass('d-flex');
}
// Collapse/Expand icon
$('#collapse-icon').toggleClass('fa-angle-double-left fa-angle-double-right');
}
</script>
<style>
</style>
{% include 'nav-mini.html' %}
<!-- Bootstrap row -->
<div class="row" id="body-row">
{% include 'nav-side.html' %}
<!-- MAIN -->
<div class="col py-3">
<article class=flashes>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message}}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</article>
{% block content %}
{% endblock %}
</div>
<!-- Main Col END -->
</div>
<!-- body-row END -->
</body>
</html>
sidenav.html
<!-- Sidebar -->
<div id="sidebar-container" class="sidebar-expanded d-none d-md-block col-2">
<ul class="list-group sticky-top sticky-offset">
{% if sidenavs %}
{% for heading, stuff in sidenavs.items() %}
<li class="list-group-item sidebar-separator-title text-muted d-flex align-items-center menu-collapsed">
<a href="#page{{heading}}" data-toggle="collapse" class="dropdown-toggle">
<br />
{{ heading }}
</a>
</li>
<br />
<ul class="collapse list-unstyled" id="page{{heading}}">
{% for name, address in stuff.items() %}
<a href="{{ address }}" class="bg-dark list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-start align-items-center">
<span class="fa fa-tasks fa-fw mr-3"></span>
<span class="menu-collapsed">{{ name }}</span>
</div>
</a>
{% endfor %}
</ul>
{% endfor %}
{% endif %}
</ul>
<div class="footer">
<h3><center>WCF Insurance</center></h3>
</div>
</div>
<!-- sidebar-container END -->
App.py (flask app)
...
from flask import Flask, url_for, render_template, redirect, jsonify
...
app = Flask(__name__)
CWD = os.path.dirname(os.path.abspath(__file__))
...
#app.route('/bokeh-example')
def page_bokeh_example():
''' iframe for Bokeh Example '''
resp = {
'mininavs': get_mini_nav(),
'sidenavs': get_side_nav(),
'iframe_url': get_iframe_url('Bokeh Example'), }
return render_template('iframe.html', **resp)
....
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5020)
Notice I'm using the render_template() flask function.
I added a JavaScript function call to the onload property of the body tag with the following code in it
function setMenuState(){
if (window.sessionStorage.getItem("MenuState") == null){
window.sessionStorage.setItem("MenuState", "--isHidden");
}
if(window.sessionStorage.getItem("MenuState") != "--isHidden"){
toggleMenu();
window.sessionStorage.setItem("MenuState", "");
}
}
function toggleMenu(){
const textnames = ["","",""]
const sidebarE1 = document.getElementsByClassName("sidebar")[0];
const contentE1 = document.getElementsByClassName("content")[0];
let menuItems = document.getElementsByClassName("fa");
sidebarE1.classList.toggle("sidebar--isHidden");
contentE1.classList.toggle("content--isHidden");
for(item in menuItems){
if(menuItems[item].innerHTML === textnames[item]){
menuItems[item].innerHTML = "";
}else{
menuItems[item].innerHTML = textnames[item];
}
}
if(window.sessionStorage.getItem("MenuState") != "--isHidden"){
window.sessionStorage.setItem("MenuState", "--isHidden");
}else{
window.sessionStorage.setItem("MenuState", "");
}
}
<body onload="setMenuState()">
This still runs the animation of the menu if it's open when you click on a link, but it retains the open/closed state in session storage.
UPDATE:
I have solved(mostly) the animations issue where the menu animation would play on page load.
function setMenuState(){
const sidebarE1 = document.getElementsByClassName("sidebar")[0];
const contentE1 = document.getElementsByClassName("content")[0];
if (window.sessionStorage.getItem("MenuState") == null){
window.sessionStorage.setItem("MenuState", "--isHidden");
}
if(window.sessionStorage.getItem("MenuState") != "--isHidden"){
toggleMenu();
window.sessionStorage.setItem("MenuState", "");
}
setTimeout(()=>{
if(!sidebarE1.classList.contains("sidebar-animated")){
sidebarE1.classList.add("sidebar-animated");
contentE1.classList.add("content-animated");
}}, 250);
}
.content {
background-color: #000000;
padding: 2rem;
height: 100vh;
position: fixed;
width: 100%;
opacity: 1;
margin-left: 4rem;
color: #00ff00;
top: 8rem;
overflow: scroll;
padding-bottom: 32rem;
z-index: 1;
}
.content-animated {
transition: transform 500ms linear;
}
by moving the actual transition property into its own css class, and only adding the class ~250ms after page load, the position and state of the menu is set without animation, and the animation is set before first click.

Categories