skip to Main Content

I have 2 buttons for now as an example. The problem here is, when I click on Button A for example it changes the class on the html document with the value from "data-accent-switcher" which in this case is BLUE, but when I press on button A again it changes with the value from button B, same happens with button b. Now even If I press like 20 times on Button A, I always want to have that value of from the data attribute (data-accent-switcher).

How can I make it possible?

<button class='ipsButton accentSwitcher' data-accent-switcher="blue">Button A</button>
<button class='ipsButton accentSwitcher' data-accent-switcher="yellow">Button B</button>
<script type="text/javascript">
  $(document).ready(function() {
    $('.accentSwitcher').on("click", function() {
      var accentValue = $(this).data('accent-switcher');
      if (document['documentElement']['classList']['contains']('accent-blue')) {
        document['documentElement']['classList']['remove']('accent-blue');
        document['documentElement']['classList']['add']('accent-yellow');
      } else {
        if (document['documentElement']['classList']['contains']('accent-yellow')) {
          document['documentElement']['classList']['remove']('accent-yellow');
          document['documentElement']['classList']['add']('accent-blue');
        }
      }
      ips['utils']['cookie']['set']('ipsTheme_type', accentValue, true)
    });
  });
</script>

I’ve tried with if statements but obviously I’m wrong and doesn’t work.

3

Answers


  1. Chosen as BEST ANSWER

    So thanks to @DavidThomas I used his code and came up with this

    <script>
      $(document).ready(function() {
        const accentButtons = $('.accentSwitcher[data-accent-switcher]'),
              accentSwitches = accentButtons.map(function() {
                return $(this).data('accent-switcher');
              }).get();
        accentButtons.on('click', function() {
          let accentChoice = $(this).data('accent-switcher')
          $(this).closest(document.documentElement)
            .removeClass(accentSwitches)
            .addClass(accentChoice)
          ips.utils.cookie.set('ipsTheme_type', accentChoice, true);
        });
      });
    </script>
    

    I hope this is right. But I'm not sure about this $(this).closest(document.documentElement)


  2. Thanks, for your question, i think you can do it, like this.

    <script type="text/javascript">
      $(document).ready(function() {
        $('.accentSwitcher').on("click", function() {
          var accentValue = $(this).data('accent-switcher');
          var currentAccentValue = document.documentElement.classList.contains('accent-blue') ? 'blue' : 'yellow';
          if (accentValue !== currentAccentValue) {
            if (currentAccentValue === 'blue') {
              document.documentElement.classList.remove('accent-blue');
              document.documentElement.classList.add('accent-yellow');
            } else {
              document.documentElement.classList.remove('accent-yellow');
              document.documentElement.classList.add('accent-blue');
            }
            ips.utils.cookie.set('ipsTheme_type', accentValue, true);
          }
        });
      });
    </script>
    
    

    I hope my solution, will help you.

    Login or Signup to reply.
  3. I’d suggest the following approach, with explanatory comments in the code:

    // a named function to handle the 'accent-switching', declared using
    // Arrow function syntax, and taking one argument 'evt', a reference
    // to the Event object passed automatically from the later use of
    // EventTarget.addEventListener():
    const accentSwitch = (evt) => {
        // we use destructuring assignment to retrieve the
        // currentTarget node (the node to which the function
        // was bound) from the Event Object:
        let {
          currentTarget
        } = evt,
        // we cache the data-accent-switcher attribute-value,
        // using the HTMLElement.dataset API:
        value = currentTarget.dataset.accentSwitcher,
        // we cache a reference to the element we wish to
        // affect (obviously, this could be changed to select
        // the appropriate ancestor element of your choice,
        // up to, and including, the <html> element):
        targetElement = currentTarget.closest('section');
        // if we have a variable called 'accentChoices', and
        // it holds a truthy value:
        if (accentChoices) {
          // we take the targetElement, and use the Element.classList
          // API to remove the list of classes from the element:
          targetElement.classList.remove(...accentChoices);
        }
        // here we again use the Element.classList API, this
        // time to add a class-name:
        currentTarget.closest('section').classList.add(value);
      },
      // using document.querySelectorAll() to retrieve a NodeList of
      // all elements that have the class of 'accentSwitcher'
      // and also have a 'data-accent-switcher' attribute:
      accentButtons = document.querySelectorAll('.accentSwitcher[data-accent-switcher]'),
    
      // here we convert that iterable NodeList to an Array and then
      // use Array.prototype.map() to create a new Array based upon
      // the first:
      accentChoices = Array.from(accentButtons).map(
        // using an Arrow function, we use the
        // HTMLElement.dataset API to retrieve
        // the attribute-value of the data-*
        // attribute:
        (el) => el.dataset.accentSwitcher
      );
    
    // iterating over the NodeList of elements we found,
    // using NodeList.prototype.forEach():
    accentButtons.forEach(
      // using an Arrow function to bind the accentSwitch()
      // function - note the deliberate lack of parentheses -
      // as the event-handler for the 'click' event:
      (el) => el.addEventListener('click', accentSwitch)
    );
    :root {
      --blue: hsl(200deg 90% 70% / 1);
      --purple: hsl(300deg 90% 70% / 1);
      --yellow: hsl(60deg 90% 70% / 1);
    }
    
    *,
    ::before,
    ::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    body {
      min-block-size: 100vh;
    }
    
    main {
      block-size: 100vh;
      display: grid;
      place-content: center;
    }
    
    .wrapper {
      background-image:
        linear-gradient(
          135deg,
          #ffff,
          #fff7
        ),
        repeating-linear-gradient(
          45deg,
          transparent 0 0.75rem,
          var(--colorChoice, var(--purple)) 0.75rem 1rem
        );
      box-shadow:
        0.75rem 0.75rem 1.5rem var(--colorChoice, var(--purple)),
        -0.75rem -0.75rem 1.5rem var(--colorChoice, var(--purple));
      display: flex;
      inline-size: clamp(15rem, 40%, 800px);
      justify-content: space-between;
      outline: 3px solid var(--purple);
      padding-block: 1em;
      padding-inline: 2em;
    }
    
    section.blue {
      --colorChoice: var(--blue);
    }
    
    section.yellow {
      --colorChoice: var(--yellow);
    }
    
    button {
      padding-block: 0.5rem;
      padding-inline: 0.75rem;
    }
    <!-- your HTML was adjusted primarily to wrap the <button> elements,
         and show an ancestor element that could be easily targeted via
         JavaScript, while providing some aesthetic hooks for the CSS: -->
    <main>
      <section class="wrapper">
        <button class='ipsButton accentSwitcher' data-accent-switcher="blue">Button A</button>
        <button class='ipsButton accentSwitcher' data-accent-switcher="yellow">Button B</button>
      </section>
    </main>

    JS Fiddle demo.

    As OP wishes to continue using jQuery, I’ve added jQuery option below, again this has explanatory comments in the code:

    // creating a const variable to hold the collection of
    // <button> elements:
    const buttons = $('.accentSwitcher[data-accent-switcher]'),
                // creating an Array from the <button> collection:
              accentSwitches = buttons.map(function() {
            // returning the data-accent-switcher attribute-
            // value, using the data() method:
            return $(this).data('accent-switcher');
          // converting the modified collection into
          // a plain JavaScript Array with get():
          }).get();
    
    // using on() to bind the anonymous function of the
    // method as the event-handler for 'clicke' events:
    buttons.on('click', function() {
        // caching the attribute-value of the
      // data-accent-switcher value:
        let accentChoice = $(this).data('accent-switcher')
      // navigating to the closest ancestor <section>
      // element:
      $(this).closest('section')
        // removing all the classes that are featured
        // in the Array of accentSwitches:
        .removeClass(accentSwitches)
        // adding the data-accent-switcher attribute-
        // value to the current element:
        .addClass(accentChoice)
        // using the css() method to update the
        // --colorChoice css custom property:
        .css('--colorChoice',
            // we're setting the above property to
          // the value held in the current <button>
          // element's own --colorChoice
          // custom property:
            $(this).css(`--colorChoice`)
        );
    });
    :root {
      --purple: hsl(300deg 90% 70% / 1);
    }
    
    *,
    ::before,
    ::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    body {
      min-block-size: 100vh;
    }
    
    main {
      block-size: 100vh;
      display: grid;
      place-items: center;
    }
    
    .wrapper {
      background-image:
        linear-gradient(
          135deg,
            #ffff,
            #fff7
        ),
        repeating-linear-gradient(
          45deg,
            transparent 0 0.75rem,
            var(--colorChoice, var(--purple)) 0.75rem 1rem
        );
      box-shadow:
        0.75rem 0.75rem 1.5rem var(--colorChoice, var(--purple)),
        -0.75rem -0.75rem 1.5rem var(--colorChoice, var(--purple));
      display: flex;
      flex-flow: row wrap;
      gap: 0.5rem;
      inline-size: clamp(15rem, 40%, 800px);
      justify-content: space-between;
      outline: 3px solid var(--purple);
      padding-block: 1em;
      padding-inline: 2em;
    }
    
    button {
      flex-grow: 1;
      padding-block: 0.5rem;
      padding-inline: 0.75rem;
    }
    <!-- your HTML was adjusted primarily to wrap the <button> elements,
         and show an ancestor element that could be easily targeted via
         JavaScript, while providing some aesthetic hooks for the CSS: -->
    <main>
      <section class="wrapper">
        <button class='ipsButton accentSwitcher' data-accent-switcher="blue" style="--colorChoice: hsl(200deg 90% 70% / 1);">Button A</button>
        <button class='ipsButton accentSwitcher' data-accent-switcher="yellow" style="--colorChoice: hsl(60deg 100% 50% / 1);">Button B</button>
        <button class='ipsButton accentSwitcher' data-accent-switcher="green" style="--colorChoice: hsl(100deg 90% 70% / 1);">Button C</button>
        <button class='ipsButton accentSwitcher' data-accent-switcher="pink" style="--colorChoice: hsl(330deg 95% 70% / 1);">Button D</button>
        <button class='ipsButton accentSwitcher' data-accent-switcher="orange" style="--colorChoice: hsl(25deg 100% 50% / 1);">Button E</button>
        <button class='ipsButton accentSwitcher' data-accent-switcher="red" style="--colorChoice: hsl(355deg 90% 70% / 1);">Button F</button>
      </section>
    </main>

    JS Fiddle demo.

    References:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search