Automatically apply Event Type color to the button and date backgrounds

We predominantly use the month layout, but when we use the list or mason layouts, the “Event Type” gets lost in the listing. We rely on this color coding! It would be great to have an option when designing certain layouts to use the “event type” color as the background, date, background, or button colors, to help visually differentiate them in these layouts.

2 Likes

Hi there and welcome to the Community, @Elizabeth_Young :wave:

Do I get it right that you’d like the event type color to be applied to date/button colors automatically, rather than having to set them manually in the Style tab?

1 Like

Yes! Because currently, the style tab will set buttons, backgrounds, etc as the same color for every entry, which makes it difficult to see the color coding on event types, depending on the combination.

The type of color coding on the month view calendar puts the event title on a background of the “right” color, and we would want to do something similar in Masonry, List, etc, so visitors can visually differentiate quickly as they scroll.

Personally, I think the “date background” field or the “button” is what we would want to use for color coding, but I thought color coding other style features might be handy for other user cases. I can share pictures to demonstrate what I mean if that is helpful.

2 Likes

Thanks, I completely got what you mean! We’ll try to think about this option in the future, especially if more users support this idea :slightly_smiling_face:

In the meantime, if you have a widget with the List or Masonry layout, please send me a link to it. I’ll be happy to check with the devs if it’s possible to implement it with the custom script :slightly_smiling_face:

2 Likes

I apologize for the delay, and sure; we are in the process of building a new website, so this is the temporary website where we’ve installed the widget in list form: Events Calendar List View

And you can see that the event type is color coded at the top, but lighter colors disappear, and some of the darker colors are indistinguishable from each other. And we can change our color selections, but they look best in our primary, monthly calendar, format. Plus, the font for the event type remains small and thin, no matter what.

Let me know what you think, but honestly this layout is the view where we are trying to accommodate/redirect mobile users, so it’s based on our primary widget, which is here: Upcoming Events Calendar | Champaign County Humane Society , and it might not be worth trying to implement custom script.

2 Likes

Thanks for the link!

Devs confirmed that it’s possible to implement this customization. I’ve passed your request on to them and will update you once the code is ready :slightly_smiling_face:

1 Like

Thank you for waiting!

Our devs came up with a custom solution for you. Please add this script to the Custom JS field on the Settings tab of your widget’s settings:

const WIDGET_ID = 'c307f3a4-ed4e-4a3c-a82c-376fb65bee06';
const calendar = document.querySelector(`.elfsight-app-${WIDGET_ID}`);

if (calendar?.dataset.elfsightAppLayout !== 'list') return;

const waitForElem = (selector, root) =>
  new Promise((resolve) => {
    if (root.querySelector(selector)) {
      return resolve(root.querySelector(selector));
    }

    const observer = new MutationObserver(() => {
      if (root.querySelector(selector)) {
        observer.disconnect();
        resolve(root.querySelector(selector));
      }
    });

    observer.observe(root, {
      childList: true,
      subtree: true,
    });
  });

const observeChildNodes = (element, callback) => {
  new MutationObserver((mutationsList) => {
    const hasChildListMutation = mutationsList.some(
      (mutation) => mutation.type === 'childList'
    );
    if (hasChildListMutation) {
      callback(element);
    }
  }).observe(element, { childList: true, subtree: true });
};

function parseRGB(rgbStr) {
  const [r, g, b] = rgbStr.match(/\d+/g).map(Number);
  return { r, g, b };
}

const getLuminance = ({ r, g, b }) => 0.2126 * r + 0.7152 * g + 0.0722 * b;

const isDarkColor = (color) => getLuminance(parseRGB(color)) < 100;

const addColorsToCards = (container) => {
  const cards = container.querySelectorAll(
    '.eapp-events-calendar-list-item-component'
  );
  cards.forEach((card) => {
    const category = card.querySelector('.eapp-events-calendar-category-item');
    if (!category) return;

    const eventColor = getComputedStyle(category).color;

    const button = card.querySelector('.eapp-events-calendar-button-link');
    if (button) {
      button.style.background = eventColor;
      if (isDarkColor(eventColor)) button.style.color = 'white';
    }

    const date = card.querySelector(
      '.eapp-events-calendar-date-element-component'
    );
    if (date && !isDarkColor(eventColor)) date.style.color = eventColor;
  });
};

waitForElem('.eapp-events-calendar-events-calendar-layout', calendar).then(
  (list) => {
    addColorsToCards(list);
    observeChildNodes(list, addColorsToCards);
  }
);

And this code should be placed in the Custom CSS field on the Style tab:

.eapp-events-calendar-list-item-date {
  color: white;
}

.eapp-events-calendar-list-item-date * {
  color: inherit !important;
}

Please try it out and let me know if you like the result :slightly_smiling_face:

2 Likes

Hello! Wow, I’m so sorry I didn’t realize I delayed a response this long! Thank you so much for your team’s help with this solution, and it did work perfectly for the custom button colors! However, the date backgrounds aren’t acting consistently.

When I first loaded the custom script, I saw that there were some low-contrast or clashing color combinations that I needed to update, so I changed the color on two event types. When that happened, one of them updated the date text color, and one of them did not.

I had originally pictured the date background being the color that changes, with the text color remaining black or white depending on the script’s existing contrast logic (I have no idea what I’m talking about, so I hope that makes sense).

In our very particular use case (sorry) I don’t think we can use the consistent background colors on the dates, unless we return to the white text for all date fields. I was able to adjust some colors and thought they were ok, but for branding purposes some of the more low-visibility pairings with the #344140 background can’t be changed. How can I return to the standard background field color and white text color for the date fields, since we don’t have the different background colors?

Here is the link to the live customized calendar: Upcoming Events List View | Champaign County Humane Society

Again, I’m so sorry that I waited this long to get back to you. I am genuinely surprised that Elfsight is taking this solution as seriously as they have, and I’m really grateful. Not all vendors have been as helpful as you during our website transition, despite my own inability to respond in a timely manner.

Thanks!

Changing “education events” color updated across both text color and button color. Left is old colors, right is new colors:

Changing “volunteering” color updated across button only - but I wasn’t too sure this color combo would work on the date fields anyway, so I’m not sure if that was intentional:

And finally, one of our event types uses that same color, #344140, and I wasn’t sure how that would appear. We didn’t have any upcoming on the calendar, so I added a test one, and the button was the right color, and the text color was white. That was good, it wouldn’t have worked if they were the same color obviously, but now I’m not sure if that test worked only because the text colors were breaking sometimes?

2 Likes

Hi there, @Elizabeth_Young :waving_hand:

Your feedback totally made our day, thanks a ton for your kind words!

Just to clear things up, you’d like to keep the same color for the date text, but the date background color should be changed based on the chosen event type, am I right?

2 Likes

Yes, originally I was thinking

Date Background = Event Type Color
Date Text Color = Black or White, depending on the color’s value. Just, the way that the monthly calendar will automatically pick.

But it’s also ok for us to switch back to a single, default color for the date background!

I really do appreciate it, as I’m learning everything I know about scripts and building a website as challenges arise. :melting_face:

2 Likes

Got it, thanks!

I’ve passed it to the devs and will update you once I have any news :slightly_smiling_face:

1 Like

Hi there, @Elizabeth_Young :waving_hand:

We’ve replaced the script in the Custom JS with the new version:

const WIDGET_ID = 'c307f3a4-ed4e-4a3c-a82c-376fb65bee06';
const calendar = document.querySelector(`.elfsight-app-${WIDGET_ID}`);

if (calendar?.dataset.elfsightAppLayout !== 'list') return;

const waitForElem = (selector, root) =>
  new Promise((resolve) => {
    if (root.querySelector(selector)) {
      return resolve(root.querySelector(selector));
    }

    const observer = new MutationObserver(() => {
      if (root.querySelector(selector)) {
        observer.disconnect();
        resolve(root.querySelector(selector));
      }
    });

    observer.observe(root, {
      childList: true,
      subtree: true,
    });
  });

const observeChildNodes = (element, callback, defaultColors) => {
  new MutationObserver(() => callback(element, defaultColors)).observe(
    element,
    { childList: true, subtree: true }
  );
};

function parseRGB(rgbStr) {
  const [r, g, b] = rgbStr.match(/\d+/g).map(Number);
  return { r, g, b };
}

const getLuminance = ({ r, g, b }) => 0.2126 * r + 0.7152 * g + 0.0722 * b;

const isDarkColor = (color) => getLuminance(parseRGB(color)) < 100;

const addColorsToCards = (container, defaultColors) => {
  const cards = container.querySelectorAll(
    '.eapp-events-calendar-list-item-component'
  );

  cards.forEach((card) => {
    const category = card.querySelector('.eapp-events-calendar-category-item');

    let eventColor, isDark;
    if (category) {
      eventColor = getComputedStyle(category).color;
      isDark = isDarkColor(eventColor);
    }

    const button = card.querySelector('.eapp-events-calendar-button-link');
    if (button) {
      button.style.background = eventColor || defaultColors.button;
      button.style.color = isDark ? 'white' : 'rgb(17, 17, 17)';
    }

    const date = card.querySelector(
      '.eapp-events-calendar-date-element-component'
    );

    if (date) date.style.background = eventColor || defaultColors.date;
  });
};

waitForElem('.eapp-events-calendar-events-calendar-layout', calendar).then(
  (list) => {
    const dateEl = list.querySelector(
      '.eapp-events-calendar-date-element-component'
    );
    const button = list.querySelector('.eapp-events-calendar-button-link');

    const defaultColors = {
      date: dateEl ? getComputedStyle(dateEl).backgroundColor : 'rgb(52, 65, 64)',
      button: button ? getComputedStyle(button).backgroundColor : 'rgb(0, 174, 239)',
    };

    addColorsToCards(list, defaultColors);
    observeChildNodes(list, addColorsToCards, defaultColors);
  }
);

And with this CSS code we’ve fixed the conflict with the filter display on your website:

.global-styles,
.eapp-events-calendar-dates-calendar tr {
  display: table-row !important;
  box-shadow: none !important;
  margin: 0 !important;
}

.global-styles,
.eapp-events-calendar-dates-calendar td {
  display: table-cell !important;
  padding: 0 !important;
}

.global-styles,
.CalendarDay:not(.CalendarDay__outside) {
  border: 1px solid #e4e7e7 !important;
}

.global-styles,
.CalendarDay__outside {
  border: 0 !important;
}

.global-styles,
.eapp-events-calendar-dates-calendar table {
  box-shadow: none !important;
  overflow: visible !important;
  width: auto !important;
}

Please check it out and let me know if you like the result :wink:

1 Like