DOM Manipulation
The DOM (Document Object Model) is a tree representation of the HTML that can be manipulated with JavaScript.
Selecting Elements
getElementById
<div id="header">Hello</div>
<script>
const element = document.getElementById('header');
element.textContent = 'World';
</script>
querySelector
<div class="container">
<p class="text">First</p>
<p class="text">Second</p>
</div>
<script>
const first = document.querySelector('.text');
const all = document.querySelectorAll('.text');
</script>
Changing Content
textContent vs innerHTML
<div id="content"></div>
<script>
const el = document.getElementById('content');
// textContent - safe, text only
el.textContent = '<b>Bold</b>'; // Displays literal text
// innerHTML - prone to XSS
el.innerHTML = '<b>Bold</b>'; // Displays bold
</script>
insertAdjacentHTML
<div id="list">
<h2>Student List</h2>
</div>
<script>
const list = document.getElementById('list');
list.insertAdjacentHTML('beforeend',
'<p>John Smith</p><p>Sarah Lee</p>');
</script>
Changing Styles
<div id="box" style="width: 100px; height: 100px; background: red;"></div>
<script>
const box = document.getElementById('box');
// Direct style
box.style.backgroundColor = 'blue';
box.style.borderRadius = '8px';
// ClassList
box.classList.add('active');
box.classList.remove('active');
box.classList.toggle('active');
box.classList.contains('active'); // true/false
</script>
Changing Attributes
<a id="link" href="https://google.com">Google</a>
<script>
const link = document.getElementById('link');
link.setAttribute('target', '_blank');
link.getAttribute('href');
link.removeAttribute('target');
</script>
Creating and Removing Elements
<ul id="list"></ul>
<button onclick="addItem()">Add</button>
<script>
function addItem() {
const li = document.createElement('li');
li.textContent = 'New item';
document.getElementById('list').appendChild(li);
}
function removeItem() {
const li = document.querySelector('li');
li.remove();
}
</script>
Case Study: Interactive Campus Dashboard
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Campus Dashboard</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', sans-serif;
background: #f0f2f5;
color: #333;
}
.header {
background: #1e3a5f;
color: white;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.main {
padding: 2rem;
max-width: 1200px;
margin: 0 auto;
}
.stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1.5rem;
margin-bottom: 2rem;
}
.stat-card {
background: white;
padding: 1.5rem;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
text-align: center;
}
.stat-card h3 {
color: #666;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.stat-card .value {
font-size: 2rem;
font-weight: bold;
color: #1e3a5f;
}
.content {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 1.5rem;
}
.card {
background: white;
padding: 1.5rem;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.card h2 {
color: #1e3a5f;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 2px solid #eee;
}
.btn {
padding: 0.5rem 1rem;
background: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 0.5rem;
margin-bottom: 0.5rem;
}
.btn:hover {
background: #2980b9;
}
.btn-danger {
background: #e74c3c;
}
.btn-danger:hover {
background: #c0392b;
}
.btn-success {
background: #2ecc71;
}
.btn-success:hover {
background: #27ae60;
}
.student-list {
list-style: none;
}
.student-item {
padding: 0.8rem;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
}
.student-item:last-child {
border-bottom: none;
}
.student-item .name {
font-weight: 500;
}
.student-item .studentId {
color: #666;
font-size: 0.85rem;
}
.student-item .actions {
display: flex;
gap: 0.5rem;
}
.student-item .btn {
padding: 0.3rem 0.6rem;
font-size: 0.8rem;
}
.add-form {
margin-top: 1rem;
padding-top: 1rem;
border-top: 2px solid #eee;
}
.form-row {
display: flex;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.form-row input {
flex: 1;
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 4px;
}
.activity-list {
list-style: none;
}
.activity-item {
padding: 0.8rem;
border-left: 3px solid #3498db;
margin-bottom: 0.8rem;
background: #f8f9fa;
border-radius: 0 4px 4px 0;
}
.activity-item .time {
font-size: 0.75rem;
color: #666;
}
.notification {
position: fixed;
top: 20px;
right: 20px;
background: #2ecc71;
color: white;
padding: 1rem 1.5rem;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
transform: translateX(120%);
transition: transform 0.3s;
}
.notification.show {
transform: translateX(0);
}
.notification.error {
background: #e74c3c;
}
</style>
</head>
<body>
<div class="header">
<h1>Campus Dashboard</h1>
<div id="clock"></div>
</div>
<div class="main">
<div class="stats">
<div class="stat-card">
<h3>Total Student</h3>
<div class="value" id="totalStudents">0</div>
</div>
<div class="stat-card">
<h3>Lecturer</h3>
<div class="value" id="totalLecturers">0</div>
</div>
<div class="stat-card">
<h3>Active Class</h3>
<div class="value" id="totalClasses">0</div>
</div>
<div class="stat-card">
<h3>Average GPA</h3>
<div class="value" id="avgGPA">0.00</div>
</div>
</div>
<div class="content">
<div class="card">
<h2>Student List</h2>
<div class="actions" style="margin-bottom: 1rem;">
<button class="btn btn-success" onclick="addRandomStudent()">Add Random</button>
<button class="btn btn-danger" onclick="clearStudents()">Delete All</button>
</div>
<ul class="student-list" id="studentList"></ul>
<div class="add-form">
<h3 style="margin-bottom: 0.5rem; font-size: 0.9rem;">Manual Add</h3>
<div class="form-row">
<input type="text" id="inputName" placeholder="Name">
<input type="text" id="inputStudentId" placeholder="StudentID">
<button class="btn" onclick="addManualStudent()">Add</button>
</div>
</div>
</div>
<div class="card">
<h2>Latest Activity</h2>
<ul class="activity-list" id="activityList"></ul>
</div>
</div>
</div>
<div class="notification" id="notification"></div>
<script>
// Data
let students = [
{ name: 'John Smith', studentId: '1234567890' },
{ name: 'Sarah Lee', studentId: '0987654321' },
{ name: 'Robert Brown', studentId: '1122334455' }
];
let activities = [
{ text: 'John enrolled in a new class', time: '2 minutes ago' },
{ text: 'Sarah submitted an assignment', time: '5 minutes ago' }
];
// Render functions
function renderStudents() {
const list = document.getElementById('studentList');
list.innerHTML = '';
students.forEach((student, index) => {
const li = document.createElement('li');
li.className = 'student-item';
li.innerHTML = `
<div>
<div class="name">${student.name}</div>
<div class="studentId">${student.studentId}</div>
</div>
<div class="actions">
<button class="btn" onclick="editStudent(${index})">Edit</button>
<button class="btn btn-danger" onclick="deleteStudent(${index})">Delete</button>
</div>
`;
list.appendChild(li);
});
updateStats();
}
function renderActivities() {
const list = document.getElementById('activityList');
list.innerHTML = '';
activities.slice(0, 5).forEach(activity => {
const li = document.createElement('li');
li.className = 'activity-item';
li.innerHTML = `
<div>${activity.text}</div>
<div class="time">${activity.time}</div>
`;
list.appendChild(li);
});
}
function updateStats() {
document.getElementById('totalStudents').textContent = students.length;
document.getElementById('totalLecturers').textContent = '25';
document.getElementById('totalClasses').textContent = '12';
document.getElementById('avgGPA').textContent = '3.45';
}
// CRUD Operations
function addRandomStudent() {
const names = ['Mike Johnson', 'Dana Lewis', 'Frank Nelson', 'Grace Parker'];
const randomName = names[Math.floor(Math.random() * names.length)];
const randomStudentId = Math.floor(1000000000 + Math.random() * 9000000000).toString();
students.push({ name: randomName, studentId: randomStudentId });
addActivity(`${randomName} added`);
renderStudents();
showNotification(`${randomName} successfully added!`);
}
function addManualStudent() {
const name = document.getElementById('inputName').value.trim();
const studentId = document.getElementById('inputStudentId').value.trim();
if (name && studentId) {
students.push({ name, studentId });
addActivity(`${name} added manually`);
renderStudents();
showNotification(`${name} successfully added!`);
document.getElementById('inputName').value = '';
document.getElementById('inputStudentId').value = '';
} else {
showNotification('Name and StudentID are required!', true);
}
}
function editStudent(index) {
const student = students[index];
const newName = prompt('New name:', student.name);
const newNim = prompt('New StudentID:', student.studentId);
if (newName && newNim) {
students[index] = { name: newName, studentId: newNim };
addActivity(`${student.name} updated`);
renderStudents();
showNotification('Data updated successfully!');
}
}
function deleteStudent(index) {
const student = students[index];
if (confirm(`Delete ${student.name}?`)) {
students.splice(index, 1);
addActivity(`${student.name} removed`);
renderStudents();
showNotification(`${student.name} successfully deleted!`);
}
}
function clearStudents() {
if (confirm('Delete all students?')) {
students = [];
addActivity('All students removed');
renderStudents();
showNotification('All data deleted successfully!');
}
}
function addActivity(text) {
activities.unshift({ text, time: 'Just now' });
renderActivities();
}
function showNotification(message, isError = false) {
const notif = document.getElementById('notification');
notif.textContent = message;
notif.className = isError ? 'notification error show' : 'notification show';
setTimeout(() => {
notif.classList.remove('show');
}, 3000);
}
// Clock
function updateClock() {
const now = new Date();
document.getElementById('clock').textContent =
now.toLocaleTimeString('id-ID') + ' - ' +
now.toLocaleDateString('id-ID', { weekday: 'long' });
}
// Initialize
renderStudents();
renderActivities();
updateClock();
setInterval(updateClock, 1000);
</script>
</body>
</html>
Everyday Case Study
Case: A developer needs to toggle section visibility.
<button onclick="toggleSection()">Toggle Section</button>
<div id="section" style="display: none;">
<p>This is content that can be toggled.</p>
</div>
<script>
function toggleSection() {
const section = document.getElementById('section');
if (section.style.display === 'none') {
section.style.display = 'block';
} else {
section.style.display = 'none';
}
}
</script>
Best Practices
- Batch DOM updates: Reduce reflow
- DocumentFragment: For multiple inserts
- Event delegation: More efficient
- querySelector vs getElementById: Pick the one that fits your needs
- Don't access the DOM repeatedly: Cache selectors
Summary
DOM manipulation enables dynamic changes to HTML pages. Use it efficiently for optimal performance.