Module 17: The AJAX Revolution
How XMLHttpRequest and jQuery transformed the web into an application platform (2005–2013)
Learning Objectives
By the end of this module, you will:
- Understand what AJAX enabled and why it mattered
- Know the role jQuery played in web development
- Recognize "Web 2.0" patterns
- See why this era was both liberating and chaotic
- Appreciate the problems that led to modern frameworks
Time: 1-2 hours (reading)
Introduction
In 2004, Google launched Gmail. Users were shocked:
- Click an email → it opens instantly (no page refresh)
- Type to search → results appear as you type
- Star an email → star appears immediately
"How is this possible? It's just a website!"
The answer: AJAX — a technique that would transform the web from a document platform into an application platform.
Part 1: The AJAX Breakthrough
XMLHttpRequest
The secret was a JavaScript object that could talk to servers in the background:
// The revolutionary code (circa 2005)
var xhr = new XMLHttpRequest();
xhr.open('GET', '/api/messages', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
// Update page WITHOUT reload!
document.getElementById('messages').innerHTML = xhr.responseText;
}
};
xhr.send();
This seems simple now. In 2005, it was revolutionary.
What "AJAX" Means
Asynchronous JavaScript And XML (coined by Jesse James Garrett, 2005)
The key word: Asynchronous
- Request happens in background
- Page stays responsive
- When response arrives, update just the relevant part
Before and After
Before AJAX:
Click "Load Messages"
→ Browser navigates to /messages
→ Server renders full page
→ Browser loads entirely new page
→ 2-5 second wait, white flash
After AJAX:
Click "Load Messages"
→ JavaScript sends background request
→ User continues interacting with page
→ Response arrives (100-500ms)
→ JavaScript updates message area
→ No flash, no scroll reset, instant feel
Part 2: Gmail and Google Maps
Gmail (2004)
Gmail demonstrated AJAX at scale:
- Conversation threading without page loads
- Keyboard shortcuts for power users
- Search that felt instant
- Rich text editing in browser
- Auto-save drafts in background
Users got 1GB of storage when competitors offered 4MB. But the interface was the real innovation.
Google Maps (2005)
Google Maps was even more impressive:
- Infinite panning — drag the map, new tiles load
- Smooth zooming without page refresh
- Search locations with instant updates
- Click for details without navigation
This was previously only possible in desktop applications.
The Message
Google proved that web applications could rival desktop software. The industry noticed.
Part 3: The Browser Wars (Again)
The Compatibility Nightmare
Different browsers implemented things differently:
// Creating an XMLHttpRequest (2005-era)
function createXHR() {
if (window.XMLHttpRequest) {
// Firefox, Safari, Opera
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
// Internet Explorer
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
return null;
}
And that's just for making requests. Everything was like this:
- DOM manipulation
- Event handling
- CSS application
- Animation
The IE Problem
Internet Explorer 6 (2001) dominated with ~90% market share. It was:
- Buggy
- Incomplete
- Didn't follow standards
- Microsoft stopped updating it
Developers spent 50% of their time on IE workarounds.
Writing Cross-Browser Code
// Adding an event listener (2005-era)
function addEvent(element, event, handler) {
if (element.addEventListener) {
// Standards-compliant browsers
element.addEventListener(event, handler, false);
} else if (element.attachEvent) {
// Internet Explorer
element.attachEvent('on' + event, handler);
} else {
// Really old browsers
element['on' + event] = handler;
}
}
Every basic operation required compatibility code.
Part 4: jQuery to the Rescue (2006)
What jQuery Solved
John Resig released jQuery in 2006. It wrapped browser differences:
// Without jQuery (handle browser differences yourself)
var element = document.getElementById('myId');
if (element.addEventListener) {
element.addEventListener('click', handleClick, false);
} else {
element.attachEvent('onclick', handleClick);
}
// With jQuery (one line, works everywhere)
$('#myId').click(handleClick);
jQuery's Killer Features
DOM selection (CSS selectors):
// Select all paragraphs with class "highlight" inside #content
$('#content p.highlight')
// This was revolutionary — CSS selectors in JavaScript!
Chaining:
$('#menu')
.addClass('active')
.find('li')
.css('color', 'blue')
.on('click', handleClick);
AJAX simplified:
// jQuery AJAX
$.ajax({
url: '/api/data',
method: 'GET',
success: function(data) {
$('#result').html(data);
},
error: function() {
alert('Failed to load');
}
});
// Even simpler
$('#result').load('/api/data');
Animations:
$('#panel').slideDown(300);
$('#overlay').fadeIn();
$('.item').animate({ left: '100px' }, 500);
jQuery's Dominance
By 2010, jQuery was on 70%+ of websites. It became synonymous with JavaScript development. Job postings asked for "jQuery developers," not "JavaScript developers."
Part 5: The "Web 2.0" Era
What "Web 2.0" Meant
The term (coined ~2004) described the new interactive web:
- User-generated content (YouTube, Wikipedia)
- Social features (Facebook, Twitter)
- Rich interfaces (Gmail, Google Docs)
- APIs for mashups (combining data sources)
Characteristics
Visual design:
- Gradients, reflections, rounded corners
- "Glossy" buttons
- Badges and ribbons
- (Later mocked as "Web 2.0 style")
Technical patterns:
- AJAX everywhere
- JSON APIs
- Tag clouds
- Infinite scroll
- Real-time updates
The API Economy
Web 2.0 spawned public APIs:
- Google Maps API (embed maps anywhere)
- Twitter API (build Twitter clients)
- Facebook API (social login, sharing)
- Flickr API (photo integration)
Developers combined APIs to create "mashups" — new applications from existing services.
Part 6: JSON Replaces XML
Why Not XML?
AJAX originally used XML:
<response>
<user>
<name>John</name>
<email>john@example.com</email>
</user>
</response>
Problems:
- Verbose (lots of repeated tags)
- Heavy parsing
- Complex to construct in JavaScript
JSON Emerges
Douglas Crockford popularized JSON (JavaScript Object Notation):
{
"user": {
"name": "John",
"email": "john@example.com"
}
}
Advantages:
- Lighter weight
- Native JavaScript parsing (
JSON.parse()) - Easier to construct
- Human-readable
The Shift
By 2010, most APIs returned JSON. The "X" in AJAX became a misnomer — hardly anyone used XML anymore. But the name stuck.
Part 7: The jQuery Spaghetti Problem
Success Created Problems
jQuery made things easy. Too easy. Anyone could:
- Attach events anywhere
- Modify any DOM element
- Make AJAX calls from any code
Spaghetti Code
Real jQuery codebases often looked like:
$(document).ready(function() {
$('#button1').click(function() {
$.get('/api/data', function(data) {
$('#results').html(data);
$('.result-item').click(function() {
var id = $(this).data('id');
$.post('/api/select', { id: id }, function(response) {
if (response.success) {
$(this).addClass('selected'); // Bug! Wrong 'this'
updateCounter();
}
});
});
});
});
$('#button2').click(function() {
// More nested callbacks...
});
// 500 more lines of nested callbacks...
});
The Problems
- No structure: Where does this code go? How is it organized?
- Callback hell: Nested callbacks become unreadable
- Shared mutable state: Any code can modify any element
- No data binding: Manually sync data and DOM
- Testing: How do you test jQuery spaghetti?
Symptoms of Scale
Small projects thrived. Large projects suffered:
- "Nobody understands this code anymore"
- "Every change breaks something unexpected"
- "We need to rewrite everything"
Part 8: The Framework Vacuum
What Developers Wanted
- Structure for organizing code
- Patterns for data management
- Components that encapsulate behavior
- Two-way data binding
- Testability
Early Attempts
Backbone.js (2010): Minimal structure
- Models for data
- Views for rendering
- Collections for groups
- Still very manual
Knockout.js (2010): Data binding focus
- Two-way binding between DOM and data
- Observables for reactive updates
- Inspired later frameworks
Angular.js (2010): Full framework
- Google's answer
- Two-way data binding
- Dependency injection
- Directives for custom HTML
- Complex but powerful
The Stage Set for React
By 2013:
- jQuery showed that rich UIs were possible
- jQuery showed that rich UIs got messy
- Angular showed that frameworks could help
- Angular showed that frameworks could be complex
- Everyone wanted something better
Facebook was working on a solution.
Part 9: Legacy and Lessons
What jQuery Got Right
- Developer experience: Easy things were easy
- Cross-browser abstraction: Write once, run anywhere
- Plugin ecosystem: Extend functionality easily
- Documentation: Exceptionally well-documented
What We Learned
- Browsers need standards: jQuery shouldn't have been necessary
- Direct DOM manipulation doesn't scale: Need abstraction
- Shared mutable state causes bugs: Need data flow patterns
- Structure matters: Freedom without structure leads to chaos
jQuery Today
jQuery still powers millions of sites. But new projects rarely choose it because:
- Browsers standardized (querySelector, fetch, addEventListener)
- Frameworks provide better structure
- React/Vue/Svelte handle what jQuery did, plus more
The problems jQuery solved are now solved at the platform level.
Exercise 1: The AJAX Request
Write vanilla JavaScript (no jQuery) to:
- Make a GET request to
/api/items - Parse JSON response
- Update a div with the results
Solution
// Modern approach (what AJAX evolved into)
fetch('/api/items')
.then(response => response.json())
.then(data => {
const container = document.getElementById('items');
container.innerHTML = data.map(item =>
`<div class="item">${item.name}</div>`
).join('');
})
.catch(error => {
console.error('Failed to load items:', error);
});
// Or with async/await
async function loadItems() {
try {
const response = await fetch('/api/items');
const data = await response.json();
const container = document.getElementById('items');
container.innerHTML = data.map(item =>
`<div class="item">${item.name}</div>`
).join('');
} catch (error) {
console.error('Failed to load items:', error);
}
}
Modern browsers have fetch() — no XMLHttpRequest needed!
Exercise 2: Spot the Spaghetti
Look at this jQuery code and identify the problems:
$('#loadUsers').click(function() {
$.get('/api/users', function(users) {
var html = '';
for (var i = 0; i < users.length; i++) {
html += '<div class="user" data-id="' + users[i].id + '">';
html += users[i].name;
html += '</div>';
}
$('#userList').html(html);
$('.user').click(function() {
var userId = $(this).data('id');
selectedUserId = userId; // Global variable!
$(this).addClass('selected');
$('.user').not(this).removeClass('selected');
loadUserDetails(userId);
});
});
});
Problems
- Global variable:
selectedUserIdis global, can be modified anywhere - String concatenation for HTML: Error-prone, XSS vulnerability
- Nested callbacks: Hard to follow flow
- Event listeners recreated: Every time users load, new click handlers added (memory leak, multiple fires)
- Mixed concerns: Data fetching, rendering, and event handling all mixed together
- No error handling: What if the API fails?
- Hard to test: How would you unit test this?
Exercise 3: jQuery to Modern
Convert this jQuery to modern vanilla JavaScript:
$('.item').hide().fadeIn(300).addClass('visible');
Solution
// CSS-based animation (preferred)
document.querySelectorAll('.item').forEach(item => {
item.classList.add('fade-in', 'visible');
});
// CSS:
// .fade-in {
// animation: fadeIn 0.3s ease-in;
// }
// @keyframes fadeIn {
// from { opacity: 0; }
// to { opacity: 1; }
// }
// Or with Web Animations API
document.querySelectorAll('.item').forEach(item => {
item.animate([
{ opacity: 0 },
{ opacity: 1 }
], {
duration: 300,
fill: 'forwards'
});
item.classList.add('visible');
});
Modern CSS handles most animations better than JavaScript.
Key Takeaways
-
AJAX enabled rich applications — Background requests changed everything
-
Browser wars created pain — Incompatibility drove library adoption
-
jQuery was revolutionary — Cross-browser, easy DOM manipulation
-
Success creates new problems — Easy code doesn't mean maintainable code
-
Structure emerged as critical — Freedom without patterns leads to chaos
-
JSON won — Simpler than XML, native to JavaScript
-
The platform caught up — Modern browsers have built-in solutions
What's Next
Module 18: The Modern Frontend
You'll learn:
- How React changed the paradigm
- The component model and virtual DOM
- Build tools and the JavaScript ecosystem
- Where we are today and what's coming
You've completed Module 17! You now understand the era that shaped modern web development. The chaos of jQuery spaghetti directly led to React and the component model you learned in Part III.