-2

I have a big list of getElementsById that looks like this:

let ahSummerCamps = document.getElementById("aH-summerCamps");
let ahTrekking = document.getElementById("aH-trekking");
let bpLongDistanceHiking = document.getElementById("bp-longDistanceHiking");
let bpThruHiking = document.getElementById("bp-thruHiking");
let cOceanCruising = document.getElementById("c-oceanCruising");
let cRiverCruising = document.getElementById("c-riverCruising");
let eRecreationsEvent = document.getElementById("e-recreationsEvent");
let eSportsEvent = document.getElementById("e-sportsEvents");
let phEscortedTours = document.getElementById("ph-escortedTours");
let phIndependentTours = document.getElementById("ph-independentTours");
let sPhotographicSafari = document.getElementById("s-photographicSafari");
let sCyclingSafari = document.getElementById("s-cyclingSafari");
let sAsBackcountrySkiing = document.getElementById("sAs-backcountrySkiing");
let sAsDownhillSkiing = document.getElementById("sAs-downhillSkiing");
let vChildcare = document.getElementById("v-childcare");
let vConservationAndEnvironment = document.getElementById("v-conservationAndEnvironment");

I won't go into details, is there any way that I can loop throught all of them and for example hide all except bpLongDistanceHiking and bpThruHiking .

I had this function but that is not good way for sure:

function hideAllExceptbP() {
ahSummerCamps.style.display = "none";
ahTrekking.style.display = "none";
/* ... and for all of them like this except bpLongDistanceHiking and bpThruHiking  */
}

So on that way I need function for every element like:

function hideAllExceptaH() {
/* ... + 10 lines */

function hideAllExceptC() {
/* ... + 10 lines */

function hideAllExceptE() {
/* ... + 10 lines */

Function

function choice() {
backpacking.addEventListener("click", () => {
    hideBackpacking();
    hideSafari();
    hidePackageHoliday();
    showBackpackingOptions();
    console.log("Backpacking");
});

So as you can see from html I have 8 divs at start, and when user click on backpacking for example function should hide all divs except bpLongDistanceHiking and bpThruHiking

Full code calling function:

HTML:

    <div class="row">

    <!--main divs-->
    <div style="background-color: #4cc9f0" class="column" id="adventureHolidays"><p>Adventure Holidays</p></div>
    <div style="background-color: #4895ef" class="column" id="backpacking"><p>Backpacking</p></div>
    <div style="background-color: #4361ee" class="column" id="cruiseHolidays"><p>Cruise Holidays</p></div>
    <div style="background-color: #4361ee" class="column" id="eventTravel"><p>Event Travel</p>
    </div>
    <div style="background-color: #3a0ca3" class="column" id="packageHoliday"><p>Package Holiday</p></div>
    <div style="background-color: #480ca8" class="column" id="safari"><p>Safari</p></div>
    <div style="background-color: #560bad" class="column" id="skiingAndSnowboarding"><p>Skiing and Snowboarding</p>
    </div>
    <div style="background-color: #7209b7" class="column" id="volunteering"><p>Volunteering</p></div>

    <!--end on main divs-->

    <!--sub divs-->

    <div style="background-color: #4cc9f0" class="column" id="aH-summerCamps"><p>Summer camps</p></div>
    <div style="background-color: #4895ef" class="column" id="aH-trekking"><p>Trekking</p></div>
    <div style="background-color: #4361ee" class="column" id="bP-longDistanceHiking"><p>Long Distance Hiking</p></div>
    <div style="background-color: #4361ee" class="column" id="bP-thruHiking"><p>Thru Hiking</p></div>
    <div style="background-color: #3a0ca3" class="column" id="c-oceanCruising"><p>Ocean Cruising</p></div>
    <div style="background-color: #480ca8" class="column" id="c-riverCruising"><p>River Cruising</p></div>
    <div style="background-color: #560bad" class="column" id="e-recreationsEvent"><p>Recreations Events</p></div>
    <div style="background-color: #7209b7" class="column" id="e-sportsEvents"><p>Sports events</p></div>
    <div style="background-color: #4cc9f0" class="column" id="pH-escortedTours"><p>Escorted Tours</p></div>
    <div style="background-color: #4895ef" class="column" id="pH-independentTours"><p>Independent Tours</p></div>
    <div style="background-color: #4361ee" class="column" id="s-photographicSafari"><p>Photographic Safari</p></div>
    <div style="background-color: #4895ef" class="column" id="s-cyclingSafari"><p>Cycling Safari</p></div>
    <div style="background-color: #3a0ca3" class="column" id="sAs-backcountrySkiing"><p>Backcountry skiing</p></div>
    <div style="background-color: #560bad" class="column" id="sAs-downhillSkiing"><p>Downhill skiing</p></div>
    <div style="background-color: #4361ee" class="column" id="v-childcare"><p>Childcare</p></div>
    <div style="background-color: #4895ef" class="column" id="v-conservationAndEnvironment"><p>Conservation And
        Environment</p></div>
</div>
<script type="text/javascript" th:src="@{/js/index.js}"></script>

js:

    let adventureHolidays = document.getElementById("adventureHolidays");
let backpacking = document.getElementById("backpacking");
let cruiseHolidays = document.getElementById("cruiseHolidays");
let eventTravel = document.getElementById("eventTravel");
let packageHoliday = document.getElementById("packageHoliday");
let safari = document.getElementById("safari");
let skiingAndSnowboarding = document.getElementById("skiingAndSnowboarding");
let volunteering = document.getElementById("volunteering");
/*End of inserting main variables*/

/*sub variables*/

let ahSummerCamps = document.getElementById("aH-summerCamps");
let ahTrekking = document.getElementById("aH-trekking");
let bPLongDistanceHiking = document.getElementById("bP-longDistanceHiking");
let bPThruHiking = document.getElementById("bP-thruHiking");
let cOceanCruising = document.getElementById("c-oceanCruising");
let cRiverCruising = document.getElementById("c-riverCruising");
let eRecreationsEvent = document.getElementById("e-recreationsEvent");
let eSportsEvent = document.getElementById("e-sportsEvents");
let phEscortedTours = document.getElementById("ph-escortedTours");
let phIndependentTours = document.getElementById("ph-independentTours");
let sPhotographicSafari = document.getElementById("s-photographicSafari");
let sCyclingSafari = document.getElementById("s-cyclingSafari");
let sAsBackcountrySkiing = document.getElementById("sAs-backcountrySkiing");
let sAsDownhillSkiing = document.getElementById("sAs-downhillSkiing");
let vChildcare = document.getElementById("v-childcare");
let vConservationAndEnvironment = document.getElementById("v-conservationAndEnvironment");

/*end of subs variables*/

const divs = ["adventureHolidays", "backpacking", "cruiseHolidays", "eventTravel", "packageHoliday", "safari", "skiingAndSnowboarding", "volunteering", "aH-summerCamps", "aH-trekking", "bP-longDistanceHiking", "bP-thruHiking", "c-oceanCruising", "c-riverCruising", "e-recreationsEvent", "e-sportsEvents", "ph-escortedTours", "ph-independentTours", "s-photographicSafari", "s-cyclingSafari", "sAs-backcountrySkiing", "v-conservationAndEnvironment", "sAs-downhillSkiing", "v-childcare"]
    .map(id => document.getElementById(id)); // gives you an array of those elements

function hideAllDivsExcept(id) {
    for (const div of divs) div.hidden = !div.id === id;
}


window.onload = function () {
    choice();
};


/* start of function choice for user clicks*/

function choice() {
    backpacking.addEventListener("click", () => {
        hideAllDivsExcept('adventureHolidays');
        console.log("Backpacking");
    })
}

CSS:

 * {
    box-sizing: border-box;
}

/* Create three equal columns that floats next to each other */
.column {
    float: left;
    width: 33.33%;
    padding: 10px;
}

/* Clear floats after the columns */
.row:after {
    content: "";
    /*
    display: table;
    */
    clear: both;
}

I'm getting:

index.js:38 Uncaught TypeError: Cannot read properties of null (reading 'id')
at hideAllDivsExcept (index.js:38:47)
at HTMLDivElement.<anonymous> (index.js:51:9)

And that is this

    function hideAllDivsExcept(id) {
   this > for (const div of divs) div.hidden = !div.id === id;
}
devnoob
  • 17
  • 3
  • Best solution would require seeing the HTML and how the functions (eg `hideAllExceptbP`) are called – CertainPerformance Jul 09 '22 at 19:32
  • Or `hideAllExcept(arr)` – IT goldman Jul 09 '22 at 19:33
  • Updated question with html and function example – devnoob Jul 09 '22 at 19:35
  • So of course you should use the `column` class to hide all. Then show only those you want. – IT goldman Jul 09 '22 at 19:35
  • I'm begginer to JS, just doing this because I need this little stuff, any example on my problem? – devnoob Jul 09 '22 at 19:36
  • Under what circumstances do you need to hide, or show, any given elements? There’s easy ways of doing it but I feel we’re not being given enough relevant details about the when, or why, elements should be shown or hidden. – David Thomas Jul 09 '22 at 19:42
  • use `document.querySelector('.yourclass')`. [possible duplicate](https://stackoverflow.com/questions/4644673/hide-all-elements-with-class-using-plain-javascript) – zeidanbm Jul 09 '22 at 19:42
  • You will need probably to see HTML example to see whats going on. I imagine my home page with 8 div at start, you can see the comment tag, those div user see at start, other divs user cant see and they are all hidden. You can see tag `sub divs`. Now, when user click on div for example `adventureHolidays` I need to hide from him all other divs except those two sub divs `aH-summerCamps` and `aH-trekking`. You can see they are connected like adventureHolidays is `aH`, backpacking from main divs is in sub divs `bP`, so if user click on `backpacking` hide all except `bP` from sub divs – devnoob Jul 09 '22 at 19:46

2 Answers2

1

One approach to the problem is as below, with explanatory comments in the code:

// defining a named function to handle clicks on the 'filter' elements, that takes one
// argument, a reference to the Event Object:
const showRelevant = (evt) =>{
  // caching a reference to the element to which the function is bound as the
  // event-handler:
    let source = evt.currentTarget,
  // retrieving the attribute-value from the custom data-* attribute, using the
  // HTMLElement.dataset API:
        category = source.dataset.category;
  
  // retrieving all <div> elements that do not have a "data-category" attribute which
  // are the children of a .row element; we iterate over that collection using
  // NodeList.prototype.forEach():
  document.querySelectorAll('.row > div:not([data-category])').forEach(
    // using an Arrow function we pass in a reference to the current
    // Node of the NodeList over which we're iterating:
    (el) => {
      // we split the element's id property-value at the '-' character,
      // and retrieve the first element of the resulting Array:
        let prefix = el.id.split('-')[0];
      
      // if the chosen category is exactly equal to 'all':
      if (category === 'all') {
        // we want to show all elements, therefore we set the hidden property
        // of every element to false; so every element is shown:
        el.hidden = false;
      } else {
        // otherwise, if the category is not equal to the prefix (above) the
        // assessment results in true and so the element is hidden; if the
        // category is equal to the prefix (therefore the current element is
        // one we wish to see) the assessment results in false, and so the
        // element is shown:
        el.hidden = category !== prefix;
      }
    })
};

// here we retrieve all child elements with a "data-category" attribute of a .row element,
// and iterate over that NodeList with NodeList.prototype.forEach():
document.querySelectorAll('.row > [data-category]').forEach(
  // using an Arrow function we pass in a reference to the current Node of the NodeList,
  // and use EventTarget.addEventListener() to bind the showRelevant() function (note the
  // deliberate lack of parentheses) as the event-handler for the 'click' event:
    (el) => el.addEventListener('click', showRelevant)
)
:root {
  --h-1: 212;
  --h-2: 194;
  --s: 84%;
  --l: 62%;
  --c-l: var(--l);
  --bgc-l: var(--l);
}

* {
  box-sizing: border-box;
}

.row {
/* rather than using float, I've used display: flex: */
  display: flex;
/* the default of flex elements is:
     flex-direction: row;
     flex-wrap: nowrap;
   flex-flow is a shorthand to update both those values;
   here I've specified:
     flex-direction: row;
     flex-wrap: wrap;
   */
  flex-flow: row wrap;
  /* adjust to taste, but this replicates the behaviour of
     floating in that elements on an incomplete row will
     align to the start of the row: */
  justify-content: start;
  /* placing a 0.2em margin on the block-axis of the element;
     in a language such as English (left-to-right, top-to-bottom)
     that aligns to the top (margin-block-start) and bottom
     (margin-block-end) margins: */
  margin-block: 0.2em;
}

.row > * {
  box-shadow: inset 0 0 0 3px currentColor, inset 0 0 0 4px #fff;
  /* basing the width of the elements - using the flex-basis
     property - to 33%: */
  flex-basis: 33%;
  padding: 10px;
}

.row > *:nth-child(even) {
  /* using CSS custom properties to set color and
     background-color: */
  color: hsl(var(--h-1) var(--s) var(--c-l));
  background-color: hsl(var(--h-2) var(--s) var(--bgc-l));
}

.row > *:nth-child(odd) {
  color: hsl(var(--h-2) var(--s) var(--c-l));
  background-color: hsl(var(--h-1) var(--s) var(--bgc-l));
}

.row > *:nth-child(even):hover,
.row > *:nth-child(odd):hover {
  /* manipulating the CSS custom properties with the
     calc function to make the color darker (by decreasing
     the lightness) and the background-color lighter (by
     increasing the lightness): */
  --c-l: calc(var(--l)*0.5);
  --bgc-l: calc(var(--l) * 1.2);
}
<div class="row">
  <!--main divs-->
  <!-- I've added a custom data-* attribute to each of the elements that would
       constitute a 'filter' element; the attribute-value is all the initial
       letters of the words written as camel-case, so:
       'Adventure Holidays' => 'AH' => 'aH' -->
  <div id="adventureHolidays" data-category="aH">
    <p>Adventure Holidays</p>
  </div>
  <div id="backpacking" data-category="bP">
    <p>Backpacking</p>
  </div>
  <div id="cruiseHolidays" data-category="cH">
    <p>Cruise Holidays</p>
  </div>
  <div id="eventTravel" data-category="eT">
    <p>Event Travel</p>
  </div>
  <div id="packageHoliday" data-category="pH">
    <p>Package Holiday</p>
  </div>
  <div id="safari" data-category="s">
    <p>Safari</p>
  </div>
  <div id="skiingAndSnowboarding" data-category="sAS">
    <p>Skiing and Snowboarding</p>
  </div>
  <div id="volunteering" data-category="v">
    <p>Volunteering</p>
  </div>
  <div data-category="all">
    <p>Show all</p>
  </div>
  <!--end on main divs-->
</div>

<!-- this isn't essential, but I prefer to separate the 'filters' from the elements to be filtered: -->

<div class="row">
  <!--sub divs-->
  <!-- I've changed the id prefix of these elements to match the 'data-category' value from the
       'filter' <div> elements: -->
  <div id="aH-summerCamps">
    <p>Summer camps</p>
  </div>
  <div id="aH-trekking">
    <p>Trekking</p>
  </div>
  <div id="bP-longDistanceHiking">
    <p>Long Distance Hiking</p>
  </div>
  <div id="bP-thruHiking">
    <p>Thru Hiking</p>
  </div>
  <div id="cH-oceanCruising">
    <p>Ocean Cruising</p>
  </div>
  <div id="cH-riverCruising">
    <p>River Cruising</p>
  </div>
  <div id="eT-recreationsEvent">
    <p>Recreations Events</p>
  </div>
  <div id="eT-sportsEvents">
    <p>Sports events</p>
  </div>
  <div id="pH-escortedTours">
    <p>Escorted Tours</p>
  </div>
  <div id="pH-independentTours">
    <p>Independent Tours</p>
  </div>
  <div id="s-photographicSafari">
    <p>Photographic Safari</p>
  </div>
  <div id="s-cyclingSafari">
    <p>Cycling Safari</p>
  </div>
  <div id="sAS-backcountrySkiing">
    <p>Backcountry skiing</p>
  </div>
  <div id="sAS-downhillSkiing">
    <p>Downhill skiing</p>
  </div>
  <div id="v-childcare">
    <p>Childcare</p>
  </div>
  <div id="v-conservationAndEnvironment">
    <p>Conservation and Environment</p>
  </div>
</div>

JS Fiddle demo.

References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
0

Add an id to your main div with class 'row', e.x. daDiv then iterate and perform whatever you want checking id attribute of each one

$('#daDiv').children('div').each(function () {
  if ($(this).attr('id') !== 'bP-longDistanceHiking' && $(this).attr('id') !== 'bP-thruHiking') {
    $(this).hide();
  }
});

CodePen

Example

UPDATE

You can even make a function

function hideExcept(arr) {

  $('#daDiv').children('div').each(function () {
    if (!arr.includes($(this).attr('id')))
      $(this).hide();
  });
}

hideExcept(['bP-longDistanceHiking', 'bP-thruHiking']); // hide all except bP-longDistanceHiking and bP-thruHiking
Ahmet Firat Keler
  • 2,603
  • 2
  • 11
  • 22