Add a class to one and only one element from an HTML list on click

I assume you need to remove the active class from the rest of the items and then update the correct item. However, I'm not sure that classList is available in the older browsers you seek to support. You should look into the polyfill for older bowsers.

const items = document.querySelectorAll(".item");

for (let i = 0; i < items.length; i++) {
  const item = items[i];
  item.addEventListener("click", changeActiveClass);
}

function changeActiveClass(e)
{
  for (let i = 0; i < items.length; i++) {
    const item = items[i];
    item.classList.remove('active');
  }
  e.target.classList.add('active');
}

Your current approach adds multiple click handlers to the element which fire sequentially in order, removing and adding the class multiple times and with unpredictable results due to the nested loop.

Existing answers use an O(n) solution that involves looping over all of the elements in the list, but there's no need for this. Simply keep a reference to the last selected element and remove the .active class from that element if it's defined:

const list = [...document.querySelectorAll("ul li")];
let selectedEl;

for (const el of list) {
  el.addEventListener("click", e => {
    selectedEl && selectedEl.classList.remove("active");
    selectedEl = e.target;
    e.target.classList.add("active");
  });
}
.active {
  background: yellow;
}
<ul>
  <li class="item">Item 1</li>
  <li class="item">Item 2</li>
  <li class="item">Item 3</li>
</ul>

An alternate approach is to set a tabindex attribute to each element, then add listeners for focus and blur (or focusin/focusout if you want bubbling) which may more accurately capture the selection/deselection semantics you're trying to achieve. Moving focus to anywhere will deselect the list item, unlike the click event approach shown above.

for (const el of [...document.querySelectorAll("ul li")]) {
  el.addEventListener("focus", e => e.target.classList.add("active"));
  el.addEventListener("blur", e => e.target.classList.remove("active"));
}
.active {
  background: yellow;
  outline: none;
}
<ul>
  <li class="item" tabindex="-1">Item 1</li>
  <li class="item" tabindex="-1">Item 2</li>
  <li class="item" tabindex="-1">Item 3</li>
</ul>

If you're looking to support legacy browsers, you could try (untested):

var list = document.getElementsByTagName("li");
var selectedEl;

for (var i = 0; i < list.length; i++) {
  list[i].addEventListener("click", function (e) {
    if (selectedEl) {
      selectedEl.className = selectedEl.className
        .split(/\s+/)
        .filter(function (e) { e !== "active"; })
        .join(" ");
    }

    selectedEl = e.target;
    e.target.className += " active";
  });
}
.active {
  background: yellow;
}
<ul>
  <li class="item">Item 1</li>
  <li class="item">Item 2</li>
  <li class="item">Item 3</li>
</ul>

or

var list = document.getElementsByTagName("li");

for (var i = 0; i < list.length; i++) {
  list[i].addEventListener("focusin", function (e) {
    e.target.className += " active";
  });
  list[i].addEventListener("focusout", function (e) {
    e.target.className = e.target.className
      .split(/\s+/)
      .filter(function (e) { e !== "active"; })
      .join(" ");
  });
}
.active {
  background: yellow;
  outline: none;
}
<ul>
  <li class="item" tabindex="-1">Item 1</li>
  <li class="item" tabindex="-1">Item 2</li>
  <li class="item" tabindex="-1">Item 3</li>
</ul>


You'll need to change the for-loop a little:

for (let i = 0; i < items.length; i++) {
  const clickedItem = items[i];
 
  // Add an event listener to each item
  clickedItem.addEventListener("click", function() {

    // Remove class from all items
    for (let j = 0; j < items.length; j++) {
      const item = items[j];
      item.classList.remove("active");
    }

    // Add class to the clicked item
    clickedItem.classList.add("active");

  });
}

Note that you could also use an arrow function, but if you're going for backwards compatibility, it's best to use function.