JavaScript file not linking to HTML in Flask application - javascript

I am making a Flask web application and I have created a part that uses JavaScript. I am trying to link my calendar.js file to my calendar.html file but the js file is not being read.
My html templates extend my base.html template, in which I have written a code block
{% block jscript %}
{%endblock%}
this is located at the bottom of the body tag because in the calendar.js file I reference some HTML elements by Id.
in calendar.html, which extends base.html, I have written
{% block jscript %}
<script type="module" src="{{url_for('static',filename='calendar.js')}}"></script>
{% endblock %}
I have also tried
<script type="text/javascript" src="{{url_for('static',filename='calendar.js')}}"></script>
and
<script type="text/javascript" src="..\static\calendar.js"></script>
I am however getting errors in my JS code saying that my HTML elements are null when I try to get them by id.
here is all of calendar.html (which isn't finished yet):
{% extends "base.html" %}
{% block title%}Calendar{% endblock %}
{% block webcontent %}
<h3 align="center">Calendar</h3>
<br/>
<p align="center">Hey! This is your calendar. Here you can add, update or delete events!</p>
<div class="container" align="center">
<form method='POST'> <!--web form to create an event object-->
<h3 align="center">Create Event</h3>
<div class="form-group">
<label for="eventName">Event Name</label>
<input type="text" class="form-control" id="eventName" name="eventName" placeholder="What is the name of the event?"/>
</div>
<div>
<label for="startDate">Start Date</label>
<input type="date" class="form-control" id="startDate" name="startDate"/>
</div>
<div>
<label for="endDate">End Date</label>
<input type="date" class="form-control" id="endDate" name="endDate"/>
</div>
<div>
<label for="startTime">Start Time</label>
<input type="time" class="form-control" id="startTime" name="startTime"/>
</div>
<div>
<label for="endTime">End Time</label>
<input type="time" class="form-control" id="endTime" name="endTime"/>
</div>
<div>
<label for="eventInfo">Description</label>
<input type="text" class="form-control" id="eventInfo" name="eventInfo" placeholder="Event Info"/>
</div>
<div>
<label for="eventLocation">Location</label>
<input type="text" class="form-control" id="eventLocation" name="eventLocation" placeholder="Location"/>
</div>
<br/>
<button type="submit" class="btn btn-primary">Add Event</button>
</form>
</div>
<br/>
<div id="calContainer">
<div id="header">
<div id="monthView"></div>
<div>
<button id="previousMonth">Previous Month</button>
<button id="nextMonth">Next Month</button>
</div>
</div>
<div id="weekdays">
<div>Monday</div>
<div>Tuesday</div>
<div>Wednesday</div>
<div>Thursday</div>
<div>Friday</div>
<div>Saturday</div>
<div>Sunday</div>
</div>
<div id="calCalendar"></div>
</div>
<div id="modalBackDrop"></div>
{% endblock %}
{% block jscript %}
<script type="module" src="{{url_for('static',filename='calendar.js')}}"></script>
{% endblock %}
here is all of calendar.js (which isn't finished yet):
//setting global variables
let currentMonth = 0; //incremented or decremented to display each month.
let clicked = null; //the day that the user has clicked on
const monthView = document.getElementById('monthView');
const calCalendar = document.getElementById('calCalendar');
const weekdays = ['Monday', 'Tuesday', 'Wednesday' , 'Thursday', 'Friday', 'Saturday', 'Sunday'];
function loadCal() {
const dateObj = new Date();
if (currentMonth !== 0) {
dateObj.setMonth(new Date().getMonth() + currentMonth); //changes the value of the current month shown by adding/subtracting the number of times the back or forward button is pressed
}
const day = dateObj.getDate();
const month = dateObj.getMonth();
const year = dateObj.getFullYear();
const firstDayInMonth = new Date(year, month, 1); //gets the date for the first day in the month
const daysInMonth = new Date(year, month + 1, 0).getDate(); //gives whatever the date is for the last day in the month.
const dateString = firstDayInMonth.toLocaleDateString('en-uk', { //ensures that uk timezone/calendar is used
weekday: 'long',
day: 'numeric',
month: 'numeric',
year: 'numeric',
});
const emptyDays = weekdays.indexOf(dateString.split(', ')[0]); //splits the value of dateString (Weekday, dd/mm/yyyy) to extract the Weekday part
monthView.innerText = `${dateObj.toLocaleDateString('en-uk', { month: 'long' })} ${year}`; //prints string of month and year above calendar
calCalendar.innerHTML = ''; //clears the calendar div upon reloading to ensure that only one calendar is printed
for(let i = 1; i <= (emptyDays + daysInMonth); i++) { //increments through the days in the month
const daySquare = document.createElement('div'); //creates a div for each day
daySquare.classList.add('day'); //so that all day divs have the proper formatting
const dayString = `${i - emptyDays}-${month + 1}-${year}`;
if (i > emptyDays) { //if it has iterated more times than there are empty squares in that month then it should actually create a day square
daySquare.innerText = i - emptyDays; //ensures that the correct day number is printed inside the square
for (var i = 0; i < eventnamesLength; i++) {
console.log(eventnames[i]);
const eventDiv = document.createElement('div');
eventDiv.classList.add('event');
eventDiv.innerText = (eventnames[i]);
daySquare.appendChild(eventDiv)
}
daySquare.addEventListener('click', () => console.log('click'));
} else {
daySquare.classList.add('empty'); //creates different style for empty squares
}
calCalendar.appendChild(daySquare);
}
}
function buttons() {
document.getElementById('nextMonth').addEventListener('click', () => {
currentMonth++;
loadCal();
}) //when the next month button is clicked, the current month value increments by +1 and the calendar is reloaded to show the next month
document.getElementById('previousMonth').addEventListener('click', () => {
currentMonth--;
loadCal();
}) //when the previous month button is clicked, the current month value decrements by -1 and the calendar is reloaded to show the previous month
}
buttons();
loadCal();

Related

How do you implement input( or form) dependent on a select menu(drop down list)?

I'm working on grading system and I'm currently working on the form that's deals with the user entering the students results now the form I have, has 2 drop-down list(classroom, students) that are dependent. The issue and where I'm stuck is
When the user select the classroom the second drop-down menu will only show the students in that class, I have already figure that out..the issue is I want the input fields for how much subject the student is doing to appear so that the user can enter the grades for each subject specific to that student in the class
Eg if I select classroom 1b and selected student Mary.. if Mary is doing 5 subjects then 5 input field should appear so that I can enter the mark for the subjects
Link with a video showing what I'm talking about video showing an examplehttps://drive.google.com/file/d/11FoCZyOBVdUhTcvCqA1Ke0fEgRmMVC-G/view?usp=drivesdk
Models.py
Class Classroom(models.Models): name = models.charfield()
Class marks (models.Models): classroom = models.foreignkey(Classroom) Grade = models.Floatfield()
Html form
<div class="container-fluid">
<form id="result-form" method="post">
{% csrf_token %}
<!-- Modal -->
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel"> {% block modal-title%} Add Result {% endblock%}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12" id="msg8" style="font-size: 2rem; color:rgb(255, 144, 47)"></div>
<div class="col-md-12 form-group p-2">
<label class="form-label">Class Name</label>
{% render_field form.room class+="form-control" %}
</div>
<div class="col-md-12 form-group p-2">
<label class="form-label">Exam Name</label>
{% render_field form.exam class+="form-control" %}
</div>
<div class="col-md-12 form-group p-2">
<label class="form-label">Student</label>
{% render_field form.student class+="form-control select2" %}
</div>
<div class="hidden" id="subject-fields"></div>
<div class="form-group mb-3 pt-2">
<button type="button" id="resBtn" class="btn btn-info" title="Add">Submit</button>
</div>
</div>
</div>
</form>
</div>
{% block script%}
{% endblock%
script
$(document).on('click', '#submit-btn', function(event){
var response_data = []
var subject_name= $('.course');
var subject_objs = $('.subject_id');
for(i=0;i<subject_name.length;i++){
var subject_id = $(subject_objs[i]).find('input').val();
var grade_input = {
"Marks": subject_id,
}
response_data.push(grade_input);
}
$.ajax({
type: "POST",
url: "{% url 'marks' %}",
data: response_data,
success: function(response){
alert("Success");
}
});
});
This is how your view should look like.
def question_choice_view(request):
if request.method == "POST":
question_choice_data = request.POST['data']
I am not a jQuery User. As far as i can see i would put a eventlistener on the student form via .addEventListener('change', (event)See here. This would fire a function every time something changes on the select option. With that you could also collect the selected option values of the classroom and student name and make a request to get the subject names for the chosen student. After successful response i would insert the subject fields via JavaScript in the DOM.
**
function createInput(item) {
// This function takes a item and creates a new input
var newLabel = ' <br><label for="$item-mark">$item:</label>'
var newInput = '<input type="text" id="$item-mark-id" name="$item-mark"><br><br>';
newLabel = newLabel.replaceAll("$item", item)
newInput = newInput.replaceAll("$item", item)
// combine into a single str
newInput = newLabel + newInput
var studInput = document.getElementById("student-id");
// insert element inputs after student
studInput.insertAdjacentHTML('afterend', newInput);
}
function cleanOldInputs(item) {
var oldELement = item + "-mark-id"
oldELement = document.getElementById(oldELement)
if (oldELement) {
// remove old label and input
oldELement.previousSibling.remove()
oldELement.remove()
} else {}
}
function getAPIcall() {
// This is what your API sends
var responsObject = ["writing", "creativity"];
// loop throug
responsObject.forEach(item => {
// if you already picked a student clean old inputs from DOM
cleanOldInputs(item)
// send to function for input creation
createInput(item)
})
}
// get the Student Input
var studentSelect = document.getElementById("student-id");
studentSelect.addEventListener("click", function() {
// Fire anything you like
getAPIcall()
});
<form action="/action_page.php">
<label for="student">Choose a student:</label>
<select name="student" id="student-id">
<option value="harry">harry</option>
<option value="ivy">ivy</option>
</select>
</form>
Quick and dirty**

Prevent future dates in HTML - vue

I need to prevent future dates in an HTML template. The date picked date value is forwarded to Vue to be further analyzed. Here is the code.
<div class="container text-center justify-content-center container-user">
<h1 class="text-center">Ciao <span v-model="user_name">{{username}}</span></h1>
<br>
<h2 >
Seleziona la data: [[date.day]]
</h2>
<br>
<form #submit.prevent="getUpdates">
<input type="date" v-model="date.day" class="disableFuturedate"/>
<button class="btn btn-primary" type="submit">Seleziona</button>
</form>
</div>
I need to find a solution using possibly vue.js or Javascript.
Thank you really much for your help!
You can define variable to hold current date in data object, then set it as max value:
new Vue({
el: "#app",
data() {
return {
username: 'Amico',
date: {day: ''},
maxDate: new Date().toISOString().split('T')[0]
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="container text-center justify-content-center container-user">
<h1 class="text-center">Ciao <span>{{username}}</span></h1>
<h2 >
Seleziona la data: {{date.day}}
</h2>
<form #submit.prevent="getUpdates">
<input type="date" v-model="date.day" :max="maxDate" class="disableFuturedate"/>
<button class="btn btn-primary" type="submit">Seleziona</button>
</form>
</div>
</div>
You can use the max attribute to achieve this:
<input type="date" v-model="date.day" max="2021-09-05" />
You can set that to be today using JavaScript:
<input type="date" v-model="date.day" id="datePicker" />
<script>
function formatToday() {
let today = new Date();
let year = today.getFullYear();
let month = ('0' + (today.getMonth() + 1)).slice(-2);
let day = ('0' + today.getDate()).slice(-2);
return year + '-' + month + '-' + day;
}
document
.getElementById("datePicker")
.setAttribute("max", formatToday());
</script>
Users can bypass this, so make sure to verify it before using it.

Not Able To Display Multiple Things in an Array

I have made an array that stores what I have inputted into local storage which works like this
<form name="myform" action="" method="GET">
Event Name: <INPUT TYPE="text" NAME="name" VALUE="" id="input1"><br />
Event Date and Time: <INPUT TYPE="datetime-local" NAME="date" Value="" id="input2"><br />
Event Location: <INPUT TYPE="text" NAME="location" VALUE="" id="input3"><br />
Event Notes: <INPUT TYPE="text" NAME="notes" VALUE="" id="input4"><br />
<button onclick="storeValues(event)" type=submit>Submit</button>
</form>
<script>
function storeValues(e) {
e.preventDefault();
let storedEvents = JSON.parse(localStorage.getItem("Events")) || [];
const newEventDetails = {
name: document.getElementById('input1').value,
dateTime: document.getElementById('input2').value,
location: document.getElementById('input3').value,
notes: document.getElementById('input4').value
}
storedEvents.push(newEventDetails);
localStorage.setItem("Events", JSON.stringify(storedEvents));
console.log('storedEvents', storedEvents);
}
</script>
And Currently, I am able to display them like this however it only displays 1 at a time and if I add this code in again but trying to display something else in the array it won't display either.
<h2>All Upcoming Events</h2>
<h2 id='input1'> </h2>
<h2 id='input2'> </h2>
<h2 id='input3'> </h2>
<h2 id='input4'> </h2>
<!-- running script here will populate H2's with values from local storage -->
<script>
const renderEvent = (event) => {
document.getElementById('input1').textContent = event.name;
document.getElementById('input2').textContent = event.dateTime;
document.getElementById('input3').textContent = event.location;
document.getElementById('input4').textContent = event.notes;
};
const index = 0; // for example: display 5th event saved
const storedEvents = JSON.parse(localStorage.getItem("Events"));
if (!storedEvents) throw new Error('No events');
const event = storedEvents[index];
renderEvent(event);
</script>
Use a <ul> element, and add items to it in a loop.
<h2>All upcoming events</h2>
<ul id="events"></ul>
const storedEvents = JSON.parse(localStorage.getItem("Events"));
var html = '';
storedEvents.forEach({name, dateTime, location, notes}) => {
html += `<li><h3>${name}</h3><h3>${dateTime}</h3><h3>${location}</h3><h3>${notes}</h3></li>';
});
document.getElementById("events").innerHTML = html;

JavaScript / jQuery - calculate number of days, receiving input data and output data

I have two fields of data entry, date of entry and date of out, which receive data using a datepicker. Is it possible to calculate the number of days, take into account the values of the date of entry and date of out, and save it in the field number of nights? How can I do this?
HTML
<div class="form-group">
<label class="col-md-4 control-label">Date Entry</label>
<div class="col-md-4 inputGroupContainer">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span>
<input name="DateEntry" id="DateEntry" class="form-control" type="text">
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">DateOut</label>
<div class="col-md-4 inputGroupContainer">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span>
<input name="DateOut" id="DateOut" class="form-control" type="text">
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">NÂșNights</label>
<div class="col-md-4 inputGroupContainer">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-list-ol"></i></span>
<input name="Nights" class="form-control" type="text">
</div>
</div>
</div>
var start = $('#DateEntry').val();
var end = $('#DateOut').val();
// end - start returns difference in milliseconds
var diff = new Date(end - start);
// get nights
var days = diff/1000/60/60/24;
//set nights
$('#Nights').val(days)
This is client side code. You have to call this from document.load or may be onchange event of both entry and out dates.
Here's a similar approach with the hook to handle the text changing.
<html>
<head>
<title>Date Diff in Nights</title>
</head>
<body>
<div id="container">
<span class="input-group-addon"><i class="glyphicon glyphicon-time">entry</i></span>
<input name="DateEntry" id="DateEntry" class="form-control" type="text" >
<span class="input-group-addon"><i class="glyphicon glyphicon-time">out</i></span>
<input name="DateOut" id="DateOut" class="form-control" type="text" >
<span class="input-group-addon"><i class="fa fa-list-ol">nights</i></span>
<input name="Nights" id="Nights" class="form-control" type="text">
</div>
<script type="text/javascript">
var input = document.getElementById('DateEntry');
input.addEventListener('input', calcNights);
var input2 = document.getElementById('DateOut');
input2.addEventListener('input', calcNights);
function calcNights() {
try {
var nightsout = document.getElementById('Nights');
var element = document.getElementById('DateEntry');
var entryDate = new Date(element.value);
var out = document.getElementById('DateOut');
var outDate = new Date(out.value);
// Set to noon to avoid any DST errors
outDate.setHours(12, 0, 0);
entryDate.setHours(12, 0, 0);
var difference = outDate - entryDate;
var nights = Math.round(difference / 8.64e7);
if (isNaN(nights) || nights < 0) {
nightsout.value = '';
return;
}
nightsout.value = nights;
}
catch (ex) {
//ignore
}
}
</script>
</body>
</html>
Here is working code with your update of date format being DD/MM/YYYY:
jQuery
I highly suggest using Momentjs. It is user friendly and very powerful when working with dates & times! That is what my solution will use. Otherwise you will have to do a bunch of parsing in order to match your date format. Just make sure that your format doesn't change or else you will have to edit this!
$(document).ready(function() {
$('#TestOne').datetimepicker({
format: 'DD/MM/YYYY HH:mm:ss',
});
$('#TestTwo').datetimepicker({
format: 'DD/MM/YYYY HH:mm:ss',
});
$("#DateOut").blur(function() {
var str1 = $("#DateEntry").val();
var str2 = $("#DateOut").val();
var dateEntry = moment(str1, "DD/MM/YYYY");
var dateOut = moment(str2, "DD/MM/YYYY");
var range = dateOut.diff(dateEntry, 'days');
$("#NightsBetween").val(range);
});
});
UPDATED FIDDLE
Here is a working JSFiddle
Hope this helps

Bind TextBox, date and dropdownlist value to parameter angularJS wcfRest

I have an angularJS using WCFrest Project
I create dropdownlist and datepicker for parameter to filter showed data.
Search Form can be seen on picture below
This is the html code
<!--Date From-->
<div class="col-md-4">
<input id="txtOldDate" type="date" value="2000-01-01" class="datepicker" />
</div>
<!--Date To-->
<div class="col-md-1">
<label for="labelTo" class="control-label">To</label>
</div>
<div class="col-md-4">
<input id="txtNewDate" type="date" class="datepicker" />
<!-- Set default date value to now-->
<script>
document.getElementById('txtNewDate').value = new Date().toISOString().substring(0, 10);
</script>
</div>
<!--Departement-->
<div class="col-sm-4">
<div class="dropdown">
<select class="form-control" ng-model="DdlDeptManager" ng-change="DdlManager(DdlDeptManager)">
<option ng-repeat="d in GetDeptManager" value="{{d.Department}}">{{d.Department}}</option>
</select>
</div>
</div>
<!--Employee-->
<div class="dropdown">
<!-- #departemen parameter from DdlDeptManager -->
<select id="ddlManagerApproval" ng-model="DdlManager" class="form-control">
<option ng-repeat="m in GetManager" value="{{m.UserName}}">{{m.FullName}}</option>
</select>
</div>
<!--Button Show-->
<div class="col-md-2">
<input id="btnSubmit" type="button" class="btn btn-primary" ng-click="SearchApproval()" value="Show" />
</div>
This is my control approvalCtrl.js
//Control for search purposes
$scope.SearchApproval = function() {
var search = {
//employeeID: $scope.employeeID,
oldDate: $scope.oldDate,
newDate: $scope.newDate,
departemen: $scope.departemen,
approver: $scope.approver
}
var promiseGet = GetApproval.GetApprovalData(search);
//GetApprovalData();
promiseGet.then(function(pl) {
$scope.GetApprovalData = pl.data
},
function(errorPl) {
console.log('Some Error in Getting Records.', errorPl);
});
}
This is the service.js, for employeeID because the session is not created, i forced add value to it on the uri
this.GetApprovalData = function(employeeID, oldDate, newDate, departemen, approver) {
return $http.get("http://localhost:51458/ServiceRequest.svc/GetApproval?employeeID=" + "11321" + "&oldDate=" + oldDate + "&newDate=" + newDate + "&departemen=" + departemen + "&approver=" + approver);
};
My Question is, how to make the value on datepicker id = txtOldDate to give a paramater value to oldDate, txtNewDate to newDate, and other dropdownlist to departemen and approver parameter?
Thanks in Advance.
Hi Randy I have reproduced your code without service sorry for that. Used hardcode array to populate dropdown. Kindly check this url
https://plnkr.co/edit/eSriV68HkhQhzt1yE6DE?p=preview
$scope.GetDeptManager = [{
Department : 'department1'
}, {
Department: 'department2'
}];
$scope.GetManager = [{
FullName : 'manager1'
}, {
FullName: 'manager2'
}]
And you have to assign ng-model values for your input elements so that you will get those values in controller.

Categories