Guide on hiding a div element when clicked outside of it?

How can I create a dropdown feature in Khan Academy where it disappears when clicked outside but stays visible when clicked inside, using JavaScript/CSS/HTML? The current implementation closes the dropdown even on internal clicks. The code includes an event listener attached to the document's click event to hide the dropdown if the clicked element is not the dropdown itself or the account image. What is causing this issue and how can it be fixed to achieve the desired functionality within Khan Academy's limitations? Here is the attempted code:

// Function to open the account dropdown
function openAccdrpdwn() {
  document.getElementById("acc-drpdwn").style.display = "block";
}

// Event listener to open the account dropdown when clicking on the account image
document.getElementById('account-signin').addEventListener('click', openAccdrpdwn);

// Event listener to close the account dropdown when clicking outside of it
document.onclick = function(event) {
  var dropdown = document.getElementById("acc-drpdwn");
  var accountImage = document.getElementById("account-signin");

  if (event.target !== dropdown && event.target !== accountImage) {
    dropdown.style.display = "none";
  }
};
#account {
  background-color: rgb(247, 247, 247);
  width: 175px;
  height: 300px;
  border-radius: 17px;
  position: absolute;
  top: 68px;
  left: 408px;
  box-shadow: 0px 0px 7px 3px lightgray;
  z-index: 1;
}
...

The above code doesn't work correctly as the dropdown still disappears when clicked inside. Any suggestions on how to implement this feature properly within Khan Academy's environment?

Answer №1

Take a look at the example provided below

<!doctype html>
<html lang="en" onclick="bubbleOut(this)">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <script>
    function bubbleOut(self) {
      const domRef = document.getElementById("disappear");
      domRef.remove();
    }
    function eatTheclick(ref) {
      event.stopPropagation();
    }
  </script>
  <body style="border: 1px salmon solid">
    <div
      style="width: 100px; height: 500; border: 1px solid red"
      onclick="eatTheclick(this)"
    >
      <p id="disappear">Click me to keep me. Click outside of the red block and I stay</p>
      <div>I will remain</div>
      <div>And so will I</div>
    </div>
  </body>
</html>

You can save this code as an HTML file and then view it in a browser. While not an exact solution to your issue, you could adapt a similar approach in your own code.

  1. The root HTML element has an onclick event that references the element to be removed when clicked.

  2. The element itself contains an onclick event that prevents click propagation.

Answer №2

Since the dropdown contains child elements, the target of the event may not necessarily be the dropdown itself but one of its children. To handle this situation, you can check if the event.target is a descendant of the dropdown:

if (!dropdown.contains(event.target) && event.target !== accountImage) {
  dropdown.style.display = "none";
}

// Function for displaying the account dropdown
function openAccountDropdown(event) {
  event.stopPropagation(); // Prevent document.onclick from triggering when opening the dropdown
  document.getElementById("acc-drpdwn").style.display = "block";
} // Event listener to display the account dropdown upon clicking on the account image
document.getElementById('account-signin').addEventListener('click', openAccountDropdown);
// Function for displaying the account dropdown

// Event listener to hide the account dropdown when clicked outside of it
document.onclick = function(event) {
  var dropdown = document.getElementById("acc-drpdwn");
  var accountImage = document.getElementById("account-signin");

  if (!dropdown.contains(event.target) && event.target !== accountImage) {
    dropdown.style.display = "none";
  }
};
#account {
  background-color: rgb(247, 247, 247);
  width: 175px;
  height: 300px;
  border-radius: 17px;
  position: absolute;
  top: 68px;
  left: 408px;
  box-shadow: 0px 0px 7px 3px lightgray;
  z-index: 1;
}

#inside-account {
  background-color: rgb(209, 255, 215);
  width: 175px;
  height: 80px;
  border-top-right-radius: 17px;
  border-top-left-radius: 17px;
  position: absolute;
  top: 68px;
  left: 408px;
  z-index: 2;
}

#acc-drpdwn {
  display: none;
}

.account-image {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  position: absolute;
  left: 0px;
  top: 1.8px;
  cursor: pointer;
}

#account-image {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background-color: #ccc;
  position: absolute;
  left: -2px;
  top: -2.2px;
  float: left;
}
<button class="account-image" id="account-signin">
  <img id="account-image" src="https://upload.wikimedia.org/wikipedia/commons/9/99/Sample_User_Icon.png" alt="Sample User Icon">
</button>
<div id="acc-drpdwn">
  <div id="account">Account</div>
  <div id="inside-account">Inside Account</div>
</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

How can I transform area, city, state, and country into latitude and longitude using Google Maps API v3?

Is there a way to retrieve the latitude and longitude for a string that includes area name, city name, state name, and country name using Google Maps API V3? ...

Launching an online platform with Express and Ember frameworks

I am embarking on a project to create a straightforward CMS using Node.js (with Express) and Ember.js. While I have experience with Angular, I am new to Ember.js. I've noticed that Ember.js operates similarly to Angular in terms of its CLI reliance, a ...

retrieving a JSON attribute that requires an additional HTTP call

Greetings, I have a dilemma related to Angular and a JSON file that I would like to share. Here is a snippet of the JSON data: { "users": [ { "gender": "male", "title": "mr", "first": "francisco", "last": "medina", "street": "2748 w dallas st", "c ...

Searching for an AngularJS and Bootstrap Dual Listbox Solution

I need a component like this to integrate into my project: I am hoping to add it using npm. However, I have tried some of the examples available but faced issues (encountered exceptions or only found bower instead of npm). The following are the examples ...

Access data from previous request and transmit it to another request in a Node.js environment

I am facing a situation where I need to extract the parsed json response from a variable in a POST request, store it in a new variable, and then pass that variable in the headers for a subsequent GET request. However, my current approach is not yielding th ...

The MVC framework coupled with a robust Javascript/JQuery validation library is a winning

Currently, I am involved in a project that utilizes MVC 2.0 along with Kendo UI. Our team has made the decision to utilize AJAX validation instead of MVC Model level validation. This means that validation occurs during most "onchange" events on HTML contro ...

My HTML and CSS design is not displaying correctly on mobile devices

Currently, I am in the process of utilizing a free website template. However, I am facing an issue with adjusting the background image. Is there anyone who can provide some guidance on resolving this particular problem? I would be happy to share the code ...

In JavaScript, the function is unable to access elements within an iteration of ng-repeat

I am using ng-repeat to display datepickers that are powered by flatpickr. To make this work, a script needs to be added on the page for each input element like so: <script> $('[name="DOB"]').flatpickr({ enableTime: false, dateForm ...

Updating all the direct components within the corresponding category with jQuery

Here is the HTML content I am working with: <li class="info"> info<li> <li class="other"> info<li> <li class="other"> info<li> <li class="Error"> error<li> <li class="other"> error<li> < ...

What is the process for adding a dot to the package.json file using the npm-pkg command?

I need help using the npm pkg set command to create a package.json file with the following structure: { ... "exports": { ".": { "import": "./dist/my-lib.js", "require": "./dist/my-l ...

How can I use JavaScript to modify the style of the first unordered list (ul) element without affecting the

function displayMenu(){ var parentElement = document.getElementById("menuItem1"); var lis = parentElement.getElementsByTagName("ul"); for (var i = 0; i < lis.length; i++) { lis[i].setAttribute("style","display: block"); } } When the button is clicke ...

Is it feasible to utilize math.max with an array of objects?

When it comes to finding the largest number in an array, solutions like this are commonly used: var arr = [1, 2, 3]; var max = Math.max(...arr); But how can we achieve a similar result for an array of objects, each containing a 'number' field? ...

Ways to prevent my website from being accessed through the Uc Browser

Is there a way to prevent my website from functioning on UC Browser using HTML or JavaScript? ...

Ways to extract particular items from a JSON array and store them in a JavaScript array

I am dealing with an external JSON-file structured as follows: { "type":"FeatureCollection", "totalFeatures":1, "features": [{ "type":"Feature", "id":"asdf", "geometry":null, "properties": { "PARAM1":"19 16 11", ...

Tips for transferring an array between two applications using AngularJS

I have two applications, appA for front end and appB for admin end. In appA, I am building an array called queries using a service through a controller. However, when I try to retrieve this array list in a controller in appB, it appears empty. Everytime ...

Is there a way to recover a deleted element from an array?

I have a list of user cards, and my task is: Clicking the "undo" button: will restore the last card that was deleted (using an array) Question 1: How can I create an array from the displayed cards list? Question 2: How do I restore the last deleted card? ...

During operational hours, an Ajax request may cause interruptions to the website's functionality

Having an issue with a large ajax request: I am querying a PHP file that makes some cURL requests, taking 15-20 seconds to complete and then returning JSON on my webpage. It's a standard ajax request, but I found a strange bug. While the ajax query i ...

CSS exhibiting variations on similar pages

Although the pages look identical, they are actually pulled from the same template file in Drupal but have different URLs. nyc.thedelimagazine.com/snacks In my document head, I've included a style rule that overrides a stylesheet further up the casc ...

I have successfully set up micro-cors on my system, and as I tried to compile, I received the following outcome

While working on the Next.js Stripe project, I ran into an unexpected problem that I need help with. ./src/pages/api/webhooks.ts:3:18 Type error: Could not find a declaration file for module 'micro-cors'. 'E:/Project/longlifecoin/node_module ...

Enabling block scrolling on a parent element using jscrollpane functionality

Is it possible to set up a jscrollpane so that the parent pane doesn't scroll when the child scroll has reached its bottom? Currently, when the child scrolling reaches the bottom, the parent also scrolls. I would like the parent to only scroll when th ...