[New Problem!] Certain details don't show up right in my online CV

My current project is an online CV where all my credentials - jobs, qualifications, etc. - are printed out with JavaScript (mostly to prove my working JS skills to prospective employers).

I store all my details in objects and among their parameters stored (ie. job title, company, location, date, etc.) are arrays containing bullet points highlight my accomplishments or other important bits.

For example, here is my object constructor for my job entries and a sample object (not) storing records of my career

function Job(title,company,location,date,summary,details) {
  this.title = title;
  this.company = company;
  this.location = location;
  this.date = date;
  this.summary = summary;
  this.details = details;
}

const JOBS = [
  new Job(
    "Office Worker",
    "Some Company I work for",
    "Nowhere in Particular",
    "Never",
    "I am a job description",
    ["Highlighted feat at my job #1",
    "Highlighted feat at my job #2",
    "Highlighted feat at my job #3"]
  )
];

So far, I’m having trouble with this piece in my code.

for (let i=0; i<JOBS.length; i++) {
  const entry = document.createElement("div");
  entry.classList.add("entry");

  const jobContentNarrow = `
          <div class="col-narrow">
            <h3>${JOBS[i].title}</h3>
            <p class="uppercase">${JOBS[i].company}, ${JOBS[i].location}</p>
            <p>${JOBS[i].date}</p>
          </div>
          `;

  const jobContentWide = document.createElement("div");
  jobContentWide.classList.add("col-wide", "description");

  const jobSummary = document.createElement("p");
  jobSummary.innerHTML = `${JOBS[i].summary}`;
  jobContentWide.appendChild(jobSummary);

  const jobDetails = document.createElement("ul");
  for (let e; e<JOBS[i].details.length;e++) {
    const listItem = document.createElement("li");
    listItem.innerHTML = `${JOBS[i].details[e]}`;
    jobDetails.appendChild(listItem);
  };
  jobContentWide.appendChild(jobDetails);
  entry.innerHTML = jobContentNarrow + jobContentWide;

Now’s my current output in HTML when I test it on a web browser

<div class="entry">
     <div class="col-narrow">
         <h3>Digital Media Designer</h3>
         <p class="uppercase">Unit 12, Winchester</p>
         <p>October 2022 ~ Now</p>
     </div>

     // In place of what should be <div class="col-wide description">,
     // this code below happens
     [object HTMLDivElement]
</div>

So what’s the problem?
If you need any further information, I’d be happy to answer.

Thanks.

Oh sorry. You mean the entire for loop or my entire script file?

// Populate the Career section
for (let i=0; i<JOBS.length; i++) {
  const entry = document.createElement("div");
  entry.classList.add("entry");

  const jobContentNarrow = `
          <div class="col-narrow">
            <h3>${JOBS[i].title}</h3>
            <p class="uppercase">${JOBS[i].company}, ${JOBS[i].location}</p>
            <p>${JOBS[i].date}</p>
          </div>
          `;

  const jobContentWide = document.createElement("div");
  jobContentWide.classList.add("col-wide", "description");

  const jobSummary = document.createElement("p");
  jobSummary.innerHTML = `${JOBS[i].summary}`;
  jobContentWide.appendChild(jobSummary);

  const jobDetails = document.createElement("ul");
  for (let e; e<JOBS[i].details.length;e++) {
    const listItem = document.createElement("li");
    listItem.innerHTML = `${JOBS[i].details[e]}`;
    jobDetails.appendChild(listItem);
  };
  jobContentWide.appendChild(jobDetails);
  entry.innerHTML = jobContentNarrow + jobContentWide;
  careerSection.appendChild(entry);
};

Okay, here’s the full script file.

import SKILLS from "./database/skills.js";
import JOBS from "./database/career.js";
import SCHOOLS from "./database/education.js";
import HOBBIES from "./database/hobbies.js";

const body = document.querySelector("body");
const main = document.querySelector("main");
const header = document.querySelector("header");

const warning = document.getElementById("warning");
warning.classList.toggle("display");

// Create the Header
const greeting = {
  name: "James Arrow",
  photo: "media/image/portrait.png",
  alt: "Photo of James Arrow",
  title: "Multimedia + Web Designer",
  description: "Add your profile summary here. You can have several paragraphs or add links.",
  email: "meetme.jw_arrow@erine.email"
};

const profileHead = document.createElement("div");
profileHead.setAttribute("id", "top");
profileHead.classList.add("content-wrap", "clearfix");

const profileImg = document.createElement("img");
profileImg.classList.add("col-narrow");
profileImg.src = greeting.photo;
profileImg.alt = greeting.alt;

const profileBio = document.createElement("div");
profileBio.classList.add("col-wide");

const profileName = document.createElement("h1");
profileName.innerHTML = greeting.name;

const profileTitle = document.createElement("h2");
profileTitle.innerHTML = greeting.title;

const profileDesc = document.createElement("p");
profileDesc.innerHTML = greeting.description;

profileBio.appendChild(profileName);
profileBio.appendChild(profileTitle);
profileBio.appendChild(profileDesc);

profileHead.appendChild(profileImg);
profileHead.appendChild(profileBio);
header.appendChild(profileHead);

// Create the top navbar

// Perhaps I'll expand the array below into a collection of objects
// or arrays containin the links and their relevant details
// i.e. fontawesome icons, etc.

const navItems = ["Skills", "Career", "Education", "Hobbies", "Contact"];
const topNav = document.createElement("nav");
topNav.setAttribute("role", "navigation");
topNav.classList.add("nav-max");
const topNavList = document.createElement("ul");
topNavList.classList.add("navbar");

// Populate the navbar
for (let i = 0; i < navItems.length; i++) {
  let item = document.createElement("li");
  let itemLink = document.createElement("a");
  let itemIcon = document.createElement("i");
  let description;
  itemIcon.classList.add("fas");
  switch (true) {
    case navItems[i] === "Skills":
      itemLink.href = "#skills";
      itemIcon.classList.add("fa-star");
      description = "Skills";
      break;
    case navItems[i] === "Career":
      itemLink.href = "#career";
      itemIcon.classList.add("fa-briefcase");
      description = "Career";
      break;
    case navItems[i] === "Education":
      itemLink.href = "#education";
      itemIcon.classList.add("fa-graduation-cap");
      description = "Education";
      break;
    case navItems[i] === "Hobbies":
      itemLink.href = "#hobbies";
      itemIcon.classList.add("fa-heart");
      description = "Hobbies";
      break;
    case navItems[i] === "Contact":
      itemLink.href = "#contact";
      itemIcon.classList.add("fa-address-book");
      description = "Contact";
      break;
  }
  let itemText = document.createTextNode(description);
  itemLink.appendChild(itemIcon);
  itemLink.appendChild(itemText);
  item.appendChild(itemLink);
  topNavList.append(item);
}
// Append the links to the top navbar
topNav.appendChild(topNavList);
main.appendChild(topNav);

// Create the Skills section
const skillsSection = document.createElement("section");
skillsSection.setAttribute("id", "skills");
skillsSection.classList.add("content-wrap", "clearfix");

const skillsHeading = document.createElement("h2");
skillsHeading.innerHTML = `<i class="fas fa-star"></i>Skills`;
skillsSection.appendChild(skillsHeading);
main.appendChild(skillsSection);

// Populate the Skills section
for (let i=0; i<SKILLS.length; i++) {
  const entry = document.createElement("div");
  entry.classList.add("entry");

  const skillType = document.createElement("div");
  skillType.classList.add("col-skill");
  skillType.innerHTML = `<h3><i class=${SKILLS[i].icon}></i> ${SKILLS[i].title}</h3>`;

  for (let e=0; e<SKILLS[i].skills.length;e++) {

  }

  entry.appendChild(skillType);
  skillsSection.appendChild(entry);
};

// Create the Career section
const careerSection = document.createElement("section");
careerSection.setAttribute("id", "career");
careerSection.classList.add("content-wrap", "clearfix");

const careerHeading = document.createElement("h2");
careerHeading.innerHTML = `<i class="fas fa-briefcase"></i>Career`;
careerSection.appendChild(careerHeading);
main.appendChild(careerSection);

// Populate the Career section
for (let i=0; i<JOBS.length; i++) {
  const entry = document.createElement("div");
  entry.classList.add("entry");

  const jobContentNarrow = `
          <div class="col-narrow">
            <h3>${JOBS[i].title}</h3>
            <p class="uppercase">${JOBS[i].company}, ${JOBS[i].location}</p>
            <p>${JOBS[i].date}</p>
          </div>
          `;

  const jobContentWide = document.createElement("div");
  jobContentWide.classList.add("col-wide", "description");

  const jobSummary = document.createElement("p");
  jobSummary.innerHTML = `${JOBS[i].summary}`;
  jobContentWide.appendChild(jobSummary);

  const jobDetails = document.createElement("ul");
  for (let e; e<JOBS[i].details.length;e++) {
    const listItem = document.createElement("li");
    listItem.innerHTML = `${JOBS[i].details[e]}`;
    jobDetails.appendChild(listItem);
  };
  jobContentWide.appendChild(jobDetails);
  entry.innerHTML = jobContentNarrow + jobContentWide;

  // const jobContent = `
  //         <div class="col-narrow">
  //           <h3>${JOBS[i].title}</h3>
  //           <p class="uppercase">${JOBS[i].company}, ${JOBS[i].location}</p>
  //           <p>${JOBS[i].date}</p>
  //         </div>
  //         <div class="col-wide description">
  //           <p>${JOBS[i].summary}</p>
  //           <ul>
  //             <li>${JOBS[i].details[0]}</li>
  //             <li>${JOBS[i].details[1]}</li>
  //             <li>${JOBS[i].details[2]}</li>
  //           </ul>
  //         </div>
  //         `;

  // entry.innerHTML = jobContent;
  careerSection.appendChild(entry);
};


// Create the Education section
const educateSection = document.createElement("section");
educateSection.setAttribute("id", "education");
educateSection.classList.add("content-wrap", "clearfix");

const educateHeading = document.createElement("h2");
educateHeading.innerHTML = `<i class="fas fa-graduation-cap"></i>Education`;
educateSection.appendChild(educateHeading);
main.appendChild(educateSection);

// Populate the Education section
for (let i=0; i<SCHOOLS.length; i++) {
  const entry = document.createElement("div");
  entry.classList.add("entry");

  const schoolContent = `
          <div class="col-narrow">
            <h3>${SCHOOLS[i].location}</h3>
          </div>
          <div class="col-wide description">
          <p class="uppercase">${SCHOOLS[i].course}, ${SCHOOLS[i].date}</p>
          <p>${SCHOOLS[i].degree}, ${SCHOOLS[i].qualification}</p>
          </div>
          `;

  entry.innerHTML = schoolContent;
  educateSection.appendChild(entry);
};

// Create the Hobbies section
const hobbySection = document.createElement("section");
hobbySection.setAttribute("id", "hobbies");
hobbySection.classList.add("content-wrap", "clearfix");

const hobbyHeading = document.createElement("h2");
hobbyHeading.innerHTML = `<i class="fas fa-heart"></i>Hobbies`;
hobbySection.appendChild(hobbyHeading);
main.appendChild(hobbySection);

// Create the bottom navbar
const bottomNav = document.createElement("nav");
bottomNav.setAttribute("role", "navigation");
bottomNav.classList.add("nav-min");
const bottomNavList = document.createElement("ul");
bottomNavList.classList.add("navbar");

// Populate the navbar
for (let i = 0; i < navItems.length; i++) {
  let item = document.createElement("li");
  let itemLink = document.createElement("a");
  let itemIcon = document.createElement("i");
  itemIcon.setAttribute("aria-hidden", true);
  let itemSpan = document.createElement("span");
  itemIcon.classList.add("fas");
  switch (true) {
    case navItems[i] === "Skills":
      itemLink.href = "#skills";
      itemIcon.classList.add("fa-star", "fa-2x");
      itemSpan.innerHTML = "Skills";
      break;
    case navItems[i] === "Career":
      itemLink.href = "#career";
      itemIcon.classList.add("fa-briefcase", "fa-2x");
      itemSpan.innerHTML = "Career";
      break;
    case navItems[i] === "Education":
      itemLink.href = "#education";
      itemIcon.classList.add("fa-graduation-cap", "fa-2x");
      itemSpan.innerHTML = "Education";
      break;
    case navItems[i] === "Hobbies":
      itemLink.href = "#hobbies";
      itemIcon.classList.add("fa-heart", "fa-2x");
      itemSpan.innerHTML = "Hobbies";
      break;
    case navItems[i] === "Contact":
      itemLink.href = "#contact";
      itemIcon.classList.add("fa-address-book", "fa-2x");
      itemSpan.innerHTML = "Contact";
      break;
  }
  itemSpan.classList.add("sr-only");
  itemLink.appendChild(itemIcon);
  itemLink.appendChild(itemSpan);
  item.appendChild(itemLink);
  bottomNavList.append(item);
}
// Append the links to the top navbar
bottomNav.appendChild(bottomNavList);
main.appendChild(bottomNav);


// Create the footer
const footer = document.createElement("footer");
footer.classList.add("content-wrap", "clearfix");
footer.setAttribute("role", "contact");
footer.setAttribute("id", "contact");

const footerTitle = document.createElement("h2");
footerTitle.innerHTML = `<i class="fas fa-paper-plane"></i>Let's Keep in Touch!`;

// An object full of objects or arrays containing my contact details
// and social media links
// const contactDetails = {
//   email
// }

const email = document.createElement("a");
email.href = `mailto:${greeting.email}`;
email.innerHTML = `<i class="fas fa-2x fa-envelope" aria-hidden="true"></i><span class="sr-only">Send an Email to James Arrow</span>`;

const year = new Date();
const copyright = document.createElement("p");
copyright.innerHTML = `&copy; ${year.getFullYear()} James Arrow`;

const backToTop = document.createElement("a");
backToTop.href = "#top";
backToTop.innerHTML = `<i class="fas fa-arrow-circle-up"></i>Back to Top`

footer.appendChild(footerTitle);
footer.appendChild(email);
footer.appendChild(copyright);
footer.appendChild(backToTop);
body.appendChild(footer);

And here’s the HTML output

<html lang="en">

<head>
  <script src="https://kit.fontawesome.com/6465a72a1f.js" crossorigin="anonymous"></script>

  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>James Arrow | Multimedia + Web Designer</title>
  <link rel="stylesheet" href="style.css">
  <script type="module" src="js/script.js" defer=""></script>
</head>

<body>
  <!--  Intro -->
  <header role="banner" class="content-wrap clearfix">
    <div id="warning" class="display">
      <h1>WARNING!</h1>
      <h2>You have JavaScript turned off!</h2>
      <p>Please turn it back on to view this website <br>
        Or visit the <a href="#">Non-JS version here</a><br><br>
        <em>Don't worry. I am definitely spying on you. ^^</em>
      </p>
    </div>
    <div id="top" class="content-wrap clearfix"><img class="col-narrow" src="media/image/portrait.png" alt="Photo of James Arrow">
      <div class="col-wide">
        <h1>James Arrow</h1>
        <h2>Multimedia + Web Designer</h2>
        <p>Add your profile summary here. You can have several paragraphs or add links.</p>
      </div>
    </div>
  </header>

  <main role="main">
    <nav role="navigation" class="nav-max">
      <ul class="navbar">
        <li><a href="#skills"><i class="fas fa-star"></i>Skills</a></li>
        <li><a href="#career"><i class="fas fa-briefcase"></i>Career</a></li>
        <li><a href="#education"><i class="fas fa-graduation-cap"></i>Education</a></li>
        <li><a href="#hobbies"><i class="fas fa-heart"></i>Hobbies</a></li>
        <li><a href="#contact"><i class="fas fa-address-book"></i>Contact</a></li>
      </ul>
    </nav>
    <section id="skills" class="content-wrap clearfix">
      <h2><i class="fas fa-star"></i>Skills</h2>
      <div class="entry">
        <div class="col-skill">
          <h3><i class="fa-solid" fa-computer=""></i> Operating Systems</h3>
        </div>
      </div>
      <div class="entry">
        <div class="col-skill">
          <h3><i class="fa-solid" fa-code=""></i> Coding</h3>
        </div>
      </div>
      <div class="entry">
        <div class="col-skill">
          <h3><i class="fa-solid" fa-palette=""></i> Graphic Design</h3>
        </div>
      </div>
      <div class="entry">
        <div class="col-skill">
          <h3><i class="fa-solid" fa-palette=""></i> Video Production</h3>
        </div>
      </div>
    </section>
    <section id="career" class="content-wrap clearfix">
      <h2><i class="fas fa-briefcase"></i>Career</h2>
      <div class="entry">
        <div class="col-narrow">
          <h3>Digital Media Designer</h3>
          <p class="uppercase">Unit 12, Winchester</p>
          <p>October 2022 ~ Now</p>
        </div>
        [object HTMLDivElement]
      </div>
    </section>
    <section id="education" class="content-wrap clearfix">
      <h2><i class="fas fa-graduation-cap"></i>Education</h2>
      <div class="entry">
        <div class="col-narrow">
          <h3>Portsmouth University</h3>
        </div>
        <div class="col-wide description">
          <p class="uppercase">MSc Digital Media, 2018</p>
          <p>Masters Degree, Merit</p>
        </div>
      </div>
      <div class="entry">
        <div class="col-narrow">
          <h3>Southampton Solent University</h3>
        </div>
        <div class="col-wide description">
          <p class="uppercase">BA (Hons) Animation, 2015</p>
          <p>Bachelor's Degree, 1st Class Honours</p>
        </div>
      </div>
    </section>
    <section id="hobbies" class="content-wrap clearfix">
      <h2><i class="fas fa-heart"></i>Hobbies</h2>
    </section>
    <nav role="navigation" class="nav-min">
      <ul class="navbar">
        <li><a href="#skills"><i aria-hidden="true" class="fas fa-star fa-2x"></i><span class="sr-only">Skills</span></a></li>
        <li><a href="#career"><i aria-hidden="true" class="fas fa-briefcase fa-2x"></i><span class="sr-only">Career</span></a></li>
        <li><a href="#education"><i aria-hidden="true" class="fas fa-graduation-cap fa-2x"></i><span class="sr-only">Education</span></a></li>
        <li><a href="#hobbies"><i aria-hidden="true" class="fas fa-heart fa-2x"></i><span class="sr-only">Hobbies</span></a></li>
        <li><a href="#contact"><i aria-hidden="true" class="fas fa-address-book fa-2x"></i><span class="sr-only">Contact</span></a></li>
      </ul>
    </nav>
  </main>
  <!-- Code injected by live-server -->
  <script type="text/javascript">
    // <![CDATA[  <-- For SVG support
    if ('WebSocket' in window) {
      (function() {
        function refreshCSS() {
          var sheets = [].slice.call(document.getElementsByTagName("link"));
          var head = document.getElementsByTagName("head")[0];
          for (var i = 0; i < sheets.length; ++i) {
            var elem = sheets[i];
            head.removeChild(elem);
            var rel = elem.rel;
            if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") {
              var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');
              elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());
            }
            head.appendChild(elem);
          }
        }
        var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
        var address = protocol + window.location.host + window.location.pathname + '/ws';
        var socket = new WebSocket(address);
        socket.onmessage = function(msg) {
          if (msg.data == 'reload') window.location.reload();
          else if (msg.data == 'refreshcss') refreshCSS();
        };
        console.log('Live reload enabled.');
      })();
    }
    // ]]>
  </script>


  <footer class="content-wrap clearfix" role="contact" id="contact">
    <h2><i class="fas fa-paper-plane"></i>Let's Keep in Touch!</h2><a href="mailto:meetme.jw_arrow@erine.email"><i class="fas fa-2x fa-envelope" aria-hidden="true"></i><span class="sr-only">Send an Email to James Arrow</span></a>
    <p>© 2022 James Arrow</p><a href="#top"><i class="fas fa-arrow-circle-up"></i>Back to Top</a>
  </footer>
</body>

</html>

I see.

Well, I changed

entry.innerHTML = jobContentNarrow + jobContentWide;

into

entry.appendChild(jobContentNarrow);
entry.appendChild(jobContentWide);

But now I find my career section empty and I got
this error message in the browser console

script.js:173 Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at script.js:173:9

So basically, when I use appendChild, I strictly use it to append elements
and innerHTML to concatenate strings?

Because each of the details arrays for my jobs may have different amounts of items I want to include so I made a for loop to add <li> elements for every one then add it to jobContentWide.

Hence

const jobDetails = document.createElement("ul");
  for (let e; e < JOBS[i].details.length; e++) {
    const listItem = document.createElement("li");
    listItem.innerHTML = `${JOBS[i].details[e]}`;
    jobDetails.appendChild(listItem);
  };
  jobContentWide.appendChild(jobDetails);

I can’t do that with a string literal by itself, can I?

However, even with this code I got the same problem I had before with
[object HTMLDivElement] showing up instead of proper HTML.

I beg your pardon?
How? You lost me.

I mean I get I can do this
const jobDetails = JOBS[i].details

But how do I put each of the array items into li elements with a template literal and not a for loop?

Good news. I just incorporated the changes you suggested and now everything’s showing properly.

Thanks.

Hey.

I just took a beginners course in JSON and began reworking my databases in JSON files. Unfortunately, the course didn’t tell me how I could import JSON data to Javascript so I had to look around and here’s what I did.

import JOBS from "./database/career.json" assert {type: "json"};
console.log(JOBS);

Unfortunately, when I tested it on my browser, I got this error message on the console.

Uncaught SyntaxError: import assertions are not currently supported

Any idea what the problem is?

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.