Site logo

Archived topic

Is it possible to fire 'generate_element_display' using wp.hooks?

12 replies · Started by Lewis on April 1, 2022

Viewing posts 1–13 of 13

Hi there,

I know you can use generate_element_display to bypass the Display Rules, so we can enable or disable an Element under our own conditions. as per the doc's (GP Doc's Link).

For Example;

add_filter( 'generate_element_display', function( $display, $element_id ) {
    if ( 100 === $element_id && is_author( 'Tom' ) ) {
        $display = true;
    }

    return $display;
}, 10, 2 );

However, I would like to know if it is possible to fire this filter using js with the addFilter( 'hookName', 'namespace', callback, priority )? as per the Block Editor Handbook? (Block Editor Handbook Link to addFilter()).

My reason for asking is I would like to fire a display filter based on a <select></select> element managed by javascript.

If this is possible it might be worth noting the doc's. :)

Thanks.

Hi there,

Are you wanting to programmatically set the Display Rules in the editor based on another value? So it would actually alter the values in the Display Rules section?

If so, this likely isn't possible at the moment as the Display Rules section isn't built in React/JS. Once we port it over to React, it will likely be possible to do something like this.

Let me know :)

Hey Tom,

Some more context might be useful, my bad.xD

I've spent the last couple of days building a colour theme toggle for my site. You can see the fruits of my labour here (jsFiddle).

I then went about creating some hooks using the elements feature, my goal here was to load the required css :root {} media query conditionally or vice versa load the various :root {} rules conditionally as it would be more appropriate.
[url=https://ibb.co/QpHnV9x][img]https://i.ibb.co/PFW4yxV/Screenshot-2022-04-01-at-20-01-27.png[/img][/url]

Most of my thoughts are just theories at the moment. I was hoping to call the hooks conditionally within my js switch case using the wp.hooks approach.

David provided an awesome tid-bit here that sparked my curiosity as to whether I could achieve a toggle rather than an automatic switch.

An exact example of what I'm trying to reproduce can be found here. (You can find the theme toggle in their footer.)

There are a few different approaches I can likely still take but I don't want to override GP's colour settings by prefixing my css with h1.dark-mode {} I'd much rather go the var route as highlighted by David.

Hi there,

i would do something like this:

1. Create a JS script to toggle a class on button click:

<script>
var html = document.querySelector('html');
var dmtoggle = document.querySelector('.dm-toggle');

dmtoggle.onclick = function() {
    html.classList.toggle('dark-mode');
    dmtoggle.classList.toggle('active');
}
</script>

2, add your button/toggle with the dm-toggle class eg.

<button class="dm-toggle">Dark Mode</button>

3. Now on click that should toggle the dark-mode class on the root HTML element. So your Darkmode CSS would be:

:root.dark-mode {
    --contrast: var(--dm-contrast);
    --contrast-2: var(--dm-contrast-2);
    --contrast-3: var(--dm-contrast-3);
    --base: var(--dm-base);
    --base-2: var(--dm-base-2);
    --base-3: var(--dm-base-3);
    --accent: var(--dm-accent);
}

Hi David,

I didn't even think about prefixing the root via the HTML tag. Pure genius!👌

I hope you don't mind but I tweaked your button version to a dropdown version. You can see the fruits of my labour here, bonus points, my solution uses local storage to remember a users previous set schema too! Feel free to tweak and distribute if you fancy it.

Thanks again for the top notch support. 👍

Thats awesome - i like your approach to the localStorage handling . very nice ;) Thanks for sharing that!

Hey there, just re-opening this thread.

I've applied the JS

<script>
var html = document.querySelector('html');
var dmtoggle = document.querySelector('.dm-toggle');

dmtoggle.onclick = function() {
    html.classList.toggle('dark-mode');
    dmtoggle.classList.toggle('active');
}
</script>

And applied the CSS

:root.dark-mode {
    --contrast: var(--dm-contrast);
    --contrast-2: var(--dm-contrast-2);
    --contrast-3: var(--dm-contrast-3);
    --base: var(--dm-base);
    --base-2: var(--dm-base-2);
    --base-3: var(--dm-base-3);
    --accent: var(--dm-accent);
}

I've also added a CSS class of 'dm-toggle' to a button. The dark theme gets enabled on click, however when I load a new page it switches back to the standard theme. How can I modify the JS to retain the user's selection of 'dark-mode' ???

Hi David,

Yes I'm trying to figure out how to implement that user's solution - https://jsfiddle.net/Beaniie/opgy6Lu1/209/

I've implemented it using WP hooks for the HTML and JS on my site, however I'm confused with the CSS that's been supplied...

body {
  padding: 0;
  margin: 0;
  font-family: sans-serif;
  font-weight: 300;
  background: var(--background-primary);
}

:root {
  /* system schema */
  --background-primary: #f8f8f8;
  --background-secondary: #c0c0c0;
  --border-primary: #808080;
  --text-primary: #000;

  /* light mode schema */
  --lm-background-primary: #f8f8f8;
  --lm-background-secondary: #c0c0c0;
  --lm-border-primary: #808080;
  --lm-text-primary: #000;

  /* dark mode schema */
  --dm-background-primary: #000;
  --dm-background-secondary: #101010;
  --dm-border-primary: #404040;
  --dm-text-primary: #fff;
}

/* automatic dark mode */
@media (prefers-color-scheme: dark) {
  :root {
    /* dark mode schema */
    --background-primary: var(--dm-background-primary);
    --background-secondary: var(--dm-background-secondary);
    --border-primary: var(--dm-border-primary);
    --text-primary: var(--dm-text-primary);
  }
}

/* automatic dark mode */
@media (prefers-color-scheme: light) {
  :root {
    /* dark mode schema */
    --background-primary: var(--lm-background-primary);
    --background-secondary: var(--lm-background-secondary);
    --border-primary: var(--lm-border-primary);
    --text-primary: var(--lm-text-primary);
  }
}

.box {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  max-width: 400px;
  margin: 0 auto;
}

.box .inner {
  text-align: center;
  width: 500px;
  color: var(--text-primary);
  background: var(--background-secondary);
  padding: 1rem;
  border-radius: 4.33px;
  border: 1px dashed var(--border-primary);
}

.box .inner p {
  margin-bottom: 1rem;
}

.box .inner select {
  margin-bottom: 0.75rem;
}

How is it meant to target the selected light/dark schema based on the Javascript..

document.addEventListener("DOMContentLoaded", function(event) {
  // Check for preference or previous setting.
  checkUserPreference();
});

// Get the select element.
const selectEle = document.getElementById('selectSchema');

// Watch the select element for change.
selectEle.addEventListener('change', function() {
  themeSchemaSetting();
});

// Check for user preference.
function checkUserPreference() {

  // Check to see if storage is set if not initialise.
  if (!localStorage.hasOwnProperty('currentSchema')) {
    const prefersDarkSchema = window.matchMedia("(prefers-color-scheme: dark)");
    const prefersLightSchema = window.matchMedia("(prefers-color-scheme: light)");

    // If user preference detected set system schema, else set light schema.
    if (prefersDarkSchema.matches || prefersLightSchema.matches) {
      selectEle.selectedIndex = 0; // Set system in select.
    } else {
      selectEle.selectedIndex = 2; // Set light in select.
    }
  }
  // Set the schema.
  themeSchemaSetting();
}

// Set the schema.
function themeSchemaSetting(currentSchema) {

  // Set & retreive local storage.
  selectValue = selectEle.value;
  localStorage.setItem('currentSchema', selectValue);
  currentSchema = localStorage.getItem('currentSchema');

  // debug log
  console.log("Select Value:", selectValue);
  console.log("Storage Schema:", currentSchema);

  // set theme based on set storage
  switch (currentSchema) {
    case 'systemSchema':
      // set light schema.
      console.log("Theme is system.");
      break;
    case 'lightSchema':
      // set dark schema.
      console.log("Theme is Light.");
      break;
    case 'darkSchema':
      // let the system decide.
      console.log("Theme is Dark.");
      break;
    default:
      // default schema developer preference.
      console.log("Theme is default. (Light)");
  }
}

What modifications should be made to the CSS in order to operate properly?

Any help is greatly appreciated..

I've also added the HTML for the toggle dropdown on my site on another hook element

<div class="box">
  <div class="inner">
    <!-- css colour mode select -->
    <div class="theme-switcher">
      <label for="selectSchema">
        <div class="select_container">

          <!-- select element -->
          <select class="select select-small" id="selectSchema" aria-label="Change color theme">
            <option value="systemSchema">System</option>
            <option value="lightSchema">Light</option>
            <option value="darkSchema">Dark</option>
          </select>

        </div>
      </label>
    </div>
  </div>
</div>

Glad to hear you got it working, and thanks for sharing the additional resource

#darkmode options

This archived topic is closed to new replies.