Clean up form hiding/showing logic

This commit is contained in:
Anna Sidwell 2018-11-25 14:59:05 +00:00
parent d6bae3b941
commit d914ffab49

View File

@ -40,6 +40,12 @@
<!-- Conditional logic for hiding and un-hiding fields. -->
<script>
//
// Helper functions for conditional field show/hide
//
// Show or hide an element, or selection of elements, depending shouldShow
function showIf(thingToShow, shouldShow) {
if (shouldShow) {
$(thingToShow).show()
@ -47,126 +53,142 @@
$(thingToShow).hide()
}
}
// Returns true if checkbox is checked
function isChecked(elem) {
return elem.checked
}
// Here we define the fields we need to conditionally toggle.
// Returns a function that returns true if its parameter matches `condition`
function isJust(condition) {
return elem => elem.value === condition
}
// Returns a function that returns true if its parameter is in `conditions`
function isOneOf(conditions) {
return elem => conditions.includes(elem.value)
}
//
// The big ol' list of controls and what sections they toggle the display of
// TODO: Move this knowledge out of the template
var conditionalFields = [
{
"field": "#id_location_context",
"showHide": ["#div_id_type_of_ecosystem"],
"condition": ["RUR"]
},
{ // 2.1 - Power Generation
"field": "#id_sector_of_economy",
"showHide": ["#power_generation_questions"],
"condition": ["RN"]
},
{
"field": "#id_generation_technology",
"showHide": ["#div_id_biomass_detail"],
"condition": ["BIO"]
},
{ // 2.2 - Power Grids
"field": "#id_sector_of_economy",
"showHide": ["#power_grids_energy_storage_questions"],
"condition": ["PG"]
},
{ // 2.3 - Supply of minerals
"field": "#id_sector_of_economy",
"showHide": ["#mineral_commodity_questions"],
"condition": ["SM"]
},
{ // 3.2
"field": "#id_positive_or_negative",
"showHide": ["#div_id_obstacles_and_hindrances"],
"condition": ["P", "N"]
}];
//
// Here we define the checkboxes that we need to use to
// conditionally toggle fields - they use slightly different
// logic as they rely on the 'checked' attribute rather than value.
var conditionalCheckboxes = [
var showHideFields = [
// 'Basic information' tab
{
checkbox: "#id_affects_indigenous",
showHide: "#div_id_affects_indigenous_detail",
control: 'location_context',
showHide: '#div_id_type_of_ecosystem',
visible: isJust('RUR') // Rural
},
// Technical/economic tab
{
control: 'sector_of_economy',
showHide: '#power_generation_questions',
visible: isJust('RN') // Energy generation project
},
{
control: 'generation_technology',
showHide: '#div_id_biomass_detail',
visible: isJust('BIO') // Bio-energy
},
{
control: 'sector_of_economy',
showHide: '#power_grids_energy_storage_questions',
visible: isJust('PG') // Energy networks or storage (stands for 'power grid')
},
{
control: 'power_technology',
showHide: '#div_id_power_technology_other',
visible: isJust('OT')
},
{
control: 'power_technology',
showHide: '#div_id_energy_storage_capacity',
visible: isOneOf(['ES', 'OT']) // Storage / other
},
{
control: 'power_technology',
showHide: '#div_id_energy_transmission_capacity',
visible: isOneOf(['PT', 'HN', 'OT']) // Transmission / heat / other
},
{
control: 'sector_of_economy',
showHide: '#mineral_commodity_questions',
visible: isJust('SM') // mining
},
{
control: 'use_in_energy_economy',
showHide: '#div_id_use_in_energy_economy_other',
visible: isJust('OTR')
},
{
control: 'sector_of_economy',
showHide: '#manufacturing_questions',
visible: isJust('MA') // manufacturing
},
// Socio-environmental tab
{
control: 'positive_or_negative',
showHide: '#div_id_obstacles_and_hindrances',
visible: isOneOf(['P', 'N']) // positive/negative (process pro / vs)
},
{
checkbox: "#id_shown_on_other_platforms",
showHide: "#div_id_shown_on_other_platforms_detail"
control: 'negative_case_reasons',
showHide: '#div_id_negative_case_reasons_other',
visible: isJust('OTHR')
},
// Contact tab
{
checkbox: "#id_negative_case_reasons_8",
showHide: "#div_id_negative_case_reasons_other"
control: 'shown_on_other_platforms',
showHide: '#div_id_shown_on_other_platforms_detail',
visible: isChecked
},
{
checkbox: "[name=use_in_energy_economy][value=OTR]",
showHide: "#div_id_use_in_energy_economy_other"
}
];
//
// Fields that require their own more advanced logic
//
var conditionalControls = [
{
name: "power_technology",
redraw: function() {
const other = document.getElementById('id_id_power_technology_0_4')
const panel = document.getElementById('div_id_power_technology_other')
showIf(panel, other.checked)
}
},
{
name: "power_technology",
redraw: function() {
const group = document.forms['case-study-form'].power_technology
// Storage / other
let showStorage = ['ES', 'OT'].includes(group.value)
// Transmission / heat / other
let showTransmission = ['PT', 'HN', 'OT'].includes(group.value)
showIf('#div_id_energy_storage_capacity', showStorage)
showIf('#div_id_energy_transmission_capacity', showTransmission)
}
},
{
name: "sector_of_economy",
redraw: function() {
const sections = {
RN: "power_generation_questions",
PG: "power_grids_energy_storage_questions",
SM: "mineral_commodity_questions",
MA: "manufacturing_questions",
}
for (const option of Object.keys(sections)) {
const input = document.querySelector(`[name=sector_of_economy][value=${option}]`)
const section = document.getElementById(sections[option])
showIf(section, input.checked)
}
}
},
{
name: "sector_of_economy",
name: 'sector_of_economy',
redraw: function() {
const sector = document.forms['case-study-form'].sector_of_economy
const input = document.querySelector(`[name=positive_case_type][value=CORS]`)
// If sector of economy is transmission, mining, or processing
// Then enable this input. Otherwise, disable.
// TODO: Could make the row invisible
input.disabled = ['PG', 'SM', 'MA'].includes(sector.value) ? false : true
}
},
{
name: "positive_or_negative",
name: 'positive_or_negative',
redraw: function() {
const setting = document.forms['case-study-form'].positive_or_negative
//
// This is some nasty hacking around wanting different field labels/
// help texts depending on the positive_or_negative option.
//
// Each piece of text whose display is dependent on what option is selected
// has the class 'organising', plus at least one of 'organising-vs/pro/none/idk'.
//
// The base `organising` class sets display: none. Then, we go through
// all the elements tagged with the current choice, reset element-specific
// display styling, and then apply `display: inline` just to the desired
// elements.
//
const relatedElements = [
{ value: 'P', elements: '.organising-pro' },
{ value: 'N', elements: '.organising-vs' },
@ -190,96 +212,43 @@
},
]
// Define a function that hides the field and then creates a listener to toggle the field.
// Takes a single conditionalField dictionary with (field, showHide and condition).
function addConditionalField(item) {
hideAll(item.showHide);
$(item.field).change(function(){
// Get the value of the option
var value = $(this).val();
// Check the value matches any of the conditions.
if (isInArray(value, item.condition)){
showAll(item.showHide);
} else {
hideAll(item.showHide);
}
});
}
// This function does the same as addConditionalField except it checks the status of
// checkboxes instead of fields.
function addConditionalCheckbox(item) {
$(item.showHide).hide();
$(item.checkbox).change(function(){
if ($(this).is(":checked")) {
$(item.showHide).show();
} else {
$(item.showHide).hide();
}
});
}
// Helper functions
function show(tag) {
$(tag).show();
}
function hide(tag) {
$(tag).hide();
}
function showAll(tags) {
tags.forEach(show);
}
function hideAll(tags) {
tags.forEach(hide);
}
function isInArray(value, array) {
return array.indexOf(value) > -1;
}
$(document).ready(function(){
$(function() {
// Button classes for tab navigation
$('.btnNext').click(function(){
$('.btnNext').click(function() {
$('.nav-tabs > .active').next('li').find('a').trigger('click');
});
$('.btnPrevious').click(function(){
$('.btnPrevious').click(function() {
$('.nav-tabs > .active').prev('li').find('a').trigger('click');
});
$('form').attr('novalidate', 'novalidate');
conditionalFields.forEach(addConditionalField);
conditionalCheckboxes.forEach(addConditionalCheckbox);
// Add conditional form show/hide logic
for (const item of showHideFields) {
const control = document.forms['case-study-form'][item.control]
conditionalFields.forEach(function(item){
$(item.field).change();
});
$(control).change(() => {
// Check the value matches any of the conditions.
showIf(item.showHide, item.visible(control))
});
conditionalCheckboxes.forEach(function(item){
$(item.checkbox).change();
});
$(control).change();
}
conditionalControls.forEach(function (group) {
// Add handlers for more advanced form logic
for (const group of conditionalControls) {
$(`[name=${group.name}]`).on('change', group.redraw)
group.redraw();
});
});
}
</script>
<script>
$(function() {
initDrafts()
initDrafts()
// Jump to error
if ($('.has-error').length) {
location.href = '#' + $('.has-error:first').attr('id');
}
})
// Jump to error
if ($('.has-error').length) {
location.href = '#' + $('.has-error:first').attr('id');
}
})
</script>
{% endblock %}