Jquery Style

Jquery Style

Jquery Styling Elements

If you are used to using jQuery’s css() method to work with styles in your document, this blog is for you. I can certainly relate to blind dependence on this magical aspect of the API. Adjusting the dimensions, color, opacity, and any other style imaginable is really easy to do with the help of jQuery. Unfortunately, this simplicity sometimes comes at a substantial cost.

 

jQuery’s internal code that backs its easy-to-use CSS API has some notable performance issues. If you value efficiency, and if you want to provide your users with an optimal experience, you should learn how to properly manipulate and read element Jquery styles using the web API. Instead of relying on a “one-size-fits-all” approach, you should choose the leanest route possible by bypassing jQuery’s abstraction.

 

You may continue to rely on jQuery, or get rid of it entirely in favor of a more “natural” programmatic approach. But there are concepts to be aware of other than which JavaScript methods and properties to use. Consider the possibility that JavaScript is not always the best way to define styles in your document. In addition to HTML and JavaScript, the browser provides a third valuable tool: style sheets.

 

This blog aims to provide you with a better understanding of the options provided natively by your browser, with each blog building on your newfound knowledge with Jquery style. In this blog, you’ll learn some new things about working with element Jquery styles, both with and without JavaScript.

 

You’ll learn enough from this blog to understand when to target elements using CSS rules in style sheets instead of resorting to JavaScript every time. Your strong knowledge of selectors and attributes, courtesy of the last few blogs, will make this much easier.

 

There Are Three Ways to Jquery Style Elements

Jquery Inline Styles

In this blog, I show you three distinct routes you may take when working with element styles. The first covers managing styles directly in your markup—something that is not recommended, but possible. Another method involves making changes to standardized properties on Element objects—one approach you may elect to take if you intend to read or update styles on demand. Finally, I go over writing CSS rules inside of style sheets as a third option.

 

Jquery Inline Styles

A couple blogs back, I introduced you to the class attribute. Although this attribute is often used for styling elements, it is also used for selecting and classifying them. This section introduces the style attribute, which is used exclusively for adjusting the appearance of an element. This attribute is not new; it was first introduced in 1996 as part of the first formal W3C CSS specification.

 

Let’s suppose you have a very simple document with a few heading elements and associated content. You’ve decided that each <h2> should be blue, and each <h3> should be green. As a novice web developer, or perhaps a developer without much knowledge of your styling options, you may choose to set the color of these headings using the style attribute, which is available on all elements, as shown in Listing 1.

 

Listing 1. Setting Styles Using the Jquery Style Attribute

<h1>Fake News</h1>
<div>Welcome to fakenews.com. All of the news that's unfit to print.</div>
<h2 style="color:blue">World</h2>
<h3 style="color:green">Valdimir Putin takes up knitting</h3>
<div>The infamous leader of Russia appears to be mellowing with age as he reportedly joined a local knitting group in Moscow.</div>
<h2 style="color:blue">Science</h2>
<h3 style="color:green">Sun goes on vacation, moon fills in</h3>
<div>Fed up after over 4 billion years without a day off, the sun headed off to the Andromeda galaxy for a few weeks of rest and relaxation.</div>

 

Looking at this example, you can see how the headings have been colored as desired. You can fit multiple styles on a single element, simply by separating the styles with a semicolon. For example, suppose we want to not only color each <h2> blue, but also ensure they stand out a bit more by making them bold:

<h2 style="color: blue; font-weight: bold">World</h2>

...

<h2 style="color: blue; font-weight: bold">Science</h2>

 

Any standardized style can be applied to any element, simply by using the style attribute as illustrated in the preceding code fragments. But there are other ways to style your elements, as you will learn shortly, so why would anyone choose this particular method?

 

First, specifying your styles alongside your elements directly in the markup seems like an intuitive and reasonable approach. But using the style attribute is most likely done out of laziness or naivete more often than not. It’s painfully obvious how easy it is to specify styles for your elements this way.

 

Styling your document using the style attribute, also known as inline styling, is something you should almost always avoid. Despite its simplicity and intuitiveness, there are a number of reasons why this practice will cause you grief. First, inline styles add quite a bit of noise to your markup.

 

In addition to content, tags, and other attributes, now you have style attributes—perhaps for many of your elements. And these attributes could very well contain a number of semicolon-separated styles. As your document begins to grow and become more complex, this noise becomes more apparent.

 

In addition to cluttering up the document, defining styles directly on each element in your markup precludes you from easily re-skinning your page. Suppose a designer took a look at the preceding code and informed you that the “green” and “blue” color values are a bit too “generic-looking,” and should be substituted for slightly different colors.

 

The designer then supplies you with hex codes for the new colors, and this adjustment requires changing style attribute for all <h2> and <h3> elements in your document. This is a common consequence of not following the “Don’t Repeat Yourself” principle3 of software development. Overuse of the style attribute can result in a maintenance nightmare.

 

Defining styles in your document via the style attribute is also a potential security risk. If you intend to implement a Content Security Policy, styling elements using attributes is strictly prohibited in the most basic (and safest) policy definition.

 

A strong Content Security Policy, also known as a CSP, is becoming more commonplace now that all modern browsers (with the exception of IE9) include support for at least the initial version of the specification.

 

Finally, peppering your page with style attributes—or <style> elements, which can contain various sets of CSS rules—can result in more overhead. If a single style needs to be changed, now the entire document has to be re-fetched by the browser the next time a user loads the page.

 

If your styles were defined in a more specific location, outside of your markup, style changes could be introduced while still allowing a portion of your page to be fetched from the browser’s cache, avoiding an unnecessary round-trip to the server. I strongly suggest avoiding the use of style attributes. There are other much more appropriate options. The initially visible benefits are shadowed by the hardships that will become a harsh reality further down the road.

 

Working with Jquery Styles Directly on the Element Object

Working with Jquery Styles

The style property on the object representation of an element was first introduced in the year 2000 as part of DOM Level 2.6 It was defined as the lone property of a new ElementCSS InlineStyle interface. The Element interface implements ElementCSS InlineStyle, which allows elements to be styled programmatically using JavaScript.

 

And all CSS properties, such as opacity and color, are accessible as properties on the associated CSSStyleDeclaration instance, where they can be read or updated. If all this talk of style properties isn’t clear, take another look at the code example from the previous section.

 

Listing 2 rewrites it by taking advantage of the style property that is available on all Element objects.

 Setting Styles Using the style Property: All Modern Browsers and Internet Explorer 8
<h1>Fake News</h1>
<div>Welcome to fakenews.com. All of the news that's unfit to print.</div>
<h2>World</h2>
<h3>Valdimir Putin takes up knitting</h3>
<div>The infamous leader of Russia appears to be mellowing with age as he report edly joined a local knitting group in Moscow.</div>
<h2>Science</h2>
<h3>Sun goes on vacation, moon fills in</h3>
<div>Fed up after over 4 billion years without a day off, the sun headed off to the Andromeda galaxy for a few weeks of rest and relaxation.</div>
<script>/*<![CDATA[*/var headings=document.querySelectorAll("h2,  h3");for(var i=0;i<headings.length;i++){if(headings[i].tagName==="H2"){headings[i].style.color="blue"}else{headings[i].style.color="green"}};/*]]>*/</script>

That seems a bit clumsy, but it illustrates how you can programmatically update styles using the web API.

 

In the last section, I extended the initial code fragment to illustrate how to define multiple styles on a single element. Let’s see how we can do this with the style property:

<h2>World</h2>
...
<h2>Science</h2>
<script>/*<![CDATA[*/var headings=document.querySelectorAll("h2");for(var i=0;i<headings.length;i++){headings[i].style.color="blue";headings[i].style.fontWeight="bold"};/*]]>*/</script>

 

Notice that the font-weight CSS style name has been converted to camel case, which is perfectly legal, but we can still change this style using the dashed name, if we really want to, like this: headings[i]. style['font-weight'] = 'bold'.

 

We’re not done just yet; there is another way to set multiple styles on a single HTML element using the style property. The CSSStyleDeclaration interface defines a special property: cssText. This allows you to read and write multiple styles to the associated element. The value string looks exactly like a collection of semicolon-separated CSS rules, as you can see in Listing 3.

 

Listing 3. Setting Multiple Styles Using the style.cssText Property: All Modern Browsers and Internet Explorer 8

<h2>World</h2>
...
<h2>Science</h2>
<script>/*<![CDATA[*/var headings=document.querySelectorAll("h2");for(var i=0;i<headings.length;i++){headings[i].style.cssText="color:  blue;  font-weight:  bold"};/*]]>*/</script>

 

Why might you want to make use of the style property on an element (or elements)? Maybe you are writing a JavaScript library that needs to make a few quick adjustments to some elements based on environmental or user input. It may be inconvenient to create and depend on a library-specific style sheet for these styles. Also, styles set using this method will usually override any other styles previously set on the element, which may be your intent.

 

But be careful about overusing this power. Styles set in this manner are difficult to override via style sheet rules. This may be your intent, but it also may not. If it is not, and you want to allow style sheets to easily make adjustments to styles, you will likely want to avoid changing styles using the style property (or inline styles).

 

Finally, using the style property can make it very difficult to track down style changes, and can clutter up your JavaScript. It seems unnatural for your code to be focused on setting specific element styles. This should be a rare practice. As you’ll see in the next section, this job is better suited for style sheets.

 

Jquery Style Sheets

Jquery Style Sheets

JavaScript isn’t the only way to attack styling challenges in the browser. It probably isn’t even the best way to change the appearance of your elements. The browser provides a dedicated mechanism for styling your document: style sheets.

 

Through this medium you may define all CSS styles for your web document in dedicated files, encapsulated in a specific HTML element, or even add them to the document via JavaScript on demand. I’ll demonstrate each of these three methods for working with styles in this section. The <style> element, first defined in the W3C CSS 1 specification, lets us group all of our styles for an entire document in one convenient location. Listing 4 is a rewrite of the previous code fragment, this time with style added courtesy of HTMLStyleElement.

 

Listing 4. Setting Styles Using the <style> Element: All Browsers

<style>h2{color:blue}h3{color:green}</style>
<h1>Fake News</h1>
<div>Welcome to fakenews.com. All of the news that's unfit to print.</div> 8
<h2>World</h2>
<h3>Valdimir Putin takes up knitting</h3>
<div>The infamous leader of Russia appears to be mellowing with age as he report edly joined a local knitting group in Moscow.<div>
<h2>Science</h2>
<h3>Sun goes on vacation, moon fills in</h3>
<div>Fed up after over 4 billion years without a day off, the sun headed off to the Andromeda galaxy for a few weeks of rest and relaxation.<div>

 

As you can see, all the JavaScript code used to style these elements in the previous section is completely replaced by two lines of CSS. Not only is this a more efficient solution, it’s also much more elegant and straightforward. And if we want to add additional styles, we can easily do so by including them among the existing styles, semicolon-separated:

<style>h2{color:blue;font-weight:bold}h3{color:green;font-weight:bold}</style>
...
The preceding styles could even be improved a bit using the power of the multiple selector, which you learned about earlier:
<style>h2,h3{font-weight:bold}h2{color:blue}h3{color:green}</style>
...

 

Jamming your styles into a <style> element may be fine for a small set of rules, but this is probably not ideal for a complex document. Perhaps you even want styles to be shared across documents/pages. Duplicating these styles in each HTML document doesn’t seem like a scalable approach. Luckily, there is a better way—style sheets—as shown in Listings 5 and 6.

 styles.css External Style Sheet: All Browsers

h2 { color: blue; }
h3 { color: green; }
Listing 6. index.html Setting Styles Using an External CSS Style Sheet File: All Browsers
<link href="styles.css" rel="style  sheet">
<h1>Fake News</h1>
<div>Welcome to fakenews.com. All of the news that's unfit to print.</div>
<h2>World</h2>

 

We’ve defined two files here: styles.css and index.html. The first houses our style sheet, the second contains our markup. In our index file, we can pull in all of these styles simply by referencing the styles.css file via the <link> element, which can be seen as early as the HTML 2.0 specification.

 

This may not be new knowledge for many of you, but it’s easy to lose sight of the entire picture when you are accustomed to using a tool like jQuery, which sometimes seems to be a solution to all browser problems.

 

It is rarely appropriate to rely exclusively on JavaScript in any form (including through jQuery’s API) to style your markup. Cascading Style Sheets exist for this purpose. But that does not mean that there is never an occasion where it is appropriate to dynamically change styles directly through JavaScript.

 

Perhaps you have constructed a web application that allows your users to create their own custom landing page. Your user needs to display all secondary headings in italics. To easily do this, you can programmatically add a CSS rule to the document using the insertRule method on the CSSStyleSheet interface:

//  This  grabs  the  first  loaded  style  sheet  on  the  current  page.
 // This also assumes the first style sheet is appropriate here. 3 var sheet = document.style Sheets[0]

   sheet.insertRule(
 'h2 { font-style: italic; }', sheet.cssRules.length - 1 7 )

 

The preceding example will create a new style that will display all <h2> elements in italics. The rule will be appended to the end of a style sheet. The style sheet variable can refer to a <style> element we’ve created on demand for these sorts of dynamic styles, or even an existing style sheet imported using a <link> tag. If you need to support Internet Explorer 8, you’ll have to use addRule instead, if it is defined in the browser’s implementation of the DOM API.

 

Using style sheets is almost always the preferred approach over a JavaScript- only solution. Even so, it is often acceptable to take a holistic approach, incorporating JavaScript, HTML, and style sheets into your solution as the situation dictates.

 

Now that you have a more complete understanding of the possibilities, you are in a better position to make these kinds of decisions correctly in your own projects. The rest of this blog is dedicated to more specific styling situations. As is customary in Beyond jQuery, I use the familiar jQuery approach as a reference, followed by copious web API examples as part of a discussion of alternatives.

 

Getting and Setting Generalized Jquery Styles

Jquery Styles

After describing and demonstrating several distinct ways to add style to your HTML elements, it’s now time to examine working with CSS a bit closer. If you are familiar with jQuery, then you already know that there is typically one narrow path to adjusting document look and feel when using jQuery.

 

I’ll provide a demonstration, for the purposes of reference. But the native route provided by the browser stack is much richer. In this section, you’ll see how to properly get styles and set them dynamically without any assistance from jQuery.

 

To set up the jQuery and non-jQuery demonstrations below, let’s start with a simple HTML fragment:

<button>cookies</button>

<button>ice cream</button>

<button>candy</button>

 

Suppose you would like to style a button a bit differently after it is clicked (or selected via the keyboard). The clicked button should be styled in some way to indicate that it has been selected. I haven’t covered event handlers yet (though I will in a later blog), so just assume that a function already exists with the associated button element passed in as a parameter whenever the button is selected. Your job is to fill in the implementation of this function by changing the background and border color of the selected button to blue, and the button text to white.

 

And to demonstrate reading styles (and further demonstrate setting them), consider an element that has already been styled as a box. Whenever this box is clicked, it becomes slightly more opaque, until it disappears entirely. Again, assume you are passed a function whenever the box is clicked. Your job is to make the box 10% more opaque whenever this function is called. I walk you through both solutions in this section, starting with the (likely) familiar jQuery approach.

 

Using jQuery

Using jQuery

jQuery, being a very popular JavaScript library relied upon by far too many developers, has a duty (in my humble opinion) to teach these developers the proper way to adjust element styles. Unfortunately, it fails to do so. Even the jQuery Learning Center article on styling10 only briefly touches on how to properly style elements, without any real demonstration of this technique at all.

 

The reason for this is simple: idiomatic jQuery is often at odds with best practices. That fact was one of several inspirations for this blog. Let’s see how most jQuery-minded developers would solve the problem:

 

function  onSelected($selectedButton)  {

$selectedButton.css({
color:  'white',
backgroundColor:  'blue',
borderColor:  'blue'

});
   }

When writing styles to elements, the css method acts as a wrapper around the style property on the HTMLElement interface. This is elegant, no doubt, but is it really the proper approach? The answer, of course, is “no.”. I covered this earlier. Granted, the previously described way is not the only solution to this problem using jQuery, but it is the most common one among jQuery developers.

 

Now, let’s examine how one would typically solve the second problem using jQuery:

function onClicked($clickedBox) {
var currentOpacity = $clickedBox.css('opacity');
if (currentOpacity > 0) {
$clickedBox.css('opacity', currentOpacity - 0.1);
}
}

 

Unfortunately, jQuery’s css API method is quite inefficient. Each call to this method to look up a style requires jQuery to utilize the getComputedStyle() method on the window object, which is completely unnecessary after the first call and adds a notable amount of processing overhead to this solution.

 

Without jQuery

The proper way to solve the first problem is to include the CSS rules in an external style sheet and trigger these rules using minimal JavaScript. Remember, we are looking to style a button, when it is selected/ pressed, to stand out. We can expect a function to be called, with the element passed as a parameter, when the button is pressed.

 

Let’s start by defining our styles for the pressed button in a style sheet, as shown in Listing 7.

Listing 7. styles.css Pressed Button Styles: All Browsers

button.selected {
color: white;
background-color: blue;
border-color: blue;
}
When the button is pressed, all we need to do is add a CSS class to the element to trigger the styles defined in the styles.css file. Now we need to implement the function that adds the “selected” class to this button in order to trigger the style rules defined in the style sheet:
function onSelected(selectedButton) {
selectedButton.className += ' selected';
}

 

What follows is a line to import the CSS file, our button element, and the function that, when called, triggers the previously defined style rules on the button:

<link  rel="style  sheet"  href="styles.css">
   <script  class='lazy' data-src="button-handler.js"></script>
   <button>demo  button</button>

 

This approach has a few advantages. First, it demonstrates a separation of concerns. In other words, rules for display belong in style sheets, behavior in JavaScript files, and content in HTML files. This separation makes maintenance simpler and potentially less risky. It also ensures that if, for example, the styles are adjusted, the HTML and JavaScript files continue to be cached by the browser.

 

If all this logic were jammed into a single HTML file, the entire file would have to be re-downloaded by the browser, regardless of the scope of the change.

 

Another advantage of tying these styles to a CSS class and defining this in an external style sheet is that these can be easily re-used for other purposes elsewhere in this document, or any other document. The idiomatic jQuery approach leaves us copying and pasting the same styles over and over again, since we are defining them inline.

 

And the second scenario? Remember, we want to increase the opacity of a box by 10% each time it is clicked. Again, we are given a function that will be called with the box element whenever it is clicked:

function onClicked(clickedBox) {
var currentOpacity = clickedBox.style.opacity ||
getComputedStyle(clickedBox, null).opacity;
if (currentOpacity > 0) {
clickedBox.style.opacity = currentOpacity - 0.1;
}
}]

Our optimized non-jQuery approach is a little more code, but it is much faster than the idiomatic jQuery solution. Here, we are only utilizing the expensive call to getComputedStyle when there is no style defined on the element’s style property. getComputedStyle determines an element’s actual style by examining not only the element’s style property, but also by looking at any available style sheets. As a result, this operation can be a bit expensive, so we avoid it unless absolutely necessary.

 

Setting and Determining Element Visibility

Element Visibility

Showing and hiding elements is a common problem in web development. These tasks may not be straightforward, but it’s often even more complicated to determine, programmatically, whether an element is visible or not. Traditionally, element visibility is a confounding problem for developers to deal with. But it doesn’t have to be this way.

 

There are two ways to do handle element visibility: the way you’ve always done it (using jQuery) and the correct way (without jQuery). You’ll see how inefficient jQuery is in this context, and how this illustrates why blind faith in this type of software library is dangerous.

 

The Typical jQuery Approach

 Typical jQuery Approach

The upside of using jQuery to show, hide, and determine the visibility of an element is simplicity. As you’ll find out soon, this is the only upside. But for now, let’s focus on this advantage.

 

Hiding and showing elements with jQuery is almost always accomplished using the show() and hide() API methods, respectively. There’s no real need to create a fragment of HTML to demonstrate these methods, so let’s just dive into a couple code samples:

//  hide  an  element
   $element.hide();

   //  show  it  again
   $element.show();

 

None of that code demands further elaboration. What does need further examination is the underlying code that actually carries out these operations. Unfortunately, both of these methods make use of window. getComputedStyle, a method discussed in the last section. In some cases, particularly with hide(), getComputedStyle() may be called multiple times. This has serious performance consequences. Why is all this processing power needed simply to hide or show a single DOM element?

 

For the most part, all the clever and generally unnecessary code underneath these two commonly used API methods is in place solely to handle styling edge cases where it is otherwise difficult to show or hide a targeted element. As I said before, element visibility doesn’t have to be a complex problem.

 

We can avoid all the CPU cycles required by jQuery to hide and show elements simply by adopting a simpler approach. More on that in the next section, where I discuss the “native web approach” to this problem.

 

What if we need to figure out whether a specific element is hidden or not? Well, jQuery makes this really easy too:

//  is  the  element  visible?
   $element.is(':visible');

   //  conversely,  is  the  element  hidden?
   $element.is(':hidden');

 

jQuery has decided to invent a couple of new pseudo-classes to represent element visibility. Even the creator of jQuery, John Resig, went on at length about the usefulness of this new innovative jQuery concoction. But just like show(), hide(), and the css() API methods, these two non-standard pseudo-classes are quite slow. Again, they delegate to window.getComputedStyle(), again, sometimes multiple times per invocation.

 

In the next section, I outline several non-jQuery methods of showing and hiding elements, as well as determining the visibility of an element. The performance differences between the native and the jQuery methods will be included as well, and the differences will be notable, to say the least.

 

The Native Web Approach

Native Web Approach

Ultimately, jQuery’s long-standing approach to toggling element visibility was exceptionally complex, and this contributed to potentially crippling performance issues. After reframing the problem, it became clear that the simplest approach was the best and most efficient one. The jQuery 3.0 release notes even suggest instead using a class name that is tied to appropriate CSS to show or hide hide an element.

 

The simplicity of hiding, showing, and evaluating the visibility of an element in jQuery is compelling. This is the part where you may expect me to say something like, “It is a bit more difficult to do all of this without jQuery,” or, “There’s an easy way to solve this problem without jQuery, but it requires use of bleeding-edge browsers.”

 

In reality, it is very easy to show, hide, and determine element visibility in any browser without jQuery. jQuery developers may want you to believe that these are complex problems to solve, and that you need jQuery to solve them, but none of this is true. In this section, I demonstrate some simple conventions that will result in simple solutions.

 

There are many ways to hide an element. Some of the more unconventional methods include setting the element’s opacity to 0, or setting the position to “absolute” and positioning it outside the visible page. These and other similar approaches may be effective, but they are generally considered to be “kludge.” As a result, using these methods is generally discouraged when attempting to hide an element. Please don’t do this; there are better ways.

 

A more reasonable approach involves setting the element’s display style property to “none”. As you have already learned, there are a number of different ways to adjust an element’s style. But you have also learned that the best approach is to define this style in an external style sheet.

 

So, perhaps the best solution would be to define a custom CSS class or attribute in your style sheet, include a display: none style for this selector, and then add the associated class or attribute to this element when it needs to be hidden.

 

So, which should we choose? An attribute or a CSS class? Does it really matter? The W3C HTML5 specification defines a hidden Boolean attribute, which, as you might expect, allows you to hide an element simply by adding this attribute to the element. Not only does this standardized attribute allow you to easily hide an element, it also enhances the semantics of your markup and provides a useful cue to all screen readers.

 

Yes, it even makes your elements more accessible. And because the hidden attribute is part of a formal specification, it isn’t just a convention—it represents the standardized way to deal with element visibility.

 

At this point, you are probably checking to see which browsers support this attribute. Let me save you the trouble—not all of them. In fact, the hidden attribute wasn’t first supported by Microsoft until Internet Explorer 11. Luckily, the polyfill for the standardized hidden attribute is unbelievably simple and elegant: just add the rule shown in Listing 8 to your global style sheet.

 

Listing 8. Polyfill for Standardized Hidden Attribute: All Browsers

[hidden] { display: none; }

 

Making sure your element is always hidden The native hidden attribute marks an element as “irrelevant,” which does not always mean that the element will be invisible to the eye. For example, if an element has an explicitly declared display style, such as display: block, the native hidden attribute will not remove it from view. Furthermore, simply including the preceding “polyfill” for this attribute will not always ensure the element is hidden from view either.

 

That is due to the rules of specificity, outlined in W3C’s CSS2 specification. Specificity determines which of several competing styles associated with an element “win.” For example, if a display: block rule pointing to the same element with a higher specificity exists, the element will remain visible. If you want any element with a hidden attribute to never be visible, you must utilize the following rule in your style sheet:

[hidden] { display: none !important; }

 

Given the preceding one-line polyfill, you can hide any element in any browser with the following line of JavaScript:

element.setAttribute('hidden', '');

 

Hiding elements couldn’t possibly be simpler, more elegant, or more performant. This approach is incredibly faster than jQuery’s hide() API method. In fact, jQuery’s hide() method is more than 25 times slower! There is no reason to continue using jQuery to hide elements.

Since the simplest and most performant method of hiding an element involves adding an attribute, you may not be surprised to learn that you can show the same element simply by removing that same attribute:

 

element.removeAttribute('hidden');

Because we’re following this convention—add an attribute to hide and element and remove it to show the element again—determining the visibility of the element is simple. All we need to do is check the element for the existence of this attribute, which is a trivial operation in all notable browsers:

// the element is hidden if this returns true

element.hasAttribute('hidden');

Yes, it’s really that easy.

 

Examining an Element Using jQuery

Examining an Element Using jQuery

Just as with the web API—described in the following section—there are many ways to discover the dimensions of an element using jQuery’s API. You may already be aware of some or even all of these methods. What you may not be aware of is the poor performance associated with jQuery’s built-in element dimension methods—most developers are not.

 

And why should you? The methods are so simple and elegant, the possibility that you are paying a substantial penalty in terms of performance is not often a concern. You probably trust that this critical library is not degrading the efficiency of your application in any noticeable way. But you would be wrong.

 

The most visible API methods are width() and height(). These two jQuery methods only measure the “content” portion of an element’s box. This sounds like a reasonable behavior, but it is not necessarily a complete representation, since content only accounts for a portion of an element’s actual width and height.

 

Remember that margin is the only element of the box model that does not directly affect the visible width and height of an element. Also remember that jQuery isn’t magic—it must delegate to the web API for all of its API methods. And the web API does not provide a simple way to determine the dimensions of an element’s content.

 

So, jQuery must perform some unpleasant operations in order to determine these values, sacrificing performance as a result. When I demonstrate how to calculate the width and height of an element using the web API in the next section, I’ll show you just how relatively inefficient jQuery’s other width and height API methods really are.

 

Options Natively Provided by the Browser

jQuery’s width

Although jQuery’s width and height are popular methods, there is no similar pair of methods or properties to be found in any web specification. The appeal of these methods is likely tied to their suggestive names. To better illustrate the code in this section, I’ll start off with a simple element that takes up space in all four segments of the box model:

<style>

   .box  {
padding:  10px;
margin:  5px;
border:  3px  solid;
display:  inline-block;
   }
   </style>
   <span  class="box">a  box</span>

To obtain the width or height of the preceding box, only considering the content and padding values, we can use the clientWidth and clientHeight properties found on the Element interface. These are comparable to jQuery’s innerWidth() and innerHeight() API methods, but the web API has significant performance advantages over jQuery’s solution. The native solution is about ten times faster!

 

These properties were first defined in the Cascading Style Sheet Object Model (CSSOM) View specification, drafted by the W3C. As of mid-2016, the CSSOM spec is not yet a recommended standard— in fact, it is only a working draft. But these two Element properties, along with many of the other items represented in this specification, have been supported by browsers for a very long time.

 

For example, the Element.clientWidth and Element.clientHeight properties are supported all the way back to Internet Explorer 6, yet they are only currently defined in this working draft spec. That seems a bit strange, doesn’t it?

 

Indeed it is, but the CSSOM spec is a special one. It exists mostly to codify and formally standardize long-standing CSS-related browser behaviors. Element.clientWidth and Element.clientHeight are two such examples, but you will see others in this section as well.

 Find width/height of Content + Padding: Web API, Modern Browsers, and Internet Explorer 8
// returns 38
document.querySelector('.box').clientHeight;
// returns 55
document.querySelector('.box').clientWidth;

 

Note that the preceding return values may vary slightly between browsers, as default fonts and styling may also vary slightly between browsers. This will ultimately lead to a slight variance in the size of the element’s content, which is to be expected. There is something else at play here that you may not be aware of. Notice the display: inline-block style attached to our <span> element? Remove it and check the return values of clientWidth and clientHeight again. Without this style, both of these properties report a value of 0.

 

By default, all browsers render <span> elements as display: inline, and inline elements will always report 0 as their clientWidth and clientHeight. Keep this in mind when using these properties. Note that floating a default inline element will also allow you to calculate width and height this way.

 

For comparison, jQuery’s width() and height() methods return 35 and 18, respectively. Remember that these methods only consider the element’s content, ignoring padding, border, and margin.

 

Width and Height of Content + Padding + Border

What if you need to include the border when reporting the width and height of an element? That is, content, padding, and border? Simple—use HTMLElement.offsetWidth and HTMLElement.offsetHeight.

 

These properties have also long been implemented by browsers, but only first brought into a formal specification in the CSSOM View standard. Both properties are comparable to jQuery’s outerWidth() and outerHeight() methods, as shown in Listing 10.

 

Listing 10. Find width/height of Content + Padding + Border: Web API, Modern Browsers, and Internet Explorer 8

// returns 44
document.querySelector('.box').offsetHeight;
// returns 61
document.querySelector('.box').offsetWidth;

 

As expected, these values are a bit larger than what clientHeight and client Width report since we are also taking border into account. In fact, each value is exactly 6 pixels larger. This is expected due to a border of 3 pixels on each side, defined in our <style> element.

 

Again, the returned values above may vary slightly between browsers due to the way browsers style element content. Also, display: inline-block is not needed for offsetHeight and offsetWidth—they will not report a zero height and width for inline elements. There is a lot more to discuss regarding styling elements, but this blog is about so much more. I’ve provided you with some of the critical concepts that will allow you to end your dependence on jQuery when facing other styling-related challenges going forward.

 

DOM Manipulation

One of the most confusing and misunderstood aspects of the web API pertains to DOM manipulation. I suspect you are already used to working with DOM elements through jQuery. But is it necessary to continue depending on a library in this regard?

 

In this blog, I show you how to create, update, and move elements and element content without any help from third-party code. You’ll come to appreciate how easy it is to work with the DOM in virtually all browsers.

 

The DOM A Central Component of Web Development

DOM Manipulation

Most likely you’ve heard about the DOM. It’s a common term in the world of web development. But maybe the DOM is still a mostly mysterious word to you. What exactly is the DOM, and why is it so important? How and why does jQuery abstract the DOM API away from developers?

 

As stated in one of the early W3C-maintained documents, “The history of the Document Object Model, known as the DOM, is tightly coupled with the beginning of the JavaScript and JScript scripting languages.” This model expresses an API, commonly implemented in JavaScript for use in web browsers, that allows programmatic access to an HTML document.

 

In addition to working with attributes, selecting elements, and storing data, the DOM API also provides a way to create new content, remove elements, and move existing elements around the document. These specific aspects of the DOM API are the primary focus of this blog.

 

jQuery Exists Because of the DOM API

Okay, it’s not the only reason why jQuery was created, but it’s certainly one of the reasons. John Resig, the creator of jQuery, famously called the DOM a “mess” in a 2009 presentation at Yahoo. So this perhaps gives us some insight into one of the problems jQuery aims to solve.

 

A few years before Resig’s talk, jQuery 1.0 was released (2006), which included about 25 DOM-manipulation-specific methods. This accounted for about 17% of the entire API. Even as the API has grown to handle all aspects of the web API, DOM manipulation functions still account for 15%.

 

Sure, jQuery provides some elegant solutions to working with the DOM. But are they really necessary? Of course not! Is the DOM still “broken”? Not in my opinion. The DOM API may have some rough edges, but it is fairly easy to use and quite reliable. You can painlessly manipulate the DOM yourself without the help of jQuery.

 

The DOM API Isn’t Broken, It’s Just Misunderstood

In Resig’s talk at Yahoo, he said “Nearly every DOM method is broken in some way, in some browser.” Although that is a bit hyperbolic, it may have had some truth to it back in 2009. The current age of browsers paints a much different picture, though. Browsers still have bugs, but this is true of all software, even jQuery.

 

The jQuery team already apparently knows that the library is no longer useful as a shield from browser bugs, as is evident in their responses to issues that appear to be browser-specific.

 

One of the major goals of jQuery has always been to shield developers from the DOM API. Why? Because it historically has been a mess. It’s also seen as a muddled path to follow when attempting to programmatically update a page’s markup. This has a bit of truth to it, but only because many developers have not taken the time to learn the DOM API.

 

As you’ll see throughout this blog, working with the DOM isn’t as hard as you might think and is well supported throughout all popular browsers. It’s hard to argue with the convenience offered by jQuery’s API. You can even make better use of jQuery, should you continue to use it, once you have a better understanding of the underlying DOM API methods that jQuery itself relies on.

 

Moving and Copying Elements

Moving and Copying Elements

In this first part, I’m going to focus on moving and copying existing elements. You’ll learn how to insert elements anywhere in the DOM, change the order of adjacent elements, and clone an element.

 

I’ll demonstrate methods present on the Document,5 Element,6 and Node7 interfaces, among others. You’ll see how basic DOM operations have been executed with jQuery, followed by explanations and demonstrations of the same tasks utilizing the DOM API alone.

 

Moving Elements Around the DOM

I’m going to start this section out with one of my patented (pending) sample documents. In order to focus primarily on the functionality of the demonstrable methods, I’ll keep this simple and straightforward. Admittedly, this results in a somewhat contrived example, but I feel it will easily allow us to compare and contrast jQuery with the DOM API in the context of DOM manipulation.

 

Our super-simple document consists of a few different categories and attributes of ice cream: flavors, types, and a section of unassigned types and flavors. This document represents some choices for customers of an ice cream shop. Using this markup, we’re going to solve several “problems,” first with jQuery, and then with the plain old DOM API.

 

The first challenge involves reordering the flavors and types in descending order, based on their popularity. Chocolate is the most popular flavor, followed by vanilla and strawberry. We’ll have to change the order of the flavors list items to reflect their popularity, but the types list is already in the correct order.

 

Second, we really want to present our readers with the types of ice cream first, followed by the flavors. The current order, which includes flavors first, is known to be less than ideal, as our customers want to be informed of the types first before deciding on flavors.

 

Finally, we need to take the items in the “unassigned” section and assign them to the proper category. “Rocky road” is a flavor that is less popular than vanilla, but more popular than strawberry. And “gelato” is a type, also the least popular of the bunch:

<body>
<h2>Flavors</h2>
<ul class="flavors">
<li>chocolate</li>
<li>strawberry</li>
<li>vanilla</li>
</ul>
<h2>Types</h2>
<ul class="types">
<li>frozen yogurt</li>
<li>custard</li>
<li>Italian ice</li>
</ul>
<ul class="unassigned">
<li>rocky road</li>
<li>gelato</li>
</ul>
</body>
After solving the problems described so far, our document should look like this:
<body>
<h2>Types</h2>
<ul class="types">
<li>frozen yogurt</li>
<li>Italian ice</li>
<li>custard</li>
<li>gelato</li>
</ul>
<h2>Flavors</h2>
<ul class="flavors">
<li>chocolate</li>
<li>vanilla</li>
<li>rocky road</li>
<li>strawberry</li>
</ul>
<ul class="unassigned">
</ul>
</body>
Moving Elements Using jQuery
In order to properly order the flavors, “vanilla” must be moved after “chocolate”. To accomplish this, we must make use of jQuery’s after() API method:
var $flavors = $('.flavors'),
$chocolate = $flavors.find('li').eq(0),
$vanilla = $flavors.find('li').eq(2);
$chocolate.after($vanilla);

 

For our second challenge, we have to move the “types” list and the heading (<h2>) for the “types” list before the “flavors” list. We can take advantage of the fact that this means the heading and list must be the first set of children inside the <body> element. First, we prepend the “types” heading to the <body> using the prependTo() method and then insert the “types” list after the newly moved heading, again using jQuery’s after() method:

var  $typesHeading  =  $('h2').eq(1);

   $typesHeading.prependTo('body');
   $typesHeading.after($('.types'));

 

Finally, we need to move the unassigned “rocky road” just above “strawberry” in the flavors list, and “gelato” to the end of the “types” list. For the first move, we can again use jQuery’s after() method. For the second move, we will use the appendTo method on the “gelato” element to insert it as the last child in the “types” list:

var  $unassigned  =  $('.unassigned'),

$rockyRoad  =  $unassigned.find('li').eq(0),
$gelato  =  $unassigned.find('li').eq(1);

   $vanilla.after($rockyRoad);
   $gelato.appendTo($('.types'));

 

None of the preceding solutions is particularly elegant or intuitive. It’s certainly possible to come up with more attractive examples to solve these problems, but I would expect this attempt to be common among jQuery developers. We also could have made use of some of jQuery’s proprietary pseudo-classes, such as :first and :last, but we already learned how inefficient those options are.

 

The DOM API’s Solution to Reordering Elements

DOM API’s Solution

In order to make the proper adjustments to our ice cream store page without jQuery, I’m going to introduce two new DOM API methods. Surprisingly, all of the code in this section works in all modern browsers and Internet Explorer 8 as well! Before we start, the eye-rolling nature of this example ice cream store markup is not lost on me, but it allows me to succinctly demonstrate a number of DOM manipulation operations without getting bogged down in details unrelated to the problem at hand. That said, let’s get started.

 

Remember that our first task is to move the “vanilla” element before the “strawberry” element. To accomplish this, we can make use of the insertBefore() method), which was added to the Node interface as part of W3C’s DOM Level 2 Core specification. This method, as you might imagine, allows us to move one element just before another in the DOM.

 

And because this is available on the Node interface, we have the power to move anything in the DOM, even a Text or Comment node! Take a look at how we move this element—I’ll explain what’s going on immediately after the following code fragment:

var flavors = document.querySelector('.flavors'),
strawberry = flavors.children[1],
vanilla = flavors.children[2];
flavors.insertBefore(vanilla, strawberry);

 

At the top of the preceding code, I’m simply selecting elements needed by our move operation. The last line is the most important one. Since the insertBefore() method is defined on the Node object’s prototype, we must call insertBefore() on an DOM object that implements this interface. In fact, this element must be a parent element of the Node we are moving. Since we are moving the “vanilla” <li> element, we can use its parent—the “flavors” <ul>.

 

The first parameter passed to insertBefore() is the element we want to relocate: the “vanilla” list item. The second parameter is the “reference node.” This is the Node that will become the next sibling of our target element (the “vanilla” <li>) after the move operation. Since we want to move “vanilla” before “strawberry,” the “strawberry” <li> is our reference node.

 

We’ve reordered our flavors, but we still need to move the flavors heading and list to the top of our document. We can easily accomplish this goal with the insertBefore() method as well:

var  headings  =  document.querySelectorAll('h2'),
flavorsHeading  =  headings[0],
typesHeading  =  headings[1],
typesList  =  document.querySelector('.types');

   document.body.insertBefore(typesHeading,  flavorsHeading);
   document.body.insertBefore(typesList,  flavorsHeading);

 

Note Regarding this line of code in the preceding code listing - document.body. insertBefore(typesHeading, flavorsHeading) - this behaves just like $typesHeading.prependTo('body’) in the earlier jQuery code listing. Why? Because flavorsHeading happens to be the first child of document.body.

 

The meat of our logic is contained in the final two lines of the preceding code. First, we’re moving the “types” <h2> to the top of our document. The parent of this heading is the <body> element, which we can easily select using document.body. Our target element is, of course, the “types” heading. We want to move this just before the “flavors” <h2>, so that becomes our reference element.

 

The second insertBefore() moves the <ul> of ice cream types after the recently moved heading. Again, <body> is our parent element. Since we need to move this list before the “flavors” heading, that is again our reference node.

 

Our final task is to move the unassigned elements into their respective lists. To accomplish this, we’ll again make use of insertBefore(), but you’ll also see a new method in action. The W3C DOM Level 1 specification, which is quite an old spec, first defined an appendChild() method on the Node interface. This method will be of some use to us as we wrap up our exercise:

flavors.insertBefore(
document.querySelector('.unassigned > li'), strawberry);
document.querySelector('.types').appendChild(
document.querySelector('.unassigned > li'));

 

In the first statement, we’re moving the “rocky road” element from the unassigned list into the flavors list. The flavors list is our parent element, as expected. The target is the first list item child of the unassigned list, which happens to be the “rocky road” <li>. And the reference node is the strawberry item in the flavors list, since we want to move “rocky road” before this element.

 

We also want to move the unassigned “gelato” list item to the end of the types list. The simplest way to do this is to use appendChild(). As with the insertBefore() method, appendChild() expects to be called on the parent of the node we plan to move—the “types” list. The appendChild() method only takes one argument—the element that is to become the last child of the parent element.

 

At this point, the “gelato” item is the first <li> child in the unassigned list, so we can use the same selector as used to locate the target element in our insertBefore() statement.

That was all surprisingly easy, wasn’t it? The DOM API may not be as scary as many make it out to be!

 

Making Copies of Elements

Making Copies of Elements

To demonstrate the various ways to clone elements using jQuery and the DOM API, consider the following markup:

<ol class="numbers">

<li>one</li>

<li>two</li> 4 </ol>

 

The DOM API offers a method to clone the <ol> and its children, as well as a way to clone only <ol> and not any of its children/content. The former is called a deep clone, and the latter a shallow clone. jQuery only offers a way to deep clone.

In jQuery-land, we must make use of $.clone():

// deep clone: return value is an exact copy

$('.numbers').clone();

 

You can optionally pass Boolean parameters to the preceding clone() if you’d like jQuery to clone any data and event listeners on the element. But be warned that jQuery will only copy event listeners and data attached to the element via jQuery. Any listeners and data added outside of jQuery’s API will be lost.

 

The DOM API provides a similarly named method, cloneNode(), available on the Node interface. It was first standardized as part of DOM Level 2 Core, which became a W3C recommendation back in 2000. As a result, cloneNode() is supported in any browser. The next example is limited to Internet Explorer 8 and up (though this is hardly a problematic limitation) due to my use of querySelector():

//  shallow  clone:  return  value  is  an  empty  <ol  class="numbers">
   document.querySelector('.numbers').cloneNode();

 // deep clone: return value is an exact copy of the tree 5 document.querySelector('.numbers').cloneNode(true);

 

In both cases, the element copies will contain everything defined in the markup, even the class names, and any other attributes such as inline styles. Event listeners are not included with the copy, nor are any properties exclusively set on the element’s JavaScript object representation. In other words, cloneNode() copies only what you see: markup. Whether you are using jQuery or the DOM API, the copy created by cloneNode() is not added to the document for you. You will need to do this yourself using one of the methods demonstrated earlier in this section.

 

Composing Your Own Elements

Now that we’ve explored moving and coping elements, how about creating and removing them? You’ll see how these common problems have been solved with jQuery, and how you can solve them just as easily with the DOM API. As with the previous section, all DOM API code here will work in all modern browsers, and most are supported in Internet Explorer 8 as well.

 

To best demonstrate all of the concepts outlined in this final section, I’ll build upon the modified example document from the previous section that I used to demonstrate moving elements. Using jQuery and then the bare DOM API, I’ll show you how to perform various operations on our example document, such as the following:

  • Add some new ice cream flavors.
  • Remove some existing types.
  • Make simple text adjustments to our document.
  • Read parts of the document to a string to allow it to be saved.
  • Create a new section to further classify our ice cream.

 

Creating and Deleting Elements

Creating and Deleting Elements

Suppose we have a couple new flavors to add to our list: pistachio and neapolitan. These of course belong in the “flavors” section. To accomplish this task, we’ll need to create two new <li> elements with Text Nodes that contain the names of these two new flavors. It’s fine to simply add these new flavors to the end of the list so that we can stay focused on creating the representative elements. We also want to remove the “gelato” type from the end of the list of types, since we no longer sell gelato ice cream.

 

Creating elements is pretty easy with jQuery, and due to chaining we can add both elements in two lines:

var $flavors = $('.flavors');
// add two new flavors
$('<li>pistachio</li>').appendTo($flavors);
$('<li>neapolitan</li>').appendTo($flavors);
Removing an element isn’t very difficult either:
// remove the "gelato" type
$('.types li:last').remove();

 

Here we’ve made use of a CSS selector, partially proprietary. The last <li> beneath the element with a “types” CSS class is being removed from the document. This happens to be our “gelato” type. The :last pseduo-class is specific to jQuery and as such is not particularly performant.

 

There is a native CSS pseduo-class we could use, which you will see in a moment, but many jQuery developers may not know that it exists, since the jQuery API provides this proprietary alternative as part of its documented API.

 

How can we achieve the same results with the DOM API? Depending on desired browser support, we may have several options. Although newer browsers may allow for more elegant options than older ones, this is not always the case, and these operations are all relatively simple in all modern browsers (and even older ones) without relying on jQuery.

 

We can add our two new flavors to the end of the “flavors” list in two total lines, just like the jQuery solution, although the lines are a bit longer:

var flavors = document.querySelector('.flavors');
// add two new flavors
flavors.insertAdjacentHTML('beforeend', '<li>pistachio</li>')
flavors.insertAdjacentHTML('beforeend', '<li>neapolitan</li>')

 

In the preceding code, I’m using the insert Adjacent HTML method present on the Element interface prototype. While this method has likely existed in browsers for many years, it was only first standardized in the W3C’s DOM Parsing and Serialization specification, drafted in 2014.

 

What about removing “gelato” from our list of types? In the newest available browsers, we have the most elegant solution:

// remove the "gelato" type

document.querySelector('.types li:last-child').remove();

 

The preceding code is very similar to the jQuery solution, with a couple noticeable differences. First, I am of course using querySelector to locate the element to remove. Second, I’m making use of the :last-child CSS3 pseudo-class selector. The remove() method, present on the ChildNode interface, is relatively new and only supported in Microsoft Edge, Chrome, Firefox, and Safari 7.

 

It is not supported by any versions of Internet Explorer, nor is it available on Apple iOS browsers. This method was first defined by the WHATWG as part of its DOM living standard and in particular is our limiting factor in terms of browser support.

 

Luckily, we have a solution that covers all modern browsers, which requires only a little more code:

var  gelato  =  document.querySelector('.types  li:last-child');

   //  remove  the  "gelato"  type
   gelato.parentNode.removeChild(gelato);

 

I’ve replaced ChildNode.remove() with Node.removeChild(), which has existed since DOM Level 1 Core, so it is supported in all browsers. To remove a child node, of course, we need to access the parent first. Luckily, it’s really easy to do this. In this instance, the code that limits us to modern browsers is the :last-child CSS3 pseudo-class, which isn’t available in Internet Explorer 8.

 

To support IE8, you’ll have to replace the selector with document.querySelectorAll('.types li'). And if you don’t want to hard-code the index of the gelato element, you’ll have to move the result of the querySelectorAll() into a variable and access the last element in the returned collection by examining this variable’s length property.

 

Text Content

 

Text Content

There are two workflows to address in terms of element text: updating and parsing. Although jQuery provides one specific method to accomplish both tasks, the DOM API offers two—both with different behaviors that accommodate different needs. In this section, I demonstrate jQuery’s text() method, the native textContent property, and the native innerText property. You’ll see how each of these differ as we make changes to our document of ice cream types and flavors and then output the resulting document as text.

 

First, let’s examine jQuery’s text() method, which allows us to both read and update text in a document. Notice that one of our types—“Italian ice”—starts with a capital letter. None of the other types or flavors shares this trait. Even though “Italian” is a proper adjective and normally should start with a capital “I,” let’s modify it to be consistent with the case of the rest of our types and flavors:

$('.types li').eq(1).text('italian ice');

 

As you probably already know, the text of an element can be updated simply by passing the new text as a parameter of the text() method. This is exactly what I have done in order to normalize the case of this type of ice cream. What would our modified document look like if we output it using jQuery’s text() method? Like this:

Types
frozen  yogurt
italian  ice
custard
gelato

Flavors
chocolate
vanilla
rocky  road
strawberry

"

The quotation marks have been added to show where the output starts and ends. They are not part of the actual text. Notice that this output reflects the structure of our markup. This can be verified by examining the indentation of the text as well as the line breaks at the end of the document.

 

The series of line breaks before the output ends account for the empty “unassigned” list. You’ll see how this output mirrors the output of one of the two native text manipulation properties offered by the DOM API.

 

There are two common properties available on the DOM elements used to read and update text: textContent and innerText. There are notable advantages and disadvantages of both properties, but their presence allows for more flexibility in dealing with text than jQuery’s text() method alone.

 

Next, I compare and contrast these two properties against each other and jQuery’s text() method, and it will be clear when you should choose one over the other.

 

Let’s first examine textContent, which was added to the Node interface in W3C’s DOM Level 3 Core.This property allows element text to be read and updated in all modern browsers. Changing the text of our “Italian ice” list item to “italian ice” is just as simple as jQuery’s text() method:

document.querySelectorAll('.types li')[1].textContent = 'italian ice';

 

The textContent property not only matches the behavior of jQuery’s text() method when writing text, it also functions exactly like jQuery when reading text as well. Take our previous example where we outputted our entire ice cream document after modifying the “Italian ice” type. The output from the DOM API’s textContent property matches that of jQuery’s text() exactly:

 

As you can see, textContent outputs the text inside an element and its descendants formatted with the structure of the document markup in mind, just like jQuery’s text().

 

The second available property, innerText, is available on the HTMLElement interface, though it is a bit strange in that it is not yet part of any formal web specification. However, it is supported by all versions of all browsers, except for Firefox, which didn’t add support until version 45.17 Even though innerText is not yet standardized, there is a rudimentary draft proposal18 in place, created by Robert O’Callahan of Mozilla.

 

Changing “Italian ice” to “italian ice” using innerText is not much different than textContent or jQuery’s text(), with the exception of the addition of Internet Explorer 8 support and lack of Firefox support for versions older than 45:

document.querySelectorAll('.types li')[1].innerText = 'italian ice';

 

So what happens if we attempt to output our document using innerText? You’ll see that the result looks a bit different than the result garnered from textContent and jQuery’s text():

 

Initially, the preceding output may look a bit odd, but it actually makes perfect sense if you understand what it represents. I’d like you to paste the markup from the modified document listed earlier into a browser, copy the rendered result to your system’s clipboard, and then paste it into a text editor. You’ll notice that the pasted text is formatted identically to the output listed here. As the draft specification describes, innerText “return(s) the ‘rendered text’ of an element.”

 

I was asked once “When dealing with reading element text, is there a general solution for using web APIs that is supported in all browsers?” Well, that depends on your requirements. If the behavior of textContent is appropriate and you only need modern browser support, then that is probably your best choice.

 

But there are certainly instances when innerText is more appropriate, as previously mentioned. jQuery's text() behaves like textContent, so, if you want to mirror the behavior of jQuery and need to support all modern browsers including older versions of Firefox, that is another reason to favor textContent.

 

Rich Content

HTML content

HTML is nothing more than text formatted per conventions defined by a set of web specifications. This reality is useful when we need to serialize or deserialize a document or a portion of a document. Deserialization of HTML may occur when receiving server-generated markup in response to an HTTP request.

 

In this instance, the HTML in the response must be inserted into the DOM in an appropriate location. I’ll demonstrate this specific scenario and talk about how this may be completed with the help of several methods available in the DOM API. And perhaps this server-generated markup must be returned to the server and persisted for later use after it is modified in some way. That, too, can be accomplished with the DOM API, and you’ll see how in this final section.

 

jQuery provides a grand total of one method for reading and writing HTML. This is accomplished using the aptly named html() function. First, let’s assume we’ve already received a string of HTML from our server and we need to insert it into our document. Keeping with the theme of this blog, this markup represents an entirely new section for our ice-cream store page.

 

We simply need to insert it after the existing sections. The markup from our server is simply a long string of HTML, such as “<h2>Containers</h2><ul><li>cone </li><li>cup</li></ul>”. This string of HTML will be stored in a variable named container. Here you can see how this should be inserted at the end of our document using jQuery:

$('<div>').html(container).appendTo('body');

 

First, we are creating a new <div>, which is disconnected from the DOM, then we’re setting the contents of this disconnected <div> to the HTML from our server, and finally this element is added to the end of our ice cream store page. After modifying our page in various ways, we now want to send the markup back to our server, which can also be accomplished using jQuery’s html() method:

var contents = $('body').html();

// ...send `contents` to server

 

The jQuery-less DOM API route is a bit less elegant, but still very simple and widely supported. In order to read and write the same markup, we’ll use the innerHTML property defined on the Element interface. This property, while supported in every browser imaginable, has only recently achieved standardization. innerHTML started as a Microsoft Internet Explorer proprietary extension, but is now part of the W3C DOM Parsing and Serialization specification.

 

We can use innerHTML to add the server-generated HTML to the end of our page:

var  div  =  document.createElement('div');
   div.innerHTML  =  container;
   document.body.appendChild(div);

 

The createElement method of the Document interface is courtesy of W3C’s DOM Level 1 Core20 specification, which means it is supported in any browser. Reading the markup of our document back for persistence server-side also uses innerHTML, and it’s just as elegant as jQuery’s html() method:

var contents = document.body.innerHTML;

// ...send `contents` to server

The DOM API is a bit more flexible than jQuery in this instance; it provides a few more options.

 

For example, the standardized Element.outerHTML property will take the reference element into account when reading or updating HTML. Conversely, innerHTML is only concerned with the descendents of the reference element. Had I used outerHTML in the “add a string” demonstration above, everything in the document including the <body> element would have been replaced with the new <div>-wrapped ice cream containers section.

 

In the last DOM API example, where we read back the contents of the document, the <body> element would have been included in the stringified-html had we used outerHTML instead. Depending on your requirements, this may be desirable.

 

Though I certainly haven’t demonstrated all the properties and methods provided by the DOM API, the point I am trying to make is that the browser already provides more than enough in terms of reasonable and intuitive native support for DOM manipulation.