Artifacts Gallery Guilds Search Wiki Login Register

Welcome, Guest. Please login or register. - Thinking of joining?
September 09, 2026 - @801.49
Activity rating: Four Stars Posts & Arts: 72/1k.beats Random | Recent Posts | Guild Recents
News: :seal: Thank you for today! :seal: Guild Events: weekly zine theme 11: tools

+  MelonLand Forum
|-+  Life & The Web
| |-+  ✁ ∙ Web Crafting
| | |-+  "Image of the Day" JavaScript


« previous next »
Pages: [1] Print Embed
Author Topic: "Image of the Day" JavaScript  (Read 30 times)
Dan Q
Hero Member ⚓︎
*****
View Profile WWWArt


I have no idea what I am doing
⛺︎ My Room
RSS: RSS

Guild Memberships:
Artifacts:
Dan Q Cruisin'I DIDN'T meet Dan Q on Melonland!Visited on Melon's 10th Anniversary!
« on: Today at @744.64 » Embed

I recently saw RG-Mage's "Image Per Day Of The Month" (thanks @EdgyRabbid for sharing!) and thought "that's cool... but I think we can do better!". So I've come up with a version of it that's better in the following ways:

1. It doesn't require exactly 31 images (you can use as many or few as you like!)
2. It doesn't "skip" images during short months (RG-Mage's won't show images 29, 30 or 31 in February for example).
3. You can have as many image-of-the-day images on a page as you like.
4. The images are a list, rather than numbered-files-of-the-same-format, which is more-flexible.

Let's go make it! As usual, I'll just "write as I code", so you can follow-along with my thought process.

HTML

My thinking with the HTML is that it should add an image that is initially-hidden (so that if the JavaScript doesn't run or fails for any reason, that shouldn't result in a "broken" image being displayed). Alternatively, it could display a static image: if you prefer that, remove the "hidden" and add a "src" instead.

It'll need a class so our JS can find it.

And it should contain the list of URLs that it'll cycle through on a daily basis. Either absolute (https://...) or relative (/...) URLs should work. I'm thinking I'll put these into a generic data- attribute, as a list of URLs with "whitespace" (spaces or new lines) between them and separate it out in the JS, for best-readability. That gives me:


Code
<img hidden class="img-of-the-day"
     data-images="
       https://placehold.co/300x300/orange/white?text=Image+1
       https://placehold.co/300x300/blue/white?text=Image+2
       https://placehold.co/300x300/maroon/white?text=Image+3
       https://placehold.co/300x300/rebeccapurple/white?text=Image+4
       https://placehold.co/300x300/gray/black?text=Image+5
     ">

Note that I'm using five images from a placeholder-image website! You should use your own!

JavaScript

Now I can write my JavaScript. Here's how it'll work:

1. It'll be wrapped in an IIFE function, so that any variables I use don't interfere with any other JavaScripts on the website.
2. It will count the number of days since the Unix epoch (1 January 1970). At time of writing, today is day 20,705, tomorrow will be 20,706, the day after will be 20,707, and so on.
3. It will loop through every "img-of-the-day" (this means that there can be multiple image-of-the-days on a page, and they can each have their own image list!).
4. It'll take that data-images="... ... ..." list and split it up based on whitespace to get the possible URLs for the image.
5. It'll do a fun bit of maths called a modulus (which in JavaScript is represented by a percent sign). Modulus basically means "remainder". We want to take the number of days since the epoch (e.g. 20,705) and divide it by the number of images (e.g. 5, in my case), then take the remainder. The remainder will always be a number between 0 and 4 (one less than the number of images), and will "cycle" through those values each day (0 > 1 > 2 > 3 > 4 > 0).
6. Finally, it'll find the image at that "position" in the list (0 through 4), update the <img src> to match it, and un-hide the image if applicable.

Here's my (annotated for your convenience) JavaScript. This bit must be later in your page than any of the images it affects: I'd suggest putting it right before your </body>! Alternatively, you can move it into a .js file.


Code
<script>
  (function(){
    /* Get the number of days since 1 Jan 1970 */
    const daysSinceEpoch = Math.floor(Date.now() / (1000 * 60 * 60 * 24));
  
    /* For each .img-of-the-day image: */
    for(const img of document.querySelectorAll('.img-of-the-day')) {
      /* Get its list of images by splitting the data-images list on any whitespace */
      const urls = img.dataset.images.trim().split(/\s+/);
      /* Note: trim() gets rid of whitespace at the start and end, .split(/\s+/) breaks up the rest on whitespace! */
      
      /* Choose the URL corresponding to the current "day", looped forever: */
      const todaysUrl = urls[ daysSinceEpoch % urls.length ];
      
      /* Update the image to use today's URL and un-hide it: */
      img.src = todaysUrl;
      img.hidden = false;
    }
  })();
</script>

Demo

You can see it working for yourself on this Everyone Page.

Hopefully all the code makes sense and it's useful to you... or inspires you to come up with your own ideas! How about a quote of the day? Link of the day? Blog post of the day? The sky's the limit!


Logged

https://danq.me/_q26t/badges/dan-q-88x31-lighter.gif https://danq.me/_q26t/badges/dan-q-88x31-peekaboo-scroller.gif https://beige-buttons.danq.dev/beige-buttons-88x31.gif https://embed-html.danq.dev/embed-html-88x31.gif

Artifact Swap: PolyamorousI met Dan Q on Melonland!Joined 2025!
Dan Q
Hero Member ⚓︎
*****
View Profile WWWArt


I have no idea what I am doing
⛺︎ My Room
RSS: RSS

Guild Memberships:
Artifacts:
Dan Q Cruisin'I DIDN'T meet Dan Q on Melonland!Visited on Melon's 10th Anniversary!
« Reply #1 on: Today at @757.88 » Embed

Just for funsies, here's a "link of the day" script based on the same principle. This one uses "new line" in the data-links attribute to separate links, and then whitespace within the line to separate the link destination from the link text. And it shows "...loading..." while it picks a link, rather than hiding the link. Otherwise it's just the same thing again. Wanna see?

Code
<p>
  Link of the day:
  <a class="link-of-the-day"
     data-links="
       https://danq.me/                Dan Q
       https://forum.melonland.net/    Melonland Forum
       http://endless.horse/           Endless Horse
       https://bubbles.town/           Bubbles Town!
     ">...loading...</a>
</p>

<script>
  (function(){
    /* Get the number of days since 1 Jan 1970 */
    const daysSinceEpoch = Math.floor(Date.now() / (1000 * 60 * 60 * 24));
  
    /* For each .link-of-the-day link: */
    for(const a of document.querySelectorAll('.link-of-the-day')) {
      /* Get its list of links by splitting the data-links list on 1+ "new lines": */
      const links = a.dataset.links.trim().split(/[\r\n]+/);
      
      /* Choose the link corresponding to the current "day", looped forever: */
      const todaysLink = links[ daysSinceEpoch % links.length ];
      
      /* Split the selected link into exactly TWO parts based on whitespace (URL and text): */
      const linkParts = todaysLink.trim().split(/\s+(.+)/);
      
      console.log(todaysLink.trim());
      
      /* Update the link to use today's URL and text: */
      a.href = linkParts[0];
      a.innerText = linkParts[1];
    }
  })();
</script>

Again, you can try it "for real" on an Everyone Page.

Logged

https://danq.me/_q26t/badges/dan-q-88x31-lighter.gif https://danq.me/_q26t/badges/dan-q-88x31-peekaboo-scroller.gif https://beige-buttons.danq.dev/beige-buttons-88x31.gif https://embed-html.danq.dev/embed-html-88x31.gif

Artifact Swap: PolyamorousI met Dan Q on Melonland!Joined 2025!
Dan Q
Hero Member ⚓︎
*****
View Profile WWWArt


I have no idea what I am doing
⛺︎ My Room
RSS: RSS

Guild Memberships:
Artifacts:
Dan Q Cruisin'I DIDN'T meet Dan Q on Melonland!Visited on Melon's 10th Anniversary!
« Reply #2 on: Today at @779.18 » Embed

Okay... one more example on almost the same principle... a general-purpose "thing of the day"! Write any HTML elements you like into a parent element. Give the parent element a special class. And the script will select the child element "of the day", cycling through them all. It can be used for links, or images... or even iframes, videos, audio, paragraphs, articles, whatever you like!

Because they're all pre-loaded it'll select pretty-much instantly. And it "tidies up" the DOM by deleting the ones it doesn't select. But you'll still want to be careful not to make your HTML file too enormous with this one:


Code
<div hidden class="thing-of-the-day">
  <!-- thing 1: -->
  <p>
    <strong>This is the first thing!</strong> It's just a paragraph of text.
  </p>
  
  <!-- thing 2: -->
  <div>
    <figure>
      <img src="//placehold.co/240x120?text=My+Image" alt="Sample image">
      <figcaption>What a nice image!</figcaption>
    </figure>
    <p>
      I hope you liked my image!
    </p>
  </div>
  
  <!-- thing 3: -->
  <article>
    <h2>My favourite kinds of pie</h2>
    <ul>
      <li><a href="https://en.wikipedia.org/wiki/Butter_pie">Butter pie</a></li>
      <li>Chicken and mushroom pie</li>
      <li>Lemon meringue pie</li>
      <li>&pi;</li>
    </ul>
  </article>
</div>

<script>
  (function(){
    /* Get the number of days since 1 Jan 1970 */
    const daysSinceEpoch = Math.floor(Date.now() / (1000 * 60 * 60 * 24));
  
    /* For each .thing-of-the-day block: */
    for(const thingCollection of document.querySelectorAll('.thing-of-the-day')) {
      /* Get its list of things (its children): */
      const things = thingCollection.children;
      
      /* Choose the thing corresponding to the current "day", looped forever: */
      const todaysThing = things[ daysSinceEpoch % things.length ];
      
      /* Remove all OTHER things from the collection; note we need to use
       * Array.from(thingCollection.children) rather than just thingCollection.children
       * or it breaks, because thingCollection.children will CHANGE mid-loop when
       * we .remove() things! */
      for(const thingToMaybeRemove of Array.from(thingCollection.children)) {
        /* If the thing we're looking for isn't TODAY'S thing, remove it! */
        if (thingToMaybeRemove !== todaysThing) thingToMaybeRemove.remove();
      }
      
      /* Unhide the thing collection: */
      thingCollection.hidden = false;
    }
  })();
</script>

Yet again, there's an Everyone Page that demonstrates this nice, generic solution.

Logged

https://danq.me/_q26t/badges/dan-q-88x31-lighter.gif https://danq.me/_q26t/badges/dan-q-88x31-peekaboo-scroller.gif https://beige-buttons.danq.dev/beige-buttons-88x31.gif https://embed-html.danq.dev/embed-html-88x31.gif

Artifact Swap: PolyamorousI met Dan Q on Melonland!Joined 2025!
Pages: [1] Print Embed 
« previous next »
 

Melonking.Net © Always and ever was! SMF 2.0.19 | SMF © 2021 | Privacy Notice | Send Feedback | Supporters ♥ Forum Guide | Rules | RSS | WAP | Mobile


MelonLand Badges and Other Melon Sites!

MelonLand Project! Visit the MelonLand Forum! Support the Forum
Visit Melonking.Net! Visit the Gif Gallery! Pixel Sea TamaNOTchi
@000 Melon
Land
Editor Recent Edits Tenement Arcade Random Link Land → Forum Art Hub Chat Webring Want to Login or Join ? Web Craft Guide Graphic Catalogue Wiki Newsletters Image Stream Zap!
Minecraft: Online
Join: craft.melonking.net