Desmond Sitt Naing
Desmond Sitt Naing

Reputation: 5

Make onclick function in HTML to do 2 functions

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

Answers (5)

David Thomas
David Thomas

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>

JS Fiddle demo.

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>

JS Fiddle demo.

References:

Bibliography:

Upvotes: 0

bron
bron

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

iamjacek
iamjacek

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

wang
wang

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

Naveen
Naveen

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

Related Questions