Advanced jQuery 3: Styling, DOM Manipulation, and Ajax

Chapter 4: Styling and Animations

Visual effects in JavaScript can significantly enhance user experience. jQuery simplifies adding dynamic styles and creating complex animations with minimal code. These effects not only improve aesthetics but also provide usability benefits, especially in Ajax applications where users need to track changes.

Dynamic CSS Modifications

Before diving into jQuery effects, let's review CSS manipulation. Previously, we modified styles by adding/removing classes. However, sometimes we need inline styles not defined in external stylesheets. jQuery's .css() method handles this.

The .css() method works as both a getter and setter. To retrieve a single property value, pass the property name as a string. For multiple properties, pass an array of property names to get an object of property-value pairs.

// Get a single property value
.css('property') 
// "value" 

// Get multiple properties' values 
.css(['property1', 'property-2']) 
// {"property1": "value1", "property-2": "value2"} 

For setting styles, .css() has two forms: single property-value or an object of property-value pairs.

// Single property and its value 
.css('property', 'value') 

// Object of property-value pairs 
.css({ 
  property1: 'value1', 
  'property-2': 'value2' 
}) 

These key-value collections are called object literals, representing JavaScript objects.

Object Literal Notation

In property values, strings are quoted, but other data types like numbers don't need quotes. Property names are strings, so they're usually quoted. However, if the property name is a valid JavaScript identifier (like camelCase), quotes aren't needed.

We use .css() similarly to .addClass(), applying it to a jQuery object referencing DOM elements. Let's demonstrate with a style switcher:

<div id="switcher"> 
  <div class="label">Text Size</div> 
  <button id="switcher-default">Default</button> 
  <button id="switcher-large">Bigger</button> 
  <button id="switcher-small">Smaller</button> 
</div> 
<div class="speech"> 
  <p>Fourscore and seven years ago our fathers brought forth 
       on this continent a new nation, conceived in liberty,  
       and dedicated to the proposition that all men are created  
       equal.</p> 
  ... 
</div> 

After linking a stylesheet with basic rules, the page initially looks like this:

When we complete our code, clicking "Bigger" and "Smaller" buttons will increase or decrease the text size of <div class="speech">, while "Default" resets it.

Setting Computed Style Values

If we only need to change font size once, .addClass() works. But for incremental changes, we calculate new sizes by getting the current size and increasing by a factor (e.g., 40%).

$(() => {
  const $textBlock = $('div.speech');
  $('#switcher-large')
    .click(() => {
      const currentSize = parseFloat($textBlock.css('fontSize'));
      $textBlock.css('fontSize', `${currentSize * 1.4}px`);
    });
}); 

The first line creates a constant $textBlock holding the jQuery object for <div class="speech">. The dollar sign reminds us it's a jQuery object. Using const prevents accidental reassignment.

Inside the click handler, parseFloat() extracts the numeric font size. For the "Smaller" button, we use division: currentSize / 1.4. Better yet, combine both in a single handler:

$(() => {
  const sizeMap = {
    'switcher-small': n => n / 1.4,
    'switcher-large': n => n * 1.4
  };

  const $textBlock = $('div.speech');

  $('#switcher button')
    .click((e) => {
      const currentSize = parseFloat($textBlock.css('fontSize'));
      $textBlock.css(
        'fontSize',
        `${sizeMap[e.target.id]}px`
      );
    });
}); 

e.target.id determines the action. sizeMap stores behaviors, making it easier to add/remove than if statements.

To reset to default, store the initial size:

$(() => {
  const sizeMap = {
    'switcher-small': n => n / 1.4,
    'switcher-large': n => n * 1.4,
    'switcher-default': () => defaultSize
  };

  const $textBlock = $('div.speech');
  const defaultSize = parseFloat($textBlock.css('fontSize'));

  $('#switcher button')
    .click((e) => {
      const currentSize = parseFloat($textBlock.css('fontSize'));
      $textBlock.css(
        'fontSize',
        `${sizeMap[e.target.id]}px`
      );
    });
}); 

Vendor-Specific Styles

When browsers introduce experimental properties, they use prefixes (e.g., -webkit-). jQuery handles this by trying standard names first, then checking prefixes.

Chapter 5: DOM Manipulation

Web experiences involve server-client collaboration. Traditionally, servers generate HTML, but JavaScript lets us modify the document directly. This chapter covers:

  • Modifying the document via DOM interfaces
  • Creating elements and text
  • Moving or removing elements
  • Transforming documents by adding/removing/modifying attributes

Manipulating Attributes and Properties

Previously, we used .addClass() and .removeClass() to change element appearance. These methods modify the className DOM property, not the class attribute. jQuery handles class manipulation efficiently.

Non-Class Attributes

For attributes like id, rel, or href, use .attr() and .removeAttr(). These methods simplify attribute changes and support multiple attributes at once.

$(() => {
  $('div.chapter a')
    .attr({
      rel: 'external',
      title: 'Learn more at Wikipedia'
    });
}); 

Value Callbacks

For unique values (like id), use value callbacks. These functions are called for each element, returning a new value.

$(() => {
  $('div.chapter a[href*="wikipedia"]')
    .attr({
      rel: 'external',
      title: function() {
        return `Learn more about ${$(this).text()} at Wikipedia.`;
      },
      id: index => `wikilink-${index}`
    });
}); 

Data Attributes

HTML5 data attributes store application-specific data. jQuery's .data() method reads/writes these values.

$(() => {
  $('#hide-read')
    .change((e) => {
      if ($(e.target).is(':checked')) {
        $('.chapter p')
          .filter((i, p) => $(p).data('read'))
          .hide();
      } else {
        $('.chapter p').show();
      }
    });

  $('.chapter p')
    .click((e) => {
      const $elm = $(e.target);

      $elm
        .css(
          'textDecoration',
          $elm.data('read') ? 'none' : 'line-through'
        )
        .data('read', !$(e.target).data('read'));
    });
}); 

DOM Tree Operations

The $() function creates new elements from HTML strings. For example:

$(() => {
  $('<a href="#top">back to top</a>')
    .insertAfter('div.chapter p'); 
  $('<a id="top"></a>')
    .prependTo('body'); 
}); 

These elements aren't in the document yet. Use insertion methods to place them:

  • .insertAfter(): Outside and after
  • .prependTo(): Inside and before
  • .appendTo(): Inside and after
  • .insertBefore(): Outside and before

Wrapping Elements

Use wrapping methods to enclose elements. For footnotes:

$(() => {
  const $notes = $('<ol id="notes"></ol>')
    .insertBefore('#footer');

  $('span.footnote')
    .each((i, span) => {
      $(span)
        .before(`<sup>${i + 1}</sup>`)
        .appendTo($notes)
        .wrap('<li></li>');
    });
}); 

Cloning Elements

Use .clone() to duplicate elements. For pull quotes:

$(() => {
  $('span.pull-quote')
    .each((i, span) => {
      $(span)
        .parent()
        .css('position', 'relative');
    });

  $('span.pull-quote')
    .each((i, span) => {
      $(span)
        .clone()
        .addClass('pulled')
        .find('span.drop')
          .html('…')
          .end()
        .text((i, text) => text)
        .prependTo(
          $(span)
            .parent()
            .css('position', 'relative')
        );
    });
}); 

Chapter 6: Using Ajax

Ajax (Asynchronous JavaScript and XML) enables loading data without page refreshes. This chapter covers:

  • Loading data without refreshing
  • Sending data to the server
  • Handling HTML, XML, and JSON
  • Providing user feedback

Loading Data on Demand

Let's build a page displaying dictionary entries grouped by starting letter. The HTML structure:

<div id="dictionary"> 
</div> 
<div class="letters"> 
  <div class="letter" id="letter-a"> 
    <h3><a href="entries-a.html">A</a></h3> 
  </div> 
  <div class="letter" id="letter-b"> 
    <h3><a href="entries-a.html">B</a></h3> 
  </div> 
  <div class="letter" id="letter-c"> 
    <h3><a href="entries-a.html">C</a></h3> 
  </div> 
  <div class="letter" id="letter-d"> 
    <h3><a href="entries-a.html">D</a></h3> 
  </div> 
  <!-- and so on --> 
</div> 

Appending HTML

Load HTML fragments with .load():

$(() => {
  $('#letter-a a')
    .click((e) => {
      e.preventDefault();
      $('#dictionary').load('a.html');
    });
}); 

Handling JSON

For structured data, use $.getJSON():

$(() => {
  $('#letter-b a')
    .click((e) => {
      e.preventDefault();
      $.getJSON('b.json', (data) => {
        const html = data.reduce((result, entry) => `
          ${result}
          <div class="entry">
            <h3 class="term">${entry.term}</h3>
            <div class="part">${entry.part}</div>
            <div class="definition">
              ${entry.definition}
            </div>
          </div>
        `, '');

        $('#dictionary').html(html);
      });
    });
}); 

Loading XML

For XML data, use $.get() with DOM traversal:

$(() => {
  $('#letter-d a')
    .click((e) => {
      e.preventDefault();
      $.get('d.xml', (data) => {
        const html = $(data)
          .find('entry')
          .get()
          .reduce((result, entry) => `
            ${result}
            <div class="entry">
              <h3 class="term">${$(entry).attr('term')}</h3>
              <div class="part">${$(entry).attr('part')}</div>
              <div class="definition">
                ${$(entry).find('definition').text()}
              </div>
            </div>
          `, '');

        $('#dictionary').html(html);
      });
    });
}); 

Sending Data to the Server

Use $.get() or $.post() to send data. For form submissions, .serialize() simplifies data preparation:

$(() => {
  $('#letter-f form')
    .submit((e) => {
      e.preventDefault();
      $.post(
        $(e.target).attr('action'),
        $(e.target).serialize(),
        (data) => { $('#dictionary').html(data); }
      );
    }); 
}); 

Handling Errors

Use .fail() for error handling:

$(() => {
  $('#letter-e a')
    .click((e) => {
      e.preventDefault();
      $.get('notfound', { term: $(e.target).text() }, (data) => {
        $('#dictionary').html(data);
      }).fail((xhr) => {
        $('#dictionary').html(`Error: ${xhr.status}`);
      });
    });
}); 

Ajax and Events

Use event delegation for dynamically added elements:

$(() => {
  $('body')
    .on('click', 'h3.term', (e) => {
      $(e.target)
        .siblings('.definition')
        .slideToggle();
    });
}); 

Tags: jquery DOM Manipulation Ajax CSS animations JSON

Posted on Thu, 25 Jun 2026 17:35:13 +0000 by Codewarrior123