简体   繁体   中英

Is there a way to combine these similar jQuery event listener functions?

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>

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>

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>

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();
    }
  });
});

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>

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM