Random page button

Hi,

I’m very new to JS and am currently learning the language for the sole purpose of adding a random page button to my website. It looks pretty close to the tutorial I was looking at, but still will not work for some reason. Any ideas why? This is what I have so far:

const pages = [
"https://benitengu.neocities.org/",
"https://benitengu.neocities.org/about",
"https://benitengu.neocities.org/virtualpets.html",
"https://benitengu.neocities.org/bestiary.html",
"https://benitengu.neocities.org/shrimp.html",
"https://benitengu.neocities.org/links.html",
"https://benitengu.neocities.org/coding.html",
"https://benitengu.neocities.org/hoard.html",
"https://benitengu.neocities.org/curios.html",
"https://benitengu.neocities.org/reading.html",
"https://benitengu.neocities.org/misc.html",
"https://benitengu.neocities.org/hellenicpaganism.html",
"https://benitengu.neocities.org/heathenry.html",
"https://benitengu.neocities.org/kemeticism.html",
"https://benitengu.neocities.org/baltic.html",
"https://benitengu.neocities.org/updates.html",
"https://benitengu.neocities.org/now.html",
"https://benitengu.neocities.org/shrines.html",
"https://benitengu.neocities.org/fanlistings.html",
"https://benitengu.neocities.org/shrines/nidai/",
"https://benitengu.neocities.org/shrines/tsumugi/",
"https://benitengu.neocities.org/shrines/madara/",
"https://benitengu.neocities.org/coding.html",
"https://benitengu.neocities.org/collections.html",
"https://benitengu.neocities.org/collections/boloties.html",
"https://benitengu.neocities.org/collections/civildefense.html",
"https://benitengu.neocities.org/collections/plushietags.html",
"https://benitengu.neocities.org/collections/cameras.html",
"https://benitengu.neocities.org/collections/newvegas.html"
];

if (url.contains("reading", "tcg", "nidai", "tsumugi", "madara", "coding"));
 add ("target=_blank");

document.getElementById("randomLinkBtn").addEventListener("click", () => {
  const randomIndex = Math.floor(Math.random() * pages.length);
  const randomPage = pages[randomIndex];
  window.location.href = randomPage;
});

if you delete this bit;

if (url.contains("reading", "tcg", "nidai", "tsumugi", "madara", "coding"));
 add ("target=_blank");

it should work. it did when i tested in codepen anyway; it gave an error for this bit. i think the code doesn’t understand what “url” means here so it just breaks.

Looks like the problem was that you were creating a list called “pages” but querying an undefined object called “url”. If you put that if back in, but modify it to this instead, it should work:

const pages = [
"https://benitengu.neocities.org/",
"https://benitengu.neocities.org/about",
"https://benitengu.neocities.org/virtualpets.html",
"https://benitengu.neocities.org/bestiary.html",
"https://benitengu.neocities.org/shrimp.html",
"https://benitengu.neocities.org/links.html",
"https://benitengu.neocities.org/coding.html",
"https://benitengu.neocities.org/hoard.html",
"https://benitengu.neocities.org/curios.html",
"https://benitengu.neocities.org/reading.html",
"https://benitengu.neocities.org/misc.html",
"https://benitengu.neocities.org/hellenicpaganism.html",
"https://benitengu.neocities.org/heathenry.html",
"https://benitengu.neocities.org/kemeticism.html",
"https://benitengu.neocities.org/baltic.html",
"https://benitengu.neocities.org/updates.html",
"https://benitengu.neocities.org/now.html",
"https://benitengu.neocities.org/shrines.html",
"https://benitengu.neocities.org/fanlistings.html",
"https://benitengu.neocities.org/shrines/nidai/",
"https://benitengu.neocities.org/shrines/tsumugi/",
"https://benitengu.neocities.org/shrines/madara/",
"https://benitengu.neocities.org/coding.html",
"https://benitengu.neocities.org/collections.html",
"https://benitengu.neocities.org/collections/boloties.html",
"https://benitengu.neocities.org/collections/civildefense.html",
"https://benitengu.neocities.org/collections/plushietags.html",
"https://benitengu.neocities.org/collections/cameras.html",
"https://benitengu.neocities.org/collections/newvegas.html"
];

if (pages.contains("reading", "tcg", "nidai", "tsumugi", "madara", "coding")) {
  add ("target=_blank");
}

document.getElementById("randomLinkBtn").addEventListener("click", () => {
  const randomIndex = Math.floor(Math.random() * pages.length);
  const randomPage = pages[randomIndex];
  window.location.href = randomPage;
});

That makes sense – I realized that it must not be reflected when I click because of my site being a frameset one. Would that be something I can make happen with targetframe?

So with frameset in mind, I think this is correct, but it’s still not working for some reason.

const pages = [
"https://benitengu.neocities.org/",
"https://benitengu.neocities.org/about",
"https://benitengu.neocities.org/virtualpets.html",
"https://benitengu.neocities.org/bestiary.html",
"https://benitengu.neocities.org/shrimp.html",
"https://benitengu.neocities.org/links.html",
"https://benitengu.neocities.org/coding.html",
"https://benitengu.neocities.org/hoard.html",
"https://benitengu.neocities.org/curios.html",
"https://benitengu.neocities.org/reading.html",
"https://benitengu.neocities.org/misc.html",
"https://benitengu.neocities.org/hellenicpaganism.html",
"https://benitengu.neocities.org/heathenry.html",
"https://benitengu.neocities.org/kemeticism.html",
"https://benitengu.neocities.org/baltic.html",
"https://benitengu.neocities.org/updates.html",
"https://benitengu.neocities.org/now.html",
"https://benitengu.neocities.org/shrines.html",
"https://benitengu.neocities.org/fanlistings.html",
"https://benitengu.neocities.org/shrines/nidai/",
"https://benitengu.neocities.org/shrines/tsumugi/",
"https://benitengu.neocities.org/shrines/madara/",
"https://benitengu.neocities.org/coding.html",
"https://benitengu.neocities.org/collections.html",
"https://benitengu.neocities.org/collections/boloties.html",
"https://benitengu.neocities.org/collections/civildefense.html",
"https://benitengu.neocities.org/collections/plushietags.html",
"https://benitengu.neocities.org/collections/cameras.html",
"https://benitengu.neocities.org/collections/newvegas.html"
];

if (pages.contains("reading", "tcg", "nidai", "tsumugi", "madara", "coding")) {
  add ("target=_blank");
}

document.getElementById("randomLinkBtn").addEventListener("click", () => {
  const randomIndex = Math.floor(Math.random() * pages.length);
  const randomPage = pages[randomIndex];
  window.top.frames['frameset2'].location.href = 'randomPage';
});

Sorry, it’s a little more complicated than that. This might work better for you:

const pages = [
  "https://benitengu.neocities.org/",
  "https://benitengu.neocities.org/about",
  "https://benitengu.neocities.org/virtualpets.html",
  "https://benitengu.neocities.org/bestiary.html",
  "https://benitengu.neocities.org/shrimp.html",
  "https://benitengu.neocities.org/links.html",
  "https://benitengu.neocities.org/coding.html",
  "https://benitengu.neocities.org/hoard.html",
  "https://benitengu.neocities.org/curios.html",
  "https://benitengu.neocities.org/reading.html",
  "https://benitengu.neocities.org/misc.html",
  "https://benitengu.neocities.org/hellenicpaganism.html",
  "https://benitengu.neocities.org/heathenry.html",
  "https://benitengu.neocities.org/kemeticism.html",
  "https://benitengu.neocities.org/baltic.html",
  "https://benitengu.neocities.org/updates.html",
  "https://benitengu.neocities.org/now.html",
  "https://benitengu.neocities.org/shrines.html",
  "https://benitengu.neocities.org/fanlistings.html",
  "https://benitengu.neocities.org/shrines/nidai/",
  "https://benitengu.neocities.org/shrines/tsumugi/",
  "https://benitengu.neocities.org/shrines/madara/",
  "https://benitengu.neocities.org/coding.html",
  "https://benitengu.neocities.org/collections.html",
  "https://benitengu.neocities.org/collections/boloties.html",
  "https://benitengu.neocities.org/collections/civildefense.html",
  "https://benitengu.neocities.org/collections/plushietags.html",
  "https://benitengu.neocities.org/collections/cameras.html",
  "https://benitengu.neocities.org/collections/newvegas.html"
];

// 1. Define target keywords
const keywords = ["reading", "tcg", "nidai", "tsumugi", "madara", "coding"];

// 2. Loop through every URL in the list
pages.forEach(url => {
  
  // 3. Check if the current URL contains ANY of the keywords
  const hasMatch = keywords.some(keyword => url.includes(keyword));
  
  if (hasMatch) {
    // 4. Find the matching <a> element on the live webpage
    const linkElement = document.querySelector(`a[href="${url}"]`);
    
    // 5. If the link exists on the page, apply the attributes safely
    if (linkElement) {
      linkElement.setAttribute('target', '_blank');
      linkElement.setAttribute('rel', 'noopener noreferrer');
      console.log(`Updated link: ${url}`); // Optional tracking line
    }
  }
});

What you have to do first is loop through each URL to test them individually. Then you can use keywords.some() to check if a URL has one or more of your keywords. From there, you can find every <a> element whose href attribute contains that URL, set target to _blank, and also set rel to noopener noreferrer for better security.

Ohhhhh, thank you so much! Good catch on the security front, I forgot to consider that.

I know I marked this as a solution because I got excited, but it doesn’t seem to be working even with a hard refresh?

Well, shit. If you hit F12 and open the inspector, does it show any errors?

I think this might be the only relevant error (assuming I’m looking in the right place).
image

Let me get back to you on this. Is everything current on your Neocities site? If so, I can do some direct digging.

@benitengu, I think I understand the problem now:

Because const pages appears to have been declared outside a function, it is globally scoped and thus conflicting with a const pages declared elsewhere (and not necessarily on your site.

I figure you have two options:

  1. Wrap random.js inside a function.
  2. Rename your const pages to something much more likely to be unique like const benitenguInternalUrlsList.

The latter is probably a more straightforward fix, but could still bite you if you declare that const elsewhere without scoping it to a function.

So that would be like this?

const benitenguInternalUrlsList = [
  "https://benitengu.neocities.org/",
  "https://benitengu.neocities.org/about",
  "https://benitengu.neocities.org/virtualpets.html",
  "https://benitengu.neocities.org/bestiary.html",
  "https://benitengu.neocities.org/shrimp.html",
  "https://benitengu.neocities.org/links.html",
  "https://benitengu.neocities.org/coding.html",
  "https://benitengu.neocities.org/hoard.html",
  "https://benitengu.neocities.org/curios.html",
  "https://benitengu.neocities.org/reading.html",
  "https://benitengu.neocities.org/misc.html",
  "https://benitengu.neocities.org/hellenicpaganism.html",
  "https://benitengu.neocities.org/heathenry.html",
  "https://benitengu.neocities.org/kemeticism.html",
  "https://benitengu.neocities.org/baltic.html",
  "https://benitengu.neocities.org/updates.html",
  "https://benitengu.neocities.org/now.html",
  "https://benitengu.neocities.org/shrines.html",
  "https://benitengu.neocities.org/fanlistings.html",
  "https://benitengu.neocities.org/shrines/nidai/",
  "https://benitengu.neocities.org/shrines/tsumugi/",
  "https://benitengu.neocities.org/shrines/madara/",
  "https://benitengu.neocities.org/coding.html",
  "https://benitengu.neocities.org/collections.html",
  "https://benitengu.neocities.org/collections/boloties.html",
  "https://benitengu.neocities.org/collections/civildefense.html",
  "https://benitengu.neocities.org/collections/plushietags.html",
  "https://benitengu.neocities.org/collections/cameras.html",
  "https://benitengu.neocities.org/collections/newvegas.html"
];

const keywords = ["reading", "tcg", "nidai", "tsumugi", "madara", "coding"];

benitenguInternalUrlsList.forEach(url => {
  

  const hasMatch = keywords.some(keyword => url.includes(keyword));
  
  if (hasMatch) {

    const linkElement = document.querySelector(`a[href="${url}"]`);
    
   
    if (linkElement) {
      linkElement.setAttribute('target', '_blank');
      linkElement.setAttribute('rel', 'noopener noreferrer');
      console.log(`Updated link: ${url}`); // Optional tracking line
    }
  }

That’s exactly what I had in mind. You might still want to wrap this whole thing inside an event listener that fires once the page has loaded.

window.addEventListener('load', (event) => {
// contents of random.js go here.
});

This should eliminate the scoping issue entirely, while still giving you a more meaningful variable name should you revisit this code in a few months.

(Sorry this took so long; I only use JS at my day job and I was a bit out of practice.)

Thank you so much! I was wondering what kind of wrapper would be appropriate and feel a bit in over my head with JS lol. Definitely still a beginner on that.

It still appears not to be working – do I need to re add window.top.frames['frameset2'].location.href ? Or something similar maybe?

The best answer I can give you is “try it and see what happens”. I don’t use frames or framesets at my day job, so I honestly don’t know off the top of my head.

I would like to provide some help. I inspected your website and the conversation here and I think there was a misunderstanding. The code starbreaker provided serves a different purpose than what you initially wanted, right now the code does the following:

  1. It iterates through your link list
  2. Only if it finds a keyword from your keyword list you provided it does the following:
    1. It searches in the document for a link with the given url (It won’t find any, because your link list includes domain names, but in your nav.html you provided links without them)
    2. If it finds a link it updates the properties to open it in another tab (Which you already did on some of your links)

I think you wanted something completely different:

  1. Get a random link from your link list
  2. If it contains a keyword from your keyword list the url should open in a new tab
  3. If not, the url should open in the “main” frame

Is that correct? If so I can help you set up the script for this solution. I found out how to open a link in a specific frame (Your main frame in this example code):
document.getElementById('main').contentWindow.location.href = 'url goes here';

I also tested how to open a new tab for specific links, but that requires the use of window.open(), which some browsers block for privacy and security reasons (Zen did that for me for example).

Let me know if I understood it correctly and if you need help.

One thing I realized, since you’re using frames: Your navigation lives in another document than the frame set and your script is executed in that navigation document. My example code to open a URL in the “main” frame won’t work, because there is no element with the id “main” in your nav.html. But it should work like this:
window.top.document.getElementById(‘main’).contentWindow.location.href = 'url goes here';
This way you are referencing the top window document where the frame set lives.

I can’t test it though, you would need to try it and see if that works.

This is correct. Should I put window.top.document.getElementById(‘frameset2’).contentWindow.location.href = 'benitenguInternalUrlsList'; at the end?

No, there are two problems:

The id “frameset2” is where your navigation lives, but when you want to click the button the content needs to show in your main frame, which has the id “main”.

If you set the location to 'benitenguInternalUrlsList', it will open a URL with the value benitenguInternalUrlsList, but you want a random URL from your array, which is set to the variable with the name benitenguInternalUrlsList.

This code should do the trick:

window.addEventListener('load', (event) => {
    // Some logging to debug if something goes wrong
    console.log('Initialize random page button...');

    const benitenguInternalUrlsList = [
        "https://benitengu.neocities.org/",
        "https://benitengu.neocities.org/about",
        "https://benitengu.neocities.org/virtualpets.html",
        "https://benitengu.neocities.org/bestiary.html",
        "https://benitengu.neocities.org/shrimp.html",
        "https://benitengu.neocities.org/links.html",
        "https://benitengu.neocities.org/coding.html",
        "https://benitengu.neocities.org/hoard.html",
        "https://benitengu.neocities.org/curios.html",
        "https://benitengu.neocities.org/reading.html",
        "https://benitengu.neocities.org/misc.html",
        "https://benitengu.neocities.org/hellenicpaganism.html",
        "https://benitengu.neocities.org/heathenry.html",
        "https://benitengu.neocities.org/kemeticism.html",
        "https://benitengu.neocities.org/baltic.html",
        "https://benitengu.neocities.org/updates.html",
        "https://benitengu.neocities.org/now.html",
        "https://benitengu.neocities.org/shrines.html",
        "https://benitengu.neocities.org/fanlistings.html",
        "https://benitengu.neocities.org/shrines/nidai/",
        "https://benitengu.neocities.org/shrines/tsumugi/",
        "https://benitengu.neocities.org/shrines/madara/",
        "https://benitengu.neocities.org/coding.html",
        "https://benitengu.neocities.org/collections.html",
        "https://benitengu.neocities.org/collections/boloties.html",
        "https://benitengu.neocities.org/collections/civildefense.html",
        "https://benitengu.neocities.org/collections/plushietags.html",
        "https://benitengu.neocities.org/collections/cameras.html",
        "https://benitengu.neocities.org/collections/newvegas.html"
    ];

    // 1. Define keywords for new window targets
    const keywords = ["reading", "tcg", "nidai", "tsumugi", "madara", "coding"];

    document.getElementById("randomLinkBtn").addEventListener("click", () => {
        console.log('Random page button clicked!');

        // Select a random url from the pages array
        const randomIndex = Math.floor(Math.random() * benitenguInternalUrlsList.length);
        const randomPage = benitenguInternalUrlsList[randomIndex];
        console.log('Selected random page: ' + randomPage);

        if (keywords.some((keyword) => randomPage.includes(keyword))) {
            // If a keyword was found in the random page, it will open in a new window
            // Keep in mind that browser might block the window.open call
            console.log('Opening random page in new window.');
            window.open(randomPage, '_blank');
        } else {
            // Otherwise it will open the page in the main content frame
            console.log('Opening random page in main content frame');
            window.top.document.getElementById('main').contentWindow.location.href = randomPage;
        }
    });
});

I added debug messages, since I can’t test the code on my end. Please let me know if it works or not. You can also ask questions about the code, if you want to understand what is going on.

As I mentioned in my other post, the pages which should open in a new window/tab will probably not work, since browser block these calls.