Almost done making Portfolio page--need help with Javascript to give page a theme change selector

I am currently working on this project at the moment:
https://www.codecademy.com/journeys/front-end-engineer/paths/fecj-22-building-interactive-websites/tracks/fecj-22-html-portfolio-project-personal-portfolio-website/modules/wdcp-22-personal-portfolio-project-21965fcf-f975-4849-8103-ac20ba18e97d/kanban_projects/portfolio-website

I am in the Front End Engineering course right now. Have gone through big hurdles to get where I am now. Javascript, however, gives me a big headache and I just need to know how to do one little thing and was wondering if I could get help from someone about this.

So basically. I’ve made a page with all the required elements like h1, h2, h3, head, footer, etc. Contact Page, main page, and an “additional info” page of sorts. I am taking this project seriously and plan to use these project files I’m working on to make a real portfolio page that showcases my art portfolio as well as my coding portfolio.

Basically, all I need to do now is one thing and I am having a hard time figuring out how to do it:

I just want to be able to make the h1 element at the top of each page clickable and allow it to change between a “light” and a “dark” theme on the website.

What I want to do with the theme changer is actually quite simple. Upon clicking the h1 header element, I want to see this functionality:
Change the background image
change the element display boxes from white to black
change the text from black to white
style links from a greenish color to a yellow-ish “streetlamp”-esque color.
be able to change back and forth between that light and dark theme each time I click the h1 header element

How can I accomplish this?

Beyond that, curious if you all have any tips on how to gain an understanding of how Javascript works. I am having a hard time retaining the info I’ve learned about it and it’s been very frustrating to me. I do not feel confident that I would be able to make a javascript file for someone upon request and that worries me.

I apologize if I posted this in the wrong area, please let me know if so.

I find it ironic how a lot of the material in the course has been quite easy to me so far, especially using the terminal and using github because I have plenty of experience with that being a full-time GNU/Linux user since about 7 years ago, but Javascript has totally stopped me in my tracks. I may even go back and redo all of the Javascript lessons, because it’s just that hard for me. I apologize if I come off frustrated–it’s because I am! it’s my main concern right now, properly learning it and applying it to my work.

you might have a class for the body element, that has different CSS stuff for it than for regular links;
for example, for a class dark-mode, you might do something like this:

JavaScript:

/* when click h1, toggle dark-mode class for body element */
const h1 = document.querySelector("h1"); // get first h1 element
h1.onclick = function toggleDarkMode(event) {
  document.body.classList.toggle("dark-mode");
};

CSS:

body.dark-mode {
  color: white;
  background-color: black; 
}

/* yellow links */
body.dark-mode a {
  color: yellow;
}

that’s just a rough idea, and you’d be doing stuff for background-image rather than for background-color.

JavaScript takes some practice (and spending time looking stuff up) in order to learn, and it takes practice to learn how to use JavaScript in web pages too.

Hi Java9731188620,

Thanks for your response, it was helpful.
I don’t have a dark mode class yet in my files. How would I implement this without it interfering with the default styling that is already present? I should have clarified, I already styled the page as well. The default theme will be the light theme. I was actually wondering if I could use an event target from within my .js file to handle the whole thing, instead of adding it as an HTML class, adding it to CSS, etc. just seems like more work? There’s gotta be some kinda way to do that, right?

I did notice in the piano key lesson that is also in the Front End Engineer course that they were able to change the background color of the keys when pressed and change what keys pop up on screen based on clicks of the mouse, but of course, that is a bit different from what I’m trying to do. I guess my problem is I am having a hard time understanding the difference between a function and an event object. I don’t get why I can’t just put
let htmlElement1.style.backgroundImage.onclick = url(‘insert image file here’);
let htmlElement2.style.backgroundColor.onclick = black;
let htmlElement2.style.color = white;

and why it is that I must create a function, that works on an event, to do that? I guess that’s where I get confused with all of it.

For this code:

you can’t do let if the variable already exists from earlier.
And note that htmlElement2 and htmlElement2.style are different objects,
so while htmlElement2.onclick might work, htmlElement2.style.onclick would not work since the .onclick is only for HTML elements or other nodes or event targets.

Event handlers must be functions, and for .onclick that would be the function that you want to call/execute when that element is clicked on.
The event object is an argument the function is called on; the event object gets used as the parameter when the function is executed. The click event object contains information about the click; such as which element was clicked, which mouse button was used, whether the shift key was pressed down during the click, and so on.

(When an element is clicked, the function as the .onclick is called, if there is such a function, with a click event object as the argument of the function.)

 

You could change the style for each element using JavaScript only 


let inDarkMode = false;

const h1 = document.querySelector("h1"); // get first h1 element

h1.onclick = function toggleDarkMode(event) {

  inDarkMode = !inDarkMode; // switches between true and false
  const anchorElements = document.getElementsByTagName("a"); // get all links

  if (inDarkMode) {
    document.body.style.color = "white";
    document.body.style.backgroundColor = "black";
    anchorElements.forEach( 
      element => { element.style.color = "yellow"; }
    );
  }
  else {
    document.body.style.removeProperty("color");
    document.body.style.removeProperty("background-color");
    anchorElements.forEach( 
      element => { element.style.removeProperty("color"); }
    );
  }

};

would do similar stuff to the CSS and JavaScript in the previous post.

Hi again,

Thanks again for helping me. This is very close to what I wanted to do. However, I noticed a few things about it that do not work as intended:
The anchor links do not change color, and remain in their default #3E3B1C color after clicking.
My contact page, despite using an H1 element at the top like the rest of the pages on the “website”, does not change color.
Also, I tried implementing my background image by rewording document.body.style.backgroundColor as simply document.body.style.background and inputting

let inDarkMode = false;

const h1 = document.querySelector("h1"); // get first h1 element

h1.onclick = function toggleDarkMode(event) {

  inDarkMode = !inDarkMode; // switches between true and false
  const anchorElements = document.getElementsByTagName("a"); // get all links

  if (inDarkMode) {
    document.body.style.color = "white";
      document.body.style.background = "black url('La Costa de Sunny Isles desde el océano by K.B.L Luccia.jpg') no-repeat center top";
    anchorElements.forEach( 
      element => { element.style.color = "#BF8930"; }
    );
  }
  else {
    document.body.style.removeProperty("color");
      document.body.style.removeProperty("background");
    anchorElements.forEach( 
      element => { element.style.removeProperty("color"); }
    );
  }

};

type or paste code here

This ALMOST does the trick, but instead of changing the background image for the entire page, it just changes the background image for the text within the scope of my flex box. I want it to change the background image for the entire page, not the box, which I want to remain black (the first solution you provided did make the flex box turn black, but I was just trying to find a way to do both, changing the flex box to black, and the background image (which I mapped simply to “html” inside my CSS file) for the entire page. Any thoughts on this? And am wondering why your solution for changing the anchor text color to #BF8930 didn’t work.

So basically,
How can I get the background image for the entire page to change and then also keep the flex box black?
How can I change the color for the anchor links?
Why isn’t the theme change applying to my contact.html page? It’s header is tagged as h1 as well.

So many questions, so little time. but again, thanks for your help!

Okay, I am super close now!

I got the desired result, as pictured here

Except for I still have the two problems still remaining:
The contacts page is still not being styled upon clicking the H1 header
The anchor links still refuse to change their color after the style change.

So we’ve narrowed it down to that. Disregard my last post. Thank you again!

p.s. here is my code as of right now:

let inDarkMode = false;

const h1 = document.querySelector("h1"); // get first h1 element

h1.onclick = function toggleDarkMode(event) {

  inDarkMode = !inDarkMode; // switches between true and false
    const anchorElements = document.getElementsByTagName("a"); // get all links

  if (inDarkMode) {
    document.body.style.color = "white";
      document.body.style.backgroundColor = "black";
      document.querySelector('html').style.backgroundImage = "url('La Costa de Sunny Isles desde el océano by K.B.L Luccia.jpg')";
    anchorElements.forEach( 
      element => { element.style.color = "#BF8930"; }
    );
  }
  else {
    document.body.style.removeProperty("color");
      document.body.style.removeProperty("background");
      document.querySelector('html').style.removeProperty("background-image");
    anchorElements.forEach( 
      element => { element.style.removeProperty("color"); }
    );
  }

};

if you want to assign the event handler to all the h1 elements, then you could use a loop to add the event handler function to each element.

I forgot that an HTMLCollection doesn’t have a .forEach method. Sorry about that.

let inDarkMode = false;

function toggleDarkMode(event) {
  // body of function goes here
}

const h1s = document.querySelectorAll("h1"); // get all h1 elements
for (let element of h1s) {
  element.onclick = toggleDarkMode;
}

And,

    anchorElements.forEach( 
      element => { element.style.color = "#BF8930"; }
    );

should be

    for (let element of anchorElements) {
      element.style.color = "#BF8930"; 
    }

or something like that.

Similarly,

    anchorElements.forEach( 
      element => { element.style.removeProperty("color"); }
    );

should be

    for (let element of anchorElements) {
      element.style.removeProperty("color"); 
    }

or stuff that does the same thing.

(I used the browser’s console in “Developer Tools” to check if there were errors from the JavaScript for a sample page.)

1 Like

Hello again and thank you for walking me through this

This is the code that I have now thanks to your suggestions:

let inDarkMode = false;

const h1 = document.querySelector("h1"); // get h1 elements

h1.onclick = function toggleDarkMode(event) {

  inDarkMode = !inDarkMode; // switches between true and false
    const anchorElements = document.getElementsByTagName("a"); // get all links

  if (inDarkMode) {
    document.body.style.color = "white";
      document.body.style.backgroundColor = "black";
      document.querySelector("main").style.backgroundImage = "url('La Costa de Sunny Isles desde el océano by K.B.L Luccia.jpg')";
      document.querySelector("main").style.color = "#BF8930";
      document.querySelector("main").style.border = "4px solid #BF8930";
      document.querySelector("main").style.textShadow = "1px 1px #AD5315";
      document.querySelector("html").style.backgroundImage = "url('La Costa de Sunny Isles desde el océano by K.B.L Luccia.jpg')";
      for (let element of anchorElements) {
	  element.style.color = "#BF8930";
	  element.style.textShadow = "1px 1px black";
    }
  }
  else {
    document.body.style.removeProperty("color");
      document.body.style.removeProperty("background");
      document.querySelector("main").style.removeProperty("background-image");
      document.querySelector("main").style.removeProperty("text-shadow");
      document.querySelector("main").style.removeProperty("color");
      document.querySelector("main").style.removeProperty("border");
      document.querySelector("html").style.removeProperty("background-image");
    for (let element of anchorElements) {
	element.style.removeProperty("color");
	element.style.removeProperty("text-shadow");
    }
  }

};

I was able to get the contacts page to change (I simply didn’t link the script on the contact.html page previously).
However, and this must be some kinda simple thing I’m missing here–Now when I change to the dark theme on my other two pages of my website, it only changes the body text and body background color, and no longer is changing the background image or the anchor link styling. What am I doing wrong here?

Here is a snapshot of the fully functional contacts page styling changes. The code is the same as I posted above:

Hey, I solved my problem and I would love to share my solution with everyone. I would post the whole website directory but it includes a number of large files and I cannot upload it here. But anyways, here is how I was able to get a fully interactive theme changer to work on my page. It had everything to do with the order of which event handlers were being called first.

let inDarkMode = false;

const h1 = document.querySelector("h1"); // get h1 elements

h1.onclick = function toggleDarkMode(event) {

  inDarkMode = !inDarkMode; // switches between true and false
    const anchorElements = document.getElementsByTagName("a"); // get all links

  if (inDarkMode) {
    document.body.style.color = "white";
      document.body.style.backgroundColor = "black";
      document.querySelector("html").style.backgroundImage = "url('La Costa de Sunny Isles desde el océano by K.B.L Luccia.jpg')";
      for (let element of anchorElements) {
	  element.style.color = "#BF8930";
	  element.style.textShadow = "1px 1px black";
      }
        document.querySelector("main").style.background = "url('La Costa de Sunny Isles desde el océano by K.B.L Luccia.jpg') no-repeat fixed left top";
      document.querySelector("main").style.color = "#BF8930";
      document.querySelector("main").style.border = "4px solid #BF8930";
      document.querySelector("main").style.textShadow = "1px 1px #AD5315";
  }
  else {
    document.body.style.removeProperty("color");
      document.body.style.removeProperty("background");
      document.querySelector("html").style.removeProperty("background-image");
    for (let element of anchorElements) {
	element.style.removeProperty("color");
	element.style.removeProperty("text-shadow");
    }
       document.querySelector("main").style.removeProperty("background");
      document.querySelector("main").style.removeProperty("text-shadow");
      document.querySelector("main").style.removeProperty("color");
      document.querySelector("main").style.removeProperty("border");
  }

};


Sorry about that. I wasn’t thinking. Fixed.

1 Like

Hey all, I was wondering, how can I get my theme to persistently stay on the website? You all can take a look at it on github now if you want, right here https://github.com/skyroz/skyroz.github.io/tree/main but I’ve been messing around all night trying to get it to stick when I click to the next page. I tried adding an event listener and I even tried using a useState (which I found out in later lessons–thanks codecademy) but it still wouldn’t make my theme changer stay changed when I click to the next page or reload the page.

Really confused by this :face_with_spiral_eyes: I’ve earned my front end engineer certification now but little things like this still hold me back sometimes.

anyone have some advice on this issue I’m having?

It’s tricky to make things stick around when you’re changing webpages (or reloading a page) because then everything starts from scratch, unless you use cookies, or find a way to store the variable, like sessionStorage or localStorage, or you could store some info in the url with url search parameters.

session storage:

url search parameters:

Window: location property:

to read the url search params of the current page, you might do something like:

const search = window.location.search; // query string
const params = search ? URLSearchParams(search) : null;
const themeFromSeachParams = params ? params.get("theme") : null;

(You might use document instead of window.)

In order to put the theme (as a string) into the url as the only search parameter (and maybe reload the page),
you might do something like:

window.location.search = `?theme=${theme}`; // query string

and if you want to link to another page but keep the search parameters (that contain the theme), you might have something like:
instead of

<a href="./page2.html">link to page2</a>

use

<a href="javascript: './page2.html' + window.location.search;">link to page2</a>

(This can probably also by done using a submit button instead of an anchor element.)

Note that this is not considered best practice (especially using JavaScript in the href attribute).

I haven’t had a chance to actually test this stuff yet, so I don’t really know whether this stuff works.

Can you point us to resources that explain location and give express do’s and don’t’s, as well as what user agents/browsers that don’t properly support it, if at all? In the olden days, IE did not support .location, and I’m wondering if that is no longer the case for Edge (which I do not use)?