Remembering color-choice through Jquery (localStorage) - javascript

I have created a very simple and basic Jquery script that changes the class for textboxes on my site in order for them to have a different colored background when a button is clicked. I then attempted (with the help of a Jquery-for-dummies-book) to set it up so that the color choice is remembered locally.
I must however be a greater "dummy" than expected because I have not been able to make this work.When I upload the script to the server and test it on the site, I can change the color, but if I close then window and then go to my website again, the color is back to default. It is NOT remembered/stored.
Is it possible the problem stems from the fact that my textboxes use the class "row" to set the background color, and you can not change a class to a different class, but must use a proper element or ID? Or should the order of the script-parts perhaps be different?
Any and all insight is appreciated on my learning-journey.
External script
$(document).ready(function(){
if (localStorage.getItem("farvevalg")=="farve") { $(".row").addClass("farve");
}
if ($(".row").hasClass("farve")) {
localStorage.setItem("farvevalg", "farve");
} else {localStorage.removeItem("farvevalg")}
$('#farvevalg').click(function(){
$(".row").toggleClass('farve');
}); }
My HTML
/*The default color of all textboxes on a page*/
.row {background-color: #e7e7e7;}
/*The color that it changes into when button is clicked*/
.farve {background-color: pink;}
/*The button that must be clicked to change color*/
#farvevalg {
margin-top: 6%;
padding: 5px;
}

Your attempt is correct but add/remove localStorage you are doing at the wrong place. You should do it inside that button click.
WORKING FIDDLE
Snippet won't work because of the CORS issue. It's for code view only.
$(document).ready(function () {
if (localStorage.getItem("farvevalg") == "farve") {
$(".row").addClass("farve");
}
$('#farvevalg').click(function () {
$(".row").toggleClass('farve');
if ($(".row").hasClass("farve")) {
localStorage.setItem("farvevalg", "farve");
} else {
localStorage.removeItem("farvevalg")
}
});
});
/*The default color of all textboxes on a page*/
.row {background-color: #e7e7e7;}
/*The color that it changes into when button is clicked*/
.farve {background-color: pink;}
/*The button that must be clicked to change color*/
#farvevalg {
margin-top: 6%;
padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<div class="row">
Test
</div>
<button id="farvevalg">
Change
</button>

some changes in login, not tested but should work
$(document).ready(function(){
if (localStorage.getItem("farvevalg")=="farve") {
$(".row").addClass("farve");
}
$('#farvevalg').click(function(){
//only here we add/remove setting
var wasFarveColor = $(".row").hasClass("farve")
$(".row").toggleClass('farve');
if(wasFarveColor)
localStorage.removeItem("farvevalg")
else
localStorage.setItem("farvevalg", "farve")
});
})

what you are doing is, at the start of your application, check it there is a saved item 'farvevalg' with value 'farve'. If that is the case, then you add the class 'farve' to all elements with class 'row'.
After this you check if there is a row element with class 'farve' and, if that is the case' you set the item in storage, otherwise you delete it. As you can see it doesn't make sense for this bit of code to be here as it won't have any effect. You should instead move this if/else block inside of the click callback ( after $(".row").toggleClass('farve'); )

Related

How to remember the buttons click state and their functions with local storage?

I have many buttons that change/add/remove elements. Some of the elements are dynamic e.g. clicking button one will create button two etc.
I'd like to save the state of the buttons/page in local storage. If I clicked button one, and then two, the background is now red. When the visitor returns (after browser close) it will be as if they have already clicked one>two and will see the red background as before.
I've been reading Mozilla setItem and every post on Stackoverflow about local storage but I can't find any examples of this exact scenario.
https://jsfiddle.net/oh9q2Lzw/1/
$('.one').on('click', function() {
$('.blue').removeClass('blue').addClass('green');
});
$('.two').on('click', function() {
$('.green').removeClass('green').addClass('red');
});
button {
padding: 10px 40px;
}
.blue {
width: 200px;
padding: 20px;
background: blue
}
.green {
width: 200px;
padding: 20px;
background: green
}
.red {
width: 200px;
padding: 20px;
background: red
}
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
<br>
<div class="box">
<button class="one">one</button>
<button class="one">one</button>
<button class="two">two</button>
</div>
<br>
<div class="blue"></div>
<br>
<div class="blue"></div>
In your example, the only memory the page needs is the class name of the divs applied when the style was last changed.
Therefore, the simple solution is to store the class name in local storage each time it changes by modifying your button events as follows:
$('.one').on('click', function() {
$('.blue').removeClass('blue').addClass('green');
localStorage.setItem("div-class", "green");
});
$('.two').on('click', function() {
$('.green').removeClass('green').addClass('red');
localStorage.setItem("div-class", "red");
});
When the page loads, the hard-coded class is always "blue" and so this can be changed if a value is stored in local storage.
This is done by adding a function to the window.onload event:
window.onload = function() {
if (localStorage.getItem("div-class")) {
$('.blue').removeClass('blue').addClass(localStorage.getItem("div-class"));
}
};
The SO snippet tool doesn't allow local storage access but I've modified your JS fiddle with a working example: https://jsfiddle.net/g5wqjo2h/
I've also made a modified version with an extra button to allow you to clear localStorage during development. If the clear memory button is clicked, when the js Fiddle is next run or loaded, the divs return to the default blue class. Otherwise, the previous colour is loaded from localStorage. : https://jsfiddle.net/g5wqjo2h/1/

Keep dark or light mode over different pages with javascript

Basically, I got a dark mode on the front page, with the script being (from W3schools) :
<script>
function darklightmode() {
var element = document.body;
element.classList.toggle("dmode");
} </script>
And the button :
<button onclick="darklightmode()" style="background:none; border: none;">
<img src="images/ld-icon.png" class="icon">
</button>
and some CSS just for example :
.dmode li a{
transition: 1s all;
color: #2E3440;
background: none;}
So how can I, with some Javascript, make the mode the user is using stay between pages and not come back to default when accessing another page ?
Beginner here, any help appreciated.
You'd need to store the current theme somewhere. Try using localstorage.
Example from How do i set dark mode theme across multiple pages? (this question is a duplicate):
checkbox.addEventListener( 'change', function() {
localStorage.setItem('dark',this.checked);
if(this.checked) {
body.classList.add('dark')
} else {
body.classList.remove('dark')
}
});
and this on each page:
if(localStorage.getItem('dark')) {
body.classList.add('dark');
}

Select <divs> within parent <div> using jQuery

I have a parent <div>, #amwcontentwrapper, which has a series of divs within it with their own classes and ids.
I want to use jQuery to select these child divs, and IF they have the class .amwhidden, do nothing, but if not, remove the .amwshown class and add the .amwhidden class.
This is what I have so far, but it is not working. I think it may be my selecting of the child divs within the parent.
Can anybody see any obvious problems? Thanks for your help.
if ($('#amwcontentwrapper > div').hasClass('amwhidden')){
} else {
$('#amwcontentwrapper > div').fadeIn(600, function(){
$('#amwcontentwrapper > div').removeClass('amwshown');
$('#amwcontentwrapper > div').addClass('amwhidden');
});
}
And here is the basic html that I am using:
<div class="amwshown" id="amwintro">
Intro Section, which should have the 'amwshown' class removed, and the
'amwhidden' class added, when the jQuery runs. Currently, this does not happen.
</div>
UPDATE: Using War10ck's solution in the comments below (i.e. $('#amwcontentwrapper > div.amwshown')) I have managed to get the classes changing as I wished. However, those which have had the .amwshown class removed and .amwhidden class added still show on the page, despite the CSS looking like this:
.amwhidden {
display:none;
}
.amwshown {
display:block;
}
Looking at the Dev Tools, it seems that, when the jQuery is run (on a click event) the classes are changing, but any classes which are having the .amwshown class added (thus displaying them on the page) are also having the a <style> tag added to them which makes them display:block;
When I then press another button, which should hide the aformentioned <div> to make way for another one, the class is being changed to .amwhidden, but that <style> tag is not being deleted, so even though it has the .amwhidden class, it is still on the page.
I've created a JSFiddle here, if anybody still wants to help!
`
$(document).ready(function() {
$('#buybutton').click(function() {
$('#amwcontentwrapper > div.amwshown').fadeIn(600, function() {
$(this).removeClass('amwshown').addClass('amwhidden');
});
if ($('#amwbuy').hasClass('amwshown')) {} else {
$('#amwbuy').fadeIn(600, function() {
$('#amwbuy').removeClass('amwhidden');
$('#amwbuy').addClass('amwshown');
});
}
});
$('#phdbutton').click(function() {
$('#amwcontentwrapper > div.amwshown').fadeIn(600, function() {
$(this).removeClass('amwshown').addClass('amwhidden');
});
if ($('#amwphd').hasClass('amwshown')) {} else {
$('#amwphd').fadeIn(600, function() {
$('#amwphd').removeClass('amwhidden');
$('#amwphd').addClass('amwshown');
});
}
});
});
#sidebar {
position: absolute;
left: 1%;
top: 1%;
font-size: 5em;
color: #000000;
width: 10%;
display: block;
background-color: red;
}
#amwcontentwrapper {
position: absolute;
left: 20%;
top: 5%;
}
.amwshown {
display: block;
}
.amwhidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="amwsidebar">
<span class="sidebarbutton" id="phdbutton">PhD Button</span>
<br />
<br />
<span class="sidebarbutton" id="buybutton">Buy Button</span>
</div>
<div id="amwcontentwrapper">
<div class="amwshown" id="amwintro">
<p>An intro section to welcome the visitor. Disappears when one of the other sections is clicked.</p>
<br />
<br />
</div>
<div class="amwhidden" id="amwbuy">
Buy Section
</div>
<div class="amwhidden" id="amwphd">
PhD Section
</div>
</div>
`
You can use not to remove the elements you do not want, like this:
$('#amwcontentwrapper > div').not('.amwhidden')
.removeClass('amwshown')
.addClass('amwhidden');
And work with that.
Try this
$(document).ready(function() {
$("#amwcontentwrapper").children().each(function(elem, x) {
if ($(x).attr("class") == "amwhidden") {
alert($(x).attr("class"));
$(x).removeClass("amwhidden").addClass("amwshow");
alert($(x).attr("class"));
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="amwcontentwrapper">
<div class="amwhidden"></div>
<div></div>
<div></div>
</div>
You can try each as follow,
$("#amwcontentwrapper div").each(function(){
if($(this).hasClass('amwhidden'))
//DO something
else
//DO something
});
Thank you for all help, it has prompted some brainstorming which has solved this issue.
Instead of adding the .amwhidden class and removing the .amwhidden class using jQuery, I have just created a .amwsection class, which all the sections belong to which has an initial display value of none. So far, so good; all of the sections are not there when you load up the page.
Then I use the .css jQuery function to change the display:none to display:block when the corresponding button is clicked, and changing all other .amwsections to display:none. This works just fine, but the effect is quite abrupt; there is no fading in, as you would get if you used the .animate function. .animate, however, does not work with the display value.
.fadeOut and .fadeIn to the rescue! By wrapping the .css change in these, I can create a fading in/out effect and can still use the display value.
Here is one example of this code.
The #buybutton is the button to be pressed.
#amwintro is just something which appears when the page loads - it will now be set to display:none if this is the first button pressed.
The .amwsection are all of the hidden sections. This portion of the code just resets all of them. This and the #amwintro section happen very quickly (1/100th of a second) to keep response time good.
The #amwbuy is the specific section that I want to reveal. As you can see, this fades in over a longer period.
Currently only tested in Chrome, but I think I've got it!
$(document).ready(function () {
$('#buybutton').click(function() {
$('#amwintro').fadeOut(1, function() {
$(this).css({
display:'none',
});
});
$('.amwsection').fadeOut(1, function() {
$(this).css({
display:'none',
});
});
$('#amwbuy').fadeIn(600, function() {
$(this).css({
display:'block',
});
});
});
});

More efficient way to change styles using Javascript?

I have an about section, where I've split it up into multiple sections loaded by JavaScript for easier reading. I'd like the side navigation for this to have a different background color if it is both hovered over and if it is the one selected, and ALSO to have a border right with a unique color for each option. I have it working with no problems, but I'm just wondering if there is a more efficient way to do this than the way I currently am.
In a nutshell, the HTML:
<nav>
<p id="bout" onclick="bout()">About Us</p>
<p id="mish" onclick="mish()">Our Mission</p>
<p id="team" onclick="team()">The Team</p>
<p id="how" onclick="how()">How It Works</p>
<p id="poli" onclick="poli()">Policies</p>
</nav>
<div class="actual">
<div id="about">
<h2>About Us</h2>
<p>We are a conglomerate of hoodlums.</p>
</div>
</div><!-- end actual -->
And the JS:
function bout() {
document.getElementById("about").innerHTML= '<h2>About Us</h2><p>We are a conglomerate of hoodlums.</p>';
document.getElementById("bout").style.borderRight='3px solid red';
document.getElementById("mish").style.borderRight='none';
document.getElementById("team").style.borderRight='none';
document.getElementById("how").style.borderRight='none';
document.getElementById("poli").style.borderRight='none';
document.getElementById("bout").style.backgroundColor='ghostwhite';
document.getElementById("mish").style.backgroundColor='bisque';
document.getElementById("team").style.backgroundColor='bisque';
document.getElementById("how").style.backgroundColor='bisque';
document.getElementById("poli").style.backgroundColor='bisque';
}
function mish() {
document.getElementById("about").innerHTML = '<h2>Mission</h2><p>Our mission is to rid the world of dust bunnies.</p>';
document.getElementById("bout").style.borderRight='none';
document.getElementById("mish").style.borderRight='3px solid orange';
document.getElementById("team").style.borderRight='none';
document.getElementById("how").style.borderRight='none';
document.getElementById("poli").style.borderRight='none';
document.getElementById("bout").style.backgroundColor='bisque';
document.getElementById("mish").style.backgroundColor='ghostwhite';
document.getElementById("team").style.backgroundColor='bisque';
document.getElementById("how").style.backgroundColor='bisque';
document.getElementById("poli").style.backgroundColor='bisque';
}
As you can see, it's quite cumbersome to have to explicitly turn off an on each style when clicked. The main key though is to have each border-right be a different color.
Here is a jsfiddle with the whole thing, but for some reason it's not actually acknowledging the JS: http://jsfiddle.net/4CrhD/
Additional random question: Is it possible to link to this page with a different piece of content loaded than about, for example, can I link to this page with "mish()" loaded instead of whats in the HTML?
The best way would be to use CSS. Add remove a class on a parent element and have the CSS apply the right rules.
body.mish #bout{
border-right : 3px solid red,
}
body.bout #bout{
border-right : 3px solid blue,
}
Yes. You need to divide between html and styling. Use CSS!
Then you can change styles e.g. with jQuery.css():
$('#mish').css({
'border-right': '3px solid orange',
'background-color':'ghostwhite'
});
Of course you can define styles in a class. A class describes the styling definition for all elements using a class.
nav > p {
border-right: none;
background-color: bisque;
}
.active {
border-right: 3px solid red;
background-color: ghostwhite;
}
If a button is clicked you can dynamically add and remove a classes with:
$('nav > p').click(function() {
$('nav > p').removeClass('active');
$(this).addClass('active')
});
Because code duplication is bad (and I don't like to set the full innerHTML), you can create a dynamic page like:
pages = {
'bout': {
'id': 'about',
'headline': 'About Us',
'body': 'We are a conglomerate of hoodlums.'
}
}
Extend the above code to
$('nav > p').click(function() {
$('nav > p').removeClass('active');
$(this).addClass('active')
if (pages[$(this).attr('id')]) {
var page = pages[$(this).attr('id')];
$('.actual').first().empty();
var container = $('<div>', { 'id': page.id });
container.append($('<h2>', { 'html': page.headline }));
container.append($('<p>', { 'html': page.body }));
$('.actual').first().append(container);
}
});
Have look at this jsfiddle for a working example
Addressing your "random" question
Additional random question: Is it possible to link to this page with a different piece of content loaded than about, for example, can I link to this page with "mish()" loaded instead of whats in the HTML?
If you want to have links pointing to this page you can parse the window.location.hash object and link with links like page.html#mish.
To set default a "page" we extend our pages object to provide such a information: http://jsfiddle.net/Eu36g/6/
Define your classes in the CSS : bout, mish, about, poli ... For each one put the CSS you want. After that, in the javascript, you just have to change the class of the element (add class or change class, or whatever) and the new CSS will apply
example
document.getElementById("bout").className = "otherclass"

toggle div if statement

I have this HTML:
<div id="parent1" class="article">
<div class="action"></div>
<div id="exp1" class="expand"></div>
</div>
<div id="parent2" class="article">
<div class="action"></div>
<div id="exp2" class="expand"></div>
</div>
and CSS:
.article:hover .action {
z-index:1000;
}
.expand {
display: none;
}
action {
background: url(../images/down.png) 0 0 no-repeat;
z-index: -999;
}
.collapse {
background: url(../images/up.png) 0 0 no-repeat !important;
z-index: 1000;
}
and Javascript:
$(".article").click(function() {
$(this).find(".action").toggleClass("collapse"); // works onclick div article
????????? // when press parent1 if parent2 pressed before ???????.find(".action").toggleClass("collapse");
$("#exp2").hide(); // if previously open
$("#exp1").toggle(300);
}
Now I need jQuery for onclick parent1 to toggleClass action in parent2 but only if prevously toggled to collapse.
There are a number of ways to do it. Normally I would store a local variable that holds the state of the drop down (boolean) and just check that.
With jQuery, since you are already using hide(), you can use:
if ($("#exp2").is(":hidden")) {
// Show content, set arrow to up.
$("#exp2").removeClass("expand").addClass("collapse");
}
else {
// Hide content, set arrow to down.
$("#exp2").removeClass("collapse").addClass("expand");
}
The toggle would make more sense if you were just adding and removing a class. Here you are alternating classes. Using addClass() and removeClass() makes it very clear what you are doing.
I take a guess here but I think you want to close any open .article and open the one you clicked on.
$(".article").click(function() {
// see explanations 1 and 2 below
$('.article.active').removeClass('active').find('#exp1').hide();
// see explanation 3 below
$(this).addClass('active').find('#exp2').show();
}
You can change the code to suit your need but so you understand it:
When we click on an .article, we look for any other .article with a specific class (.active in my exemple). Technically, there will likely be only one of .article.active
We remove its .active class and do whatever on it or its child
We finally do whatever on the clicked article

Categories