Change css site-wide on click - javascript

What I'm trying to do is display two different menus based on an option that is selected.
In my snippet you can see I have option a and option b
.option-a, .option-b {
text-transform: uppercase;
display: inline-block;
}
.option-a:hover, .option-b:hover {
text-decoration: underline;
}
.option-a-content {
display: block;
}
.option-b-content {
display: none;
}
<div class="option-a">
Option A
</div>
<div class="option-b">
Option B
</div>
<br>
<br>
<div class="option-a-content">
This is the contents of A
</div>
option-a-content is set to display: block and option-b-content is set to display: none;
I want to make it so when you click 'Option B' it changes the css of option-a-content to display: none and it to display: block
Edit: for clarification, my issue is that I can get the css to change on click, however when I navigate away from the page, it reverts back to default.

Here's a simple example of storing the state in localstorage:
$(function(){
$(".option-toggle").on("click", function(){
//get the href of the clicked item. This is the id of the element we wish to show
var selectedOptionID=$(this).attr("href");
//hide all option-content elements
$(".option-content").attr("aria-hidden",true);
//show the one we want
$(selectedOptionID).attr("aria-hidden",false);
//remember the active one in localstorage
localStorage.setItem("selectedOptionID", selectedOptionID);
});
//onload, read from local storage and trigger a click on the appropriate option:
var selectedOptionIdFromStorage = localStorage.getItem("selectedOptionID");
if(selectedOptionIdFromStorage){
//trigger a click on the select-option having a href equal to selectedOptionIdFromStorage:
$(".option-toggle[href='"+selectedOptionIdFromStorage+"']").trigger("click");
}
});
https://jsfiddle.net/jvsnphmn/3/

Related

ChromeVox Fails to Read Span After Checkbox Toggled State

I'm refactoring pattern library components to comply with accessibility standards, and I'm dealing with an expandable header menu that is in actuality a hidden checkbox. It opens and closes on the checkbox's checked state. Because it's hidden it didn't have any labeling for ChromeVox to read, and it no longer could be activated via the spacebar, which is normally a default. I decided to add some spans that described when the menu is expanded or collapsed, and an event listener that triggers on a keystroke, and changed the display from one to the other so ChromeVox could read the spans and announce the change. The menu works completely on a click, the state changes and the reader works, but on keystroke the menu will open and the reader fails to announce the change to the spans.
This is my event listener-
function checkboxToggle() {
const el = document.querySelector('.site-header__button');
function handleCheckboxEvent(e) {
const checkbox = document.querySelector('.site-header-toggle');
if (e.keyCode === 13) {
checkbox.checked = !checkbox.checked;
}
}
el.addEventListener('keydown', handleCheckboxEvent);
}
The html is created through a Twig template-
<input hidden type="checkbox" id="site-header-toggle" class="site-header-toggle">
<header class="{{ classes|join(' ') }}">
<label tabindex="0" for="site-header-toggle" class="site-header__button icon--menu">
<span class="u-hide expanded-text">navigation menu expanded</span>
<span class="u-hide collapsed-text">navigation menu collapsed</span>
</label>
{% if menu_items %}
<nav class="site-header__menu">
{...}
</nav>
{% endif %}
</header>
With Scss I'm using an interpolation to effect everything in the .site-header parent when it's sibling, the checkbox, changes states. On keystroke all the displays change as expected, but it's just not triggering ChromeVox to read the spans as they are changing displays.
$open: '.site-header-toggle:checked + .site-header';
.site-header {
{...}
}
&__button {
font-size: 1.5rem;
.expanded-text {
display: none;
}
.collapsed-text {
display: inline;
}
&:hover { cursor: pointer; }
#{$open} & {
#include icon(close);
.expanded-text {
display: inline;
}
.collapsed-text {
display: none;
}
}
}
&__menu {
display: none;
width: 100%;
#{$open} & {
display: block;
}
}
}
I'm newish to screen readers so maybe there's something about ChromeVox that I'm just not taking into account. Any insight would be so helpful or resources I can check out to try and find a solution.

Using slideToggle() jQuery, and remembering settings on page refresh

I have the following code that slideToggle() a div while at the same time displaying a button that allows you to slideToggle() back and then hides itself.
$(document).ready(function() {
$("#about-user-widget .hide-btn").click(function(){
$("#about-user-widget").slideToggle();
$("#show-button").attr('style', 'margin-bottom: 5px; font-size: 11px; color: #ddd; display: visible;');
});
//reverses the above action
$("#show-button").click(function(){
$("#about-user-widget").slideToggle();
$("#show-button").attr('style', 'margin-bottom: 5px; font-size: 11px; color: #ddd; display: none;');
});
})
The above works great, however when I refresh the page it goes back to the default. The about-user-widget is open and the show-button visibility is set to hidden.
My question is, how would I get the page reload to remember what my settings are at? So for example, if one had clicked hide, and the about-user-widget was hidden and the show-button was visible. How could I get that setting to stay when the page is refreshed?
The show-button is set to hidden by default.
<div class="pull-right" id="show-button" style="margin-bottom: 5px; font-size: 11px; color: #ddd; visibility: hidden;"><i class="fa fa-eye"></i> Show<span> | </span></div>
I know I'd need to commit this to memory somehow (cookie, local storage of some kind) but being new to jquery I'm not sure how to implement this.
Any help would be appreciated.
First I don't understand why you need two buttons? You can achieve this with one button.
As per saving the state of div shown/hidden
You can use storage in cookies or your preferred metnod.
As per cookie; read the following stack post
Then this for example how you can try:
I used this plugin: https://github.com/js-cookie/js-cookie
$(document).ready(function() {
var currentstate = Cookies.get('divstate');
console.log('on refresh=' + currentstate);
if (currentstate == 'open')
$("#about-user-widget").show();
else
$("#about-user-widget").hide();
$("#button").click(function() {
$("#about-user-widget").slideToggle();
var currentstate = Cookies.get('divstate');
if (currentstate == 'close' || currentstate == undefined) {
Cookies.set('divstate', 'open');
console.log('when click');
} else {
Cookies.set('divstate', 'close');
console.log('else');
}
console.log(Cookies.get('divstate'));
});
});
the HTML part:
<input id="button" type="button" value="show/hide" />
<div id="about-user-widget" style="display: none; width: 100px; height: 100px; background: #b2000b">some text</div>
Be aware about cookies plugin's compatibility with browsers; I tested with FireFox and working.

How do I toggle between divs based on anchor tag on page load?

I'm toggling between two divs that display pricing options. It defaults to the first option on page load. Using an anchor link, how can I have the toggle launch option two?
Here's the page for reference. and a Fiddle of a condensed version to show the code I'm working with.
I want the "Club and Youth" pricing to show when #Club-Youth is anchored to the URL.
Any help is greatly appreciated!
HTML
<div class="pricing-switcher">
<a class="toggle active" id="HS-College">High School and College</a>
<a class="toggle" id="Club-Youth">Club and Youth</a>
</div>
<div class="pricing-wrapper">
<div class="panels HS-College">Option 1 Option 1 Option 1 Option 1 Option 1 Option 1 Option 1 Option 1 Option 1</div>
<div class="panels Club-Youth hide">Option 2 Option 2 Option 2 Option 2 Option 2 Option 2 Option 2 Option 2 Option 2</div>
</div>
CSS
.panels {
display: flex;clear:both;
padding-bottom: 30px;
}
.panels.HS-College {
justify-content: center;
}
.panels.hide {
display: none
}
.pricing-switcher {
float: left;
width: 100%;
}
.toggle {
float: left;
display: flex;
border: 2px solid #000;
margin-right: 10px;
cursor: pointer;
}
.toggle.active {
background-color: red;
}
JS Toggle
$(document).ready(function(){
$('.toggle').click(function(){
var self = $(this);
$('.panels').addClass('hide');
$('.toggle').removeClass('active');
self.addClass('active');
$('.panels.'+ self.attr('id')).removeClass('hide');
});
});
$(window.location.hash).click();
window.location.hash will return #Club-Youth from the below url.
https://www.hudl.com/products/assist/volleyball?token=K6~s9DTGVrSKh~X9VMetZv6YLKSMtAAp#Club-Youth
Using $(window.location.hash) will be the same as $('#Club-Youth') and fire the click event on that element.
Make sure this code is below your $('.toggle').click(function(){}) so it fires the code you have attached already.
Look for a hash value in the URL on page load
var hash = window.location.hash;
if (!(typeof object === 'undefined')) {
// show/hide based on value of hash
if (hash=='Club-Youth') {
// show panel 1
} else {
// show panel 2
}
}

How could I make this tab controller code cleaner and simpler?

How would I be able to simplify this jquery code. I feel like I am repeating myself and just wondering if there is a shorter way to write this which I'm sure there is. I am a bit new to javascript and jquery. I have created a two tabs with their own containers with miscellaneous information in them. Basically I want the container to open when it's related tab is clicked on. I also would like the tab to be highlighted when it's active. Also, how would I be able to write code to make all tab containers disappear when you click off from the tab containers.
<!-- HTML Code -->
<div class="sort-filters">
<span class="sort-by active">SORT BY</span>
<span class="filter">FILTER</span>
</div>
<div class="sort-containers">
<div class="sort-by-container">Sort by click me here</div>
<div class="filter-container">Filter click me here</div>
</div>
/* CSS */
.sort-filters {
display: flex;
width: 500px;
height: 30px;
}
.sort-by,
.filter {
background: #CCC;
color: #756661;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Arial', sans-serif;
cursor: pointer;
}
.sort-by-container,
.filter-container {
width: 500px;
background: #756661;
color: #FFF;
height: 100px;
display: none;
}
.active {
background: #756661;
color: #FFF;
transition: 0.2s;
}
// Jquery Code
js = $.noConflict();
var sort = js('.sort-by');
var filter = js('.filter');
var sortContainer = js('.sort-by-container');
var filterContainer = js('.filter-container');
js(sort).click(function() {
js(filterContainer).hide();
js(sortContainer).show();
js(sort).addClass('active');
js(filter).removeClass('active');
});
js(filter).click(function() {
js(sortContainer).hide();
js(filterContainer).show();
js(filter).addClass('active');
js(sort).removeClass('active');
});
In order to avoid such repetitive actions I like to stick to naming conventions, so that I can apply the ID's, classes or attributes from one element to select other elements, for instance:
<div id="tabs">
<span class="active" data-type="sort-by">SORT BY</span>
<span data-type="filter">FILTER</span>
</div>
Now, all you need is one click handler on #tabs span, and get the data-type of the span you clicked on. You can use that to filter on the classes of the other container elements.
The second thing is that you can attach handler to more than 1 element at the same time. So in your example, js('#sort-containers div').hide(); will hide all the div's that match the selector at once.
results
I changed some classes to ID's, and some classes to data attributes. Here's a fiddle: https://jsfiddle.net/mq9xk29y/
HTML:
<div id="tabs">
<span data-type="sort-by">SORT BY</span>
<span data-type="filter">FILTER</span>
</div>
<div id="sort-containers">
<div class="sort-by-container">Sort by click me here</div>
<div class="filter-container">Filter click me here</div>
</div>
JS:
js = $.noConflict();
var $tabs = js('#tabs span');
$tabs.click(function() {
var $clicked = js(this); //get the element thats clicked on
var type = $clicked.data('type'); //get the data-type value
$tabs.removeClass('active'); //remove active from all tabs
$clicked.addClass('active'); //add active to the current tab
js('#sort-containers div').hide(); //hide all containers
js('.' + type + '-container').show().addClass('active'); //add active to current container
});
As long as you follow the naming convention of data-type: bla in the tabs, and bla-container on the classes in sort-container, you never have to worry about coding for additional tabs.
There might still be things that could be further optimised, but at least it'll take care of the repetition.

How do I make the dropdown menu not being down when you enter the website?

When you enter my website (goerann.com) the dropdown register-box is down by default.
If I click in Register, the register-box toogles it visibility as I want, but it doesn't start hidden by default.
$(document).ready(function() {
$('#signup').click(function() {
$('.signupmenu').slideToggle("fast");
});
});
I want it to only show when you click on it. How can I make this happen?
Here's my jsfiddle (http://jsfiddle.net/bdv2doxr/)
Since you're already using the $(document).ready event, you can hide the menu there:
$(document).ready(function() {
$('.signupmenu').hide();
$('#signup').click(function() {
$('.signupmenu').slideToggle("fast");
});
});
And here is your fiddle updated.
You need to make two changes, both involving the removal of display: block. When you toggle this div, it will make the display block. Therefore, you can initialize it as display: none.
Change this:
<div class="signupmenu" style="display: block;">
to this:
<div class="signupmenu">
And also change this:
.signupmenu {
background-color: #FFF;
display: block;
...
to this:
.signupmenu {
background-color: #FFF;
display: none;
...
Updated fiddle here

Categories

Resources