4 Javascript commands execute simultaneously when 1 button is clicked - javascript

I have four html elements on a page that are each meant to execute a different setTheme JS command when clicked. However, when I click one, nothing happens. I'm pretty sure they all execute at the same time, and because they're all basically the same code, they cancel each other out and it reverts back to the default theme, which means I see nothing. However, I could be wrong. How do I fix this?
A note about this code: I couldn't figure this out at first, so I looked online but couldn't find anything, so I modified some code meant for the toggleTheme function, not the setTheme function. If that's the problem, I don't know how to solve it but it might help you.
This is the code for one of them (the others are similar, but with, for example, 'theme-light-purple' replaced by 'theme-light-blue' or 'theme-dark-blue'. 'theme-dark-purple' is the default.):
<button id="switch-light-purple" onclick="setTheme()">Light Purple</button>
<script>
// function to set a given theme/color-scheme
function setTheme(themeName) {
localStorage.setItem('theme', themeName);
document.documentElement.className = themeName;
}
// function to set theme
function setTheme() {
setTheme('theme-light-purple');
}
// Immediately invoked function to set the theme on initial load
(function () {
if (localStorage.getItem('theme') === 'theme-light-purple') {
setTheme('theme-light-purple');
} else {
setTheme('theme-dark-purple');
}
})();
</script>

<button id="switch-light-purple" onclick="setTheme('theme-light-purple-dark')">Light Purple</button>
<script>
// function to set a given theme/color-scheme
function setTheme(themeName) {
localStorage.setItem('theme', themeName);
document.documentElement.className = themeName;
}
// Immediately invoked function to set the theme on initial load
(function () {
if (localStorage.getItem('theme') === 'theme-light-purple') {
setTheme('theme-light-purple');
} else {
setTheme('theme-dark-purple');
}
})();
</script>
You don't need to write 2 functions.

This is how you should have your code
function setTheme(themeName = 'theme-light-purple') {
localStorage.setItem('theme', themeName);
document.documentElement.className = themeName;
}
Here, you are providing a default value to your first parameter in case you want to call the setTheme function without any parameters like this setTheme()
So, if you call setTheme() it automatically means you are calling setTheme('theme-light-purple')
Here's the official documentation for default parameters if you want to go through.

If you want setTheme() to behave differently whether it receives or not an argument (and if I understood what you want to achieve), you need to replace:
// function to set a given theme/color-scheme
function setTheme(themeName) {
localStorage.setItem('theme', themeName);
document.documentElement.className = themeName;
}
// function to set theme
function setTheme() {
setTheme('theme-light-purple');
}
with:
// function to set a given theme/color-scheme or a default one if none is provided
function setTheme(themeName) {
const chosenTheme = themeName ? themeName : 'theme-light-purple';
localStorage.setItem('theme', chosenTheme);
document.documentElement.className = chosenTheme;
}
[EDIT] Following the comment, I am adding a partial demo; unfortunately the code snippet cannot access window.localStorage therefore the storing to and retrieving from localStorage of the theme cannot be demonstrated here:
/* theme default */
html.theme-default body {
color: #333;
background-color: #efefef;
}
html.theme-default button {
border: 2px solid #333;
border-radius: 3px;
color: #333;
}
html.theme-default p {
border: 1px dashed #333;
color: #333;
}
/* theme red */
html.theme-red body {
color: #300;
background-color: #ffefef;
}
html.theme-red button {
border: 2px solid #c00;
border-radius: 3px;
color: #300;
}
html.theme-red p {
border: 1px dashed #c00;
color: #300;
}
/* theme green */
html.theme-green body {
color: #030;
background-color: #efffef;
}
html.theme-green button {
border: 2px solid #0c0;
border-radius: 3px;
color: #030;
}
html.theme-green p {
border: 1px dashed #0c0;
color: #030;
}
/* theme blue */
html.theme-blue body {
color: #003;
background-color: #efefff;
}
html.theme-blue button {
border: 2px solid #00c;
border-radius: 3px;
color: #003;
}
html.theme-blue p {
border: 1px dashed #00c;
color: #003;
}
<body>
<button id="switch-default" onclick="setTheme()">default (grey)</button>
<button id="switch-red" onclick="setTheme('theme-red')">red</button>
<button id="switch-green" onclick="setTheme('theme-green')">green</button>
<button id="switch-blue" onclick="setTheme('theme-blue')">blue</button>
<p>Lorem ipsum dolor sit consecutor amet</p>
<script>
function setTheme(themeName) {
const chosenTheme = themeName ? themeName : 'theme-default';
// window.localStorage.setItem('theme', chosenTheme); // this line is commented as the code snippet has no access to localStorage
document.documentElement.className = chosenTheme;
}
// Immediately invoked function to set the theme on initial load
(function() {
/* the following lines are commented as the code snippet has no access to localStorage
const storedTheme = window.localStorage.getItem('theme') || null;
if (storedTheme) {
setTheme(storedTheme);
} else {
setTheme();
}
*/
setTheme() // this line should be deleted in the actual code
})();
</script>
</body>

Related

How to toggle True or False in sessionStorage

I am trying to add dark-mode to the website. When someone clicks the dark mode button it will add additional CSS classes and remove them when the button is clicked again.
I know I can do it easily with toggleClass but I don't want to disable this automatically when the page refreshes or some other page is opened on the website.
I have been playing with sessionStorage but unable to succeed so far I have come up with this code here:
Dark Mode
<div class="header-wrap">
Testing toggle with session
</div>
$('.darkmode-button').click(function() {
if (sessionStorage.getItem('darkmode', 'true')) {
$('.header-wrap').removeClass('dark-header');
sessionStorage.setItem('darkmode', 'false');
}
if (sessionStorage.getItem('darkmode', 'false')) {
$('.header-wrap').addClass('dark-header');
sessionStorage.setItem('darkmode', 'true');
}
});
function changeText() {
var x = document.getElementById("dmbutton");
if (x.innerHTML === "Dark Mode") {
x.innerHTML = "Light Mode";
} else {
x.innerHTML = "Dark Mode";
}
}
.header-wrap {
color: black;
}
.dark-header {
color: white;
background-color: black;
}
Can someone please share a working example of how it can be achieved?
I already created a question before but it was marked duplicate with this answer. I read it all but still could not figure it out.
To do what you require simply set a single class on a parent element, the body would work well in this case, to indicate when dark mode has been turned on. You can then use this class in all the relevant selectors in your CSS to update the UI.
Regarding the session storage logic, set a boolean flag when the dark mode is updated when the button is clicked and set the class on the body based on the session storage flag when the page loads.
Putting it all together would look something like this:
Dark Mode
<div class="header-wrap">
Testing toggle with session
</div>
let body = document.body;
let dmButton = document.querySelector('#dmbutton');
dmButton.addEventListener('click', e => {
body.classList.toggle('dark');
sessionStorage.setItem('darkmode', body.classList.contains('dark'));
e.target.textContent = e.target.textContent.trim() === 'Dark Mode' ? 'Light Mode' : 'Dark Mode';
});
let darkModeEnabled = JSON.parse(sessionStorage.getItem('darkmode')); // boolean type coercion
if (darkModeEnabled) {
body.classList.add('dark');
dmButton.textContent = 'Light Mode';
}
.header-wrap {
color: black;
}
body.dark {
background-color: #666;
}
body.dark .header-wrap {
color: white;
background-color: black;
}
Here's a working example in a jsFiddle, as SO snippets are sandboxed and disallow local/session storage access.
I don't know the logic of this code but it works for me which I found from this solution thanks to Stackoverflow
Dark Mode
<div class="header-wrap">
Testing toggle with session
</div>
var $dark = $('.header-wrap')
if (localStorage.getItem('darkmode') === 'true') {
$dark.addClass('dark-header');
}
$('.darkmode-button').click(function() {
$dark.toggleClass('dark-header');
localStorage.setItem('darkmode', $dark.hasClass('dark-header'));
});
.header-wrap {
color: black;
}
.dark-header {
color: white;
background-color: black;

Remove backgroundImage on componentDidMount

I currently have a <Login/> page, and a <Dashboard/>.
The login page has a background of #222, and when you login the Dashboard has a background of whitesmoke
The way I am doing this is having this on the body css:
body {
background-color: #222222;
}
and this in the Dashboard.js:
componentWillMount() {
document.body.style.backgroundColor = "whitesmoke";
}
componentWillUnmount() {
document.body.style.backgroundColor = null;
}
Up to now, this was working. But I now have an Image as my background on the Login page, as seen here:
body {
background-color: #222222;
background: url('../../public/img/bg.png');
background-repeat: repeat;
}
but my Dashboard inherits the background image, even when I put something like this:
componentWillMount() {
document.body.style.backgroundImage = null;
document.body.style.backgroundColor = "whitesmoke";
}
componentWillUnmount() {
document.body.style.backgroundColor = null;
}
How do I get around this?
Thanks
Why not use classes instead?
componentWillMount() {
$('body').addClass('has-background');
}
componentWillUnmount() {
$('body').removeClass('has-background');
}
Also, you may want to abstract those addClass / removeClass and use emits.

Styling Polymer Element Dynamically

I am trying to make an paper-card element change colors based on the status of the customers data on Fire base, but for some reason the color only updates on the second click of the customer. Right now I have the paper cards ID set to the firebase data in order to make it change colors. Here's my elements style code:
<style is="custom-style">
:host {
display: block;
}
#cards {
#apply(--layout-vertical);
#apply(--center-justified);
}
.row {
padding: 20px;
margin-left: 10px;
}
paper-card {
padding: 20px;
}
#check {
float: right;
bottom: 15px;
--paper-card
}
#Done {
--paper-card-header: {
background: var(--paper-green-500);
};
--paper-card-content: {
background: var(--paper-green-300);
};
}
#Default {
/*Apply Default Style*/
/*--paper-card-content: {*/
/* background: var(--paper-red-500);*/
/*};*/
}
paper-icon-button.check{
color: var(--paper-green-500);
}
paper-icon-button.check:hover{
background: var(--paper-green-50);
border-radius: 50%;
}
#check::shadow #ripple {
color: green;
opacity: 100%;
}
.iron-selected{
color: green;
}
And here is the template:
<template>
<firebase-collection
location="https://calllistmanager.firebaseio.com/Wilson"
data="{{wilsonData}}"></firebase-collection>
<div id="cards">
<template id="cards" is="dom-repeat" items="{{wilsonData}}" as="customer">
<paper-card id="{{customer.status}}" class="{{customer.status}}" heading="[[customer.__firebaseKey__]]">
<div class="card-content">
<span>Phone: </span><span>[[customer.number]]</span>
<span>Status: </span><span>[[customer.status]]</span>
<paper-icon-button style="color: green" id="check" on-tap="checktap" icon="check">
</paper-icon-button>
</div>
</paper-card>
</template>
</div>
Here is my script:
<script>
(function() {
Polymer({
is: 'list-display',
properties: {
wilsonData: {
type: Object,
observer: '_dataObserver'
}
},
ready: function() {
var listRef = new Firebase("https://calllistmanager.firebaseio.com/Wilson");
},
checktap: function(e){
// e.model.customer.status = "Done";
console.log("Starting Status: " + e.model.customer.status);
ref = new Firebase("https://calllistmanager.firebaseio.com/Wilson")
var stat;
var store = ref.child(e.model.customer.__firebaseKey__);
store.on("value", function(snapshot){
stat = snapshot.child("status").val();
});
if(stat == "Done"){
store.update({
"status": "Default"
});
e.model.customer.status = "Default";
}
else {
store.update({
"status": "Done"
});
e.model.customer.status = "Done";
}
console.log("Ending Status: " + e.model.customer.status);
this.updateStyles()
}
});
})();
at first I thought the problem may be that the function runs updateStyles(); faster than firebase can update but it always works fine on the second click...any suggestions?
I think the problem could be caused by the call to firebase. store.on("value", is not a synchronous function. However, later in your code you assume that you already have a value, that will be set later on whenever the value event fires. You could try adding the rest of your code in the event handler. Like this:
checktap: function(e){
// e.model.customer.status = "Done";
console.log("Starting Status: " + e.model.customer.status);
ref = new Firebase("https://calllistmanager.firebaseio.com/Wilson")
var store = ref.child(e.model.customer.__firebaseKey__);
store.once("value", function(snapshot){
var stat = snapshot.child("status").val();
if(stat == "Done"){
store.update({
"status": "Default"
});
e.model.set("customer.status", "Default");
}
else {
store.update({
"status": "Done"
});
e.model.set("customer.status", "Done");
}
console.log("Ending Status: " + e.model.customer.status);
this.updateStyles();
}.bind(this));
}
Essentially, you wait until the stat variable has been set to do the rest of your tasks. Also note, the bind(this) at the end, which will allow you to update the the styles from the event handler.
Update
There are a couple of more issues. First it's better to uses classes for changing the styles and not IDs. IDs should not change. Then, to bind to the class attribute, use the $ sign. When you update the model, you should use the set API.
Have a look at this plunker. It is a small working example (only works in Chrome) that changes styles when you click the checkmark. It does not use Firebase, however.
Here's how you could to the style with classes.
.Done {
--paper-card-header: {
background: var(--paper-green-500);
};
--paper-card-content: {
background: var(--paper-green-300);
};
}
And in your template:
<paper-card class$="{{customer.status}}" heading="[[customer.__firebaseKey__]]">

Errors with changing a header's color

I have a webpage I am designing with html, css, and JS. I have them properly hooked up, but for some reason my header will not do what I want. I have tried everything, does anyone know where I went wrong?
I want it so that when I mouse over the header or click the header, the color will change. This does not happen.
The important code in a JS-Fiddle: https://jsfiddle.net/DITTO/c37zxdke/
//javascript
var col = document.getElementById("webTitle").style.color;
function orangeToBlue() {
col = "#197CFF";
}
function blueToGreen() {
col = "#19FF29";
}
function greenToPink() {
col = "#FF19EF";
}
function pinkToOrange() {
col = "#FF9C19";
}
function changeColor() {
if (document.getElementById("webTitle").style.color === "#FF9C19") {
orangeToBlue();
} else if (document.getElementById("webTitle").style.color === "#197CFF") {
blueToGreen();
} else if (document.getElementById("webTitle").style.color === "#19FF29") {
greenToPink();
} else if(document.getElementById("webTitle").style.color === "#FF19EF") {
pinkToOrange();
}
}
//html
<h1 id="webTitle" onmouseover="changeColor()">Webpage Title</h1>
//css
#webTitle:hover {
cursor: pointer;
}
#webTitle {
text-shadow: 3.5px 3.5px 0px rgba(0, 0, 0, 0.3);
font-size: 100px;
font-family: fantasy;
color: #FF9C19;
}
Did you try to get what
document.getElementById("webTitle").style.color output?
When I log this action it's give me a blank string, can you confirm?
If you have the same blank string, then look at this this post the answer looks really good, and has nice links.
Or you can just look at this answer (from a duplicate).
Hope it's gonna help you a bit.
And the answer of Eduardo Escobar is important too.
Your functions orangeToBlue(), blueToGreen(), greenToPink() and pinkToOrange() aren't making any effect, although they are being called, they're just defining a variable, nothing else.
You should use rgb(rrr,ggg,bbb) color values in javaScript at theplace of using #rrggbb color values and CSS for seting initial color for your text.
//javascript
document.getElementById("webTitle").style.color = "#197CFF";
function orangeToBlue() {
document.getElementById("webTitle").style.color = "#197CFF";
}
function blueToGreen() {
document.getElementById("webTitle").style.color = "#19FF29";
}
function greenToPink() {
document.getElementById("webTitle").style.color = "#FF19EF";
}
function pinkToOrange() {
document.getElementById("webTitle").style.color = "#FF9C19";
}
function changeColor() {
if (document.getElementById("webTitle").style.color === "rgb(255, 156, 25)") {
orangeToBlue();
}
else
if (document.getElementById("webTitle").style.color === "rgb(25, 124, 255)") {
blueToGreen();
}
else
if (document.getElementById("webTitle").style.color === "rgb(25, 255, 41)") {
greenToPink();
}
else
if (document.getElementById("webTitle").style.color === "rgb(255, 25, 239)") {
pinkToOrange();
}
}
//html
<h1 id="webTitle" onclick="changeColor()" style="color: #FF9C19;" >Webpage Title</h1>
//css
#webTitle:hover {
cursor: pointer;
}
#webTitle {
text-shadow: 3.5px 3.5px 0px rgba(0, 0, 0, 0.3);
font-size: 100px;
font-family: fantasy;
}
The fiddle I posted most recently under g4u's answer works, fiddle doesn't work. FIDDLE IS BROKEN! Try it in a notepad and run it.

How to escape quotes in Less variable which stores a color name?

I am working on a HTML/CSS project. I want to create classes for labels and texts based on the color. For example
text-red{
color: red;
}
label-white{
color: white;
}
To do this I am trying to create a mixin which accepts a name and a color as argument and creates this class. I wrote the following mixin :
.mixin(#name, #color) {
.text-#{name} {
color: #color !important;
}
.label-#{name} {
color: #color !important;
}
}
.mixin('white', white);
This gives me the following output
.text-'white'{ /* notice the quotes*/
color: #ffffff
}
If I run this mixin as .mixin(white, white); I get
.text-#ffffff{
color: #ffffff
}
How can I create a class like text-white using a mixin?
From the LESS "e" function reference:
e(#string); // escape string content
If you use the function e you'll get the correct result.
.mixin(#name, #color) {
.text-#{name} {
color: #color !important;
}
.label-#{name} {
color: #color !important;
}
}
.mixin(e('white'), white);
You can also create a variable and then use it for multiple purposes:
#whiteLiteral: e('white');
//mixin declaration code
.mixin(#whiteLiteral, white);
LightStyle is right but if you have many named color to set, you could use a recursive loop with a list of string color like this :
.recursive-loop(#list_size, #list) when (#list_size > 0) {
// Get the current color from the list #list at index #list_size
#current_color: e( extract(#list, #list_size) );
.myclass1-#{current_color} {
color: #current_color;
}
.myclass2-#{current_color} {
background-color: #current_color;
}
//etc...
// until the end of list
.recursive-loop( (#list_size - 1), #list)
}
.mixin-color(){
// Add color you need to this list and get size of it.
#list: "black", "dimgrey", "grey", "lightgrey", "white", "red", "blue", "green";
#list_size: length(#list);
// Call recursive loop with the preview list
.recursive-loop(#list_size, #list);
}
// mixin call
.mixin-color();
I hope it will help...

Categories