0

I try to sort Images by landscape/portrait format therefor I first select all images on the page with the selectFunction() then I sort them with the function "hochquer" which triggers further actions.

my Problem: One image shows up with a width and height of 0 in console.log() even though it is properly displayed on my page and has a actual width and height. If I reload the Page for a second time it works perfectly fine and I get a width and height for this Image.

can anyone help me with this?

//Screenshot of the console added
function selectFunction() {
  img = document.querySelectorAll(".img");
  let imgSelector = Array.from(img);

  if (imgSelector % 2 != 0) {
    imgSelector.push("even'er");
  }
  return imgSelector;
}

function hochquer(callback) {
    for (let i = 0; i < selectFunction().length; i++) {
      console.log(selectFunction()[i]);
      let Width = selectFunction()[i].naturalWidth;
      console.log(Width, "w");
      let Height = selectFunction()[i].naturalHeight;
      console.log(Height, "h");
      let Ratio = Width / Height;

      if (Ratio >= 1) {
        //quer
        querFormat.push(selectFunction()[i]);
      } else {
        querFormat.push(undefined);
      }
      if (Ratio < 1) {
        //hoch
        hochFormat.push(selectFunction()[i]);
      } else {
        hochFormat.push(undefined);
      }
    }
    callback();
  }

Update:

  1. Screenshot of the console: [1]: https://i.stack.imgur.com/Jr6P8.png

  2. some more code I use which I think addresses what @54ka mentioned

  function newImg() {
    let createImg = [];
    let imgSrc = [];
    const imgContainer = document.querySelector(".gallery");

    for (let i = 0; i < Gallery.length; i++) {
      createImg.push(new Image());
      imgSrc.push(Pfad + Gallery[i]);
      createImg[i].setAttribute("src", imgSrc[i]);
      createImg[i].setAttribute("class", "Img");
      imgContainer.appendChild(createImg[i]);

      function checkImage(path) {
        return new Promise((resolve) => {
          createImg[i].onload = () => resolve({ path, status: "ok" });
          createImg[i].onerror = () => resolve({ path, status: "error" });
        });
      }
      loadImg = function (...path) {
        return Promise.all(path.map(checkImage));
      };
    }

    loadImg(imgSrc).then(function (result) {
      console.log(result);
      hochquer(sort);
    });
  }
  newImg();
  • Can you show us the UI and console, say in a screenshot? – Link Nov 10 '20 at 11:53
  • The reason is that when you first load, you take a size from a picture that has not yet been loaded. In the refresh browser, it lays it down and manages to show it before the script passes. To resolve this issue, add an "onload Event" such as: or try this link: [Javascript - execute after all images have loaded](https://stackoverflow.com/questions/11071314/javascript-execute-after-all-images-have-loaded) – 54ka Nov 10 '20 at 12:29
  • 1
    thank you for your quick replies. I added a screenshot and updated the code + showed a new sample of it wich I think that it already fixes the problem @54ka mentiones. – Moritz Valentin Nov 10 '20 at 14:16
  • @Link done_____ – Moritz Valentin Nov 10 '20 at 14:42
  • Please see my answer, it is not the solution to your problem, but I need you to run the code from my answer and let me know if the width and height are still being displayed incorrectly. – Link Nov 10 '20 at 14:54
  • `createImg[i].onerror = () => resolve({ path, status: "error" });` Here, this should be reject shouldn't it? Like so: `createImg[i].onerror = () => reject({ path, status: "error" });` – Link Nov 13 '20 at 10:44

2 Answers2

0

Edit: I have made the following changes basing on your comment below after executing previous code.

I'm now adding the event listeners to all images in imgLoadCallback( ) and created a callback function containing code from hochquer( ) function. Please try to run this code.

    const imgLoadCallback = function(){
  for (let i = 0; i < selectFunction().length; i++) {
    console.log(selectFunction()[i]);
    let Width = selectFunction()[i].naturalWidth;
    console.log(Width, 'w');
    let Height = selectFunction()[i].naturalHeight;
    console.log(Height, 'h');
    let Ratio = Width / Height;

    if (Ratio >= 1) {
      //quer
      querFormat.push(selectFunction()[i]);
    } else {
      querFormat.push(undefined);
    }
    if (Ratio < 1) {
      //hoch
      hochFormat.push(selectFunction()[i]);
    } else {
      hochFormat.push(undefined);
    }
  }
}

function selectFunction() {
  img = document.querySelectorAll(".img");
  img.forEach(i => i.addEventListener('load', imgLoadCallback))
  let imgSelector = Array.from(img);

  if (imgSelector % 2 != 0) {
    imgSelector.push("even'er");
  }
  return imgSelector;
}

function hochquer(callback) {
  imgLoadCallback();
  callback();
}

From before edit:

Like @54ka has mentioned in the comments, it is possible that the image does not load immediately, usually stuff like loading images from src etc happen in the WEB API Environment asynchronously while execution , in order to not block the primary execution thread. Remainder of your code is synchronous, including console.log( )s that you are performing in order to log the width and height to the console, so those happen pretty much immediately as soon as that particular line of code is reached.

Therefore, what I have done in the below code is basically add an event handler for each of the image tags and only when the image has completed 'load' the below code inside the handler will be executed (this is where we are printing the width and height to console now). Now, this callback function that I have added will only execute after image loads. So, with this, it will most likely print the correct width and height to console. But I cannot be sure until we run it at your end because you are calling a callback at the very end.

Link
  • 1,198
  • 4
  • 14
  • the callback I run at the end sorts the Images on the page. I ran your event listener but the debugger prints me the the following error: "TypeError: selectFunction()[i].addEventListener is not a function". In my console I get an other error: "Uncaught (in promise) TypeError: selectFunction()[i].addEventListener is not a function". Screenshot of the console: [1]: https://i.stack.imgur.com/oToJh.png – Moritz Valentin Nov 10 '20 at 15:26
  • Can you please try and run this updated code? Please read 'Edit:' section from my answer for the details about the changes I've made. – Link Nov 10 '20 at 15:38
  • I really appreciate your help. I tried the edited code and it doesnt solve my problem. Still all the images but one are loading properly. is there anything else that could cause such behavior? – Moritz Valentin Nov 11 '20 at 11:20
  • No sorry, this is all I can come up with from the code that is available for me to see. But, I probably would be able to help better if I had the actual source code. – Link Nov 11 '20 at 11:22
  • actually this is almost all of my code. The only difference is that there are some variables defined at the top. And all the js I postet but the select function is wrapped into a main function. I did some more troubleshooting and found out that the one picture which won't load is the largest of them - -. One more question for now I showed a function which creates the images in my initial question. I tried to solve the problem with the to late loading images in this function with promises. Is this code valid and does it provide what it should? – Moritz Valentin Nov 13 '20 at 10:42
0

It was about a delay in the loading of the picture I fixed it with a new approach by using the onload event and code from the link @54ka provided.

comment of @54ka:

The reason is that when you first load, you take a size from a picture that has not yet been loaded. In the refresh browser, it lays it down and manages to show it before the script passes. To resolve this issue, add an "onload Event" such as: <body onload="myFunction()"> or try this link: Javascript - execute after all images have loaded

Dharman
  • 30,962
  • 25
  • 85
  • 135