Brandi Maxam
Brandi Maxam

Reputation: 41

Creating nested divs using javascript

I've successfully created a div using javascript and it's filled with data gathered from an API. I'd like to take part of that data (all the innerHTML text from Episode, SeasonxEpisode, etc.) and place it into a containing div so I can isolate it for css styling.

Here is my code as it is, with everything in the same parent. There is also an image pulled from the API displaying in the episodeDiv, but it is not included in this code snippet because it's not part of the issue.

<script>
let savedResponse;

function clickSeason (seasonNum) {

    const currentSeason = savedResponse['season'+ seasonNum];

    $("#episode-list").html("");

    currentSeason.forEach(function(episode){
        const episodeDiv = document.createElement('div');
        $(episodeDiv).addClass("episodeStyle");

        episodeDiv.innerHTML = 
            "Episode: " + episode.title + '<br />' + '<br />' + 
            "SeasonxEpisode: " + episode.episode + '<br />' + 
            "Original Airdate: " + episode.airdate + '<br />'  + 
            " Stardate: " + episode.stardate + '<br />' + 
            episode.summary;

        $('#episode-list').append(episodeDiv);
</script>

You may see the full project here: http://idesn3535-flamingo.surge.sh/Final/index.html

And the full code is here: https://github.com/bmaxdesign/idesn3535-flamingo/blob/master/Final/index.html

I tried several versions of:

const episodeData = document.createElement('p');
                $(episodeData).addClass("episodeDataStyle");

episodeData.innerHTML = 
                    "Episode: " + episode.title + '<br />' + '<br />' + 
                    "SeasonxEpisode: " + episode.episode + '<br />' + 
                    "Original Airdate: " + episode.airdate + '<br />'  + 
                    " Stardate: " + episode.stardate + '<br />' + 
                    episode.summary;

$("episodeData").appendChild(episodeDiv);

I want the parent node to be the episodeDiv, and then I want to nest episodeData as a child with a separate id to style in css. Unfortunately what I have above actually makes the whole episodeDiv not even show, which I think means there is some error in how I've appended. I think I have some labeling confusion or syntax errors, or all of the above. I'm trying to avoid leaving an empty element in my HTML page, but I'd also be confused with that approach and how to place the text in the empty div. I'm clearly not understanding DOM manipulation yet.

Please make sure your responses include a why and how, and any keywords or links that I could use to better understand this in general. Teach a man to fish, etc. Thank you so much!!

Upvotes: 3

Views: 3380

Answers (4)

posit labs
posit labs

Reputation: 9471

I like to use template literals and Array.map to achieve what you want to do. There are many ways to skin a cat, but this is pretty compact and readable.

// map the episode objects into strings of html
var episodeHTMLArray = currentSeason.map(episode => {
    return `
        <div class='episode'>
            Episode: ${episode.title} <br /> <br />
            SeasonxEpisode: ${episode.episode} <br />
            Original Airdate: ${episode.airdate} <br />
            Stardate: ${episode.stardate}<br />
            ${episode.summary}
        </div>
    `
})

// join the array of html into a plain string
$('#episode-list').html(episodeHTMLArray.join(''))

Template literals are backticks instead of quotes, and they can render any variable in the current scope by using the syntax ${varName}.

Also, I think I should point out that $("episodeData") is looking for an element that looks like <episodeData></episodeData>. Careful with your selectors.

Upvotes: 2

Zorak
Zorak

Reputation: 709

Well, I write you little bit different code here, I like making DOM elements manually more than programatically and I prefer jQuery syntax - and as you are using jquery, it should not be a problem:

        function clickSeason (seasonNum) {

                    const currentSeason = savedResponse['season'+ seasonNum];
                /*empty (remove everything from) the epsiode list div*/
                    $("#episode-list").empty();
            /*declare empty !string! variable for loop, where we can store all the 
            generated divs - this div has to be declared above the FOR loop,
            as we dont want to overwrite it each loop, 
            we want to add something to it each loop*/        
            var ep = "";
            /*loop through current season array/JSON*/
                    for(var i = 0; i<currentSeason.epsiode.length; i++){
                    /*every loop, we add this structure to ep variable*/
                   /*generate div id by variables, in this example, the id will be for
                   first season second episode like ep1-2*/
                      ep+= "<div id='ep"+seasonNum+"-"i+"' class='episodeStyle'>";
                      ep+= "Episode: " + currentSeason.episode[i].title + "<br /><br />"; 
                      ep+= "SeasonxEpisode: " + currentSeason.episode[i].episode + "<br />"; 
                      ep+= "Original Airdate: " + currentSeason.episode[i].airdate + "<br />";
                      ep+= " Stardate: " + currentSeason.episode[i].stardate + "<br />"; 
                      ep+= currentSeason.episode[i].summary;
                      ep+= "</div>";

                    }
            /*loop ended, you can now add it to any other dom element you like*/
                        $('#episode-list').append(ep);
                 }

now a little bit of theory: $('#myElementID').append(something); appends (puts as last child) to an exact element with that ID. $('.myElementCLASS').append(something); appends (puts as last child) to ALL elements that have given class. $('div').append(something); appends (puts as last child) to ALL DIVs in DOM

you can also combine it with variables like

var elem="myElementID";

$("#"+elem+"1").append(something); will append to #myElementID1

Upvotes: 1

Omar Yafer
Omar Yafer

Reputation: 863

In the code below I will show a manner in which I might actually do it. Hope it helps since it is very barebones compared to what oyu want to accomplish

$(document).ready(function() {


  function clickSeason() {

    /*Lets say this is the data you received form your API*/
    let season1 = [{
      title: 'Episode 1',
      episode: 1
    }, {
      title: 'Episode 2',
      episode: 2
    }, {
      title: 'Episode 3',
      episode: 3
    }];


    let seasonSelector = $("#season");
    //This will Help you select the place where you 
    //are going to load your episodes

    let divHolder;
    let mainContent;

    //We iterate through each element in our object array
    season1.forEach(function(episode) {
      //With jquery you can create a div like this. 
      //You also get the jQuery object for that new div. 
      //With this object you can manipulate your new div even further
      divHolder = $("<div class='episode'></div>");
      //You can append data directrly to the div
      divHolder.append("<h4>" + episode.title + "</h4>");
      divHolder.append("<h5>Episode:" + episode.episode + "</h5>");

      //You could create new containers and still be able to manipulate the.
      mainContent = $("<p class='Content'></p>");

      //It could be less performant, but I prefer 
      //appending in sections instead of all in strings.
      mainContent.append("Original Airdate: " + episode.airdate + '<br /><br />');
      mainContent.append("Stardate: " + episode.stardate + '<br /><br />');
      mainContent.append(episode.summary);

      //We append our mainContent div to the divholder
      divHolder.append(mainContent);
      //We append our divHolder to the Season
      seasonSelector.append(divHolder);
    });
  }

  clickSeason();

});
#season {
  border: 1px solid gray;
  padding: 10px;
}

.episode {
  border: 1px solid gray;
  min-width: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="season">
</div>

Upvotes: 0

metamorph_online
metamorph_online

Reputation: 204

if I had to make templating with jQuery I would probably do something like:

currentSeason.forEach(function(episode){

    let myHtml = '<div class="episodeStyle"> "Episode:" ' + episode.title + '<br />' + '<br />' + '"SeasonxEpisode: "' + episode.episode + '<br />' + '"Original Airdate: "' + episode.airdate + '<br />'  + '" Stardate: "' + episode.stardate + '<br />' + episode.summary + '</div>';

    myHtml.appendTo($('#episode-list'));
});

Upvotes: 0

Related Questions