JavaScript - Unable to unselect a button without triggering a page refresh

I have a series of buttons in a row that I can select individually. However, I only want to be able to choose one button at a time. Every time I deselect the previously selected button, it causes the page to reload when all I really want is for all the buttons to be deselected. Is there a way to achieve this?

https://jsfiddle.net/donfontaine12/um05k6cw/33/#&togetherjs=Hm5JqaEvUi

let rankedNo1 = document.querySelector("#ranked_no1");
let rankedNo2 = document.querySelector("#ranked_no2");
let rankedNo3 = document.querySelector("#ranked_no3");
let rankedNo4 = document.querySelector("#ranked_no4");
let rankedNo5 = document.querySelector("#ranked_no5");
let rankedNo6 = document.querySelector("#ranked_no6");
let rankedNo7 = document.querySelector("#ranked_no7");
let rankedNo8 = document.querySelector("#ranked_no8");
let rankedNo9 = document.querySelector("#ranked_no9");
let rankedNo10 = document.querySelector("#ranked_no10");

let rankedNoArray = [rankedNo1, rankedNo2, rankedNo3, rankedNo4, rankedNo5, rankedNo6, rankedNo7, rankedNo8, rankedNo9, rankedNo10];

rankedNo1.addEventListener("click", function() {
  toggleHighlight(rankedNo1);
  event.preventDefault();
});
rankedNo2.addEventListener("click", function() {
  toggleHighlight(rankedNo2);
  event.preventDefault();
});
rankedNo3.addEventListener("click", function() {
  toggleHighlight(rankedNo3);
  event.preventDefault();
});
rankedNo4.addEventListener("click", function() {
  toggleHighlight(rankedNo4);
  event.preventDefault();
});
rankedNo5.addEventListener("click", function() {
  toggleHighlight(rankedNo5);
  event.preventDefault();
});
rankedNo6.addEventListener("click", function() {
  toggleHighlight(rankedNo6);
  event.preventDefault();
});
rankedNo7.addEventListener("click", function() {
  toggleHighlight(rankedNo7);
  event.preventDefault();
});
rankedNo8.addEventListener("click", function() {
  toggleHighlight(rankedNo8);
  event.preventDefault();
});
rankedNo9.addEventListener("click", function() {
  toggleHighlight(rankedNo9);
  event.preventDefault();
});
rankedNo10.addEventListener("click", function() {
  toggleHighlight(rankedNo10);
  event.preventDefault();
});

function toggleHighlight(r) {
  let highlighted = lastHighlighted();
  if (highlighted) {
    for (let h of highlighted) {
      if (h == r) {
        r.firstElementChild.classList.remove("selected");
        highlighted[h.index].remove();
      } else {
        h.firstElementChild.classList.remove("selected");
        if (r.firstElementChild.classList.contains("selected")) {
          r.firstElementChild.classList.remove("selected");
        } else {
          r.firstElementChild.classList.add("selected");
        }
      }
    }
  } else {
    if (r.firstElementChild.classList.contains("selected")) {
      r.firstElementChild.classList.remove("selected");
    } else {
      r.firstElementChild.classList.add("selected");
    }
  }
}

function lastHighlighted() {
  let highlightedNos = rankedNoArray.filter(x => x.firstElementChild.classList.contains("selected"));
  return highlightedNos;
}
#rank_flex_combo #ranked_nos,
#rank_flex_combo,
#ranked_no,
#ranked_no1,
#ranked_no2,
#ranked_no3,
#ranked_no4,
#ranked_no5,
#ranked_no6,
#ranked_no7,
#ranked_no8,
#ranked_no9,
#ranked_no10 {
  display: flex;
  flex-direction: row;
  margin: 0em 0.5em;
}

#ranked_nos a,
#ranked_no1 a,
#ranked_no2 a,
#ranked_no3 a,
#ranked_no4 a,
#ranked_no5 a,
#ranked_no6 a,
#ranked_no7 a,
#ranked_no8 a,
#ranked_no9 a,
#ranked_no10 a {
  font-weight: bold;
  text-decoration: none;
  padding: 0.25em 0.5em;
  color: dodgerblue;
  background-color: lightcyan;
  border: 2px solid cyan;
  border-radius: 5px;
}

#ranked_nos .selected,
#ranked_no1 .selected,
#ranked_no2 .selected,
#ranked_no3 .selected,
#ranked_no4 .selected,
#ranked_no5 .selected,
#ranked_no6 .selected,
#ranked_no7 .selected,
#ranked_no8 .selected,
#ranked_no9 .selected,
#ranked_no10 .selected {
  color: mediumpurple;
  background-color: lavender;
  border: 2px solid mediumpurple;
}

#ranked_no a {
  font-weight: bold;
  text-decoration: none;
  padding: 0.25em 2em;
  color: dodgerblue;
  background-color: white;
  border: 2px solid cyan;
  border-radius: 5px;
}

#ranked_no1 a:hover,
#ranked_no2 a:hover,
#ranked_no3 a:hover,
#ranked_no4 a:hover,
#ranked_no5 a:hover,
#ranked_no6 a:hover,
#ranked_no7 a:hover,
#ranked_no8 a:hover,
#ranked_no9 a:hover,
#ranked_no10 a:hover {
  color: mediumpurple;
  background-color: lavender;
  border: 2px solid mediumpurple;
}
<div id="rank_flex_combo">
  <div id="ranked_no">
    <a href="">Rank No.</a>
  </div>
  <div id="ranked_no1">
    <a href="" class="selected">1</a>
  </div>
  <div id="ranked_no2">
    <a href="">2</a>
  </div>
  <div id="ranked_no3">
    <a href="">3</a>
  </div>
  <div id="ranked_no4">
    <a href="">4</a>
  </div>
  <div id="ranked_no5">
    <a href="">5</a>
  </div>
  <div id="ranked_no6">
    <a href="">6</a>
  </div>
  <div id="ranked_no7">
    <a href="">7</a>
  </div>
  <div id="ranked_no8">
    <a href="">8</a>
  </div>
  <div id="ranked_no9">
    <a href="">9</a>
  </div>
  <div id="ranked_no10">
    <a href="">10</a>
  </div>
</div>

Answer №1

Simply follow these steps:

const rankFlexCombo = document.getElementById('rank_flex_combo')
  ,   rankedNo1     = document.querySelector('#rank_flex_combo > div#ranked_no1')
  ,   rankedNoAll   = document.querySelectorAll('#rank_flex_combo > div')
  ;
rankedNo1.classList.add('selected')
var OnSelect = rankedNo1
  ;
rankFlexCombo.onclick= e => 
  {
  if (!e.target.matches('#rank_flex_combo > div')) return
  let rDiv = (e.target.id==='ranked_no') ? rankedNo1 : e.target;
  rankedNoAll.forEach(d=>d.classList.remove('selected'))

  if (rDiv===OnSelect)
    {
    // rankedNo1.classList.add('selected')
    //  OnSelect = rankedNo1              //   for default selected
    OnSelect = null
    }
  else 
    {
    rDiv.classList.add('selected')
    OnSelect = rDiv
    } 
  }
#rank_flex_combo {
  display: flex;
  flex-direction: row;
}
#rank_flex_combo > div {
  font-weight: bold;
  padding: 0.25em 0.5em;
  color: dodgerblue;
  background-color: lightcyan;
  border: 2px solid cyan;
  border-radius: 5px;
  margin: 0em 0.5em;
  cursor: pointer;
  }
#rank_flex_combo > div:hover,
#rank_flex_combo > div.selected {
  color: mediumpurple;
  background-color: lavender;
  border: 2px solid mediumpurple;
  }
<div id="rank_flex_combo">
  <div id="ranked_no"> Rank No.  </div>
  <div id="ranked_no1"> 1  </div>
  <div id="ranked_no2"> 2 </div>
  <div id="ranked_no3"> 3 </div>
  <div id="ranked_no4"> 4 </div>
  <div id="ranked_no5"> 5 </div>
  <div id="ranked_no6"> 6 </div>
  <div id="ranked_no7"> 7 </div>
  <div id="ranked_no8"> 8 </div>
  <div id="ranked_no9"> 9 </div>
  <div id="ranked_no10"> 10 </div>
 </div>

Answer №2

Here is a solution for your query: [Works]

let topRanked1 = document.querySelector("#top_ranked_1");
let topRanked2 = document.querySelector("#top_ranked_2");
let topRanked3 = document.querySelector("#top_ranked_3");
let topRanked4 = document.querySelector("#top_ranked_4");
let topRanked5 = document.querySelector("#top_ranked_5");
let topRanked6 = document.querySelector("#top_ranked_6");
let topRanked7 = document.querySelector("#top_ranked_7");
let topRanked8 = document.querySelector("#top_ranked_8");
let topRanked9 = document.querySelector("#top_ranked_9");
let topRanked10 = document.querySelector("#top_ranked_10");

let topRankedArray = [topRanked1, topRanked2, topRanked3, topRanked4, topRanked5, topRanked6, topRanked7, topRanked8, topRanked9, topRanked10];

topRanked1.addEventListener("click", function() {
  toggleSelection(topRanked1);
  event.preventDefault();
});
topRanked2.addEventListener("click", function() {
  toggleSelection(topRanked2);
  event.preventDefault();
});
// Repeat event listeners for topRanked3 to topRanked10...

function toggleSelection(r) {
  let selectedItems = getSelectedItems();
  
  if (selectedItems && selectedItems.length) {
    for (let item of selectedItems) {
      if (item == r) {
        r.firstElementChild.classList.remove("chosen");
      } else {
        item.firstElementChild.classList.remove("chosen");
        
        if (r.firstElementChild.classList.contains("chosen")) {
          r.firstElementChild.classList.remove("chosen");
        } else {
          r.firstElementChild.classList.add("chosen");
        }
      }
    }
  } else {
    r.firstElementChild.classList.add("chosen");
  }
}

function getSelectedItems() {
  return topRankedArray.filter(x => x.firstElementChild.classList.contains("chosen"));
}
#rank_select_combo #top_ranked_items, #rank_select_combo, #top_ranked_item,
#top_ranked_1, #top_ranked_2, #top_ranked_3, #top_ranked_4, #top_ranked_5,
#top_ranked_6, #top_ranked_7, #top_ranked_8, #top_ranked_9, #top_ranked_10 { 
    display: flex;
    flex-direction: row;
    margin: 0em 0.5em;
}
#top_ranked_items a,
// Styles for remaining elements should go here...
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="rank_select_combo">
        <div id="top_ranked_item">
            <a href="" >Top Ranked Item</a>
        </div>
        <div id="top_ranked_1">
            <a href="" class="chosen">1</a>
        </div>
        <div id="top_ranked_2">
            <a href="">2</a>
        </div>
        // Include similar HTML structure for topRanked3 to topRanked10...
    </div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to get 100% height to work properly in HTML5 ASP.net because of the DOCTYPE

I'm currently working on creating an Asp.net website with a unique single-page portfolio style for the homepage. Each project or section should be 100% height of the viewport, stacked underneath each other to make use of anchor tags. However, I'm ...

JavaScript form validation issue unresolved

When I attempt to validate form fields using Javascript functions, they seem to not load or check the field upon clicking the submit button. <html> <body> <?php require_once('logic.php'); ?> <h1>New Region/Entit ...

Mastering the art of utilizing clearInterval effectively

This reset button needs to clear/reset the timer. The issue is that when the user presses the start button more than once, it sets two timers - one from the previous start and one from the current start. I will be using clearInterval to solve this problem ...

What is the approach for utilizing Vue List Rendering with v-if to verify the presence of items within an array?

My current implementation utilizes v-if to conditionally display a list of cafes. However, I am interested in filtering the list based on whether a specific drink item is found in an array. For instance, I have a collection of cafes and I only want to dis ...

Stopping jQuery fadeOut from setting the display property to 'hidden'

I am currently working on a project that involves creating a lightbox effect. I am using jQuery's fadeIn and fadeOut functions to display enlarged div elements. However, I have encountered an issue - when I use fadeOut on the enlarged div, the smaller ...

The CSS3 selector matching a value starting with "[attribute^=value]" does not match a value that has spaces after the quotation marks

When using the div[class^="test"] selector, keep in mind that it will not select an element with a class attribute like class=" test-something" (This selector was generated on the backend.) Using the div[class^=" test"] is not a valid choice. ...

Utilizing Node.js and express to promptly address client requests while proceeding with tasks in the nextTick

I am looking to optimize server performance by separating high CPU consuming tasks from the user experience: ./main.js: var express = require('express'); var Test = require('./resources/test'); var http = require('http'); va ...

Buttons are not aligned with the rest of the row's height

I'm currently working on designing an upload layout that consists of a container with a row inside. Within the row, there are two buttons (each containing input elements) and one h3. For some reason, I am having difficulty getting them to align at the ...

Unlocking request header field access-control-allow-origin on VueJS

When attempting to send a POST request to the Slack API using raw JSON, I encountered the following error: Access to XMLHttpRequest at '' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field acces ...

django ajax request returning a 403 error

While attempting to compile project https://github.com/kannan4k/django-carpool, I encountered an error during an ajax call. The error message displayed was: "Failed to load resource: the server responded with a status of 400 (BAD REQUEST)." I suspect that ...

Guide to creating a new window without a menu bar for an onclick function in electronJS

After trying to remove the menu bar from the main window using win.setMenu(null) in the main.js file, I encountered a new issue. When opening a new window (referred to as the "add items window"), I struggled to find a way to hide the menu bar in it as well ...

Tips for Customizing Dialogs with CSS Classes in mui5 Using Emotion/Styled

When attempting to customize the styling of a mui Dialog, I encountered an issue where it wouldn't accept className even when placed inside PaperProps. While inline styles worked, my preference was to import styles from a separate stylesheet named Sty ...

Setting cookies in Express will not work if you are using res.sendFile()

After implementing the res.sendFile() function, I noticed that the set-cookie header is not being received in the response. app.get(sessionTracker, (req, res, next) => { res.cookie('tracker', '123a', { maxAge: 172800000, h ...

What is the best way to filter specific data types when using ngFor in Angular?

As I loop through the array named "fruits," which contains objects of type "FruitService" that I created, I want to display each element. However, when I delete them (I know it's strange, no database involved), they turn into type "undefined" and star ...

I am having trouble getting the bootstrap link and css files to work on a specific URL. Can you please help me troubleshoot this issue and let me know if there are any additional files needed to

When attempting to apply the bootstrap link and css files to the URL "/list/:customListName", they are not working. However, changing the URL to "/:customListName" somehow makes it work. What is the reason behind this behavior and how can I properly style ...

ERROR: Running out of memory in JavaScript heap while executing a command with "npm"

Encountered a fatal error (FATAL ERROR: MarkCompactCollector: semi-space copy, fallback in old gen Allocation failed - JavaScript heap out of memory) while attempting to execute any npm command. The error persists even with the simple "npm -v" command. I ...

Efficiency levels of reach = within angular instructions

Creating a directive can be done in various ways. Here is an example of how I structured mine: 'use strict'; myApp.directive('mySwitchOnOff', [ '$rootScope', function($rootScope) { return { restrict: 'C' ...

WindiCSS classes are not functioning properly within a Nuxt application

I've been encountering some difficulties with WindiCSS. The classes are not being applied to the elements as expected. I attempted to install an older version of Windi, but the issue persisted. I even tried switching to Tailwind instead of Windi, but ...

Using jQuery to Drag: Creating a draggable effect on a div element

I recently posted a question, but I feel like I need to rephrase it to make it more general. Basically, I have an element that can be moved around and resized using jQuery. I used CSS to attach another div to the right of this element. Initially, when you ...

exploring div element(s) with jQuery

My HTML page contains multiple div elements in the body. I have also included buttons with associated click functions in jQuery to change the background-color of a div element based on the button pressed. However, I'm facing an issue at the 'term ...