Reputation: 271
I have multiple jquery event listener functions that either show or hide a checkmark button based on if there is any input in the input box. The functions are practically identical minus the ID names. I'm wondering if there's a way to combine these similar functions into one, maybe using a for loop or forEach method? Any advice on how to achieve this is greatly appreciated! Code is listed down below but I also made a codepen sample.
$("#chwValue").on("input", function() {
$("#addChw").removeAttr("style");
if ($(this).val() === "") {
$("#addChw").hide();
}
});
$("#eleValue").on("input", function() {
$("#addEle").removeAttr("style");
if ($(this).val() === "") {
$("#addEle").hide();
}
});
$("#stmValue").on("input", function() {
$("#addStm").removeAttr("style");
if ($(this).val() === "") {
$("#addStm").hide();
}
});
$("#hhwValue").on("input", function() {
$("#addHhw").removeAttr("style");
if ($(this).val() === "") {
$("#addHhw").hide();
}
});
$("#gasValue").on("input", function() {
$("#addGas").removeAttr("style");
if ($(this).val() === "") {
$("#addGas").hide();
}
});
$("#wtrValue").on("input", function() {
$("#addWtr").removeAttr("style");
if ($(this).val() === "") {
$("#addWtr").hide();
}
});
$("#peakChwValue").on("input", function() {
$("#addPeakChw").removeAttr("style");
if ($(this).val() === "") {
$("#addPeakChw").hide();
}
});
$("#laborValue").on("input", function() {
$("#addLabor").removeAttr("style");
if ($(this).val() === "") {
$("#addLabor").hide();
}
});
.checkMark:hover {
cursor: pointer;
transition: transform 0.2s;
transform: scale(1.1)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" />
<table id="tableData" class="table text-light text-end table-borderless inputTable">
<thead>
<tr class='text-center bordered'>
<th></th>
<th class="bordered" scope="col">CHW
<span class='units'>[tonhr]</span>
</th>
<th class="bordered" scope="col">ELE
<span class='units'>[kWh]</span>
</th>
<th class="bordered" scope="col">STM
<span class='units'>[lb]</span>
</th>
<th class="bordered" scope="col">HHW
<span class='units'>[mmbtu]</span>
</th>
<th class="bordered" scope="col">GAS
<span class='units'>[CCF]</span>
</th>
<th class="bordered" scope="col">WTR
<span class='units'>[kgal]</span>
</th>
<th class="bordered" scope="col">Peak CHW
<span class='units'>[ton]</span>
</th>
<th class="bordered" scope="col">Labor
<span class='units'>[Hours]</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<th style="width: 100px" class="bordered">Baseline</th>
<td class="text-center inputBorder">
<input type="text" id="chwValue" class="chwInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="eleValue" class="eleInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="stmValue" class="stmInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="hhwValue" class="hhwInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="gasValue" class="gasInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="wtrValue" class="wtrInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="peakChwValue" class="peakChwInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="laborValue" class="laborInput">
</td>
</tr>
<tr class='text-center borderTop'>
<td></td>
<td>
<i id="addChw" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addEle" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addStm" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addHhw" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addGas" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addWtr" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addPeakChw" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addLabor" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
</tr>
</tbody>
</table>
Upvotes: 0
Views: 50
Reputation: 384
How about this?
$("#chwValue, #eleValue, #stmValue, #hhwValue, #gasValue, #wtrValue, #peakChwValue, #laborValue").on("input", function() {
//get the id selector from the id value (everything before 'Value')
let idName = $(this).attr('id').split('Value')[0]
//capitalize the first character
idName = idName[0].toUpperCase() + idName.slice(1);
//add the id selector dynamically
$("#add"+idName).removeAttr("style");
if ($(this).val() === "") {
$("#add"+idName).hide();
}
});
$("#chwValue, #eleValue, #stmValue, #hhwValue, #gasValue, #wtrValue, #peakChwValue, #laborValue").on("input", function() {
//get the id selector from the id value (everything before 'Value')
let idName = $(this).attr('id').split('Value')[0]
//capitalize the first character
idName = idName[0].toUpperCase() + idName.slice(1);
//add the id selector dynamically
$("#add"+idName).removeAttr("style");
if ($(this).val() === "") {
$("#add"+idName).hide();
}
});
.checkMark:hover {
cursor: pointer;
transition: transform 0.2s;
transform: scale(1.1)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" />
<table id="tableData" class="table text-light text-end table-borderless inputTable">
<thead>
<tr class='text-center bordered'>
<th></th>
<th class="bordered" scope="col">CHW
<span class='units'>[tonhr]</span>
</th>
<th class="bordered" scope="col">ELE
<span class='units'>[kWh]</span>
</th>
<th class="bordered" scope="col">STM
<span class='units'>[lb]</span>
</th>
<th class="bordered" scope="col">HHW
<span class='units'>[mmbtu]</span>
</th>
<th class="bordered" scope="col">GAS
<span class='units'>[CCF]</span>
</th>
<th class="bordered" scope="col">WTR
<span class='units'>[kgal]</span>
</th>
<th class="bordered" scope="col">Peak CHW
<span class='units'>[ton]</span>
</th>
<th class="bordered" scope="col">Labor
<span class='units'>[Hours]</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<th style="width: 100px" class="bordered">Baseline</th>
<td class="text-center inputBorder">
<input type="text" id="chwValue" class="chwInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="eleValue" class="eleInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="stmValue" class="stmInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="hhwValue" class="hhwInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="gasValue" class="gasInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="wtrValue" class="wtrInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="peakChwValue" class="peakChwInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="laborValue" class="laborInput">
</td>
</tr>
<tr class='text-center borderTop'>
<td></td>
<td>
<i id="addChw" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addEle" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addStm" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addHhw" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addGas" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addWtr" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addPeakChw" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addLabor" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
</tr>
</tbody>
</table>
Upvotes: 0
Reputation: 23654
Store the relationships in an array of objects and iterate through.
let objs = [
{'chwValue': 'addChw'},
{'eleValue': 'addEle'},
{'stmValue': 'addStm'},
{'hhwValue': 'addHhw'},
{'gasValue': 'addGas'},
{'wtrValue': 'addWtr'},
{'peakChwValue': 'addPeakChw'},
{'laborValue': 'addLabor'}];
objs.forEach(e => {
let [input, el] = Object.entries(e)[0];
$(`#${input}`).on("input", function() {
$(`#${el}`).removeAttr("style");
if ($(this).val() === "") $(`$${el}`).hide();
});
});
.checkMark:hover {
cursor: pointer;
transition: transform 0.2s;
transform: scale(1.1)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<table id="tableData" class="table text-light text-end table-borderless inputTable">
<thead>
<tr class='text-center bordered'>
<th></th>
<th class="bordered" scope="col">CHW
<span class='units'>[tonhr]</span>
</th>
<th class="bordered" scope="col">ELE
<span class='units'>[kWh]</span>
</th>
<th class="bordered" scope="col">STM
<span class='units'>[lb]</span>
</th>
<th class="bordered" scope="col">HHW
<span class='units'>[mmbtu]</span>
</th>
<th class="bordered" scope="col">GAS
<span class='units'>[CCF]</span>
</th>
<th class="bordered" scope="col">WTR
<span class='units'>[kgal]</span>
</th>
<th class="bordered" scope="col">Peak CHW
<span class='units'>[ton]</span>
</th>
<th class="bordered" scope="col">Labor
<span class='units'>[Hours]</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<th style="width: 100px" class="bordered">Baseline</th>
<td class="text-center inputBorder">
<input type="text" id="chwValue" class="chwInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="eleValue" class="eleInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="stmValue" class="stmInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="hhwValue" class="hhwInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="gasValue" class="gasInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="wtrValue" class="wtrInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="peakChwValue" class="peakChwInput">
</td>
<td class="text-center inputBorder">
<input type="text" id="laborValue" class="laborInput">
</td>
</tr>
<tr class='text-center borderTop'>
<td></td>
<td>
<i id="addChw" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addEle" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addStm" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addHhw" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addGas" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addWtr" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addPeakChw" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
<td>
<i id="addLabor" style="display: none" class="far fa-check-circle fa-3x checkMark"></i>
</td>
</tr>
</tbody>
</table>
Upvotes: 0
Reputation: 2452
You can try something like this:
var mappings = { //Need a better name
'#chwValue': '#addChw',
'#hhwValue': '#addHhw'
// Add the rest of the mappings here
}
Object.keys(mappings).forEach(function(key) {
var value = mappings[key];
$(key).on("input", function() {
$(value).removeAttr("style");
if ($(this).val() === "") {
$(value).hide();
}
});
});
Upvotes: 1
Reputation: 780673
Give all the inputs a common class. Give them an attribute that refers to the related addXxx
element.
$(".inputValue").on("input", function() {
let rel = $($(this).data("add"));
rel.removeAttr("style");
if ($(this).val() === "") {
rel.hide();
}
});
.checkMark:hover {
cursor: pointer;
transition: transform 0.2s;
transform: scale(1.1)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="tableData" class="table text-light text-end table-borderless inputTable">
<thead>
<tr class='text-center bordered'>
<th></th>
<th class="bordered" scope="col">CHW
<span class='units'>[tonhr]</span>
</th>
<th class="bordered" scope="col">ELE
<span class='units'>[kWh]</span>
</th>
<th class="bordered" scope="col">STM
<span class='units'>[lb]</span>
</th>
<th class="bordered" scope="col">HHW
<span class='units'>[mmbtu]</span>
</th>
<th class="bordered" scope="col">GAS
<span class='units'>[CCF]</span>
</th>
<th class="bordered" scope="col">WTR
<span class='units'>[kgal]</span>
</th>
<th class="bordered" scope="col">Peak CHW
<span class='units'>[ton]</span>
</th>
<th class="bordered" scope="col">Labor
<span class='units'>[Hours]</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<th style="width: 100px" class="bordered">Baseline</th>
<td class="text-center inputBorder">
<input type="text" id="chwValue" class="chwInput inputValue" data-add="#addChw">
</td>
<td class="text-center inputBorder">
<input type="text" id="eleValue" class="eleInput inputValue" data-add="#addEle">
</td>
<td class="text-center inputBorder">
<input type="text" id="stmValue" class="stmInput inputValue" data-add="#addStm">
</td>
<td class="text-center inputBorder">
<input type="text" id="hhwValue" class="hhwInput inputValue" data-add="#addHhw">
</td>
<td class="text-center inputBorder">
<input type="text" id="gasValue" class="gasInput inputValue" data-add="#addGas">
</td>
<td class="text-center inputBorder">
<input type="text" id="wtrValue" class="wtrInput inputValue" data-add="#addWtr">
</td>
<td class="text-center inputBorder">
<input type="text" id="peakChwValue" class="peakChwInput inputValue" data-add="#addPeakChw">
</td>
<td class="text-center inputBorder">
<input type="text" id="laborValue" class="laborInput inputValue" data-add="#addLabor">
</td>
</tr>
<tr class='text-center borderTop'>
<td></td>
<td>
<i id="addChw" style="display: none" class="far fa-check-circle fa-3x checkMark">x</i>
</td>
<td>
<i id="addEle" style="display: none" class="far fa-check-circle fa-3x checkMark">x</i>
</td>
<td>
<i id="addStm" style="display: none" class="far fa-check-circle fa-3x checkMark">x</i>
</td>
<td>
<i id="addHhw" style="display: none" class="far fa-check-circle fa-3x checkMark">x</i>
</td>
<td>
<i id="addGas" style="display: none" class="far fa-check-circle fa-3x checkMark">x</i>
</td>
<td>
<i id="addWtr" style="display: none" class="far fa-check-circle fa-3x checkMark">x</i>
</td>
<td>
<i id="addPeakChw" style="display: none" class="far fa-check-circle fa-3x checkMark">x</i>
</td>
<td>
<i id="addLabor" style="display: none" class="far fa-check-circle fa-3x checkMark">x</i>
</td>
</tr>
</tbody>
</table>
Upvotes: 1
Reputation: 337550
To achieve this in a more DRY manner you can relate the cells in the columns by their index. When an input
element raises an input
event you can capture its index within the parent tr
, then retrieve the corresponding icon cell from the following row by that same index. Something like this:
let $iconCells = $('.icon-row td');
$('.input-row input').on('input', e => {
let $input = $(e.target)
let index = $input.closest('td').index();
$iconCells.eq(index).find('i').toggle($input.val().length > 0);
});
.checkMark:hover {
cursor: pointer;
transition: transform 0.2s;
transform: scale(1.1)
}
.icon-row i {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" />
<table id="tableData" class="table text-light text-end table-borderless inputTable">
<thead>
<tr class='text-center bordered'>
<th></th>
<th class="bordered" scope="col">
CHW
<span class='units'>[tonhr]</span>
</th>
<th class="bordered" scope="col">
ELE
<span class='units'>[kWh]</span>
</th>
<th class="bordered" scope="col">
STM
<span class='units'>[lb]</span>
</th>
<th class="bordered" scope="col">
HHW
<span class='units'>[mmbtu]</span>
</th>
<th class="bordered" scope="col">
GAS
<span class='units'>[CCF]</span>
</th>
<th class="bordered" scope="col">
WTR
<span class='units'>[kgal]</span>
</th>
<th class="bordered" scope="col">
Peak CHW
<span class='units'>[ton]</span>
</th>
<th class="bordered" scope="col">
Labor
<span class='units'>[Hours]</span>
</th>
</tr>
</thead>
<tbody>
<tr class="input-row">
<th style="width: 100px" class="bordered">Baseline</th>
<td class="text-center inputBorder">
<input type="text" name="chwValue" class="chwInput" />
</td>
<td class="text-center inputBorder">
<input type="text" name="eleValue" class="eleInput" />
</td>
<td class="text-center inputBorder">
<input type="text" name="stmValue" class="stmInput" />
</td>
<td class="text-center inputBorder">
<input type="text" name="hhwValue" class="hhwInput" />
</td>
<td class="text-center inputBorder">
<input type="text" name="gasValue" class="gasInput" />
</td>
<td class="text-center inputBorder">
<input type="text" name="wtrValue" class="wtrInput" />
</td>
<td class="text-center inputBorder">
<input type="text" name="peakChwValue" class="peakChwInput" />
</td>
<td class="text-center inputBorder">
<input type="text" name="laborValue" class="laborInput" />
</td>
</tr>
<tr class="text-center borderTop icon-row">
<td></td>
<td><i class="far fa-check-circle fa-3x checkMark"></i></td>
<td><i class="far fa-check-circle fa-3x checkMark"></i></td>
<td><i class="far fa-check-circle fa-3x checkMark"></i></td>
<td><i class="far fa-check-circle fa-3x checkMark"></i></td>
<td><i class="far fa-check-circle fa-3x checkMark"></i></td>
<td><i class="far fa-check-circle fa-3x checkMark"></i></td>
<td><i class="far fa-check-circle fa-3x checkMark"></i></td>
<td><i class="far fa-check-circle fa-3x checkMark"></i></td>
</tr>
</tbody>
</table>
Upvotes: 0