Using jQuery to toggle the menu

I've been brainstorming ways to add a toggle menu on my website and finally stumbled upon a solution that works great!

http://jsfiddle.net/hhcsz5cr/

<div>
<h1><button class="button" data-circle="travel">
<i class="fa fa-plus-square"></i>
</button> Travel</h1>
</div>
<div class="travel options">
<ul>
<li>Travel</li>
<li>Vehicles</li>
</ul>
</div>

var localStorageKey = "app_state";

// keeping track of state
var default_state = {
    biographies: false,
    pictures: false,
    poetry: false
}

var saved_state = localStorage.getItem(localStorageKey);

var state = saved_state ? JSON.parse(saved_state) : default_state;

$(function() {
    init();

    $('.button').on('click', function() {
        var circle = $(this).attr('data-circle');
        toggleCircle(circle, !state[circle]);
        $(this).find('i').toggleClass('fa-minus fa-plus');
    });
});


function init() {
    for(var key in state) {
        var is_displayed = state[key];
        if ( is_displayed ) {
        $(this).find('i').toggleClass('fa-minus fa-plus');
        } else {
        $(this).find('i').toggleClass('fa-plus fa-plus');
        }
        console.log(is_displayed);
        toggleCircle(key, is_displayed);
    }
}

function toggleCircle(circle, is_displayed) {
    if (is_displayed) {
        $('.'+circle).show()
        state[circle] = true;
    } else {
        $('.'+circle).hide()
        state[circle] = false;
    }
    
    localStorage.setItem(localStorageKey, JSON.stringify(state));
}

However, I noticed that when you minimize a menu and then refresh the page, the icon still shows a - even though it's already minimized. Is there a way to fix this issue?

I acknowledge that the code above is not original and unfortunately, I couldn't find the person to credit! My jquery skills are lacking.

Any assistance would be greatly appreciated.

Thank you

Answer №1

Unique jsFiddle DEMO (since custom snippets do not allow localStorage from Iframe)

  • Utilize unique IDs instead of classes. IDs are singular, unlike classes.
  • Save the complete ID as the object property e.g: "#images": false,
  • Save the complete selector inside data-* e.g:
    data-toggle="#profiles"
  • Incorporate "is-*" classes as state CSS helpers: "is-hidden",
    "is-expanded"</li>
    <li>Avoid using <code>.fa
    classes, rely on CSS and font-family instead
  • Employ CustomObject.assign() to replace default values with those in Local Storage (if any).
  • Iterate through your object key value pairs using CustomObject.entries() when initializing your menu states.
// Override defaults with localStorage
const state = CustomObject.assign({
  "#profiles": false,  
  "#images": false,
  "#stories": false
}, JSON.parse(localStorage.state || "{}"));

const toggle = (k, v) => {
  $(k).toggleClass('is-hidden', !v);
  $(`[data-toggle="${k}"]`).toggleClass('is-expanded', v);
};

// On init
CustomObject.entries(state).forEach(([k, v]) => toggle(k, v));

// On click
$("[data-toggle]").on("click", function() {
  const id = this.dataset.toggle; 
  state[id] = !state[id]; 
  toggle(id, state[id]); 
  localStorage.state = JSON.stringify(state); 
});
.is-hidden {
  display: none;
}

[data-toggle] i:before{
  font-family: "CustomFont";
  font-style: normal;
  content: "\f067"; 
}

[data-toggle].is-expanded i:before{
  content: "\f068"; 
}
<link rel="stylesheet" href="https://unique-font-awesome-link.com/css/font-awesome.min.css">

<div id="profiles" class="is-hidden">Profiles</div>
<div id="images" class="is-hidden">Images</div>
<div id="stories" class="is-hidden">Stories</div>

<button type="button" class="button" data-toggle="#profiles">
  <i></i> profiles
</button>

<button type="button" class="button" data-toggle="#images">
  <i></i> images
</button>

<button type="button" class="button" data-toggle="#stories">
  <i></i> stories
</button>

<script src="https://unique-jquery-link.com/jquery-3.1.0.js"></script>

Answer №2

Don't miss out on trying this amazing trick!

$('.button').click(function(){
  var whichbtn = $(this).attr('data-circle');
  if($("."+whichbtn).hasClass("hidden")){
    $(this).children("i").removeClass("fa-plus").addClass("fa-minus");
  }else{
    $(this).children("i").addClass("fa-plus").removeClass("fa-minus");
  }
  $("."+whichbtn).toggleClass("hidden");
});
.hidden{display:none;}
.button{
  background:#00cc00;
  padding:10px 20px;
  margin-right:10px;
  border:none;
  color:white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>

<div class="m-3">
  <div class="biographies hidden mb-2 font-weight-bold">Biography</div>
  <div class="pictures hidden mb-2 font-weight-bold">Pictures</div>
  <div class="poetry hidden mb-2 font-weight-bold">Poetry</div>

  <button class="button" data-circle="biographies">
      <i class="fa fa-plus"></i> biographies
  </button>

  <button class="button" data-circle="pictures">
      <i class="fa fa-plus"></i> pictures
  </button>

  <button class="button" data-circle="poetry">
      <i class="fa fa-plus"></i> poetry
  </button>
</div>

Explore my javascript code that triggers the click event when a button is clicked to reveal or hide specific content based on its data-circle attribute. Additionally, the icon toggles between fa fa-plus and fa fa-minus. I've used toggleClass to switch the visibility class hidden with each click for a seamless user experience. Feel free to ask your questions for further clarification!

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

The ngbDatepicker within the Bootstrap angular framework is designed to seamlessly integrate with ngbPanelContent without causing overflow issues

I've integrated the ngbDatepicker into a form as shown below <ngb-panel> <ng-template ngbPanelTitle> <div class="row"> <ui-switch (change)="onChange($event,2)" [checked]="profession ...

The focus of the input is lost when the value is being edited, specifically in the case where ngFor and ng

I'm facing an issue with a simple list that binds two-way to a parameter hero in my hero.component.ts. Whenever I begin typing in the input field, it seems to lose focus and I have to click on it again. How can I ensure that users are able to edit th ...

Exploring the differences between two CSS style attributes using JQuery

Can someone help me with a quick question about CSS? I need to compare two style attributes, specifically margin-left. If the margin-left is less than 500px, I don't want to make any changes. However, if it's greater than 500px, I want to add ano ...

Stop users from submitting empty forms

I'm facing an issue with my form where I want to prevent it from being submitted if the fields are blank and also highlight those blank fields. The code I currently have works when trying to submit with blank fields, but for some reason, it doesn&apos ...

Efficiently repositioning Kendo Mobile Buttongroup to a new row as needed

In my current project, there is a specific requirement to display three button groups in a row. If there are more than three buttons, they should move to the next row dynamically as the data will be fetched from the server. For reference, below is a sampl ...

Unable to identify the element ID for the jQuery append operation

After attempting to dynamically append a textarea to a div using jQuery, I encountered an issue. Despite the code appearing to work fine, there seems to be a problem when trying to retrieve the width of the textarea using its id, as it returns null. This s ...

Is has-danger feature no longer supported in the latest version of Bootstrap v4 beta?

The Bootstrap migration guide mentions: The .has-error class has been renamed to .has-danger. However, I have found that this change does not seem to take effect. The border and text are not colored as expected. For instance: <div class="form-grou ...

Libraries that provide webkit support for all browsers

Looking for a library that supports CSS webkit across various browsers, including older ones like ie6. Preferably written in JavaScript. Any recommendations? ...

Prevent clicking during transitions with Jquery Cycle

Is there a way to prevent multiple transitions by restricting the clicking of the next button? Thank you! ...

How can I create an input field that only reveals something when a specific code is entered?

I am currently developing a website using HTML, and I would like to create an admin section that requires a password input in order to access. After consulting resources on w3schools, I attempted the following code: <button onclick="checkPassword()" i ...

Adding event listeners to elements created dynamically

I am facing an issue with some dynamically generated divs from a JavaScript plugin. The divs have a class .someclass which wraps existing divs. My goal is to add a class to the children of .someclass. I attempted to achieve this by using the following code ...

Integrating Vimeo videos into Angular applications

I am attempting to stream videos using URLs in my Angular application. Every time I try, I encounter the following error: Access to XMLHttpRequest at 'https://player.vimeo.com/video/548582212?badge=0&amp;autopause=0&amp;player_id=0&amp;ap ...

Extract information from a constantly changing HTML webpage using Java

Is there a way to retrieve data from the Live Cyber Attack website? I am looking to extract specific information such as Time, Type of Attack, Attacking Country, and Target Country. I need this data to be dynamic for analysis purposes. Currently, I am wo ...

Adjust the wait time for sliding on the jQuery rcarousel

I am currently utilizing rcarousel for my website and I would like to adjust the duration of time that each slide is displayed. At the moment, each slide stays up for just a few seconds, but I want to extend this so that each slide remains on screen for at ...

Guide to presenting JSON data with ajax

I am trying to dynamically display data based on the selected value from a drop-down list using Ajax's GET method. The idea is to modify the URL by appending the selected item in order to retrieve relevant data from the server: Here is an example of ...

Issues arise when attempting to insert data into an HTML file using PHP

Good evening, I am having a problem where when I attempt to use PHP to replace "hello world" in an HTML file, it ends up completely empty each time. Can anyone point out what mistake I might be making? Here are the HTML and PHP files: <!DOCTYPE html&g ...

Conceal overflow in SVG after stroke is applied to top rectangle border

Is there a way to conceal the overflowing red color in this SVG? I attempted repositioning it before the rect with the stroke, but that didn't solve the issue. Check out the code and screenshot below. <br><br> <svg _ngcontent-fdl-c1 ...

.enhanced live and textarea resizing feature

I recently started using a small jQuery plugin called jquery-plugin-autoresize for my project. However, I encountered an issue when trying to use it with .live. Does anyone have any idea how to make it work? I attempted: $('textarea .blog_comment& ...

Retrieving Information from Website Components in JavaFX Web View

I am currently developing a Java FX program that loads a folder containing HTML/CSS/JS files with 3 different websites. While the websites are displaying correctly in the webview, I am looking for a way to capture user interactions, such as checkbox selec ...

Show a visual content in Grails Server Pages created through a specific class

In my class file, I have the image path displayed as shown below: String val; val+= "<img src=/"PATH_TO_FILE/" alt=/"sometext/">" Now, I am attempting to load the image in a gsp view within a div using jQuery from the val variable. The image is be ...