You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

185 lines
17 KiB

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My Learning Website</title>
<link href="/styles/styles.css" rel="stylesheet" type="text/css">
<link href="/webdevelopment/styles/styles.css" rel="stylesheet" type="text/css">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div>
<h1 class="courselink">JavaScript Essential Training</h1>
<h2 class="lecturer">LinkedIn Learning : Morten Rand-Hendriksen</h2>
<h2 class="episodetitle">Sidebar: String Output</h2>
</div>
<article>
<h2 class="sectiontitle">Mix Text and Variables with Template Literals</h2>
<p>Up to this point, the output we have seen has been sent to the console, but in reality, if we want a user to see the output, this is going to have to be displayed in an HTML document. With JavaScript, we can</p>
<pre class="inset">
&bull; generate HTML
&bull; modify existing HTML
&bull; remove existing HTML</pre>
<p>Generating HTML and adding it to a document is probably the most basic way of manipulating HTML in a browser, but we need to be able to access an existing element within the web document before we can do that. This is perhaps one of the reasons why we covered classes and objects so early in the course, because manipulating the document really means manipulating objects. These may be objects within the document, but it may also be the document itself which is an object.</p>
<p>You can verify the fact that the document is an object by going to the index.html page in the exercise files, opening up the console and typing</p>
<pre class="inset">document</pre>
<p>Press return and you eill see that the document object is returned and this contains the HTML form the current page (note that you may have to dig into it a little top find the HTML elements you can see in the HTML code and it seems to be a little easier to do this in Chrome than in Firefox. I did notice that these were much more obvious in the browser dev tools that Morten is using which are a couple of years older than mine but I opened the page in the Brave browser and this looked more like what Morten was seeing. This suggests that the Brave browser may be very useful when developing JavaScript if you need to injspect the HTML in the dev tools.</p>
<p>WE can access thie document via the Document Object Model which we will look at in the next chapter. For now, we just need to know that we can manipulate the HTML by using a template literal. Now, if we open up the files for this exercise in Visual Studio Code and access the live server, you will notice that this time, the HTML page is not blank. For reference, the HTML code is in <a href="codesamples/chapter4/sample1.html">sample1.html</a>. This is displaying the names of the properties of a backpack object, but not the values. These names are hard-coded into the HTML, we are not getting them from either the Backpack class or from a backpack object. We are going to also display the values, and we will need to get those from a backpack object.</p>
<p>As you can see, the properties are listed in an unoredered list and we can access elements of the document using dot notation.</p>
<p>Before we dive into that, let's see a quick and dirty example of how we can manipulate the HTML. In the console, type this.</p>
<pre class="inset">document.body.innerHTML</pre>
<p>As you might expect, this returns the HTML from within the &lt;body&gt; element. We can easily change this by assigning something else to the innerHTML like this.</p>
<pre class="inset">document.body.innerHTML = "Some text"</pre>
<p>This essentially erases all of the HTML and replaces it with the text, "Some text" so this is now all that is visible in our page, but bear in mind that we are only making this change in the browser, if we refresh the page the HTML coded into index.html appears again.</p>
<p>A template literal is similar to a string template you might see in other programming languages and it allows you to mix HTML, strings and JavaScript elements which we can assign to a DOM element i much the same way as we did with the string above.</p>
<p>To start with, we will copy and remove the HTML text from body in index.html. In our JavaScript file (script.js) we will create a constant value called content as follows.</p>
<pre class="inset">const content = ``;</pre>
<p>You will notice that I have used back ticks rather than single or double quotes and this tells the browser that anything between these back ticks is a template literal.</p>
<p>Next, we will paste the HTML code from body between these back ticks.</p>
<p>At this point, we can access the body and add the HTML back to it form the JavaScript file by adding the following line of code to script.js.</p>
<pre class="inset">document.body.innerHTML = content;</pre>
<p>If we refresh the page, we can see that it looks exactly as it did originally because we are using the same HTML as we did before, the only difference is that the JavaScript file is injecting the HTML into the page rather than it being coded in the HTML as it was previously.</p>
<p>To add JavaScrpt expression to this HTML, we need to add a placeholder. For example, the name of our backpack is Everyday Backpack and this had been coded into the HTML as a literal, but we want to replace it with the name property from our backpack object. At the moment, the line in the HTNL which displays the name looks like this.</p>
<pre class="inset">&lt;h1&gt;Everyday Backpack&lt;/h1&gt;</pre>
<p>The general syntax for a placholder is a dollar sign followed by a pair of curly braces containing the JavaScript expression so in this case, the line is going to be replaced with</p>
<pre class="inset">&lt;h1&gt;${everydayPack.name}&lt;/h1&gt;</pre>
<p>We can use a similar method to add values to the other properties, but this is slightly different because we don't want to replace the proerty name with the property value, we want to display both. Let's take the first property, which at the moment looks like this.</p>
<pre class="inset">&lt;li&gt;Volume: &lt;/li&gt;</pre>
<p>Rather than remove the text that is already there, we just want to put our placeholder after it like this.</p>
<pre class="inset">&lt;li&gt;Volume: ${everydayPack.volume}&lt;/li&gt;</pre>
<p>If we do this for all of the properties and then refresh the page, the properties are now displayed with those values as shown in the image below.</p>
<img src="codesamples/chapter4/images/backpack.png" alt="The backpack object displayed in our HTML page with the values from the backpack object">
<p>For reference, I have added both the amend version of the index.html file and the script.js file (minus the console.log statements) to the <a href="codesamples/chapter4/sample1.html" target="_blank">sample1.html</a> file.</p>
<p>Note that in the placeholders used in the template literal, we can put any valid JavaScript. In most cases, here, we are simply accessing the value of a property using simple dot notation but for the age, we are using the backpacks backpackAge function to generate the value that we are adding to the HTML.</p>
<p>So, template literals are a simple but quite powerful tool for generating HTML contnent and adding it to a document and you will see that they are used a lot in JavaScript.</p>
<h2 class="sectiontitle">Traditional String Output</h2>
<p>Template literals are very new and they replace a method for mixing text and JavaScript that just uses standar strings. It is a more conoluted method so you may never actually use it, but you may very well see it in older code so it is a good idea to be familiar with it.</p>
<p>Remember that the template literal was enclodes in a pair of back ticks which gives us a line such as</p>
<pre class="inset">const content = ` `;</pre>
<p>and later, we used this constant, content, to set the value for the body's innerHTML in our HTML document. This time, we will be using a standard string, so we will use double quotes instead of back ticks.</p>
<pre class="inset">const content = " ";</pre>
<p>Inside this string, we will put our HTML, much as we did before. Take the following example</p>
<pre class="inset">const content = "&lt;h1&gt;name goes here&lt;\h1&gt;";</pre>
<p>We can go ahead and open our live server and we will see the text, "name goes here", being displayed as an &lt;h1&gt; element. This is a string literal so it will take whatever is in the quotes, add that to the body in our HTML document and display that in the browser.</p>
<p>If we try to add some JavaScript as we did with our template literal, like this.</p>
<pre class="inset">const content = "<h1>${everdayPack.name}</h1>";</pre>
<p>We can see just by looking at the code in Visual Studio Code that this will not work. There is no autocompletion or suggestions and the whole string is a uniform colour. Strictly speaking, it will work perfectly well as a string literal, but it won't get the property value from the backpack object. If we run this, we will see the following.</p>
<img src="codesamples/chapter4/images/backpack1.png" alt="The output we see when we add our JavaScript property to a string literal">
<p>To make this work, we have to remember that we are working with a string literal so anything inside double quotes is going to be interpreted as literal text and will be displayed as is in our web page as we saw above. This means that we have to take our JavaScript out of the double quotes and add them to the string literal using string concatenation. For example, to get the name value from a backpack object and display it in an &lt;h1&gt; element, we would use something like this.</p>
<pre class="inset">const content = "&lt;h1&gt;" + everydayPack.name + "&lt;/h1&gt;";</pre>
<p>This gives the result shown below.</p>
<img src="codesamples/chapter4/images/backpack2.png" alt="The result of using string concatenation to build a string with our HTML">
<p>So what we are doing here is using string concatenation to build up a string containing our HTML code and as you may imagine, even with a simple example of an HTML page displaying the properties of a single backpack object, it would become messy and difficult to read quite quickly. It is hard to imagine a scenario where you would have to use this method, but clearly is using a template literal is an option, you would use that method.</p>
<p>However, since you may see this in older code, it may be worth considering how we would use this in practice in order to get a better idea of what you might see in older code.</p>
<p>Off the top of my head, I would say that there are three possible approaches. The first would be to do something similar to what we did with the string literal. For example, we might start out with just the HTML displaying the properties and where we previously then inserted our placeholders, we would insert the dot notation for accessing the value with a plus sign before and after it and the whole thing enclosed in double quotes. This last step may seem counter-intuitive but remember that we are inserting this inside a string that is already in double quotes so this will terminate the first string and start a new one. Consider the following example where the volume is being displayed. I am treating this as if it were the whole string to keep things simple.</p>
<pre class="inset">"&lt;li&gt;Volume: &lt;/li&gt;"</pre>
<p>Instead of a placeholder we would insert this.</p>
<pre class="inset">" + everydayPack.volume + "</pre>
<p>and this would give us</p>
<pre class="inset">"&lt;li&gt;Volume: " + everydayPack.volume + "&lt;/li&gt;"</pre>
<p>To take this a step further, we could express the entire block of HTML code as a single string like this.</p>
<pre class="inset">
const content = "
&lt;main&gt;
&lt;article&gt;
&lt;h1&gt;&lt;h1&gt;
&lt;ul&gt;
&lt;li&gt;Volume: &lt;li&gt;
&lt;li&gt;Color: &lt;/li&gt;
&lt;li&gt;Age: &lt;/li&gt;
&lt;li&gt;Number of pockets: &lt;/li&gt;
&lt;li&gt;Left strap length: &lt;/li&gt;
&lt;li&gt;Right strap length: &lt;/li&gt;
&lt;li&gt;Lid status: &lt;/li&gt;
&lt;/ul&gt;
&lt;/article&gt;
&lt;/main&gt;
";</pre>
<p>If we add all of the property values in the manner described above, we will get something like this.</p>
<pre class="inset">
const content = "
&lt;main&gt;
&lt;article&gt;
&lt;h1&gt;" + everydayPack.name + "&lt;h1&gt;
&lt;ul&gt;
&lt;li&gt;Volume: " + everydayPack.volume &lt;li&gt;
&lt;li&gt;Color: " + everydayPack.color + "&lt;/li&gt;
&lt;li&gt;Age: " + everydayPack.backpackAge() + "&lt;/li&gt;
&lt;li&gt;Number of pockets: " + everydayPack.pocketNum + "&lt;/li&gt;
&lt;li&gt;Left strap length: " + everydayPack.strapLength.left + "&lt;/li&gt;
&lt;li&gt;Right strap length: " + everydayPack.strapLength.right + "&lt;/li&gt;
&lt;li&gt;Lid status: " + everydayPack.lidOpen + "&lt;/li&gt;
&lt;/ul&gt;
&lt;/article&gt;
&lt;/main&gt;
";</pre>
<p>This isn't quite the whole story since Visual Studio Code seemed to have problems with the line feeds and so I had to condense everything into a single line to get it to work although adding line feeds in certain places seems to work. Actaully, prettifier rearranged my code to look like this.</p>
<pre class="inset">
const content =
"&lt;h1&gt;" +
everydayPack.name +
"&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;Volume: " +
everydayPack.volume +
"&lt;/li&gt;&lt;li&gt;Color: " +
everydayPack.color +
"&lt;/li&gt;&lt;li&gt;Age: " +
everydayPack.backpackAge() +
"&lt;/li&gt;&lt;li&gt;Number of pockets: " +
everydayPack.pocketNum +
"&lt;/li&gt;&lt;li&gt;Left strap length: " +
everydayPack.strapLength.left +
"&lt;/li&gt;&lt;li&gt;Right strap length: " +
everydayPack.strapLength.right +
"&lt;/li&gt;&lt;li&gt;Lid status: " +
everydayPack.lidOpen +
"&lt;/li&gt;&lt;/ul&gt;";</pre>
<p>Actually, this is probably about as readable as code like this could get and if you are starting out from scratch and building up your string a line at a time, laying it out like this may be the best approach.</p>
<p>The second approach I thought of is perhaps both more straight forward and more cumbersome. This would involve creating a variable called content and then adding the HTML a single element at a time. The result would look something like this.</p>
<pre class="inset">
content += "&lt;h1&gt;" + everydayPack.name;
+"&lt;/h1&gt;";
content += "&lt;ul&gt;";
content += "&lt;li&gt;Volume: " + everydayPack.volume + "&lt;/li&gt;";
content += "&lt;li&gt;Color: " + everydayPack.color + "&lt;/li&gt;";
content += "&lt;li&gt;Age: " + everydayPack.backpackAge() + "&lt;/li&gt;";
content += "&lt;li&gt;Number of pockets: " + everydayPack.pocketNum + "&lt;/li&gt;";
content += "&lt;li&gt;Left strap length: " + everydayPack.strapLength.left + "&lt;/li&gt;";
content +=
"&lt;li&gt;Right strap length: " + everydayPack.strapLength.right + "&lt;/li&gt;";
content += "&lt;li&gt;Lid status: " + everydayPack.lidOpen + "&lt;/li&gt;";
content += "&lt;/ul&gt;";</pre>
<p>Bear in mind the fact that we are modifying the value of content, so we can't create it as a constant.</p>
<p>Of these two approaches, I would suggest the first would work best if you already have a skeleton HTML file and you just want to add values into each line. The second approach would work best if you were building up your HTML from scratch.</p>
<p>I will only mention the third approach in passing since it involves a construct that we will look at later in the course and it is very similar to the second method but uses an array to store each line of the HTML. I'm not sure if there would be any benefits to that but it may help if you are adding several different sections of HTML to the document since you could add these as separate arrays. The key point here is how easy it is to add the array to the document. If it is a simple task, then this might be a useful method but hopefully we will get a clearer idea on this when we look at arrays in more detail.</p>
<p>The most impoortant thing to remember about building HTML with strings like this is that template literals were created to help solve some of the problems with the complexity and general messiness of this type of approach to generating HTML so you should always use template literals. However, it can be useful to think about how we would write our code if we didn't have template literals available because this may be helpful when looking at older code.</p>
</article>
<div class="btngroup">
<button class="button" onclick="window.location.href='objects.html';">
Previous Chapter - Objects
</button>
<button class="button" onclick="window.location.href='dom.html';">
Next Chapter - DOM
</button>
<button class="button" onclick="window.location.href='javascriptessentialtraining2021.html'">
Course Contents
</button>
<button class="button" onclick="window.location.href='/webdevelopment/webdevelopment.html'">
Web Development Page
</button>
<button class="button" onclick="window.location.href='/index.html'">
Home
</button>
</div>
</body>
</html>