Dynamically load all images from folder/subfolders with JavaScript

Viewed 630

I have an /img directory on my Github Pages website. There are about 50 images in /img and sub folders that I want to display in a grid on a page. I have no interest in typing out the following 50 times for each image...

  <a href="...">
     <img alt=".." src="img/...">
  </a>

... especially since I will be adding and removing images over time.

How do dynamically create the HTML code with JavaScript? I obviously can't use PHP since this is Github Pages.

I have already tried AJAX and requirejs but couldn't get anything to work.

1 Answers

You can do this by using Github Actions

In your repository add a new file update-image-list.yml under path .github/workflows/ (you may need to create the folders)

Put this code into the file:

name: Update Image List
on:
  push
jobs:
  updateImageList: # you can put any name here
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2 # Checkout repo
      - shell: bash
        run: ls -Rpm1 ./img/ > images.txt # Saving file list into a file
      - name: Save changes
        uses: actions-go/push@v1 # pushing the changes to the repo
        with:
          force: true
          commit-files: images.txt
          commit-message: Updating image list

Now, every time you push something to your repo this script will be executed saving an up-to-date list of the image files into images.txt file using ls command line and then pushing the file to the repo. The content will be something like:

images.txt

./img/:
image1.jpg
child-folder/
image2.png
image3.jpg

./img/child-folder:
image4.jpg

Now that you have the list of image files into images.txt, you just have to get the file to the frontend side and process its content

Something like this works:

In your HTML:

<div class="images" id="images"></div>

<script>
function loadImages() {
    const xhttp = new XMLHttpRequest();

    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            const fileList = this.responseText.split('\n'); // Split by lines
            let currentFolder = '';

            const filePaths = fileList
                .map(f => { // Build correct path for each file
                    let filePath = '';

                    if (f) {
                        if (f[0] === '.') {
                            currentFolder = f.replace('.', '').replace(':', '/');
                        }
                        else if (f[f.length - 1] !== '/') {
                            filePath = `${location.href}${currentFolder}${f}`;
                        }
                    }
          
                    return filePath;
                })
                .filter(f => f); // Remove empty lines
      
            const imagesContainer = document.getElementById('images');
      
            filePaths.map(f => { // Create and put images to the DOM
                const img = document.createElement('IMG');
                img.src = f;
                imagesContainer.appendChild(img);
            });
        }
    };

    xhttp.open("GET", "images.txt", true);
    xhttp.send();
}

loadImages();
</script>

But of course you can use any library/framework to do the same

Related