2

I am trying to make my webpage load quicker and be more responsive. I am loading in upto 4k images that a user can scroll down through, apply filters to, and sort.

My filter usese the below code;

function filter(){
// NEED A WAY TO ADD MULTI FILTER HERE
var input, filter, span, txtValue, i, a;
input = document.getElementById('userFilter'); //usersinput
filter = input.value.toUpperCase(); //userinput capitalized
itemWrappers = document.getElementsByClassName('itemWrapperColumns');

for (i = 0; i < itemWrappers.length; i++){
    a = itemWrappers[i];
    txtValue = a.innerText;
    if (txtValue.toUpperCase().indexOf(filter) > -1) {
        itemWrappers[i].style.display = ""; // refer to the comment on span - need to hide the item container, not the span
    }else{
        itemWrappers[i].style.display = "none";
    }
}

}

This was working when I was displaying all images on a very long scroll bar. I then found a way to "hide" images until the user scrolls down, at which point the images render. I am using

  content-visibility: auto;

for this.

But now I am using this, the filter dosnt quite work. It will still apply the filter to the items that are currently visible on the users screen, but to the items that have not been rendered yet, these do not appear.

The elements of the un-rendered items are still on the page as I can see this in the console.

I am not stuck on using content-visiblity, if someone has a way to make a page with thousands of images render quickly and I can use filters/sorts that would also work.

Thanks in advance.

Edit: for a bit more context, i am trying to hide my top level div wrapper that contains everything enter image description here

  • 1
    Can't you just add the `loading="lazy"` attribute to the images, for native lazy loading? – Reyno Sep 18 '21 at 13:36
  • I have a similar question here : https://stackoverflow.com/questions/69144542/how-to-get-the-number-of-cards-showing-the-result-from-search-bar which have some stuff which may help you for your search – Rana Sep 18 '21 at 13:48
  • @Reyno edited original post, seems loading='lazy' wont fit here as I am hiding not just the images, but a bunch of other content that goes a long with it. Apologies for not adding that context first – ConfusedSpark Sep 18 '21 at 13:56
  • Why don't you apply your function when the user is scrolled and images is appeared ? – JS_INF Sep 18 '21 at 14:04
  • Did you also add a `contain-intrinsic-size` to your elements? [See MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/contain-intrinsic-size) – Reyno Sep 18 '21 at 14:06
  • Can you provide some code with images so that problem can be replicated – Rana Sep 18 '21 at 14:23

1 Answers1

0

Here I have depicted images with cards you can give heading to your images about the scene they are about and let user search through each heading . You can also hide (not remove) so that search can be done in the back through headings .
Used comments in the code

document.getElementById("search").addEventListener("input", searchDeviceFunc);

function searchDeviceFunc() {
  let wordFound = false;//Initial values and will be true when word found
  var deviceCardHeadHTML = document.getElementsByClassName("deviceCardHead")
  
  //loop through each heading text
  for (let i = 0; i < deviceCardHeadHTML.length; i++) {
    var deviceCardHeadText = deviceCardHeadHTML[i].textContent
    //value is taken from input
    var searchBarValue = document.getElementById("search").value;
    var searchBarValueNeutral = searchBarValue.toLowerCase();
    //if search is not empty run this 
    if (searchBarValue != '') {
    //Used regEx to replace search words and match them
      deviceCardHeadHTML[i].innerHTML = deviceCardHeadText.replace(new RegExp(searchBarValue, 'gi'), (match) => `<span class="highlight">${match}</span>`);
      if (deviceCardHeadHTML[i].textContent.toLowerCase().indexOf(searchBarValueNeutral) > -1) {
        wordFound = true;//Word is found using index property
        deviceCardHeadHTML[i].parentElement.style.display = "block";
      } else {
        deviceCardHeadHTML[i].parentElement.style.display = "none";
      }
    } else {
      deviceCardHeadHTML[i].innerHTML = deviceCardHeadText;
      deviceCardHeadHTML[i].parentElement.style.display = "block";
    }
  }
}
.highlight {
  background: yellow;
}


/*.deviceCardFlex1 {
  display: flex;
  justify-content: center;
}*/

.deviceCardFlex {
  display: flex;
  flex-wrap: wrap;
  padding-left: auto;
  padding-right: auto;
  justify-content: flex-start;
}

.deviceCard {
  position: relative;
  /* float: left; */
  width: 300px;
  height: 300px;
  margin: 2% 2%;
  padding: 0 1% 1%;
  border: 2px solid rgb(126, 126, 126);
  border-radius: 5px;
  background-color: white;
  transition: 0.3s;
}
<div id="devicesBtnData">
  <div class="searchDevice">
    <span class="searchDeviceBtn">Search Device</span>
    <input id="search" type="search" placeholder="Try it">
    <br>
  </div>

  <!--<div class="deviceCardFlex1">-->
  <div class="deviceCardFlex">
    <div class="deviceCard">
      <h3 class="deviceCardHead">Laptop Pro</h3>
      <!--Contains image Here-->
    </div>
    <div class="deviceCard">
      <h3 class="deviceCardHead">Lenova Yoga </h3>
      <!--Contains image Here-->
    </div>
    <div class="deviceCard">
      <h3 class="deviceCardHead">Yatch</h3>
      <!--Contains image Here-->
    </div>
    <div class="deviceCard">
      <h3 class="deviceCardHead">Aeroplane</h3>
      <!--Contains image Here-->
    </div>
    <div class="deviceCard">
      <h3 class="deviceCardHead">Lenova Yoga Laptop Pro</h3>
      <!--Contains image Here-->
    </div>
    <div class="deviceCard">
      <h3 class="deviceCardHead">Vistara</h3>
      <!--Contains image Here-->
    </div>
    <div class="deviceCard">
      <h3 class="deviceCardHead">Quwait Airliner</h3>
      <!--Contains image Here-->
    </div>
  </div>
  <!--</div>-->
Rana
  • 2,500
  • 2
  • 7
  • 28