{"id":18694,"date":"2016-10-18T10:00:00","date_gmt":"2016-10-18T14:00:00","guid":{"rendered":"https:\/\/alistapart.com\/article\/javascript-for-web-designers\/"},"modified":"2016-10-18T10:00:00","modified_gmt":"2016-10-18T14:00:00","slug":"javascript-for-web-designers","status":"publish","type":"article","link":"https:\/\/alistapart.com\/article\/javascript-for-web-designers\/","title":{"rendered":"JavaScript for Web Designers: DOM Scripting"},"content":{"rendered":"<p>Before we do anything with a page, you and I need to have a talk about something very important: the Document Object Model. There are two purposes to the DOM: providing JavaScript with a map of all the elements on our page, and providing us with a set of methods for accessing those elements, their attributes, and their contents.<\/p>\n<p>The \u201cobject\u201d part of Document Object Model should make a lot more sense now than it did the first time the DOM came up, though: the DOM is a representation of a web page in the form of an object, made up of properties that represent each of the document\u2019s child elements and subproperties representing each of those elements\u2019 child elements, and so on. It\u2019s objects all the way down.<\/p>\n<h2><code>window<\/code>: The Global Context<\/h2>\n<p>Everything we do with JavaScript falls within the scope of a single object: <code>window<\/code>. The <code>window<\/code> object represents, predictably enough, the entire browser window. It contains the entire DOM, as well as\u2014and this is the tricky part\u2014the whole of JavaScript.<\/p>\n<p>When we first talked about variable scope, we touched on the concept of there being \u201cglobal\u201d and \u201clocal\u201d scopes, meaning that a variable could be made available either to every part of our scripts or to their enclosing function alone.<\/p>\n<p>The <code>window<\/code> object <em>is<\/em> that global scope. All of the functions and methods built into JavaScript are built off of the <code>window<\/code> object. We don\u2019t have to reference <code>window<\/code> constantly, of course, or you would\u2019ve seen a lot of it before now\u2014since <code>window<\/code> is the global scope, JavaScript checks <code>window<\/code> for any variables we haven\u2019t defined ourselves. In fact, the <code>console<\/code> object that you\u2019ve hopefully come to know and love is a method of the <code>window<\/code> object:<\/p>\n<pre><code class=\"language-javascript\">window.console.log\nfunction log() { [native code] }<\/code><\/pre>\n<p>It\u2019s hard to visualize globally vs. locally scoped variables before knowing about <code>window<\/code>, but much easier after: when we introduce a variable to the global scope, we\u2019re making it a property of <code>window<\/code>\u2014and since we don\u2019t explicitly have to reference <code>window<\/code> whenever we\u2019re accessing one of its properties or methods, we can call that variable anywhere in our scripts by just using its identifier. When we access an identifier, what we\u2019re really doing is this:<\/p>\n<pre><code class=\"language-javascript\">function ourFunction() {\n    var localVar = \"I\u2019m local.\";\n    globalVar = \"I\u2019m global.\";\n\n    return \"I\u2019m global too!\";\n};<\/code>\n<samp>undefined<\/samp>\n\n<code class=\"language-javascript\">window.ourFunction();<\/code>\n<samp>I\u2019m global too!<\/samp>\n\n<code class=\"language-javascript\">window.localVar;<\/code>\n<samp>undefined<\/samp>\n\n<code class=\"language-javascript\">window.globalVar;<\/code>\n<samp>I\u2019m global.<\/samp><\/pre>\n<p>The DOM\u2019s entire representation of the page is a property of <code>window<\/code>: specifically, <code>window.document<\/code>. Just entering <code>window.document<\/code> in your developer console will return all of the markup on the current page in one enormous string, which isn\u2019t particularly useful\u2014but everything on the page can be accessed as subproperties of <code>window.document<\/code> the exact same way. Remember that we don\u2019t need to specify <code>window<\/code> in order to access its <code>document<\/code> property\u2014<code>window<\/code> is the only game in town, after all.<\/p>\n<pre>\n<code class=\"language-javascript\">document.head\n<samp>&lt;head&gt;...&lt;&sol;head&gt;<\/samp>\n\ndocument.body\n<samp>&lt;body&gt;...&lt;&sol;body&gt;<\/samp><\/code><\/pre>\n<p>Those two properties are themselves objects that contain properties that are objects, and so on down the chain. (\u201cEverything is an object, kinda.\u201d)<\/p>\n<h2>Using the DOM<\/h2>\n<p>The objects in <code>window.document<\/code> make up JavaScript\u2019s map of the document, but it isn\u2019t terribly useful for us\u2014at least, not when we\u2019re trying to access DOM nodes the way we\u2019d access any other object. Winding our way through the <code>document<\/code> object manually would be a huge headache for us, and that means our scripts would completely fall apart as soon as any markup changed.<\/p>\n<p>But <code>window.document<\/code> isn&#8217;t just a representation of the page; it also provides us with a smarter API for accessing that information. For instance, if we want to find every <code>p<\/code> element on a page, we don\u2019t have to write out a string of property keys\u2014we use a helper method built into <code>document<\/code> that gathers them all into an array-like list for us. Open up any site you want\u2014so long as it likely has a paragraph element or two in it\u2014and try this out in your console:<\/p>\n<pre><code class=\"language-javascript\">document.getElementsByTagName( \"p\" );\n[&lt;p&gt;...&lt;&sol;p&gt;, &lt;p&gt;...&lt;&sol;p&gt;, &lt;p&gt;...&lt;&sol;p&gt;, &lt;p&gt;...&lt;&sol;p&gt;]<\/code><\/pre>\n<p>Since we\u2019re dealing with such familiar data types, we already have some idea how to work with them:<\/p>\n<pre><code class=\"language-javascript\">var paragraphs = document.getElementsByTagName( \"p\" );\nundefined\n\nparagraphs.length\n4\n\nparagraphs[ 0 ];\n&lt;p&gt;...&lt;&sol;p&gt;<\/code><\/pre>\n<p>But DOM methods don\u2019t give us arrays, strictly speaking. Methods like <code>getElementsByTagName<\/code> return \u201cnode lists,\u201d which behave a lot like arrays. Each item in a <code>nodeList<\/code> refers to an individual node in the DOM\u2014like a <code>p<\/code> or a <code>div<\/code>\u2014and will come with a number of DOM-specific methods built in. For example, the <code>innerHTML<\/code> method will return any markup a node contains\u2014elements, text, and so on\u2014as a string:<\/p>\n<pre><code class=\"language-javascript\">var paragraphs = document.getElementsByTagName( \"p\" ),\n    lastIndex = paragraphs.length \u2013 1, \/* Use the length of the `paragraphs` node list minus 1 (because of zero-indexing) to get the last paragraph on the page *\/\n    lastParagraph = paragraphs[ lastIndex ]; \n\nlastParagraph.innerHTML;\nAnd that\u2019s how I spent my summer vacation.<\/code><\/pre>\n<figure>\n<picture><source media=\"(min-width: 600px)\"  \nsrcset=\"https:\/\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.12x.jpg 2x\" ><br \/>\n<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.1.jpg?w=960&#038;quality=89&#038;ssl=1\" alt=\"Fig 5.1: First drafts are always tough.\">\n<\/picture><figcaption>Fig 5.1: First drafts are always tough.<\/figcaption><\/figure>\n<p>The same way these methods give us access to information on the rendered page, they allow us to alter that information, as well. For example, the <code>innerHTML<\/code> method does this the same way we\u2019d change the value of any other object: a single equals sign, followed by the new value.<\/p>\n<pre><code class=\"language-javascript\">var paragraphs = document.getElementsByTagName( \"p\" ),\n    firstParagraph = paragraphs[ 0 ];\n\nfirstParagraph.innerHTML = \"Listen up, chumps:\";\n<samp>\"Listen up, chumps:\"<\/samp><\/code><\/pre>\n<p>JavaScript\u2019s map of the DOM works both ways: <code>document<\/code> is updated whenever any markup changes, and our markup is updated whenever anything within <code>document<\/code> changes (Fig 5.1).<\/p>\n<p>Likewise, the DOM API gives us a number of methods for creating, adding, and removing elements. They\u2019re all more or less spelled out in plain English, so even though things can seem a little verbose, it isn\u2019t too hard to break down.<\/p>\n<h2>DOM Scripting<\/h2>\n<p>Before we get started, let\u2019s abandon our developer console for a bit. Ages ago now, we walked through setting up a bare-bones HTML template that pulls in a remote script, and we\u2019re going to revisit that setup now. Between the knowledge you\u2019ve gained about JavaScript so far and an introduction to the DOM, we\u2019re done with just telling our console to parrot things back to us\u2014it\u2019s time to build something.<\/p>\n<p>We\u2019re going to add a \u201ccut\u201d to an index page full of text\u2014a teaser paragraph followed by a link to reveal the full text. We\u2019re not going to make the user navigate to another page, though. Instead, we\u2019ll use JavaScript to show the full text on the same page.<\/p>\n<p>Let\u2019s start by setting up an HTML document that links out to an external stylesheet and external script file\u2014nothing fancy. Both our stylesheet and script files are empty with .css and .js extensions, for now\u2014I like to keep my CSS in a \/css subdirectory and my JavaScript in a \/js subdirectory, but do whatever makes you most comfortable.<\/p>\n<pre><code class=\"language-markup\">&lt;!DOCTYPE html>\n&lt;html>\n    &lt;head>\n        &lt;meta charset=\"utf-8\">\n        &lt;link rel=\"stylesheet\" type=\"text\/css\" href=\"css\/style.css\">\n    &lt;\/head>\n    &lt;body>\n\n        &lt;script src=\"js\/script.js\">&lt;\/script>\n    &lt;\/body>\n&lt;\/html><\/code><\/pre>\n<p>We\u2019re going to populate that page with several paragraphs of text. Any ol\u2019 text you can find laying around will do, including\u2014with apologies to the content strategists in the audience\u2014a little old-fashioned lorem ipsum. We\u2019re just mocking up a quick article page, like a blog post.<\/p>\n<pre><code class=\"language-markup\">&lt;!DOCTYPE html>\n&lt;html>\n    &lt;head>\n        &lt;meta charset=\"utf-8\">\n        &lt;link rel=\"stylesheet\" type=\"text\/css\" href=\"css\/style.css\">\n    &lt;\/head>\n    &lt;body>\n        &lt;h1>JavaScript for Web Designers&lt;\/h1>\n\n        &lt;p>In all fairness, I should start this book with an apology\u2014not to you, reader, though I don\u2019t doubt that I\u2019ll owe you at least one by the time we get to the end. I owe JavaScript a number of apologies for the things I\u2019ve said to it during the early years of my career, some of which were strong enough to etch glass.&lt;\/p>\n\n        &lt;p>This is my not-so-subtle way of saying that JavaScript can be a tricky thing to learn.&lt;\/p>\n\n        [ \u2026 ]\n\n        &lt;script src=\"js\/script.js\">&lt;\/script>\n    &lt;\/body>\n&lt;\/html><\/code><\/pre>\n<p>Feel free to open up the stylesheet and play with the typography, but don\u2019t get too distracted. We\u2019ll need to write a little CSS later, but for now: we\u2019ve got scripting to do.<\/p>\n<p>We can break this script down into a few discrete tasks: we need to add a Read More link to the first paragraph, we need to hide all the <code>p<\/code> elements apart from the first one, and we need to reveal those hidden elements when the user interacts with the Read More link.<\/p>\n<p>We\u2019ll start by adding that Read More link to the end of the first paragraph. Open up your still-empty script.js file and enter the following:<\/p>\n<pre><code class=\"language-javascript\">var newLink = document.createElement( \"a\" );<\/code><\/pre>\n<p>First, we\u2019re intializing the variable <code>newLink<\/code>, which uses <code>document.createElement( \"a\" )<\/code> to\u2014just like it says on the tin\u2014create a new <code>a<\/code> element. This element doesn\u2019t really exist anywhere yet\u2014to get it to appear on the page we\u2019ll need to add it manually. First, though, <code>&lt;a>&lt;\/a><\/code> without any attributes or contents isn\u2019t very useful. Before adding it to the page, let\u2019s populate it with whatever information it needs.<\/p>\n<p>We could do this <em>after<\/em> adding the link to the DOM, of course, but there\u2019s no sense in making multiple updates to the element on the page instead of one update that adds the final result\u2014doing all the work on that element before dropping it into the page helps keep our code predictable.<\/p>\n<p>Making a single trip to the DOM whenever possible is also better for performance\u2014but performance micro-optimization is easy to obsess over. As you\u2019ve seen, JavaScript frequently offers us multiple ways to do the same thing, and one of those methods may <em>technically<\/em> outperform the other. This invariably leads to \u201cexcessively clever\u201d code\u2014convoluted loops that require in-person explanations to make any sense at all, just for the sake of shaving off precious picoseconds of load time. I\u2019ve done it; I still catch myself doing it; but you should try not to. So while making as few round-trips to the DOM as possible is a good habit to be in for the sake of performance, the main reason is that it keeps our code readable and predictable. By only making trips to the DOM when we really need to, we avoid repeating ourselves and we make our interaction points with the DOM more obvious for future maintainers of our scripts.<\/p>\n<p>So. Back to our empty, attribute-less <code>&lt;a>&lt;\/a><\/code> floating in the JavaScript ether, totally independent of our document.<\/p>\n<p>Now we can use two other DOM interfaces to make that link more useful: <code>setAttribute<\/code> to give it attributes, and <code>innerHTML<\/code> to populate it with text. These have a slightly different syntax. We can just assign a string using <code>innerHTML<\/code>, the way we\u2019d assign a value to any other object. <code>setAttribute<\/code>, on the other hand, expects two arguments: the attribute <em>and<\/em> the value we want for that attribute, in that order. Since we don\u2019t actually plan to have this link go anywhere, we\u2019ll just set a hash as the <code>href<\/code>\u2014a link to the page you\u2019re already on.<\/p>\n<pre><code class=\"language-javascript\">var newLink = document.createElement( \"a\" );\n\n<mark>newLink.setAttribute( \"href\", \"#\" );\nnewLink.innerHTML = \"Read more\";<\/mark><\/code><\/pre>\n<p>You\u2019ll notice we\u2019re using these interfaces on our stored reference to the element instead of on <code>document<\/code> itself. <em>All<\/em> the DOM\u2019s nodes have access to methods like the ones we\u2019re using here\u2014we only use <code>document.getElementsByTagName( \"p\" )<\/code> because we want to get all the paragraph elements in the document. If we only wanted to get all the paragraph elements inside a certain <code>div<\/code>, we could do the same thing with a reference to that <code>div<\/code>\u2014something like <code>ourSpecificDiv.getElementsByTagName( \"p\" );<\/code>. And since we\u2019ll want to set the <code>href<\/code> attribute and the inner HTML of the link we\u2019ve created, we reference these properties using <code>newLink.setAttribute<\/code> and <code>newLink.innerHTML<\/code>.<\/p>\n<p>Next: we want this link to come at the end of our first paragraph, so our script will need a way to reference that first paragraph. We already know that <code>document.getElementsByTagName( \"p\" )<\/code> gives us a node list of all the paragraphs in the page. Since node lists behave like arrays, we can reference the first item in the node list one by using the index <code>0<\/code>.<\/p>\n<pre><code class=\"language-javascript\">var newLink = document.createElement( \"a\" );\n<mark>var allParagraphs = document.getElementsByTagName( \"p\" );\nvar firstParagraph = allParagraphs[ 0 ];<\/mark>\n\nnewLink.setAttribute( \"href\", \"#\" );\nnewLink.innerHTML = \"Read more\";<\/code><\/pre>\n<p>For the sake of keeping our code readable, it\u2019s a good idea to initialize our variables up at the top of a script\u2014even if only by initializing them as <code>undefined<\/code> (by giving them an identifier but no value)\u2014if we plan to assign them a value later on. This way we know all the identifiers in play.<\/p>\n<p>So now we have everything we need in order to append a link to the end of the first paragraph: the element that we want to append (<code>newLink<\/code>) and the element we want to append it to (<code>firstParagraph<\/code>). <\/p>\n<p>One of the built-in methods on all DOM nodes is <code>appendChild<\/code>, which\u2014as the name implies\u2014allows us to append a child element to that DOM node. We\u2019ll call that <code>appendChild<\/code> method on our saved reference to the first paragraph in the document, passing it <code>newLink<\/code> as an argument.<\/p>\n<pre><code class=\"language-javascript\">var newLink = document.createElement( \"a\" );\nvar allParagraphs = document.getElementsByTagName( \"p\" );\nvar firstParagraph = allParagraphs[ 0 ];\n\nnewLink.setAttribute( \"href\", \"#\" );\nnewLink.innerHTML = \"Read more\";\n\n<mark>firstParagraph.appendChild( newLink );<\/mark><\/code><\/pre>\n<p>Now\u2014finally\u2014we have something we can point at when we reload the page. If everything has gone according to plan, you\u2019ll now have a Read More link at the end of the first paragraph on the page. If everything hasn\u2019t gone according to plan\u2014because of a misplaced semicolon or mismatched parentheses, for example\u2014your developer console will give you a heads-up that something has gone wrong, so be sure to keep it open.<\/p>\n<p>Pretty close, but a little janky-looking\u2014our link is crashing into the paragraph above it, since that link is <code>display: inline<\/code> by default (Fig 5.2).<\/p>\n<figure>\n<picture><source media=\"(min-width: 600px)\"  \nsrcset=\"https:\/\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.22x.jpg 2x\" ><br \/>\n<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.2.jpg?w=960&#038;quality=89&#038;ssl=1\" alt=\"Well, it\u2019s a start.\">\n<\/picture><figcaption>Fig 5.2: Well, it\u2019s a start.<\/figcaption><\/figure>\n<p>We have a couple of options for dealing with this: I won\u2019t get into all the various syntaxes here, but the DOM also gives us access to <em>styling<\/em> information about elements\u2014though, in its most basic form, it will only allow us to read and change styling information associated with a <code>style<\/code> attribute. Just to get a feel for how that works, let\u2019s change the link to <code>display: inline-block<\/code> and add a few pixels of margin to the left side, so it isn\u2019t colliding with our text. Just like setting attributes, we\u2019ll do this before we add the link to the page:<\/p>\n<pre><code class=\"language-javascript\">var newLink = document.createElement( \"a\" );\nvar allParagraphs = document.getElementsByTagName( \"p\" );\nvar firstParagraph = allParagraphs[ 0 ];\n\nnewLink.setAttribute( \"href\", \"#\" );\nnewLink.innerHTML = \"Read more\";\n<mark>newLink.style.display = \"inline-block\";\nnewLink.style.marginLeft = \"10px\";<\/mark>\n\nfirstParagraph.appendChild( newLink );<\/code><\/pre>\n<p>Well, adding those lines <em>worked<\/em>, but not without a couple of catches. First, let\u2019s talk about that syntax (Fig 5.3).<\/p>\n<figure>\n<picture><source media=\"(min-width: 600px)\"  \nsrcset=\"https:\/\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.32x.jpg 2x\" ><br \/>\n<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.3.jpg?w=960&#038;quality=89&#038;ssl=1\" alt=\"Now we\u2019re talking.\">\n<\/picture><figcaption>Fig 5.3: Now we\u2019re talking.<\/figcaption><\/figure>\n<p>Remember that identifiers can\u2019t contain hyphens, and since everything is an object (sort of), the DOM references styles in object format as well. Any CSS property that contains a hyphen instead gets camel-cased: <code>margin-left<\/code> becomes <code>marginLeft<\/code>, <code>border-radius-top-left<\/code> becomes <code>borderRadiusTopLeft<\/code>, and so on. Since the <em>value<\/em> we set for those properties is a string, however, hyphens are just fine. A little awkward and one more thing to remember, but this is manageable enough\u2014certainly no reason to avoid styling in JavaScript, if the situation makes it absolutely necessary.<\/p>\n<p>A better reason to avoid styling in JavaScript is to maintain a separation of behavior and presentation. JavaScript is our \u201cbehavioral\u201d layer the way CSS is our \u201cpresentational\u201d layer, and seldom the twain should meet. Changing styles on a page shouldn\u2019t mean rooting through line after line of functions and variables, the same way we wouldn\u2019t want to bury styles in our markup. The people who might end up maintaining the styles for the site may not be completely comfortable editing JavaScript\u2014and since changing styles in JavaScript means we\u2019re indirectly adding styles via <code>style<\/code> attributes, whatever we write in a script is going to override the contents of a stylesheet by default.<\/p>\n<p>We can maintain that separation of concerns by instead using <code>setAttribute<\/code> again to give our link a class. So, let\u2019s scratch out those two styling lines and add one setting a class in their place.<\/p>\n<pre><code class=\"language-javascript\">var newLink = document.createElement( \"a\" );\nvar allParagraphs = document.getElementsByTagName( \"p\" );\nvar firstParagraph = allParagraphs[ 0 ];\n\nnewLink.setAttribute( \"href\", \"#\" );\n<mark>newLink.setAttribute( \"class\", \"more-link\" );<\/mark>\nnewLink.innerHTML = \"Read more\";\n\nfirstParagraph.appendChild( newLink );<\/code><\/pre>\n<p>Now we can style <code>.more-link<\/code> in our stylesheets as usual:<\/p>\n<pre><code class=\"language-css\">.more-link {\n    display: inline-block;\n    margin-left: 10px;\n}<\/code><\/pre>\n<p>Much better (Fig 5.4). It\u2019s worth keeping in mind for the future that using <code>setAttribute<\/code> this way on a node in the DOM would mean overwriting any classes already on the element, but that\u2019s not a concern where we\u2019re putting this element together from scratch. <\/p>\n<figure>\n<picture><source media=\"(min-width: 600px)\"  \nsrcset=\"https:\/\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.42x.jpg 2x\" ><br \/>\n<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.4.jpg?w=960&#038;quality=89&#038;ssl=1\" alt=\"No visible changes, but this change keeps our styling decisions in our CSS and our behavioral decisions in JavaScript.\">\n<\/picture><figcaption>Fig 5.4: No visible changes, but this change keeps our styling decisions in our CSS and our behavioral decisions in JavaScript.<\/figcaption><\/figure>\n<p>Now we\u2019re ready to move on to the second item on our to-do list: hiding all the other paragraphs.<\/p>\n<p>Since we\u2019ve made changes to code we know already worked, be sure to reload the page to make sure everything is still working as expected. We don\u2019t want to introduce a bug here and continue on writing code, or we\u2019ll eventually get stuck digging back through all the changes we made. If everything has gone according to plan, the page should look the same when we reload it now.<\/p>\n<p>Now we have a list of all the paragraphs on the page, and we need to act on each of them. We need a loop\u2014and since we\u2019re iterating over an array-like node list, we need a <code>for<\/code> loop. Just to make sure we have our loop in order, we\u2019ll log each paragraph to the console before we go any further:<\/p>\n<pre><code class=\"language-javascript\">var newLink = document.createElement( \"a\" );\nvar allParagraphs = document.getElementsByTagName( \"p\" );\nvar firstParagraph = allParagraphs[ 0 ];\n\nnewLink.setAttribute( \"href\", \"#\" );\nnewLink.setAttribute( \"class\", \"more-link\" );\nnewLink.innerHTML = \"Read more\";\n\nfor( var i = 0; i &lt; allParagraphs.length; i++ ) {\n    console.log( allParagraphs[ i ] );\n}\n\nfirstParagraph.appendChild( newLink );<\/code><\/pre>\n<p>Your Read More link should still be kicking around in the first paragraph as usual, and your console should be rich with filler text (Fig 5.5).<\/p>\n<figure>\n<picture><source media=\"(min-width: 600px)\"  \nsrcset=\"https:\/\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.52x.jpg 2x\" ><br \/>\n<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/alistapart.com\/wp-content\/uploads\/2016\/10\/Fig-5.5.jpg?w=960&#038;quality=89&#038;ssl=1\" alt=\"Fig 5.5: Looks like our loop is doing what we expect.\">\n<\/picture><figcaption>Fig 5.5: Looks like our loop is doing what we expect.<\/figcaption><\/figure>\n<p>Now we have to hide those paragraphs with <code>display: none<\/code>, and we have a couple of options: we could use a class the way we did before, but it wouldn\u2019t be a terrible idea to use styles in JavaScript for this. We\u2019re controlling all the hiding and showing from our script, and there\u2019s no chance we\u2019ll want that behavior to be overridden by something in a stylesheet. In this case, it makes sense to use the DOM\u2019s built-in methods for applying styles:<\/p>\n<pre><code class=\"language-javascript\">var newLink = document.createElement( \"a\" );\nvar allParagraphs = document.getElementsByTagName( \"p\" );\nvar firstParagraph = allParagraphs[ 0 ];\n\nnewLink.setAttribute( \"href\", \"#\" );\nnewLink.setAttribute( \"class\", \"more-link\" );\nnewLink.innerHTML = \"Read more\";\n\nfor( var i = 0; i &lt; allParagraphs.length; i++ ) {\n    <mark>allParagraphs[ i ].style.display = \"none\";<\/mark>\n}\n\nfirstParagraph.appendChild( newLink );<\/code><\/pre>\n<p>If we reload the page now, everything is gone: our JavaScript loops through the entire list of paragraphs and hides them all. We need to make an exception for the first paragraph, and that means conditional logic\u2014an <code>if<\/code> statement, and the <code>i<\/code> variable gives us an easy value to check against:<\/p>\n<pre><code class=\"language-javascript\">var newLink = document.createElement( \"a\" );\nvar allParagraphs = document.getElementsByTagName( \"p\" );\nvar firstParagraph = allParagraphs[ 0 ];\n\nnewLink.setAttribute( \"href\", \"#\" );\nnewLink.setAttribute( \"class\", \"more-link\" );\nnewLink.innerHTML = \"Read more\";\n\nfor( var i = 0; i &lt; allParagraphs.length; i++ ) {\n\n    <mark>if( i === 0 ) {\n            continue;<\/mark>\n    }\n    allParagraphs[ i ].style.display = \"none\";\n}\n\nfirstParagraph.appendChild( newLink );<\/code><\/pre>\n<p>If this is the first time through of the loop, the <code>continue<\/code> keyword skips the rest of the current iteration and then\u2014unlike if we\u2019d used <code>break<\/code>\u2014the loop continues on to the next iteration.<\/p>\n<p>If you reload the page now, we\u2019ll have a single paragraph with a Read More link at the end, but all the others will be hidden. Things are looking good so far\u2014and if things aren\u2019t looking quite so good for you, double-check your console to make sure nothing is amiss. <\/p>\n<p>Now that you&#8217;ve got a solid grounding in the DOM, let&#8217;s <em>really<\/em> dig in and see where to take it from here. <\/p>\n<h2>Want to read more?<\/h2>\n<p>The rest of this chapter (even more than you just read!) goes even deeper\u2014and that&#8217;s only one chapter out of Mat&#8217;s hands-on, help-you-with-your-current-project guide. Check out the rest of <cite>JavaScript for Web Designers<\/cite> at <a href=\"https:\/\/abookapart.com\/products\/javascript-for-web-designers\">A Book Apart<\/a>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>JavaScript&#8217;s ability to access and modify elements on the page is undeniable, and the Document Object Model is an essential component of that. In this excerpt from Mat Marquis&#8217; new book, <cite>JavaScript for Web Designers<\/cite>, Mat shows us how to manhandle the DOM to get better results from our scripts.<\/p>\n","protected":false},"author":13,"featured_media":1018694,"comment_status":"closed","ping_status":"open","template":"","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false},"categories":[11],"tags":[],"coauthors":[392],"class_list":["post-18694","article","type-article","status-publish","has-post-thumbnail","hentry","category-javascript"],"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/article\/18694","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/article"}],"about":[{"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/types\/article"}],"author":[{"embeddable":true,"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/comments?post=18694"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/media\/1018694"}],"wp:attachment":[{"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/media?parent=18694"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/categories?post=18694"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/tags?post=18694"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/alistapart.com\/wp-json\/wp\/v2\/coauthors?post=18694"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}