-
Notifications
You must be signed in to change notification settings - Fork 581
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement new layout for the sponsorship application (#1744)
* Order benefits by amount of associated packages * Minimal HTML logic to control program and benefits exhibition * Better display package inputs * Allow the benefits table to overflow and have a width greater than the article * Remove sponsorship substring from program name * Display checkbox if it's a potential add-on * Separate add-ons benefits from packages' ones * Display add-on as checkbox in the frontend + row/col css refactoring * Add headers with form sections titles * Bass CSS defined in the specs * Section titles styling * Initial benefits table styling * Final styles to packages/benefits table * Enable filter by package as well * Style add-ons cards * Add styles to submit section * Style section titles * Run black * Implement sponsorship's footer * Remove legacy benefits input fields and styles * Move thank you section closer to footer * Simplify JS code to only select benefits after package selection * Replace png by svg img * Add selected CSS * Display selected packages when page loads * Clean-up add-ons selectons after changing the package * Potential add-on checkboxes updating django's form related ones. * Hide inputs This is not a problem because the backend code runs all validations needed as well * Display form errors * Surrounds package radio inputs in a div * Style package selection input * Add event to handle click on package input container * Add mobile style to add-on selection * Style form submit section form moble * Style benefits list for the mobile version * Refactor and load ticks on mobile if form has initial data * Make sure add-on benefits are being saved * Get value only if checked inputs * compile scss * Replace add-on input by images * Reset add-on image if package changes * Enable user to unselect benefits as well * Display image considering form initial * Add-ons considering form initial * Prevent package names from overlapping * Respect initial values for potential add-ons * Update sponsors/forms.py Co-authored-by: Éric Araujo <merwok@netwok.org> * perhaps yuglify isn't necessary? * noop compressor * trying to debug deployed js * disable wrapping Javascript * Revert "trying to debug deployed js" This reverts commit 178d8aa. * display/bolden sponsorship program title Co-authored-by: Ernest W. Durbin III <ewdurbin@gmail.com> Co-authored-by: Éric Araujo <merwok@netwok.org>
- Loading branch information
1 parent
7d00625
commit 159f0bb
Showing
18 changed files
with
836 additions
and
335 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,103 +1,89 @@ | ||
$(document).ready(function(){ | ||
const SELECTORS = { | ||
checkboxesContainer: function() { return $("#benefits_container"); }, | ||
costLabel: function() { return $("#cost_label"); }, | ||
clearFormBtn: function() { return $("#clear_form_btn"); }, | ||
packageInput: function() { return $("input[name=package]"); }, | ||
applicationForm: function() { return $("#application_form"); }, | ||
getPackageInfo: function(packageId) { return $("#package_benefits_" + packageId); }, | ||
getPackageBenefits: function(packageId) { return SELECTORS.getPackageInfo(packageId).children(); }, | ||
benefitsInputs: function() { return $("input[id^=id_benefits_]"); }, | ||
getBenefitLabel: function(benefitId) { return $('label[benefit_id=' + benefitId + ']'); }, | ||
getBenefitInput: function(benefitId) { return SELECTORS.benefitsInputs().filter('[value=' + benefitId + ']'); }, | ||
getBenefitConflicts: function(benefitId) { return $('#conflicts_with_' + benefitId).children(); }, | ||
getSelectedBenefits: function() { return SELECTORS.benefitsInputs().filter(":checked"); }, | ||
} | ||
|
||
displayPackageCost = function(packageId) { | ||
let packageInfo = SELECTORS.getPackageInfo(packageId); | ||
let cost = packageInfo.attr("data-cost"); | ||
SELECTORS.costLabel().html('Sponsorship cost is $' + cost.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + ' USD') | ||
} | ||
|
||
|
||
|
||
SELECTORS.clearFormBtn().click(function(){ | ||
SELECTORS.applicationForm().trigger("reset"); | ||
SELECTORS.applicationForm().find(".active").removeClass("active"); | ||
SELECTORS.packageInput().prop("checked", false); | ||
SELECTORS.checkboxesContainer().find(':checkbox').each(function(){ | ||
$(this).prop('checked', false); | ||
if ($(this).attr("package_only")) $(this).attr("disabled", true); | ||
}); | ||
SELECTORS.costLabel().html(""); | ||
}); | ||
const SELECTORS = { | ||
packageInput: function() { return $("input[name=package]"); }, | ||
getPackageInfo: function(packageId) { return $("#package_benefits_" + packageId); }, | ||
getPackageBenefits: function(packageId) { return SELECTORS.getPackageInfo(packageId).children(); }, | ||
benefitsInputs: function() { return $("input[id^=id_benefits_]"); }, | ||
getBenefitInput: function(benefitId) { return SELECTORS.benefitsInputs().filter('[value=' + benefitId + ']'); }, | ||
getSelectedBenefits: function() { return SELECTORS.benefitsInputs().filter(":checked"); }, | ||
tickImages: function() { return $(`.benefit-within-package img`) }, | ||
} | ||
|
||
SELECTORS.packageInput().change(function(){ | ||
let package = this.value; | ||
if (package.length == 0) return; | ||
|
||
SELECTORS.costLabel().html("Updating cost...") | ||
|
||
SELECTORS.checkboxesContainer().find(':checkbox').each(function(){ | ||
$(this).prop('checked', false); | ||
let packageOnlyBenefit = $(this).attr("package_only"); | ||
if (packageOnlyBenefit) $(this).attr("disabled", true); | ||
}); | ||
|
||
SELECTORS.getPackageBenefits(package).each(function(){ | ||
let benefit = $(this).html() | ||
let benefitInput = SELECTORS.getBenefitInput(benefit); | ||
let packageOnlyBenefit = benefitInput.attr("package_only"); | ||
benefitInput.removeAttr("disabled"); | ||
benefitInput.trigger("click"); | ||
}); | ||
displayPackageCost(package); | ||
}); | ||
const initialPackage = $("input[name=package]:checked").val(); | ||
if (initialPackage && initialPackage.length > 0) mobileUpdate(initialPackage); | ||
|
||
SELECTORS.benefitsInputs().change(function(){ | ||
let benefit = this.value; | ||
if (benefit.length == 0) return; | ||
|
||
// display package cost if custom benefit change result matches with package's benefits list | ||
let isChangeFromPackageChange = SELECTORS.costLabel().html() == "Updating cost..." | ||
if (!isChangeFromPackageChange) { | ||
let selectedBenefits = SELECTORS.getSelectedBenefits(); | ||
selectedBenefits = $.map(selectedBenefits, function(b) { return $(b).val() }).sort(); | ||
let selectedPackageId = SELECTORS.packageInput().filter(":checked").val() | ||
let packageBenefits = SELECTORS.getPackageBenefits(selectedPackageId); | ||
packageBenefits = $.map(packageBenefits, function(b) { return $(b).text() }).sort(); | ||
|
||
// check same num of benefits and join with string. if same string, both lists have the same benefits | ||
if (packageBenefits.length == selectedBenefits.length && packageBenefits.join(',') === selectedBenefits.join(',')){ | ||
displayPackageCost(selectedPackageId); | ||
} else { | ||
let msg = "Please submit your customized sponsorship package application and we'll contact you within 2 business days."; | ||
SELECTORS.costLabel().html(msg); | ||
} | ||
} | ||
SELECTORS.packageInput().click(function(){ | ||
let package = this.value; | ||
if (package.length == 0) return; | ||
|
||
// updates the input to be active if needed | ||
let active = SELECTORS.getBenefitInput(benefit).prop("checked"); | ||
if (!active) { | ||
return; | ||
} else { | ||
SELECTORS.getBenefitLabel(benefit).addClass("active"); | ||
// clear previous customizations | ||
SELECTORS.tickImages().each((i, img) => { | ||
const initImg = img.getAttribute('data-initial-state'); | ||
const src = img.getAttribute('src'); | ||
|
||
if (src !== initImg) { | ||
img.setAttribute('data-next-state', src); | ||
} | ||
|
||
// check and ensure conflicts constraints between checked benefits | ||
SELECTORS.getBenefitConflicts(benefit).each(function(){ | ||
let conflictId = $(this).html(); | ||
let checked = SELECTORS.getBenefitInput(conflictId).prop("checked"); | ||
if (checked){ | ||
conflictCheckbox.trigger("click"); | ||
conflictCheckbox.parent().removeClass("active"); | ||
} | ||
}); | ||
img.setAttribute('src', initImg); | ||
}); | ||
$(".selected").removeClass("selected"); | ||
|
||
// clear hidden form inputs | ||
SELECTORS.getSelectedBenefits().each(function(){ | ||
$(this).prop('checked', false); | ||
}); | ||
|
||
// update package benefits display | ||
$(`.package-${package}-benefit`).addClass("selected"); | ||
$(`.package-${package}-benefit input`).prop("disabled", false); | ||
|
||
// populate hidden inputs according to package's benefits | ||
SELECTORS.getPackageBenefits(package).each(function(){ | ||
let benefit = $(this).html(); | ||
let benefitInput = SELECTORS.getBenefitInput(benefit); | ||
benefitInput.prop("checked", true); | ||
}); | ||
|
||
$(document).tooltip({ | ||
show: { effect: "blind", duration: 0 }, | ||
hide: false | ||
mobileUpdate(package); | ||
}); | ||
}); | ||
|
||
|
||
function mobileUpdate(packageId) { | ||
// Mobile version lists a single column to controle the selected | ||
// benefits and potential add-ons. So, this part of the code | ||
// controls this logic. | ||
const mobileVersion = $(".benefit-within-package:hidden").length > 0; | ||
if (!mobileVersion) return; | ||
$(".benefit-within-package").hide(); // hide all ticks and potential add-ons inputs | ||
$(`div[data-package-reference=${packageId}]`).show() // display only package's ones | ||
} | ||
|
||
|
||
// For an unknown reason I couldn't make this logic work with jQuery. | ||
// To don't block the development process, I pulled it off using the classic | ||
// onclick attribute. Refactorings are welcome =] | ||
function benefitUpdate(benefitId, packageId) { | ||
// Change tick image for the benefit. Can't directly change the url for the image | ||
// due to our current static files storage. | ||
const clickedImg = document.getElementById(`benefit-${ benefitId }-package-${ packageId }`); | ||
|
||
// Img container must have "selected" to class to be editable | ||
if (!clickedImg.parentElement.classList.contains('selected')) return; | ||
|
||
const newSrc = clickedImg.getAttribute("data-next-state"); | ||
clickedImg.setAttribute("data-next-state", clickedImg.src); | ||
|
||
// Update benefit's hidden input (can't rely on click event though) | ||
const benefitsInputs = Array(...document.querySelectorAll('[data-benefit-id]')); | ||
const hiddenInput = benefitsInputs.filter((b) => b.getAttribute('data-benefit-id') == benefitId)[0]; | ||
hiddenInput.checked = !hiddenInput.checked; | ||
clickedImg.src = newSrc; | ||
}; | ||
|
||
|
||
function updatePackageInput(packageId){ | ||
const packageInput = document.getElementById(`id_package_${ packageId }`); | ||
packageInput.click(); | ||
} |
Oops, something went wrong.