Reputation: 5
So this the code I'm doing
<a onclick="setStyleSheet('css/blue.css')" href="#">Switch</a>
<a onclick="setStyleSheet('css/red.css')" href="#">Switch</a>
On click it'll switch to blue theme. But I want to keep the button same. Instead of using 2 buttons. I just want one Switch button to change to blue, then if I click that button again, it'll change to red. Is there anyway to do this? THanks all in advance!
Upvotes: 0
Views: 119
Reputation: 253506
One approach, that may work (depending upon the complexity of your stylesheets) is to update a CSS custom property to update the properties you wish to change or edit:
// defining the colours to be used (the approach taken in these
// code snippets allows for other values to be added to this
// Array to extend the number of colours/values used):
let cssStyles = ['blue', 'red'],
// defining the function (using Arrow syntax, since
// we don't need to use the 'this' object within):
modifyCSS = (styles) => {
// 'styles': the Array of colours passed into the function.
// here we find the root-element of the document:
let root = document.querySelector(':root'),
// we retrieve the current value of the '--colorValue'
// CSS property defined in that Node's CSS (if present):
current = root.style.getPropertyValue('--colorValue'),
// and, because this property-value is a String, we search
// the Array of colours to retrieve the index of the current
// colour:
index = styles.indexOf(current);
// here we update the '--colorValue' custom property to the
// property held in the next index of the Array; or to the
// value held at the Array's zeroth/first index:
root.style.setProperty('--colorValue', styles[++index % styles.length]);
}
// binding the function to the click event on the '#updatecss' button:
document.querySelector('#updatecss').addEventListener('click', (e) => modifyCSS(cssStyles) );
let cssStyles = ['blue', 'red'],
modifyCSS = (event, styles) => {
let root = document.querySelector(':root'),
current = root.style.getPropertyValue('--colorValue'),
index = styles.indexOf(current);
root.style.setProperty('--colorValue', styles[++index % styles.length]);
}
document.querySelector('#updatecss').addEventListener('click', (e) => modifyCSS(e, cssStyles) );
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
display: grid;
grid-template-columns: 40vw 40vw;
width: 80vw;
margin: auto;
grid-gap: 4px;
}
.wrapper>div {
color: var(--colorValue, black);
border: 2px solid currentColor;
grid-column: 1/-1;
}
<div class="wrapper">
<button id="updatecss">Switch CSS</button>
<div>element 1</div>
<div>element 2</div>
<div>element 3</div>
<div>element 4</div>
</div>
Given that your question requires new stylesheets, and is probably a simplified version of your requirements, it may be more difficult to update CSS custom properties to meet your needs. However, we can use a similar approach with an array of stylesheet names:
// CSS stylesheet filenames:
let stylesheets = ['blue.css', 'red.css'],
// named function, using Arrow syntax as above, to change
// the stylesheets:
modifyCSS = (sheets) => {
// finding the relevant <link> element:
let link = document.querySelector('.linkedResource'),
// finding the index of the last '/' character in
// the href property-value of the <link>; adding 1
// so that the last slash is included in the 'path'
// and not the 'file':
lastSlashIndex = link.href.lastIndexOf('/') + 1,
// here we find the substring of the href up to,
// and including, the last '/' character:
path = link.href.substring(0, lastSlashIndex),
// finding the filename (based on the assumption
// that the filename follows the last '/' character):
file = link.href.slice(lastSlashIndex),
// finding the index of the current filename in the
// Array of filenames:
currentSheetIndex = sheets.indexOf(file);
// updating the href of the <link> element to be equal
// to the concatenated value of the path and the
// filename held at the next, or first, index of the Array:
link.href = path + sheets[++currentSheetIndex % sheets.length];
};
document.querySelector('#updatecss').addEventListener('click', () => modifyCSS(stylesheets));
let stylesheets = ['blue.css', 'red.css'],
modifyCSS = (sheets) => {
let link = document.querySelector('.linkedResource'),
lastSlashIndex = link.href.lastIndexOf('/') + 1,
path = link.href.substring(0, lastSlashIndex),
file = link.href.slice(lastSlashIndex),
currentSheetIndex = sheets.indexOf(file);
link.href = path + sheets[++currentSheetIndex % sheets.length];
};
document.querySelector('#updatecss').addEventListener('click', () => modifyCSS(stylesheets));
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
display: grid;
grid-template-columns: 40vw 40vw;
width: 80vw;
margin: auto;
grid-gap: 4px;
}
.wrapper>div {
color: var(--colorValue, black);
border: 2px solid currentColor;
grid-column: 1/-1;
}
<link rel="stylesheet" href="https://www.davidrhysthomas.co.uk/linked/blue.css" class="linkedResource" />
<div class="wrapper">
<button id="updatecss">Switch CSS</button>
<div>element 1</div>
<div>element 2</div>
<div>element 3</div>
<div>element 4</div>
</div>
References:
Bibliography:
Upvotes: 0
Reputation: 1558
I suggest not to use the href="#". This will give uggly urls. If you use the anchor better use
<a onclick="setStyleSheet('....')" href="javascript:void(0)">Switch</a>
Another option is using event.preventDefault();
in your javascript function.
Upvotes: 0
Reputation: 1
I would use another helper function and set some condition first.
function setElement(){
var style = document.styleSheets[0]; //set the index
if(style.href ==='css/blue.css'){
style.href = 'css/red.css';
}else if (style.href ==='css/red.css'){
style.href = 'css/blue.css';
}else{
console.log('error');
}
}
<a onclick="setElement();" href="#">Switch</a>
Upvotes: 0
Reputation: 1780
You can set a global flag
window.blueTheme = true
function setStyleSheet() {
var styleSheetToBeSet = window.blueTheme ? "css/red.css" : "css/blue.css"
window.blueTheme = !window.blueTheme
// your code here
}
Of course, you can change blueTheme to theme and store theme name instead of boolean variable.
And then just call the function without parameter:
<a onclick="setStyleSheet()" href="#">Switch</a>
Upvotes: 2
Reputation: 852
Simple, use if loop to compare the argument like
function StyleSheet(arg) {
if (arg == "css/blue.css") {
var styleSheetToBeSet = "css/red.css";
}
else {
var styleSheetToBeSet = "css/blue.css";
}
//set style sheet here with js
}
Upvotes: 0