`);
- $(".alert").delay(5000).fadeOut();
+ $(".close-alert").click(function(){
+ $(this).closest(".alert").delay(1000).fadeOut();
+ })
}
+
+
+
$(document).ready(function() {
$("select[name='newuser']").on('change', function(e) {
$(e.target).parent().submit();
});
-
$(flashMessages).each((i, messageData) => {msgFlash(messageData[1], messageData[0])})
toastElementList = [].slice.call(document.querySelectorAll('.toast'))
diff --git a/app/static/js/createEvents.js b/app/static/js/createEvents.js
index d72701977..615dc3841 100644
--- a/app/static/js/createEvents.js
+++ b/app/static/js/createEvents.js
@@ -1,18 +1,20 @@
import searchUser from './searchUser.js'
-
+let pendingmultipleEvents = []
// updates max and min dates of the datepickers as the other datepicker changes
+// No need for / for Firefox compatiblity
function updateDate(obj) {
- // we need to replace "-" with "/" because firefox cannot turn a date with "-" to a datetime object
- var selectedDate = ($(obj).val()).replaceAll("-", "/")
- var dateToChange = new Date(selectedDate);
- var newMonth = dateToChange.getMonth();
- var newYear = dateToChange.getFullYear();
- var newDay = dateToChange.getDate();
- if(obj.className.includes("startDatePicker")) {
- $("#endDatePicker-"+$(obj).data("page-location")).datepicker({minDate: new Date(newYear, newMonth, newDay)});
- $("#endDatePicker-"+$(obj).data("page-location")).datepicker("option", "minDate", new Date(newYear, newMonth, newDay));
+ var selectedDate = $(obj).datepicker("getDate");
+ var newMonth = selectedDate.getMonth();
+ var newYear = selectedDate.getFullYear();
+ var newDay = selectedDate.getDate();
+
+ if (obj.className.includes("startDatePicker")) {
+ $("#endDatePicker-" + $(obj).data("page-location")).datepicker("option", "minDate", new Date(newYear, newMonth, newDay));
+ } else if (obj.className.includes("endDatePicker")) {
+ $("#startDatePicker-" + $(obj).data("page-location")).datepicker("option", "maxDate", new Date(newYear, newMonth, newDay));
}
+
if (obj.className.includes("endDatePicker")) {
$("#startDatePicker-"+$(obj).data("page-location")).datepicker({maxDate: new Date(newYear, newMonth, newDay)});
$("#startDatePicker-"+$(obj).data("page-location")).datepicker("option", "maxDate", new Date(newYear, newMonth, newDay));
@@ -21,203 +23,483 @@ function updateDate(obj) {
// turns a string with a time with HH:mm format to %I:%M %p format
// used to display 12 hour format but still use 24 hour format in the backend
-function format24to12HourTime(timeStr){
+function format24to12HourTime(timeStr) {
var formattedTime;
- if (parseInt(timeStr.slice(0, 2)) > 12){
- formattedTime = "0" + String(parseInt(timeStr.slice(0, 2)) - 12) + timeStr.slice(2) + " PM";
+ if (parseInt(timeStr.slice(0, 2)) > 12) {
+ formattedTime = "0" + String(parseInt(timeStr.slice(0, 2)) - 12) + timeStr.slice(2) + " PM";
+ } else if (parseInt(timeStr.slice(0, 2)) < 12) {
+ formattedTime = timeStr + " AM";
+ } else {
+ formattedTime = timeStr + " PM";
+ }
+ return formattedTime;
+}
+
+function calculateRecurringEventFrequency(){
+ var eventDatesAndName = {name:$("#inputEventName").val(),
+ isRecurring: true,
+ startDate:$(".startDatePicker")[0].value,
+ endDate:$(".endDatePicker")[0].value}
+ $.ajax({
+ type:"POST",
+ url: "/makeRecurringEvents",
+ //get the startDate, endDate and name as a dictionary
+ data: eventDatesAndName,
+ success: function(jsonData){
+ var recurringEvents = JSON.parse(jsonData)
+ var recurringTable = $("#recurringEventsTable")
+ $("#recurringEventsTable tbody tr").remove();
+ for(var event of recurringEvents){
+ var eventdate = new Date(event.date).toLocaleDateString()
+ recurringTable.append("
"+event.name+"
"+eventdate+"
");
+ }
+ },
+ error: function(error){
+ console.log(error)
}
- else if (parseInt(timeStr.slice(0, 2)) < 12 ){
- formattedTime = timeStr + " AM";
+ });
+}
+
+function setViewForSingleOffering(){
+ $(".startDatePicker").prop('required', true);
+ $("#multipleOfferingTableDiv").addClass('d-none');
+ $(".endDateStyle, #recurringTableDiv").addClass('d-none');
+ $('#nonMultipleOfferingTime, #nonMultipleOfferingDate').removeClass('d-none');
+}
+
+function setViewForMultipleOffering(){
+ $(".startDatePicker").prop('required', false);
+ $("#multipleOfferingTableDiv").removeClass('d-none');
+ $(".endDateStyle, #recurringTableDiv").addClass('d-none');
+ $('#nonMultipleOfferingTime, #nonMultipleOfferingDate').addClass('d-none');
+}
+
+function displayNotification(message) {
+ $('#textNotifierPadding').addClass('pt-5');
+ $('.invalidFeedback').text(message);
+ $('.invalidFeedback').css('display', 'block');
+ $('.invalidFeedback').on('animationend', function() {
+ $('.invalidFeedback').css('display', 'none');
+ $('#textNotifierPadding').removeClass('pt-5')
+ });
+}
+
+function isDateInPast(dateString) {
+ const date = new Date(dateString);
+ const today = new Date();
+ today.setHours(0, 0, 0, 0);
+ return date < today;
+}
+
+function createOfferingModalRow({eventName=null, eventDate=null, startTime=null, endTime=null, isDuplicate=false}={}){
+
+ let clonedMultipleOffering = $("#multipleOfferingEvent").clone().removeClass('d-none').removeAttr("id");
+ // insert values for the newly created row
+ if (eventName) {clonedMultipleOffering.find('.multipleOfferingNameField').val(eventName)}
+ if (eventDate) {clonedMultipleOffering.find('.multipleOfferingDatePicker').val(eventDate)}
+ if (startTime) {clonedMultipleOffering.find('.multipleOfferingStartTime').val(startTime)}
+ if (endTime) {clonedMultipleOffering.find('.multipleOfferingEndTime').val(endTime)}
+ if (isDuplicate) {clonedMultipleOffering.addClass('border-red')}
+
+ $("#multipleOfferingSlots").append(clonedMultipleOffering);
+ pendingmultipleEvents.push(clonedMultipleOffering);
+
+ //this is so that the trash icon can be used to delete the event
+ clonedMultipleOffering.find(".deleteMultipleOffering").on("click", function() {
+ let attachedRow = $(this).closest(".eventOffering")
+ attachedRow.animate({
+ opacity: 0,
+ height: '0px'
+ }, 500, function() {
+ // After the animation completes, remove the row
+ attachedRow.remove();
+ });
+ });
+ return clonedMultipleOffering
+}
+
+$('#multipleOfferingSave').on('click', function() {
+ //Requires that modal info updated before it can be saved, gives notifier if there are empty fields
+ let eventOfferings = $('#multipleOfferingSlots .eventOffering');
+ let eventNameInputs = $('#multipleOfferingSlots .multipleOfferingNameField');
+ let datePickerInputs = $('#multipleOfferingSlots .multipleOfferingDatePicker');
+ let startTimeInputs = $('#multipleOfferingSlots .multipleOfferingStartTime');
+ let endTimeInputs = $('#multipleOfferingSlots .multipleOfferingEndTime');
+ let isEmpty = false;
+ let hasValidTimes = true;
+ let hasDuplicateListings = false;
+ let hasInvalidDates = false;
+ const allowPastStart = $("#allowPastStart").is(":checked");
+
+
+ // Check if the input field is empty
+ eventNameInputs.each((index, eventNameInput) => {
+ if (eventNameInput.value.trim() === '') {
+ isEmpty = true;
+ $(eventNameInput).addClass('border-red');
+ } else{
+ $(eventNameInput).removeClass('border-red');
}
- else {
- formattedTime = timeStr + " PM";
- }
- return formattedTime;
- }
-
- function calculateRecurringEventFrequency(){
- var eventDatesAndName = {name:$("#inputEventName").val(),
- isRecurring: true,
- startDate:$(".startDatePicker")[0].value,
- endDate:$(".endDatePicker")[0].value}
- $.ajax({
- type:"POST",
- url: "/makeRecurringEvents",
- data: eventDatesAndName, //get the startDate, endDate and name as a dictionary
- success: function(jsonData){
- var recurringEvents = JSON.parse(jsonData)
- var recurringTable = $("#recurringEventsTable")
- $("#recurringEventsTable tbody tr").remove();
-
- for (var event of recurringEvents){
- var eventdate = new Date(event.date).toLocaleDateString()
- recurringTable.append("
"+event.name+"
"+eventdate+"
");
- }
- },
- error: function(error){
- console.log(error)
- }
+ });
+
+ // Check if the date input field is empty
+ datePickerInputs.each((index, datePickerInput) => {
+ if (datePickerInput.value.trim() === '') {
+ isEmpty = true;
+ $(datePickerInput).addClass('border-red');
+ } else {
+ $(datePickerInput).removeClass('border-red');
+ }
+ });
+
+
+ // Check if the start time is after the end time
+ for(let i = 0; i < startTimeInputs.length; i++){
+ if(startTimeInputs[i].value < endTimeInputs[i].value){
+ $(startTimeInputs[i]).removeClass('border-red');
+ $(endTimeInputs[i]).removeClass('border-red');
+ } else {
+ $(startTimeInputs[i]).addClass('border-red');
+ $(endTimeInputs[i]).addClass('border-red');
+ hasValidTimes = false;
+ }
+ }
+
+ // Check if there are duplicate event offerings
+ let eventListings = {};
+ for(let i = 0; i < eventOfferings.length; i++){
+ let eventName = eventNameInputs[i].value
+ let date = datePickerInputs[i].value.trim()
+ let startTime = startTimeInputs[i].value
+ let eventListing = JSON.stringify([eventName, date, startTime])
+
+ if (eventListing in eventListings){ // If we've seen this event before mark this event and the previous as duplicates
+ hasDuplicateListings = true
+ $(eventOfferings[i]).addClass('border-red');
+ $(eventOfferings[eventListings[eventListing]]).addClass('border-red')
+ } else { // If we haven't seen this event before
+ $(eventOfferings[i]).removeClass('border-red');
+ eventListings[eventListing] = i
+ }
+ }
+
+ // Add past date validation
+ datePickerInputs.each(function(index, element) {
+ if (!allowPastStart && isDateInPast($(element).val())) {
+ $(element).addClass('border-red');
+ hasInvalidDates = true;
+ } else {
+ $(element).removeClass('border-red');
+ }
+ });
+
+ if (isEmpty){
+ let emptyFieldMessage = "Event name or date field is empty";
+ displayNotification(emptyFieldMessage);
+ }
+ else if (!hasValidTimes) {
+ let invalidTimeMessage = "Event end time must be after start time";
+ displayNotification(invalidTimeMessage);
+ }
+ else if (hasDuplicateListings) {
+ let eventConflictMessage = "Event listings cannot have the same event name, date, and start time";
+ displayNotification(eventConflictMessage);
+ }
+ else if (hasInvalidDates) {
+ displayNotification ("Some events have dates in the past. Please correct them or enable 'Allow start date to be in the past'.", "danger");
+ }
+ else {
+ let offerings = [];
+ eventOfferings.each(function(index, element) {
+ offerings.push({
+ eventName: $(element).find('.multipleOfferingNameField').val(),
+ eventDate: $(element).find('.multipleOfferingDatePicker').val(),
+ startTime: $(element).find('.multipleOfferingStartTime').val(),
+ endTime: $(element).find('.multipleOfferingEndTime').val()
});
+ });
+
+ let offeringsJson = JSON.stringify(offerings);
+ $("#multipleOfferingData").val(offeringsJson);
+ updateOfferingsTable();
+ pendingmultipleEvents = [];
+ $("#checkIsMultipleOffering").prop('checked', true);
+ $('#modalMultipleOffering').modal('hide');
+ msgFlash("Multiple time offering events saved!", "success");
}
+});
+
+
+// Save the offerings from the modal to the hidden input field
+function loadOfferingsToModal(){
+ let offerings = JSON.parse($("#multipleOfferingData").val())
+ offerings.forEach((offering, i) =>{
+ let newOfferingModalRow = createOfferingModalRow(offering)
+ //stripes odd event sections in event modal
+ newOfferingModalRow.css('background-color', i % 2 ?'#f2f2f2':'#fff');
+ })
+}
+// Update the table of offerings with the offerings from the hidden input field
+function updateOfferingsTable() {
+ let offerings = JSON.parse($("#multipleOfferingData").val())
+
+ var multipleOfferingTable = $("#multipleOfferingEventsTable");
+ multipleOfferingTable.find("tbody tr").remove(); // Clear existing rows
+ offerings.forEach(function(offering){
+ //fromat to 12hr time for display
+ var formattedEventDate = formatDate(offering.eventDate);
+ var startTime = format24to12HourTime(offering.startTime);
+ var endTime = format24to12HourTime(offering.endTime);
+ multipleOfferingTable.append(`
` +
+ "
" + offering.eventName + "
" +
+ "
" + formattedEventDate + "
" +
+ "
" + startTime + "
" +
+ "
" + endTime + "
" +
+ "
"
+ );
+ });
+}
+
+
+//visual date formatting for multi-event table
+function formatDate(originalDate) {
+ var dateObj = new Date(originalDate);
+ //ensures that time zone is not inconsistent, keeping the date consistent with what the user selects
+ dateObj.setUTCHours(0, 0, 0, 0);
+ var month = dateObj.toLocaleString('default', { month: 'short' });
+ var day = dateObj.getUTCDate();
+ var year = dateObj.getUTCFullYear();
+ return month + " " + day + ", " + year;
+}
/*
* Run when the webpage is ready for javascript
*/
$(document).ready(function() {
+ //makes sure bonners toggle will stay on between event pages
+ if (window.location.pathname == '/event/' + $('#newEventID').val() + '/edit') {
+ if ($("#checkBonners")) {
+ $("#checkBonners").prop('checked', true);
+ }
+}
+// Initialize datepicker with proper options
+$.datepicker.setDefaults({
+ dateFormat: 'yy/mm/dd', // Ensures compatibility across browsers
+ minDate: new Date()
+});
+
+$(".datePicker").datepicker({
+ dateFormat: 'mm/dd/yy',
+ minDate: new Date()
+});
+
+ $(".datePicker").each(function() {
+ var dateStr = $(this).val();
+ if (dateStr) {
+ var dateObj = new Date(dateStr);
+ if (!isNaN(dateObj.getTime())) {
+ $(this).datepicker("setDate", dateObj);
+ }
+ }
+});
+
+// Update datepicker min and max dates on change
+$(".startDatePicker, .endDatePicker").change(function () {
+ updateDate(this);
+});
if ( $(".startDatePicker")[0].value != $(".endDatePicker")[0].value){
calculateRecurringEventFrequency();
}
-
handleFileSelection("attachmentObject")
- $("#checkRSVP").on("click", function() {
- if ($("#checkRSVP").is(":checked")) {
- $("#limitGroup").show();
- }
- else{
- $("#limitGroup").hide();
- }
- })
- // Disable button when we are ready to submit
- $("#saveEvent").on('submit',function(event) {
- $(this).find("input[type=submit]").prop("disabled", true);
- });
-
- $("#checkIsRecurring").click(function() {
- var recurringStatus = $("input[name='isRecurring']:checked").val()
- if (recurringStatus == 'on') {
- $(".endDateStyle, #recurringTableDiv").removeClass('d-none')
- $(".endDatePicker").prop('required', true);
+ $("#checkRSVP").on("click", function () {
+ if ($("#checkRSVP").is(":checked")) {
+ $("#limitGroup").show();
} else {
- $(".endDateStyle, #recurringTableDiv").addClass('d-none')
- $(".endDatePicker").prop('required', false);
+ $("#limitGroup").hide();
}
});
+ // Determine which checkbox was clicked and its current checked status, uncheck others
+ let typeBoxes = $("#checkIsTraining, #checkServiceHours, #checkEngagement, #checkBonners")
+ typeBoxes.on('click', function (event) {
+ typeBoxes.not($(event.target)).prop('checked', false);
+ });
+ $("#saveEvent").on('submit', function (event) {
+ let trainingStatus = $("#checkIsTraining").is(":checked")
+ let serviceHourStatus = $("#checkServiceHours").is(":checked")
+ let engagementStatus = $("#checkEngagement").is(":checked")
+ let bonnersStatus = $("#checkBonners").is(":checked")
- $("#allowPastStart").click(function() {
- var allowPast = $("#allowPastStart:checked").val()
- if (allowPast == 'on') {
- $.datepicker.setDefaults({
- minDate: new Date('1999/10/25'),
- dateFormat:'mm-dd-yy'
- });
- } else {
- $.datepicker.setDefaults({
- minDate: new Date($.now()),
- dateFormat:'mm-dd-yy'
- });
+ //check if user has selected a toggle, cancel form submission if not
+ let isAllVolunteer = $("#pageTitle").text() == 'Create All Volunteer Training'
+ if(trainingStatus || serviceHourStatus || engagementStatus || bonnersStatus || isAllVolunteer) {
+ // Disable button when we are ready to submit
+ $(this).find("input[type=submit]").prop("disabled", true);
}
+ else {
+ msgFlash("You must indicate whether the event is a training, is an engagement, earns service hours, or is a Bonners Scholars event!", "danger");
+ event.preventDefault();
+ }
});
+
+ updateOfferingsTable();
+
+ if ($("#checkIsMultipleOffering").is(":checked")){
+ setViewForMultipleOffering();
+ }
+
+ let modalOpenedByEditButton = false;
+ //#checkIsRecurring, #checkIsMultipleOffering are attributes for the toggle buttons on create event page
+ $("#checkIsRecurring, #checkIsMultipleOffering, #edit_modal").click(function(event) {
+ if(!($('#inputEventName').val().trim() == '')){
+ //keeps main page event name for multiple event modal
+ $('#eventName').val($('#inputEventName').val());
+ }
+ // retrieves toggle status, 'on' or undefined
+ let recurringStatus = $("#checkIsRecurring").is(":checked")
+ let multipleOfferingStatus = $("#checkIsMultipleOffering").is(":checked")
+ modalOpenedByEditButton = ($(this).attr('id') === 'edit_modal');
+
+
+ if (multipleOfferingStatus == true && recurringStatus == true){
+ msgFlash("You may not toggle recurring event and multiple time offering event at the same time!", "danger");
+ $(event.target).prop('checked', false);
+ return;
+ }
+ if (recurringStatus == true) {
+ $(".endDateStyle, #recurringTableDiv").removeClass('d-none');
+ $("#checkIsMultipleOffering").prop('checked', false);
+ $('#multipleOfferingTableDiv').addClass('d-none');
+ $(".endDatePicker").prop('required', true);
+ }
+ else if (multipleOfferingStatus == true) {
+ setViewForMultipleOffering();
+ loadOfferingsToModal();
+ $('#modalMultipleOffering').modal('show');
+ }
+ else {
+ //adds the display none button of bootstrap so that the end-date div disappears for recurring even
+ $(".endDateStyle, #recurringTableDiv").addClass('d-none');
+ $(".endDatePicker").prop('required', false);
+ //set page UI back to default
+ $("#multipleOfferingTableDiv").addClass('d-none');
+ $('#modalMultipleOffering').modal('hide');
+ $('#nonMultipleOfferingTime, #nonMultipleOfferingDate').removeClass('d-none');
+ $(".startDatePicker").prop('required', true);
+ }
+ });
+
+ //untoggles the button when the modal cancel or close button is clicked
+ $("#cancelModalPreview, #multipleOfferingXbutton").click(function(){
+ if (modalOpenedByEditButton == false) {
+ $('#modalMultipleOffering').modal('hide');
+ $("#checkIsMultipleOffering").prop('checked', false);
+ setViewForSingleOffering()
+ }
+ pendingmultipleEvents.forEach(function(element){
+ element.remove();
+
+ });
+ });
+
+ /*cloning the div with ID multipleOfferingEvent and cloning, changing the ID of each clone going up by 1. This also changes
+ the ID of the deleteMultipleOffering so that when the trash icon is clicked, that specific row will be deleted*/
+ $(".addMultipleOfferingEvent").click(createOfferingModalRow)
+
+ $("#allowPastStart").click(function() {
+ var minDate = $("#allowPastStart:checked").val() ? new Date('10/25/1999') : new Date()
+ $("#startDatePicker-main").datepicker("option", "minDate", minDate)
+ })
+
// everything except Chrome
if (navigator.userAgent.indexOf("Chrome") == -1) {
$('input.timepicker').timepicker({
- timeFormat : 'hh:mm p',
- scrollbar: true,
- dropdown: true,
- dynamic: true,
- minTime: "08:00am",
- maxTime: "10:00pm"
+ timeFormat: 'hh:mm p',
+ scrollbar: true,
+ dropdown: true,
+ dynamic: true,
+ minTime: "08:00am",
+ maxTime: "10:00pm"
});
$(".timepicker").prop("type", "text");
$(".timeIcons").prop("hidden", false);
var formattedStartTime = format24to12HourTime($(".startTime").prop("defaultValue"));
var formattedEndTime = format24to12HourTime($(".endTime").prop("defaultValue"));
- $(".startTime"[0]).val(formattedStartTime);
- $(".endTime"[0]).val(formattedEndTime);
- }
- else {
+ $(".startTime").val(formattedStartTime);
+ $(".endTime").val(formattedEndTime);
+ } else {
$(".timepicker").prop("type", "time");
$(".timeIcons").prop("hidden", true);
}
if ($(".datePicker").is("readonly")) {
- $(".datePicker" ).datepicker( "option", "disabled", true )
- };
-
- //makes the input fields act like readonly (readonly doesn't work with required)
- $(".readonly").on('keydown paste', function(e){
- if(e.keyCode != 9) // ignore tab
- e.preventDefault();
- });
+ $(".datePicker").datepicker("option", "disabled", true);
+ }
- $.datepicker.setDefaults({
- minDate: new Date($.now()),
- dateFormat:'mm-dd-yy'
+ $(".readonly").on('keydown paste', function (e) {
+ if (e.keyCode != 9) // ignore tab
+ e.preventDefault();
});
- $(".startDate").click(function() {
- $("#startDatePicker-" + $(this).data("page-location")).datepicker().datepicker("show");
+ $(".startDate").click(function () {
+ $("#startDatePicker-" + $(this).data("page-location")).datepicker("show");
});
- $(".endDate").click(function() {
- $("#endDatePicker-" + $(this).data("page-location")).datepicker().datepicker("show");
+ $(".endDate").click(function () {
+ $("#endDatePicker-" + $(this).data("page-location")).datepicker("show");
});
-
- $(".startDatePicker, .endDatePicker").change(function(){
- if ( $(this).val() && $("#endDatePicker-" + $(this).data("page-location")).val()){
+ $(".startDatePicker, .endDatePicker").change(function () {
+ if ($(this).val() && $("#endDatePicker-" + $(this).data("page-location")).val()) {
calculateRecurringEventFrequency();
}
});
- $("#checkRSVP").click(function(){
- if ($("input[name='isRsvpRequired']:checked").val() == 'on'){
- $("#checkFood").prop('checked', true);
-
- } else{
- $("#checkFood").prop('disabled', false);
- }
- });
-
-
var facilitatorArray = []
function callback(selectedFacilitator) {
- // JSON.parse is required to de-stringify the search results into a dictionary.
- let facilitator = (selectedFacilitator["firstName"]+" "+selectedFacilitator["lastName"]+" ("+selectedFacilitator["username"]+")");
+ let facilitator = (selectedFacilitator["firstName"] + " " + selectedFacilitator["lastName"] + " (" + selectedFacilitator["username"] + ")");
let username = selectedFacilitator["username"];
- if (!facilitatorArray.includes(username)){
- facilitatorArray.push(username);
- let tableBody = $("#facilitatorTable").find("tbody");
- let lastRow = tableBody.find("tr:last");
- let newRow = lastRow.clone();
- newRow.find("td:eq(0) p").text(facilitator);
- newRow.find("td:eq(0) div button").data("id", username);
- newRow.find("td:eq(0) div input").attr("id", username);
- newRow.attr("id", username);
- newRow.prop("hidden", false);
- lastRow.after(newRow);
- $("#hiddenFacilitatorArray").attr("value", facilitatorArray);
- }
- }
-
- $("#eventFacilitator").on('input', function() {
- // To retrieve specific columns into a dict, create a [] list and put columns inside
+ if (!facilitatorArray.includes(username)) {
+ facilitatorArray.push(username);
+ let tableBody = $("#facilitatorTable").find("tbody");
+ let lastRow = tableBody.find("tr:last");
+ let newRow = lastRow.clone();
+ newRow.find("td:eq(0) p").text(facilitator);
+ newRow.find("td:eq(0) div button").data("id", username);
+ newRow.find("td:eq(0) div input").attr("id", username);
+ newRow.attr("id", username);
+ newRow.prop("hidden", false);
+ lastRow.after(newRow);
+ $("#hiddenFacilitatorArray").attr("value", facilitatorArray);
+ }
+ }
+
+ $("#eventFacilitator").on('input', function () {
searchUser("eventFacilitator", callback, true, undefined, "instructor");
});
- $("#facilitatorTable").on("click", "#remove", function() {
- let username = $(this).closest("tr")[0].id
- const index = facilitatorArray.indexOf(username)
- facilitatorArray.splice(index, 1);
- $("#hiddenFacilitatorArray").attr("value", facilitatorArray);
- $(this).closest("tr").remove();
+ $("#facilitatorTable").on("click", "#remove", function () {
+ let username = $(this).closest("tr")[0].id;
+ const index = facilitatorArray.indexOf(username);
+ facilitatorArray.splice(index, 1);
+ $("#hiddenFacilitatorArray").attr("value", facilitatorArray);
+ $(this).closest("tr").remove();
});
- $(".endDatePicker").change(function(){
- updateDate(this)
+ $(".endDatePicker").change(function () {
+ updateDate(this);
});
$(".startDatePicker").change(function(){
updateDate(this)
});
- $("#inputCharacters").keyup(function(event){
- setCharacterLimit(this, "#remainingCharacters")
- });
-
- setCharacterLimit($("#inputCharacters"), "#remainingCharacters");
+ $("#inputCharacters").keyup(function () {
+ setCharacterLimit(this, "#remainingCharacters");
+ });
+ setCharacterLimit($("#inputCharacters"), "#remainingCharacters");
});
diff --git a/app/static/js/displayFilesMacro.js b/app/static/js/displayFilesMacro.js
index 336fcf11b..49c04951c 100644
--- a/app/static/js/displayFilesMacro.js
+++ b/app/static/js/displayFilesMacro.js
@@ -1,35 +1,45 @@
$(document).ready(function(){
- $("a.fileName").tooltip()
+ $("a.fileName").tooltip();
+
$(".removeAttachment").on("click", function(){
- let fileId= $(this).data("id")
- let deleteLink = $(this).data("delete-url")
- let fileData = {fileId : fileId,
- databaseId:$(this).data('database-id')}
+ let fileId = $(this).data("id");
+ let deleteLink = $(this).data("delete-url");
+ let fileData = {
+ fileId: fileId,
+ databaseId: $(this).data('database-id')
+ };
+
$.ajax({
- type:"POST",
+ type: "POST",
url: deleteLink,
- data: fileData, //get the startDate, endDate and name as a dictionary
+ data: fileData,
success: function(){
- msgFlash("Attachment removed successfully", "success")
- $("#attachment_"+fileId).remove()
-
+ msgFlash("Attachment removed successfully", "success");
+ $("#attachment_" + fileId).remove();
},
- error: function(error){
- msgFlash(error)
+ error: function(error){
+ msgFlash(error);
}
- });
});
+ });
$('.attachmentCheck').change(function() {
+ // Store the current checkbox state
+ var isChecked = $(this).is(':checked');
+
// Uncheck all checkboxes
$('.attachmentCheck').prop('checked', false);
- // Check the selected checkbox
- $(this).prop('checked', true);
+
+ // Toggle the current checkbox
+ if (!isChecked) {
+ $(this).prop('checked', true);
+ } else {
+ $(this).prop('checked', false);
+ }
var attachmentId = $(this).data('id');
var isChecked = $(this).is(':checked');
-
$.ajax({
url: '/displayEventFile',
method: 'POST',
@@ -38,16 +48,31 @@ $(document).ready(function(){
checked: isChecked
},
success: function(response) {
- msgToast("Event Cover ", "Successfully updated the event cover.")
+ msgToast("Event Cover", "Successfully updated the event cover.");
},
error: function(xhr, status, error) {
- msgFlash(error)
+ msgFlash(error);
+ }
+ });
+ });
+
+ // Additional functionality to handle click events
+ document.querySelectorAll('.attachmentCheck').forEach(item => {
+ item.addEventListener('click', event => {
+ if (item.checked) {
+ item.checked = false; // This toggles the checkbox off if it was already checked
+ } else {
+ uncheckAll();
+ item.checked = true;
}
});
});
-
-
-})
+ function uncheckAll() {
+ document.querySelectorAll('.attachmentCheck').forEach(checkbox => {
+ checkbox.checked = false;
+ });
+ }
+});
diff --git a/app/static/js/eventKiosk.js b/app/static/js/eventKiosk.js
index 32b1c30b8..96a48f86f 100644
--- a/app/static/js/eventKiosk.js
+++ b/app/static/js/eventKiosk.js
@@ -1,10 +1,86 @@
-$(document).keydown(function(e){
- if (e.key === "Escape") {
- $("#fullscreenCheck").prop("checked", false)
+var elem = document.getElementById("show");
+
+$(document).on("fullscreenchange", function() {
+ if (!document.fullscreenElement && !document.webkitFullscreenElement && !document.mozFullScreenElement && !document.msFullscreenElement) {
+ closeFullscreen(true);
+ }
+});
+
+$(document).keydown(function(e) {
+ if (e.key === "F11") {
+ e.preventDefault();
toggleFullscreen();
}
});
+function toggleFullscreen() {
+ if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) {
+ closeFullscreen(true);
+ } else {
+ openFullscreen();
+ }
+}
+
+function openFullscreen() {
+ $("#show").css({
+ 'background-color': 'white',
+ 'position': 'absolute',
+ 'top': '50%',
+ 'left': '50%',
+ 'transform': 'translate(-50%, -50%)',
+ 'height': '100%',
+ 'width': '100%',
+ 'box-sizing': 'border-box'
+ });
+
+ if (elem.requestFullscreen) {
+ elem.requestFullscreen();
+ } else if (elem.webkitRequestFullscreen) { /* Safari */
+ elem.webkitRequestFullscreen();
+ } else if (elem.msRequestFullscreen) { /* IE11 */
+ elem.msRequestFullscreen();
+ }
+ ensureFocus();
+
+
+ $("#fullscreenCheck").attr("onclick", "toggleFullscreen()").text("Close Full Screen");
+}
+
+function ensureFocus() {
+ if (!$("#submitScannerData").is(":focus")) {
+ $("#submitScannerData").focus();
+ }
+}
+
+function closeFullscreen(toggleButton) {
+ $("#show").css({
+ 'background-color': 'white',
+ 'position': 'static',
+ 'top': 'auto',
+ 'left': 'auto',
+ 'transform': 'none',
+ 'height': 'auto',
+ 'width': 'auto',
+ 'box-sizing': 'content-box'
+ });
+
+ if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) {
+ if (document.exitFullscreen) {
+ document.exitFullscreen();
+ } else if (document.webkitExitFullscreen) { /* Safari */
+ document.webkitExitFullscreen();
+ } else if (document.msExitFullscreen) { /* IE11 */
+ document.msExitFullscreen();
+ }
+ }
+
+ ensureFocus();
+
+ if (toggleButton) {
+ $("#fullscreenCheck").attr("onclick", "toggleFullscreen()").text("Open Full Screen");
+ }
+}
+
$(document).ready(function(e) {
$("#submitScannerData").focus();
@@ -13,125 +89,82 @@ $(document).ready(function(e) {
submitData();
}
});
+
+ // Click event for the Enter button
+ $("#enter-button").click(function() {
+ submitData();
+ });
- // Opens the camera to scan the ID
+
+ // Opens the camera to scan the ID
$('.qr-reader-button').on("click", function() {
- $('#qr-reader').toggle()
- let lastResult, countResults = 0;
- let onScanSuccess = function(decodedText, decodedResult) {
- if (decodedText && decodedText.length > 9 && decodedText !== lastResult) {
- lastResult = decodedText;
-
- $("#submitScannerData").val(decodedText)
- submitData();
- } else {
- message = decodedText + " Invalid B-number"
- flasherStatus = "danger"
- }
- }
- let qrboxFunction = function(viewfinderWidth, viewfinderHeight) {
- let minEdgePercentage = 0.9; // 90%
- let minEdgeSize = Math.min(viewfinderWidth, viewfinderHeight);
- let qrboxSize = Math.floor(minEdgeSize * minEdgePercentage);
- return {
- width: qrboxSize,
- height: qrboxSize
+ $('#qr-reader').toggle();
+ let lastResult, countResults = 0;
+ let onScanSuccess = function(decodedText, decodedResult) {
+ if (decodedText && decodedText.length > 9 && decodedText !== lastResult) {
+ lastResult = decodedText;
+
+ $("#submitScannerData").val(decodedText);
+ submitData();
+ } else {
+ message = decodedText + " Invalid B-number";
+ flasherStatus = "danger";
+ }
};
- }
- let scanner = new Html5QrcodeScanner("qr-reader", {
- fps: 2,
- qrbox: qrboxFunction,
- preferFrontCamera: false,
- facingMode: { exact: "environment" },
- useBarCodeDetectorIfSupported: true,
- }, true);
- scanner.render(onScanSuccess);
-
-
- // we have to delay this so that the element exists before we try to add the event
- window.setTimeout(function() {
- $('#html5-qrcode-button-camera-stop').on("click", function() {
- $('#qr-reader').toggle()
- })}, 500);
- })
+ let qrboxFunction = function(viewfinderWidth, viewfinderHeight) {
+ let minEdgePercentage = 0.9; // 90%
+ let minEdgeSize = Math.min(viewfinderWidth, viewfinderHeight);
+ let qrboxSize = Math.floor(minEdgeSize * minEdgePercentage);
+ return {
+ width: qrboxSize,
+ height: qrboxSize
+ };
+ };
+ let scanner = new Html5QrcodeScanner("qr-reader", {
+ fps: 2,
+ qrbox: qrboxFunction,
+ preferFrontCamera: false,
+ facingMode: { exact: "environment" },
+ useBarCodeDetectorIfSupported: true,
+ }, true);
+ scanner.render(onScanSuccess);
+
+ // Delay to ensure the element exists before adding the event
+ window.setTimeout(function() {
+ $('#html5-qrcode-button-camera-stop').on("click", function() {
+ $('#qr-reader').toggle();
+ });
+ }, 500);
+ });
});
-function submitData(){
- $(".alert").remove()
+function submitData() {
+ $(".alert").remove();
$.ajax({
- method: "POST",
- url: '/signintoEvent',
- data: {
- "eventid": $("#eventid").val(),
- "bNumber": $("#submitScannerData").val()
- },
-
- success: function(resultID) {
- if (resultID.status == "already signed in") {
- msgFlash(`${resultID.user} already signed in!`, "warning");
- } else if (resultID.status === "banned") {
- msgFlash(`${resultID.user} is ineligible!`, "danger");
- } else if (resultID.status === "does not exist") {
- msgFlash("User does not exist", "danger");
- } else {
- msgFlash(`${resultID.user} successfully signed in!`, "success");
+ method: "POST",
+ url: '/signintoEvent',
+ data: {
+ "eventid": $("#eventid").val(),
+ "bNumber": $("#submitScannerData").val()
+ },
+ success: function(resultID) {
+ if (resultID.status == "already signed in") {
+ msgFlash(`${resultID.user} already signed in!`, "warning");
+ } else if (resultID.status === "banned") {
+ msgFlash(`${resultID.user} is ineligible!`, "danger");
+ } else if (resultID.status === "does not exist") {
+ msgFlash("User does not exist", "danger");
+ } else {
+ msgFlash(`${resultID.user} successfully signed in!`, "success");
+ }
+ $("#submitScannerData").val("").focus();
+ },
+ error: function(request, status, error) {
+ console.log(status, error);
+ msgFlash("See Attendant; Unable to sign in.", "danger");
+ $("#submitScannerData").val("").focus();
}
- $("#submitScannerData").val("").blur();
- },
-
- error: function(request, status, error) {
- console.log(status, error);
- msgFlash("See Attendant; Unable to sign in.", "danger");
- $("#submitScannerData").val("").blur();
- }
- })
-}
-
-function hideElements(hide) {
- if (hide == true) {
-
- $("footer").hide();
- $("kiosk-hide").animate({ opacity: 0 }, 1);
- $("kiosk-hide").css("width", "0");
- $("kiosk-hide").prop("disabled", true);
- $("a").hide();
- $("nav").css("width", "0");
- } else {
- $("footer").show();
- $("kiosk-hide").css("width", "inherit");
- $("kiosk-hide").animate({ opacity: 1 }, 1);
- $("kiosk-hide").prop("disabled", false);
- $("a").show();
- $("nav").css("width", "inherit");
- }
+ });
}
-// Source: https://stackoverflow.com/questions/1125084/how-to-make-the-window-full-screen-with-javascript-stretching-all-over-the-screen
-function toggleFullscreen() {
- if($("#fullscreenCheck").prop("checked") == false){
- hideElements(false);
- document.exitFullscreen() || document.webkitExitFullscreen() || document.msExitFullscreen()
- } else {
- hideElements(true);
-
- var el = document.documentElement
- , rfs = // for newer Webkit and Firefox
- el.requestFullscreen
- || el.webkitRequestFullScreen
- || el.mozRequestFullScreen
- || el.msRequestFullscreen
- ;
- if(typeof rfs!="undefined" && rfs){
- rfs.call(el);
- } else if(typeof window.ActiveXObject!="undefined"){
- // for Internet Explorer
- var wscript = new ActiveXObject("WScript.Shell");
- if (wscript!=null) {
- wscript.SendKeys("{F11}");
- }
- }
- }
- $('#submitScannerData').focus();
-};
-
diff --git a/app/static/js/event_list.js b/app/static/js/event_list.js
index b09170722..305a96bc0 100644
--- a/app/static/js/event_list.js
+++ b/app/static/js/event_list.js
@@ -1,32 +1,39 @@
$(document).ready(function(){
- $("#removeRsvpBtn").click(function(){
- removeRsvpForEvent($("#removeRsvpBtn").val())
- })
- $("#rsvpBtn").click(function(){
- rsvpForEvent($("#rsvpBtn").val())
- })
- var viewPastEventsToggle = $("#viewPastEventsToggle");
- viewPastEventsToggle.prop("checked", g_isPastTerm);
- toggleRows(g_isPastTerm);
- viewPastEventsToggle.prop("disabled", g_isPastTerm);
-
- viewPastEventsToggle.on("change", function(){
- var isChecked = $(this).prop("checked");
- toggleRows(isChecked);
-
- localStorage.setItem("toggleState", isChecked ? "checked" : "unchecked")
- });
- function toggleRows(isChecked) {
- var tableRows = $(".showlist");
- if (isChecked){
- tableRows.show();
- } else {
- tableRows.hide();
- }
+ $("#removeRsvpBtn").click(function(){
+ removeRsvpForEvent($("#removeRsvpBtn").val())
+ })
+ $("#rsvpBtn").click(function(){
+ rsvpForEvent($("#rsvpBtn").val())
+ })
+ //ensure that toggle state is consistent across terms
+ var toggleState = sessionStorage.getItem('toggleState') || 'unchecked';
+ var viewPastEventsToggle = $("#viewPastEventsToggle");
+ viewPastEventsToggle.prop('checked', toggleState === 'checked');
+ var isChecked = viewPastEventsToggle.prop("checked");
+ toggleRows(isChecked);
+
+ updateIndicatorCounts(isChecked)
+ //update indicator numbers when toggle is changed
+ viewPastEventsToggle.on("change", function(){
+ if (!g_isPastTerm) {
+ let isChecked = $(this).prop("checked");
+ toggleRows(isChecked);
+ updateIndicatorCounts(isChecked);
+ sessionStorage.setItem('toggleState', isChecked ? "checked" : "unchecked");
}
});
+ function toggleRows(isChecked) {
+ var tableRows = $(".showlist");
+ if (isChecked) {
+ tableRows.show();
+ } else {
+ tableRows.hide();
+ }
+ }
+});
+
function rsvpForEvent(eventID){
rsvpInfo = {id: eventID,
from: 'ajax'}
@@ -58,9 +65,34 @@ function removeRsvpForEvent(eventID){
error: function(error, status){
console.log(error, status)
}
-
})
}
+//gets number indicator of events in each event list category
+function updateIndicatorCounts(isChecked){
+ $.ajax({
+ url: "/eventsList/" + $('#termID').val(),
+ type: "GET",
+ data: {
+ toggleState: isChecked ? "checked" : "unchecked",
+ },
+ success: function(eventsCount) {
+ const studentLedEventsCount = Number(eventsCount.studentLedEventsCount);
+ const trainingEventsCount = Number(eventsCount.trainingEventsCount);
+ const bonnerEventsCount = Number(eventsCount.bonnerEventsCount);
+ const otherEventsCount = Number(eventsCount.otherEventsCount);
+ const toggleStatus = eventsCount.toggleStatus;
+
+ $("#viewPastEventsToggle").prop(toggleStatus, true);
-
+ // use ternary operators to populate the tab with a number if there are events, and clear the count if there are none
+ studentLedEventsCount > 0 ? $("#studentLedEvents").html(`Student Led Service (${studentLedEventsCount})`) : $("#studentLedEvents").html(`Student Led Service`)
+ trainingEventsCount > 0 ? $("#trainingEvents").html(`Training and Education (${trainingEventsCount})`) : $("#trainingEvents").html(`Training and Education`)
+ bonnerEventsCount > 0 ? $("#bonnerScholarsEvents").html(`Bonner Scholars (${bonnerEventsCount})`) : $("#bonnerScholarsEvents").html(`Bonner Scholars`)
+ otherEventsCount > 0 ? $("#otherEvents").html(`Other Events (${otherEventsCount})`) : $("#otherEvents").html(`Other Events`)
+ },
+ error: function(request, status, error) {
+ console.log(status,error);
+ }
+ });
+}
diff --git a/app/static/js/manageServiceLearningFaculty.js b/app/static/js/manageServiceLearningFaculty.js
index 4e1b17d2b..f821b9ed5 100644
--- a/app/static/js/manageServiceLearningFaculty.js
+++ b/app/static/js/manageServiceLearningFaculty.js
@@ -69,7 +69,7 @@ $(document).ready( function () {
$("#submitImportedCourses").modal("toggle");
});
- $('#closeAddCourseParticipants').on('click', function () {
+ $('#closeAddCourseParticipants, #addCourseParticipantsXBtn').on('click', function () {
$('#addCourseParticipants')[0].form.reset()
$('#previewButton').prop('disabled', true)
})
@@ -85,7 +85,7 @@ $(document).ready( function () {
}
}
- $("#cancelModalPreview").click(function(){
+ $("#cancelModalPreview, #closeModalPreview").click(function(){
$.ajax({
url: "/deleteUploadedFile",
type: 'POST',
diff --git a/app/static/js/manageVolunteers.js b/app/static/js/manageVolunteers.js
index 5446f085e..693aa7968 100644
--- a/app/static/js/manageVolunteers.js
+++ b/app/static/js/manageVolunteers.js
@@ -91,7 +91,8 @@ $(document).ready(function() {
url: `/addVolunteersToEvent/${eventId}`,
type: "POST",
data: {"selectedVolunteers": selectedVolunteers, "ajax": true},
- success: function(s){
+ success:
+ function(s){
location.reload()
},
error: function(request, status, error){
diff --git a/app/static/js/minorAdminPage.js b/app/static/js/minorAdminPage.js
index fd0e03cb2..f145bd1af 100644
--- a/app/static/js/minorAdminPage.js
+++ b/app/static/js/minorAdminPage.js
@@ -1,3 +1,4 @@
+import searchUser from './searchUser.js'
function emailAllInterested(){
// Read all student emails from the input as a string and put them in mailto format
let interestedStudentEmails = $("#interestedStudentEmails").val();
@@ -14,6 +15,87 @@ function emailAllInterested(){
msgFlash("No interested students to email.", "info")
}
}
+
+
+$(document).ready(function() {
+ $(document).on('click', '.remove_interested_student', function() {
+ let username = $(this).attr('id');
+
+
+ $.ajax({
+ type: 'POST',
+ url: '/profile/' + username + '/indicateInterest',
+ success: function(response) {
+ msgToast("Student successfully removed")
+ location.reload();
+ },
+ error: function(error) {
+ console.log("error")
+ }
+ });
+ });
+});
+
+
+
+
+function getInterestedStudents() {
+ // get all the checkboxes and return a list of users who's
+ // checkboxes are selected
+ let checkboxesDisplayedInModal = $("#addInterestedStudentsModal input[type=checkbox]:checked")
+ let interestedStudentsList = []
+ checkboxesDisplayedInModal.each(function(index, checkbox){
+ interestedStudentsList.push(checkbox["value"])
+ })
+ return interestedStudentsList
+}
+
+function updateInterestedStudents(){
+ let interestedStudentList = getInterestedStudents()
+ let buttonContent = $("#addInterestedStudentsbtn").html()
+ if (interestedStudentList.length > 1) {
+ if (buttonContent.charAt(buttonContent.length-1) != "s") {
+ // make the button text plural if there are multiple users selected
+ $("#addInterestedStudentsbtn").html(buttonContent + "s")
+ }
+ } else if (buttonContent.charAt(buttonContent.length-1) == "s") {
+ // remove the s if it is plural and we have less than 2 volunteers
+ $("#addInterestedStudentsbtn").html(buttonContent.slice(0, -1))
+ }
+ // disable the submit button if there are no selectedCheckboxes
+ if (interestedStudentList.length == 0) {
+
+ $("#addInterestedStudentsbtn").prop("disabled", true)
+ } else {
+ $("#addInterestedStudentsbtn").prop("disabled", false)
+ }
+}
+
+var userlist = []
+function callback(selected) {
+ let user = $("#addStudentInput").val()
+ if (userlist.includes(selected["username"]) == false){
+ userlist.push(user)
+ let i = userlist.length;
+ $("#interestedStudentList").prepend("