How to revert styles on second click? - javascript

This is my script:
function panelShow(index, code) {
buttons.forEach(function(button){
button.style.borderBottom="";
});
tabButtons[index].style.borderBottom="none";
panels.forEach(function(panel){
panel.style.display="none";
});
panels[index].style.display="block";
panels[index].style.backgroundColor=code;
}
The panelShow() takes parameters like index and code (code of the color). For example panelShow(1, #0000);
If there is a second click I want to revert styles and make panels[index].style.display="none";
How to do so? Please VanillaJS only.
Thanks.

try (answer is for this version of question)
let panels = [...document.querySelectorAll('.panel')];
panels.map(e=> e.ondblclick = e=> e.target.style.display="none" );
function panelShow(index, code) {
// ...your code
panels[index].style.display="block";
panels[index].style.backgroundColor=code;
}
panelShow(0,"#ff0000");
<div class="panel">panel 1 contetn</div>
<div class="panel">panel 2 contetn</div>

Related

Save darkmode state html / css / js

Need to know how I could possibly save the state of the darkmode?
I got this js code right here:
$('#switch').on('click', () => {
if ($('#switch').prop('checked')) {
$('body').addClass('dark');
$('main').addClass('darklight');
$('footer').addClass('darklight');
$('.topnav').addClass('darklight');
$('.lightm').addClass('darklight');
$('section').addClass('darklight');
$('button').addClass('button');
$('.links').addClass('llinks');
} else {
$('body').removeClass('dark');
$('body').addClass('light');
$('main').removeClass('darklight');
$('main').addClass('light');
$('footer').removeClass('darklight');
$('footer').addClass('light');
$('.topnav').removeClass('darklight');
$('.topnav').addClass('light');
$('.lightm').removeClass('darklight');
$('.lightm').addClass('light');
$('section').removeClass('darklight');
$('section').addClass('light');
$('button').removeClass('button');
$('button').addClass('dbutton');
$('.links').removeClass('llinks');
$('.links').addClass('dlinks');
}
})
Here is the code in Codepen with the html and css things:
https://codepen.io/TRGYT/pen/eYmNBPo
Does anyone have idea on how to achieve this? And can this darkmode state also be saved for other sites I created?
Please find the site here:
https://15min.netlify.com
Sorry in advance for the bad code, I'm a beginner...
Welcome to the world of coding. Before we get to the problem, it will be of some use to you to get to grips with the DRY principle (Don't Repeat Yourself). Your code (20 or so lines) could easily be abbreviated to just four. For example:
$("#switch").on("click", () => {
$("body").toggleClass("dark"));
// Local storage. Will get to this later
});
You could then change your CSS to respond to whether or not the body tag has the dark class. Much cleaner.
As for saving the state of the dark mode: use window.localStorage like so:
if (window.localStorage) {
const darkMode = window.localStorage.getItem("darkMode");
if (darkMode) {
$("body").addClass("dark");
} else {
$("body").removeClass("dark");
}
}
I found a way that wored. The one answer I got helped me understand it, but I was too lazy to implement it. But still thank you!
function activateDarkMode() {
$('body').addClass('dark').removeClass('light');
$('main').addClass('darklight').removeClass('light');
$('footer').addClass('darklight').removeClass('light');
$('.topnav').addClass('darklight').removeClass('light');
$('.lightm').addClass('darklight').removeClass('light');
$('section').addClass('darklight').removeClass('light');
$('button').addClass('button').removeClass('button');
$('.links').addClass('llinks').removeClass('dlinks');
}
function deactivateDarkMode() {
$('body').removeClass('dark').addClass('light');
$('main').removeClass('darklight').addClass('light');
$('footer').removeClass('darklight').addClass('light');
$('.topnav').removeClass('darklight').addClass('light');
$('.lightm').removeClass('darklight').addClass('light');
$('section').removeClass('darklight').addClass('light');
$('button').removeClass('button').addClass('dbutton');
$('.links').removeClass('llinks').addClass('dlinks');
}
$('#switch').on('click', () => {
if ($('#switch').prop('checked')) {
activateDarkMode();
localStorage.setItem("darkmode", "enabled")
} else {
deactivateDarkMode();
localStorage.setItem("darkmode", "disabled")
}
});
let mode;
mode = localStorage.getItem("darkmode");
if (mode == 'enabled') {
activateDarkMode();
$('#switch').prop('checked', 'checked');
}
All I did was putting the addClass and removeClass into a function. He also added the localStorage and let the localStorage be in a variable called mode. After I created these things, I put them into an if to check if the darkmode is turned on or not.

How to set navigation page opened by default in jQuery template

We downloaded html template: https://codyhouse.co/gem/sliding-panels-template.
As for the full-page navigation, the .cd-primary-nav is placed below the .cd-projects-container. When the user clicks the .cd-nav-trigger, the .slide-out class is added to the project previews to reveal the navigation.
We want change position of full page navigation, place it over cd-projects-container. In other words, we want to set navigation page opened by default.
I have basic knowledge of css but I can not do what we want. Can anybody help and explain how it works? Thanks in advance.
try this:
Clone this repo https://github.com/CodyHouse/sliding-panels-template (this is the original template. The other repo you passed is different).
In the code, make this seven changes:
// In style.css
// at the end, that is line 788, add:
.hide-in-default { opacity: 0; }
// In index.html
// Add class .nav-visible to `<a>` in line 16
<a class="cd-nav-trigger cd-text-replace nav-visible" href="#primary-nav">Menu<span aria-hidden="true" class="cd-icon"></span></a>
// Add class .hide-in-default to `<div>` in line 18:
<div class="cd-projects-container hide-in-default">
// replace line 134 with:
<nav class="cd-primary-nav nav-visible nav-clickable" id="primary-nav">
// In main.js
// in line 29 add:
removeHideInDefault();
// in line 67 add:
function removeHideInDefault() {
try {
var projectsContainer = document.querySelector('.cd-projects-container');
var isHidden = projectsContainer && projectsContainer.classList.contains('hide-in-default');
if (isHidden) projectsContainer.classList.remove('hide-in-default');
} catch (reason) {
console.error(reason);
}
}
// finally, replace line 80 with:
projectPreview.addClass('bg-loaded slide-out');
Hope it helps.

How to say 'if ALL Instances of a CSS Class are Removed' in an if/else inside of a foreach Method

I'm having trouble removing the CSS 'active_bg' class of the wheel's core circle when it's removed from all segments.
The full code is on Github and Codepen.
Codepen: https://codepen.io/Rburrage/pen/xmqJoO
Github: https://github.com/RBurrage/wheel
In my click event, I tried saying that if the class exists on a segment, add it to the core circle, too -- ELSE -- remove it from the core circle. My code is within a forEach method that loops through all groups in the SVG.
The part in question is in the last event listener below (the 'click' event).
var secondGroups = document.querySelectorAll('.sols-and-mods');
secondGroups.forEach(function (secondGroup) {
let solution = secondGroup.childNodes[1];
let module = secondGroup.childNodes[3];
let core = document.querySelector('.core_background');
secondGroup.addEventListener('mouseover', () => {
solution.classList.add('hovered_bg');
module.classList.add('hovered_bg');
})
secondGroup.addEventListener('mouseout', () => {
solution.classList.remove('hovered_bg');
module.classList.remove('hovered_bg');
})
secondGroup.addEventListener('click', () => {
solution.classList.toggle('active_bg');
module.classList.toggle('active_bg');
if (solution.classList.contains('active_bg')) {
core.classList.add('active_bg');
solution.classList.remove('hovered_bg');
module.classList.remove('hovered_bg');
}else{
core.classList.remove('active_bg');
}
})
})
When the user clicks on a segment of the wheel, the CSS 'active_bg' class gets added to both the clicked segment and the wheel's core circle.
I want to remove the 'active_bg' class from the wheel's core circle but only when it is removed from ALL segments.
Currently, as soon as I remove the class from any ONE segment, it gets removed from the core circle.
Can someone please tell me what I'm doing wrong?
Thank you!
Explained
Okay, so to keep this as short and simply as possible, I changed your logic only ever so slightly, I've just included a check to see if there's at least one option selected, if not, then the core circle has the default class, otherwise, it will continue to have the class name of active_bg.
Here's the JSFiddle that I've made.
If there's any further issues with this solution, don't hesitate to ask.
Edit
I just thought I'd go ahead an include the JavaScript that I was playing around with.
window.onload = function() {
TweenMax.staggerFrom('.solution', .5, {
opacity: 0,
delay: 0.25
}, 0.1);
TweenMax.staggerFrom('.module', .5, {
opacity: 0,
delay: 0.5
}, 0.1);
}
var secondGroups = document.querySelectorAll('.sols-and-mods');
secondGroups.forEach(function(secondGroup) {
let solution = secondGroup.childNodes[1];
let module = secondGroup.childNodes[3];
let core = document.querySelector('.core_background');
secondGroup.addEventListener('mouseover', () => {
solution.classList.add('hovered_bg');
module.classList.add('hovered_bg');
})
secondGroup.addEventListener('mouseout', () => {
solution.classList.remove('hovered_bg');
module.classList.remove('hovered_bg');
})
secondGroup.addEventListener('click', () => {
solution.classList.toggle('active_bg');
module.classList.toggle('active_bg');
if (solution.classList.contains('active_bg')) {
core.classList.add('active_bg');
solution.classList.remove('hovered_bg');
module.classList.remove('hovered_bg');
}
// Added this line.
if (document.querySelector(".sols-and-mods .active_bg") == null) {
core.classList.remove('active_bg');
}
})
})

intro.js show and hide data-hint

I want to have a button that can turn on and off the 'hints' function in intro.js.
I have a working version to show and then hide but the show only works once. How can I get it to work repeatedly? This functionality works for the standard data-intro but not for data-hint.
<div class="jumbotron">
<h1 id='step1'>Hints</h1>
<p class="lead">Adding hints using JSON + callbacks</p>
<a id='step2' class="btn btn-large btn-success" href="javascript:void(0);">Add hints</a>
</div>
function addHints(){
intro = introJs();
intro.setOptions({
hints: [
{
element: document.querySelector('#step1'),
hint: "This is a tooltip.",
hintPosition: 'top-middle'
},
{
element: '#step2',
hint: 'More features, more fun.',
position: 'left'
},
{
element: '#step4',
hint: "<b>Another</b> step.",
hintPosition: 'top-middle'
}
]
});
intro.onhintsadded(function() {
console.log('all hints added');
});
intro.onhintclick(function(hintElement, item, stepId) {
console.log('hint clicked', hintElement, item, stepId);
});
intro.onhintclose(function (stepId) {
console.log('hint closed', stepId);
});
intro.addHints();
}
$(function() {
$('#step2').click(function(){
if ( $('#step2').hasClass('clicked') ) {
introJs().hideHints();
$('#step2').removeClass('clicked');
} else {
addHints();
$('#step2').addClass('clicked');
}
});
});
Instead of using hideHints intro.js API method just remove the div block of intro.js from DOM:
var introDiv = document.getElementsByClassName("introjs-hints")[0];
introDiv.parentNode.removeChild(introDiv);
(You can do the same thing with jQuery if you want to).
When the div is removed from DOM, just initialize hints once again as you do with your addHints method when you want to show hints and it'll work.
Instead of deleting the div block with javascript. You can use .removeHints()
This function is part of intro.js, but is not included in the documentation.
Perhaps a bit hacky, but this works for me...
First, put your hints into their own variable:
hints = [{...}, ...]
then, reset your hints in the intro options
intro.onhintclose(function(stepId) {
if (document.querySelectorAll('.introjs-hidehint').length === hints.length) {
intro.setOptions({hints: hints})
}
})
The hidden hints are given a class of introjs-hidehint, and document.querySelectorAll will return all of them in an array. Once that array is the same size as your hints array, reset your hints in your intro options and that will reset all your hints so you can show them all again.
Here's a more complete example that also allows:
(a) toggling hints on/off by clicking a button (located on a nav bar so used across multiple pages).
(b) once all hints have been clicked, the hints div gets removed so that clicking show hints button will again actually...show hints...
(c) allow you to store hints for multiple pages in a single json object array (re: nav bar).
var jquery = require('jquery');
var introJs = require('intro.js');
* ===========================================================================
* define onclick of hints button
* =========================================================================*/
jquery('#hints_button').on('click', function() {
if (document.getElementsByClassName('introjs-hints').length == 0){
addSomeHints();
}
else {
destroyHints();
};
});
/* ===========================================================================
* Add hints using the IntroJS library
* =========================================================================*/
/* define hints */
var theHints = [
{
element: document.querySelector('#step1'),
hint: "This is a tooltip.",
hintPosition: 'top-middle'
},
{
element: '#step2',
hint: 'More features, more fun.',
hintPosition: 'left'
},
{
element: '#step4',
hint: "<b>Another</b> step.",
hintPosition: 'top-middle'
}
];
/* generate hints with introjs */
function addSomeHints() {
intro = introJs();
intro.setOptions({
hints: theHints
});
intro.onhintclose(function (stepId) {
var remaining_hints = all_hints - document.getElementsByClassName("introjs-hidehint").length;
if (remaining_hints == 0) {
destroyHints();
};
});
/* add hints */
intro.addHints();
/* store number of hints created */
var all_hints = document.getElementsByClassName('introjs-hint').length;
};
/* remove hints div */
function destroyHints() {
var hintsDiv = document.getElementsByClassName("introjs-hints")[0]
hintsDiv.parentNode.removeChild(hintsDiv);
};
... hopefully this saves someone the 20 minutes it took me to piece together the answers and adapt it for what seems like a super common use case.

Comparison between Javascript objects

I have made a simple accordion for my site using jQuery... It worked great, but I've recently started working on a change where if you click the currently opened segments title (the clickable area to slide up/down), it should close the current section.
var sideMenu = {
activated: {},
setup: function() {
$('.menu-category-heading').bind('click', function() {
sideMenu.slideMenu($('ul', $(this).parent()));
});
},
slideMenu: function(menuObj) {
if (sideMenu.activated == menuObj) {
$(sideMenu.activated).slideUp(400);
sideMenu.activated = null;
console.log('same');
} else {
$(sideMenu.activated).slideUp(400);
menuObj.slideDown(500);
sideMenu.activated = menuObj;
console.log('new');
}
}
}
For some reason the comparison is never working... it does if I add $(menuObj).attr('id') and the same for activated. But this is not ideal as not all items will have an id attribute.
Any suggestions as to make the object comparison work? Or any other tips?
Thank you!
You are probably saving a jQuery object (the result of a $ call) rather than the native element. Each time you do a $(myEl) a new object is created and the references will not match up, but the native element will. Try:
if (slideMenu.activated[0] == menuObj[0]) {
...
}

Categories