admin管理员组

文章数量:1123181

I am working on a feature where posts have an ellipsis menu (three dots) that can be clicked to open a dropdown menu with additional options (e.g., edit, delete, etc.). The behavior I want is:

  1. When I click the ellipsis on a specific post, its dropdown menu should appear.
  2. If I then click the ellipsis on another post, the dropdown menu for the first post should close automatically, and only the dropdown menu for the second post should be visible.
  3. At any time, only one dropdown menu should be open across all posts.
  4. If I scroll, the menu should hide

Currently it is like this

app.js [function fetchPosts]


function fetchPosts() {
  if (user != "") {
    const postsRef = database.ref("posts/");
    postsRef.once("value", (snapshot) => {
      const postsContainer = document.getElementById("posts");
      postsContainer.innerHTML = ""; // Clear existing posts

      // Collect posts into an array
      const postsArray = [];
      snapshot.forEach((postSnapshot) => {
        const post = postSnapshot.val();
        post.id = postSnapshot.key; // Add the post ID to the object
        postsArray.push(post);
      });

      // Sort posts by date (newest to oldest)
      postsArray.sort((a, b) => b.time - a.time);

      // Loop through the sorted posts
      postsArray.forEach((post) => {
        // Create elements for the post data
        const postDiv = document.createElement("div");
        postDiv.classList.add("post");
        postDiv.setAttribute("id", post.id);

        // Create elements for each attribute
        const user_pic = document.createElement("div");
        user_pic.classList.add("user-pic");
        const img = document.createElement("img");
        const img_address = database.ref("users/" + post.user_id + "/user_pic");
        img_address.on("value", (snapshot) => {
          const data = snapshot.val();
          img.src = data;
        });
        user_pic.appendChild(img);

        const post_content = document.createElement("div");
        const row = document.createElement("div");
        post_content.classList.add("post_content");
        row.classList.add("row");
        post_content.appendChild(row);

        const title = document.createElement("p");
        title.classList.add("title");
        title.innerText = post.title;
        const usernameAndTime = document.createElement("div");
        const username = document.createElement("p");
        username.classList.add("username");
        const f_name = database.ref("users/" + post.user_id + "/full_name");
        f_name.on("value", (snapshot) => {
          const data = snapshot.val();
          username.innerText = data;
        });
        usernameAndTime.appendChild(username)
        const description = document.createElement("p");
        description.classList.add("description");
        description.innerText = post.description;

        const time = document.createElement("p");
        time.classList.add("time");
        const dateString = new Date(post.time).toString();
        let date = new Date(dateString);

        // const formattedDate = timeSince(date)
        time.innerText = formatDate(date);
        // time.innerText = timeSince(date);
        usernameAndTime.appendChild(time);
        usernameAndTime.classList.add("usernameAndTime");
        // Append all elements to the post div
        row.appendChild(usernameAndTime);
        post_content.appendChild(description);
        postDiv.appendChild(user_pic);
        postDiv.appendChild(post_content);

        const postImg = database.ref("posts/" + post.id + "/images");
        postImg.on("value", (snapshot) => {
          const data = snapshot.val();
          if (data != "") {
            const imgPostDiv = document.createElement("div");
            const imgPic = document.createElement("img");
            imgPostDiv.appendChild(imgPic);
            imgPostDiv.style.display = "block";
            imgPic.src = data;
            post_content.appendChild(imgPostDiv);
            imgPostDiv.classList.add("post-image");
            const master_post = document.createElement("div");
            master_post.appendChild(postDiv);
            master_post.classList.add("master_post");
            const responseBar = document.createElement("div");
            responseBar.classList.add("responseBar");
            const likes = document.createElement("div"); // change to btn
            likes.classList.add("responseItem");
            const likesIcon = document.createElement("img");
            likesIcon.classList.add("responseIcon");
            const likesCount = document.createElement("p");
            likesCount.classList.add("likesCount");
            likesCount.innerText = post.likes;
            likes.onclick = function () {
              toggleLike(post.id);
            };
            const likesRef = database.ref("posts/" + post.id);
            likesRef.on("value", (snapshot) => {
              const data = snapshot.val();
              const likes = data.likes || 0;
              const likedBy = data.liked_by || [];
              if (likedBy.includes(user)) {
                likesIcon.src = "/assets/heart-filled.svg";
              }
              else {
                likesIcon.src = "/assets/heart-outline.svg";
              }

              // likesCount.innerText = formatNumber(likes);
              // likes.innerText = likedBy[user.uid] ? "Unlike" : "Like"; // Toggle button text
            });
            // likesRef.on("value", (snapshot) => {
            //   const data = snapshot.val();
            //   const likes = data.likes || 0;
            //   const likedBy = data.liked_by || {};
            //   likesCount.innerText = formatNumber(likes);
            //   likes.innerText = likedBy[user.uid] ? "Unlike" : "Like"; // Toggle button text
            // });
            // likes.innerText = "hellow world"
            likes.appendChild(likesIcon);
            likes.appendChild(likesCount);
            responseBar.appendChild(likes);
            master_post.appendChild(responseBar);
            postsContainer.appendChild(master_post);
            const share = document.createElement("div"); // change to btn
            share.classList.add("responseItem");
            const shareIcon = document.createElement("img");
            shareIcon.src = "assets/share.svg"
            shareIcon.classList.add("responseIcon");
            const shareCount = document.createElement("p");
            shareCount.classList.add("shareCount");
            shareCount.innerText = 0
            responseBar.appendChild(share);
            share.appendChild(shareIcon);
            share.appendChild(shareCount);
            const comments = document.createElement("div"); // change to btn
            comments.classList.add("responseItem");
            const commentsIcon = document.createElement("img");
            commentsIcon.src = "assets/comments.svg"
            commentsIcon.classList.add("responseIcon");
            const commentsCount = document.createElement("p");
            commentsCount.classList.add("commentsCount");
            commentsCount.innerText = 0;
            const bookmark = document.createElement("div"); // change to btn
            bookmark.classList.add("responseItem");
            const bookmarkIcon = document.createElement("img");
            const bookmarkCount = document.createElement("p");
            bookmarkIcon.src = "assets/bookmark.svg";
            bookmarkCount.innerText = 0;
            bookmarkIcon.classList.add("responseIcon");
            bookmarkCount.classList.add("commentsCount");

            bookmark.appendChild(bookmarkIcon);
            bookmark.appendChild(bookmarkCount);
            responseBar.appendChild(comments);
            responseBar.appendChild(bookmark);
            comments.appendChild(commentsIcon);
            comments.appendChild(commentsCount);
            
          }
          
          else {
            const master_post = document.createElement("div");
            master_post.appendChild(postDiv);
            master_post.classList.add("master_post");
            const responseBar = document.createElement("div");
            responseBar.classList.add("responseBar");
            const likes = document.createElement("div"); // change to btn
            likes.classList.add("responseItem");
            const likesIcon = document.createElement("img");
            likesIcon.classList.add("responseIcon");
            const likesCount = document.createElement("p");
            likesCount.classList.add("likesCount");
            likesCount.innerText = post.likes;
            likes.onclick = function () {
              toggleLike(post.id);
            };
            const likesRef = database.ref("posts/" + post.id);
            likesRef.on("value", (snapshot) => {
              const data = snapshot.val();
              const likes = data.likes || 0;
              const likedBy = data.liked_by || [];
              if (likedBy.includes(user)) {
                likesIcon.src = "/assets/heart-filled.svg";
              }
              else {
                likesIcon.src = "/assets/heart-outline.svg";
              }}
            )
            responseBar.classList.add("responseBar")
            // likesRef.on("value", (snapshot) => {
            //   const data = snapshot.val();
            //   const likes = data.likes || 0;
            //   const likedBy = data.liked_by || {};
            //   likesCount.innerText = formatNumber(likes);
            //   likes.innerText = likedBy[user.uid] ? "Unlike" : "Like"; // Toggle button text
            // });
            // likes.innerText = "hellow world"
            responseBar.appendChild(likes);
            likes.appendChild(likesIcon);
            likes.appendChild(likesCount);
            const share = document.createElement("div"); // change to btn
            share.classList.add("responseItem");
            const shareIcon = document.createElement("img");
            shareIcon.classList.add("responseIcon");
            const shareCount = document.createElement("p");
            shareCount.classList.add("shareCount");
            shareCount.innerText = 0; // innertext
            responseBar.appendChild(share);
            share.appendChild(shareIcon);
            share.appendChild(shareCount);

            const comments = document.createElement("div"); // change to btn
            comments.classList.add("responseItem");
            const commentsIcon = document.createElement("img");
            commentsIcon.classList.add("responseIcon");
            const commentsCount = document.createElement("p");
            commentsCount.classList.add("commentsCount"); 
            commentsCount.innerText = 0; //inner text
            responseBar.appendChild(comments);
            comments.appendChild(commentsIcon);
            comments.appendChild(commentsCount);
            shareIcon.src = "assets/share.svg";
            commentsIcon.src = "assets/comments.svg"; 
            master_post.appendChild(responseBar);
            postsContainer.appendChild(master_post)

            const bookmark = document.createElement("div"); // change to btn
            bookmark.classList.add("responseItem");
            const bookmarkIcon = document.createElement("img");
            const bookmarkCount = document.createElement("p");
            bookmarkIcon.src = "assets/bookmark.svg";
            bookmarkCount.innerText = 0;
            bookmarkIcon.classList.add("responseIcon");
            bookmarkCount.classList.add("commentsCount");

            bookmark.appendChild(bookmarkIcon);
            bookmark.appendChild(bookmarkCount);
                        responseBar.appendChild(bookmark);

          }
        });
        // postDiv.style.backgroundColor = "red";
        // posts_content.style.backgroundColor = "green";
        // Append the post div to the posts container
        //all content in postContainer
        // postsContainer > master_post > upper, lower
        
        
        // Create "Other Details" section with time and options
        const otherDetails = document.createElement("div");
        otherDetails.classList.add("otherDetails");
        // otherDetails.appendChild(time);
        row.appendChild(otherDetails);
        
        // Create Details button with dropdown menu
        const details = document.createElement("button");
        const dots_icon = document.createElement("img");
        dots_icon.src = "assets/dots.svg";
        dots_icon.classList.add("dots_icon");
        details.classList.add("details-post");
        details.appendChild(dots_icon);
        otherDetails.appendChild(details);

        

        // Create options menu (only once)
        const optionsMenu = document.createElement("div");
        optionsMenu.classList.add("options-menu");
        optionsMenu.style.display = "none"; // Initially hidden
        optionsMenu.style.position = "absolute"; // To position it below the button

        // Check if the logged-in user is the owner of the post
        if (post.user_id === user) {
          const editOption = document.createElement("button");
          editOption.innerText = "Edit Post";     
          editOption.onclick = function () {
            alert("Edit functionality goes here.");
          };
          optionsMenu.appendChild(editOption);

          const deleteOption = document.createElement("button");
          deleteOption.innerText = "Delete Post";
          deleteOption.onclick = function () {
            deletePost(post.id);
          };
          optionsMenu.appendChild(deleteOption);
        } else {
          const shareOption = document.createElement("button");
          shareOption.innerText = "Share Post";
          shareOption.onclick = function () {
            navigator.clipboard.writeText("/app.html#" + post.id);
            alert("Copied URL - /app.html#" + post.id);
          };
          optionsMenu.appendChild(shareOption);
        }

        // Append the options menu to the post div
        row.appendChild(optionsMenu);
        // const likeSection = document.createElement("div");
        // likeSection.classList.add("likes-section");

        // const likeButton = document.createElement("button");
        // likeButton.classList.add("like-button");
        // likeButton.onclick = function () {
        //   toggleLike(post.id);
        // };

        // const likeCount = document.createElement("p");
        // likeCount.classList.add("like-count");

        // const likesRef = database.ref("posts/" + post.id);

        // likesRef.on("value", (snapshot) => {
        //   const data = snapshot.val();
        //   const likes = data.likes || 0;
        //   const likedBy = data.liked_by || {};
        //   likeCount.innerText = `Likes: ${likes}`;
        //   likeButton.innerText = likedBy[user.uid] ? "Unlike" : "Like"; // Toggle button text
        // });

        // likeSection.appendChild(likeButton);
        // likeSection.appendChild(likeCount);

        // postDiv.appendChild(likeSection);

        // Track visibility of options menu
        let optionsMenuVisible = false;
        const postsSection = document.querySelector(".posts-section");

        // Listen for the scroll event on the posts-section
        postsSection.addEventListener("scroll", function () {
          // Hide the options menu when scrolling
          optionsMenu.style.display = "none";
        });
        // Add functionality for the details button
        details.onclick = function (event) {  
          event.stopPropagation();

          if (optionsMenuVisible) {
            // Hide options menu
            optionsMenu.style.display = "none";
            optionsMenuVisible = false;
          } else {
            // Show options menu
            optionsMenu.style.display = "block";

            // Get the button's position to position the options menu
            const rect = details.getBoundingClientRect();

            // Adjust the options menu position relative to the viewport
            optionsMenu.style.top = `${rect.bottom + window.scrollY}px`; // Position below the button
            optionsMenu.style.left = `${rect.left}px`; // Align with the button horizontally
            optionsMenuVisible = true;
          }
        };

        // Close the options menu if the user clicks anywhere outside of it
        document.addEventListener("click", function (event) {
          const optionsMenu = postDiv.querySelector(".options-menu");
          const detailsButton = postDiv.querySelector(".details-post");
          optionsMenu.style.display = "none";
          optionsMenuVisible = false;

        });
      });
    });
  }
}

I am working on a feature where posts have an ellipsis menu (three dots) that can be clicked to open a dropdown menu with additional options (e.g., edit, delete, etc.). The behavior I want is:

  1. When I click the ellipsis on a specific post, its dropdown menu should appear.
  2. If I then click the ellipsis on another post, the dropdown menu for the first post should close automatically, and only the dropdown menu for the second post should be visible.
  3. At any time, only one dropdown menu should be open across all posts.
  4. If I scroll, the menu should hide

Currently it is like this

app.js [function fetchPosts]


function fetchPosts() {
  if (user != "") {
    const postsRef = database.ref("posts/");
    postsRef.once("value", (snapshot) => {
      const postsContainer = document.getElementById("posts");
      postsContainer.innerHTML = ""; // Clear existing posts

      // Collect posts into an array
      const postsArray = [];
      snapshot.forEach((postSnapshot) => {
        const post = postSnapshot.val();
        post.id = postSnapshot.key; // Add the post ID to the object
        postsArray.push(post);
      });

      // Sort posts by date (newest to oldest)
      postsArray.sort((a, b) => b.time - a.time);

      // Loop through the sorted posts
      postsArray.forEach((post) => {
        // Create elements for the post data
        const postDiv = document.createElement("div");
        postDiv.classList.add("post");
        postDiv.setAttribute("id", post.id);

        // Create elements for each attribute
        const user_pic = document.createElement("div");
        user_pic.classList.add("user-pic");
        const img = document.createElement("img");
        const img_address = database.ref("users/" + post.user_id + "/user_pic");
        img_address.on("value", (snapshot) => {
          const data = snapshot.val();
          img.src = data;
        });
        user_pic.appendChild(img);

        const post_content = document.createElement("div");
        const row = document.createElement("div");
        post_content.classList.add("post_content");
        row.classList.add("row");
        post_content.appendChild(row);

        const title = document.createElement("p");
        title.classList.add("title");
        title.innerText = post.title;
        const usernameAndTime = document.createElement("div");
        const username = document.createElement("p");
        username.classList.add("username");
        const f_name = database.ref("users/" + post.user_id + "/full_name");
        f_name.on("value", (snapshot) => {
          const data = snapshot.val();
          username.innerText = data;
        });
        usernameAndTime.appendChild(username)
        const description = document.createElement("p");
        description.classList.add("description");
        description.innerText = post.description;

        const time = document.createElement("p");
        time.classList.add("time");
        const dateString = new Date(post.time).toString();
        let date = new Date(dateString);

        // const formattedDate = timeSince(date)
        time.innerText = formatDate(date);
        // time.innerText = timeSince(date);
        usernameAndTime.appendChild(time);
        usernameAndTime.classList.add("usernameAndTime");
        // Append all elements to the post div
        row.appendChild(usernameAndTime);
        post_content.appendChild(description);
        postDiv.appendChild(user_pic);
        postDiv.appendChild(post_content);

        const postImg = database.ref("posts/" + post.id + "/images");
        postImg.on("value", (snapshot) => {
          const data = snapshot.val();
          if (data != "") {
            const imgPostDiv = document.createElement("div");
            const imgPic = document.createElement("img");
            imgPostDiv.appendChild(imgPic);
            imgPostDiv.style.display = "block";
            imgPic.src = data;
            post_content.appendChild(imgPostDiv);
            imgPostDiv.classList.add("post-image");
            const master_post = document.createElement("div");
            master_post.appendChild(postDiv);
            master_post.classList.add("master_post");
            const responseBar = document.createElement("div");
            responseBar.classList.add("responseBar");
            const likes = document.createElement("div"); // change to btn
            likes.classList.add("responseItem");
            const likesIcon = document.createElement("img");
            likesIcon.classList.add("responseIcon");
            const likesCount = document.createElement("p");
            likesCount.classList.add("likesCount");
            likesCount.innerText = post.likes;
            likes.onclick = function () {
              toggleLike(post.id);
            };
            const likesRef = database.ref("posts/" + post.id);
            likesRef.on("value", (snapshot) => {
              const data = snapshot.val();
              const likes = data.likes || 0;
              const likedBy = data.liked_by || [];
              if (likedBy.includes(user)) {
                likesIcon.src = "/assets/heart-filled.svg";
              }
              else {
                likesIcon.src = "/assets/heart-outline.svg";
              }

              // likesCount.innerText = formatNumber(likes);
              // likes.innerText = likedBy[user.uid] ? "Unlike" : "Like"; // Toggle button text
            });
            // likesRef.on("value", (snapshot) => {
            //   const data = snapshot.val();
            //   const likes = data.likes || 0;
            //   const likedBy = data.liked_by || {};
            //   likesCount.innerText = formatNumber(likes);
            //   likes.innerText = likedBy[user.uid] ? "Unlike" : "Like"; // Toggle button text
            // });
            // likes.innerText = "hellow world"
            likes.appendChild(likesIcon);
            likes.appendChild(likesCount);
            responseBar.appendChild(likes);
            master_post.appendChild(responseBar);
            postsContainer.appendChild(master_post);
            const share = document.createElement("div"); // change to btn
            share.classList.add("responseItem");
            const shareIcon = document.createElement("img");
            shareIcon.src = "assets/share.svg"
            shareIcon.classList.add("responseIcon");
            const shareCount = document.createElement("p");
            shareCount.classList.add("shareCount");
            shareCount.innerText = 0
            responseBar.appendChild(share);
            share.appendChild(shareIcon);
            share.appendChild(shareCount);
            const comments = document.createElement("div"); // change to btn
            comments.classList.add("responseItem");
            const commentsIcon = document.createElement("img");
            commentsIcon.src = "assets/comments.svg"
            commentsIcon.classList.add("responseIcon");
            const commentsCount = document.createElement("p");
            commentsCount.classList.add("commentsCount");
            commentsCount.innerText = 0;
            const bookmark = document.createElement("div"); // change to btn
            bookmark.classList.add("responseItem");
            const bookmarkIcon = document.createElement("img");
            const bookmarkCount = document.createElement("p");
            bookmarkIcon.src = "assets/bookmark.svg";
            bookmarkCount.innerText = 0;
            bookmarkIcon.classList.add("responseIcon");
            bookmarkCount.classList.add("commentsCount");

            bookmark.appendChild(bookmarkIcon);
            bookmark.appendChild(bookmarkCount);
            responseBar.appendChild(comments);
            responseBar.appendChild(bookmark);
            comments.appendChild(commentsIcon);
            comments.appendChild(commentsCount);
            
          }
          
          else {
            const master_post = document.createElement("div");
            master_post.appendChild(postDiv);
            master_post.classList.add("master_post");
            const responseBar = document.createElement("div");
            responseBar.classList.add("responseBar");
            const likes = document.createElement("div"); // change to btn
            likes.classList.add("responseItem");
            const likesIcon = document.createElement("img");
            likesIcon.classList.add("responseIcon");
            const likesCount = document.createElement("p");
            likesCount.classList.add("likesCount");
            likesCount.innerText = post.likes;
            likes.onclick = function () {
              toggleLike(post.id);
            };
            const likesRef = database.ref("posts/" + post.id);
            likesRef.on("value", (snapshot) => {
              const data = snapshot.val();
              const likes = data.likes || 0;
              const likedBy = data.liked_by || [];
              if (likedBy.includes(user)) {
                likesIcon.src = "/assets/heart-filled.svg";
              }
              else {
                likesIcon.src = "/assets/heart-outline.svg";
              }}
            )
            responseBar.classList.add("responseBar")
            // likesRef.on("value", (snapshot) => {
            //   const data = snapshot.val();
            //   const likes = data.likes || 0;
            //   const likedBy = data.liked_by || {};
            //   likesCount.innerText = formatNumber(likes);
            //   likes.innerText = likedBy[user.uid] ? "Unlike" : "Like"; // Toggle button text
            // });
            // likes.innerText = "hellow world"
            responseBar.appendChild(likes);
            likes.appendChild(likesIcon);
            likes.appendChild(likesCount);
            const share = document.createElement("div"); // change to btn
            share.classList.add("responseItem");
            const shareIcon = document.createElement("img");
            shareIcon.classList.add("responseIcon");
            const shareCount = document.createElement("p");
            shareCount.classList.add("shareCount");
            shareCount.innerText = 0; // innertext
            responseBar.appendChild(share);
            share.appendChild(shareIcon);
            share.appendChild(shareCount);

            const comments = document.createElement("div"); // change to btn
            comments.classList.add("responseItem");
            const commentsIcon = document.createElement("img");
            commentsIcon.classList.add("responseIcon");
            const commentsCount = document.createElement("p");
            commentsCount.classList.add("commentsCount"); 
            commentsCount.innerText = 0; //inner text
            responseBar.appendChild(comments);
            comments.appendChild(commentsIcon);
            comments.appendChild(commentsCount);
            shareIcon.src = "assets/share.svg";
            commentsIcon.src = "assets/comments.svg"; 
            master_post.appendChild(responseBar);
            postsContainer.appendChild(master_post)

            const bookmark = document.createElement("div"); // change to btn
            bookmark.classList.add("responseItem");
            const bookmarkIcon = document.createElement("img");
            const bookmarkCount = document.createElement("p");
            bookmarkIcon.src = "assets/bookmark.svg";
            bookmarkCount.innerText = 0;
            bookmarkIcon.classList.add("responseIcon");
            bookmarkCount.classList.add("commentsCount");

            bookmark.appendChild(bookmarkIcon);
            bookmark.appendChild(bookmarkCount);
                        responseBar.appendChild(bookmark);

          }
        });
        // postDiv.style.backgroundColor = "red";
        // posts_content.style.backgroundColor = "green";
        // Append the post div to the posts container
        //all content in postContainer
        // postsContainer > master_post > upper, lower
        
        
        // Create "Other Details" section with time and options
        const otherDetails = document.createElement("div");
        otherDetails.classList.add("otherDetails");
        // otherDetails.appendChild(time);
        row.appendChild(otherDetails);
        
        // Create Details button with dropdown menu
        const details = document.createElement("button");
        const dots_icon = document.createElement("img");
        dots_icon.src = "assets/dots.svg";
        dots_icon.classList.add("dots_icon");
        details.classList.add("details-post");
        details.appendChild(dots_icon);
        otherDetails.appendChild(details);

        

        // Create options menu (only once)
        const optionsMenu = document.createElement("div");
        optionsMenu.classList.add("options-menu");
        optionsMenu.style.display = "none"; // Initially hidden
        optionsMenu.style.position = "absolute"; // To position it below the button

        // Check if the logged-in user is the owner of the post
        if (post.user_id === user) {
          const editOption = document.createElement("button");
          editOption.innerText = "Edit Post";     
          editOption.onclick = function () {
            alert("Edit functionality goes here.");
          };
          optionsMenu.appendChild(editOption);

          const deleteOption = document.createElement("button");
          deleteOption.innerText = "Delete Post";
          deleteOption.onclick = function () {
            deletePost(post.id);
          };
          optionsMenu.appendChild(deleteOption);
        } else {
          const shareOption = document.createElement("button");
          shareOption.innerText = "Share Post";
          shareOption.onclick = function () {
            navigator.clipboard.writeText("https://deardevs.vercel.app/app.html#" + post.id);
            alert("Copied URL - https://deardevs.vercel.app/app.html#" + post.id);
          };
          optionsMenu.appendChild(shareOption);
        }

        // Append the options menu to the post div
        row.appendChild(optionsMenu);
        // const likeSection = document.createElement("div");
        // likeSection.classList.add("likes-section");

        // const likeButton = document.createElement("button");
        // likeButton.classList.add("like-button");
        // likeButton.onclick = function () {
        //   toggleLike(post.id);
        // };

        // const likeCount = document.createElement("p");
        // likeCount.classList.add("like-count");

        // const likesRef = database.ref("posts/" + post.id);

        // likesRef.on("value", (snapshot) => {
        //   const data = snapshot.val();
        //   const likes = data.likes || 0;
        //   const likedBy = data.liked_by || {};
        //   likeCount.innerText = `Likes: ${likes}`;
        //   likeButton.innerText = likedBy[user.uid] ? "Unlike" : "Like"; // Toggle button text
        // });

        // likeSection.appendChild(likeButton);
        // likeSection.appendChild(likeCount);

        // postDiv.appendChild(likeSection);

        // Track visibility of options menu
        let optionsMenuVisible = false;
        const postsSection = document.querySelector(".posts-section");

        // Listen for the scroll event on the posts-section
        postsSection.addEventListener("scroll", function () {
          // Hide the options menu when scrolling
          optionsMenu.style.display = "none";
        });
        // Add functionality for the details button
        details.onclick = function (event) {  
          event.stopPropagation();

          if (optionsMenuVisible) {
            // Hide options menu
            optionsMenu.style.display = "none";
            optionsMenuVisible = false;
          } else {
            // Show options menu
            optionsMenu.style.display = "block";

            // Get the button's position to position the options menu
            const rect = details.getBoundingClientRect();

            // Adjust the options menu position relative to the viewport
            optionsMenu.style.top = `${rect.bottom + window.scrollY}px`; // Position below the button
            optionsMenu.style.left = `${rect.left}px`; // Align with the button horizontally
            optionsMenuVisible = true;
          }
        };

        // Close the options menu if the user clicks anywhere outside of it
        document.addEventListener("click", function (event) {
          const optionsMenu = postDiv.querySelector(".options-menu");
          const detailsButton = postDiv.querySelector(".details-post");
          optionsMenu.style.display = "none";
          optionsMenuVisible = false;

        });
      });
    });
  }
}
Share Improve this question asked 6 hours ago Sai Santosh PalSai Santosh Pal 13 bronze badges 1
  • 2 Please edit your question to include a minimal reproducible example; we don't currently have enough code context to help. – mykaf Commented 6 hours ago
Add a comment  | 

1 Answer 1

Reset to default 1

You can get close using only CSS for this behavior, using focus-able elements, such as links or buttons (styled however you want).

See:
https://developer.mozilla.org/en-US/docs/Web/CSS/:focus

https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible

https://developer.mozilla.org/en-US/docs/Web/CSS/:has

Here is a minimal example that you could apply with little translating, and without touching your javascript:

.menu-items {
    display: none;
    flex-direction: column;
}
.post-container:has(.elipsis:focus) .menu-items,
.menu-items:focus-within,
.menu-items:hover {
    display: flex;
}
<div class="post-container">
    <a class="elipsis" href="#">...</a>
    <div class="menu-items">
        <a href="#">Interact with me</a>
        <a href="#">Me too</a>
        <a href="#">Me three</a>
    </div>
</div>
<div class="post-container">
    <a class="elipsis" href="#">...</a>
    <div class="menu-items">
        <a href="#">Interact with me</a>
        <a href="#">Me too</a>
        <a href="#">Me three</a>
    </div>
</div>

I would use <button> tags instead of <a> tags, and style them as needed.

I sometimes prefer this method to managing with javascript because users already have expectations for how browsers handle clicked/focussed items. This method gives them a familiar default behavior - when you focus something - any existing focussed item should lose its focus.

本文标签: javascriptHow to hide a ellipsis when another ellipsis is clickedStack Overflow