Move results section below and use table format

  • Issue description: Is it possible to drop the results section below the calculator fields and display the results in table format using CSS?

  • Link to the page with the widget in question: I am trying to replicate this format to create a Salary Sacrifice Calculator:

The best I can come up with using the calculator widget is:

2 Likes

Hi there and welcome to the Community, @ben_wood_tpt :waving_hand:

You can place the Results section under the fields using this code - Move Results section under the fields.

Unfortunately, there is no way to customize the results to make it look like a table. However, I’ve added this idea to the Wishlist on your behalf - Display results in table format

If this request gets more votes, it might be considered in the future :slightly_smiling_face:

1 Like

That’s great thanks Max, Is there a way to split the results section into 2 columns?

2 Likes

I think, yes. I’ll discuss it with the devs and update you tomorrow :wink:

Hi @ben_wood_tpt :waving_hand:

Devs confirmed that it’s possible to implement the 2-column view. Could you please clarify how you’d like it to look? Do you want two equal columns with the same number of results, or would you prefer specific results in each column?

Great thanks Max, ideally so the Employee and Employer results are in each column e.g.

Also, can the second column have its own heading?

So column 1 is ‘Employee summary’ and column 2 is ‘Employer summary’

Thanks

Ben

1 Like

Thank you!

I guess it’s also possible to create a separate heading for the 2nd column.

Your request is in the capable hands of our devs. I’ll report back once the solution is ready :wink:

1 Like

Hi there, @ben_wood_tpt :waving_hand:

We’ve added this code to the Custom CSS field on the Settings tab of your widget’s settings:

.summaries-wrapper {
  display: grid;
  grid-template-columns: 50% 50%;
  gap: 24px;
  align-items: start;
  margin: 0;
  padding: 0;
}

.summary-column {
  background: transparent;
  padding: 0;
}

.summary-column__title {
  font-size: 26px;
  font-weight: 700;
  margin: 0 0 12px 0;
  padding: 0;
}

.summary-list > * {
  margin: 0 0 10px 0;
}

And this code was added to the Custom JS field:

const waitForElement = (selector, root = document) => new Promise(res => {
    const observer = new MutationObserver(() => {
        const element = root.querySelector(selector);
        if (element) {
            res(element);
            observer.disconnect();
        }
    });
    
    observer.observe(root, { childList: true, subtree: true });
});


waitForElement('[class*="results__Container-sc"]').then(container => {
  if (container.dataset.summariesInitialized) return;
  container.dataset.summariesInitialized = "1";

  const children = Array.from(container.children);

  const wrapper = document.createElement("div");
  wrapper.className = "summaries-wrapper";

  const empCol = document.createElement("div");
  empCol.className = "summary-column employee";
  const empTitle = document.createElement("h3");
  empTitle.className = "summary-column__title";
  empTitle.textContent = "Employee summary";
  const empList = document.createElement("div");
  empList.className = "summary-list";
  empCol.appendChild(empTitle);
  empCol.appendChild(empList);

  const emp2Col = document.createElement("div");
  emp2Col.className = "summary-column employer";
  const emp2Title = document.createElement("h3");
  emp2Title.className = "summary-column__title";
  emp2Title.textContent = "Employer summary";
  const emp2List = document.createElement("div");
  emp2List.className = "summary-list";
  emp2Col.appendChild(emp2Title);
  emp2Col.appendChild(emp2List);

  const others = [];

  function nodeText(n) {
    try {
      return (n.textContent || "").replace(/\s+/g, " ").trim();
    } catch {
      return "";
    }
  }

  children.forEach(child => {
    const text = nodeText(child).toLowerCase();

    if (text.includes("employee")) {
      empList.appendChild(child);
    } else if (text.includes("employer")) {
      emp2List.appendChild(child);
    } else {
      others.push(child);
    }
  });

  container.innerHTML = "";
  container.appendChild(wrapper);

  wrapper.appendChild(empCol);
  wrapper.appendChild(emp2Col);

  if (others.length) {
  const empPositions = [8, 11];
  const emp2Positions = [6, 9];

  const insertAfterNth = (list, n, node) => {
    const items = Array.from(list.children);
    const ref = items[n - 1];
    if (ref) {
      if (ref.nextSibling) list.insertBefore(node, ref.nextSibling);
      else list.appendChild(node);
    } else {
      list.appendChild(node);
    }
  };

  for (let pos of empPositions) {
    if (others.length === 0) break;
    const node = others.shift();
    insertAfterNth(empList, pos, node);
  }

  for (let pos of emp2Positions) {
    if (others.length === 0) break;
    const node = others.shift();
    insertAfterNth(emp2List, pos, node);
  }

  if (others.length) {
    others.forEach(node => {
      if (node.matches('[class*="footer__Container-sc"]')) {
        wrapper.after(node);
      }
    });
  }
}
});

Note: Custom JS codes don’t function in the editor, so, you’ll see the final result on your website


Please check it out and let me know if it’s fine :slightly_smiling_face:

1 Like

Thanks Max, yes looks good, I decided to change the calc names and remove Employee/Employer as wasn’t necessary if there are summary titles - I’ve done this but seems to have made them disappear (or will I need to reinstate for it to work?) not sure if you can help? (see below)

1 Like

Hi there, @ben_wood_tpt :waving_hand:

The thing is that the JS code has a condition to display the results in a specific column if they include employee, employer:


I’ll discuss with the devs if it’s possible to adjust the code to show the results without employee/employer caption. I’ll report back once I have any news :slightly_smiling_face:

1 Like

We’ve restored the employee/employer words in the configurator to make the code work fine. However, these word won’t appear on your website.

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

Hi Max - hoping you can help, I need a couple of design tweaks on the calculator is this something you can do with the Custom CSS?

  1. I’ve added some dividers between the sections in the tool, but it’s not showing on the website, e.g. between Gross pay and Income tax as an example - marked with dashes below
  2. Is it possible to move the Employer ‘Total cost’ section down to align with Employee ‘Take Home Pay’?
  3. Can the 3 primary results all sit on the same line e.g. Total Employer Saving to the right of Employer saving
  4. Can ‘Total employer saving’ be bigger as that’s the key figure?

Also is doesn’t seem to respond well on mobile is there anything that can be done about that?

Many thanks

Ben

1 Like

Hi there, @ben_wood_tpt :waving_hand:

Yep, I’ve forwarded your request to the devs and will let you know once the solution is ready :slightly_smiling_face:

Thank you for waiting!

We’ve adjusted the script in your widget:

const waitForElement = (selector, root = document) =>
  new Promise((res) => {
    const observer = new MutationObserver(() => {
      const element = root.querySelector(selector);
      if (element) {
        res(element);
        observer.disconnect();
      }
    });

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

waitForElement('[class*="results__Container-sc"]').then((container) => {
  if (container.dataset.summariesInitialized) return;
  container.dataset.summariesInitialized = "1";

  const children = Array.from(container.children);

  const wrapper = document.createElement("div");
  wrapper.className = "summaries-wrapper";

  const empCol = document.createElement("div");
  empCol.className = "summary-column employee";
  const empTitle = document.createElement("h3");
  empTitle.className = "summary-column__title";
  empTitle.textContent = "Employee summary";
  const empList = document.createElement("div");
  empList.className = "summary-list";
  empCol.appendChild(empTitle);
  empCol.appendChild(empList);

  const emp2Col = document.createElement("div");
  emp2Col.className = "summary-column employer";
  const emp2Title = document.createElement("h3");
  emp2Title.className = "summary-column__title";
  emp2Title.textContent = "Employer summary";
  const emp2List = document.createElement("div");
  emp2List.className = "summary-list";
  emp2Col.appendChild(emp2Title);
  emp2Col.appendChild(emp2List);

  const others = [];
  const primaryRows = [];

  function nodeText(n) {
    try {
      return (n.textContent || "").replace(/\s+/g, " ").trim();
    } catch {
      return "";
    }
  }

  function removeFirstWord(node) {
    const target = node.querySelector("div");
    if (!target) return;
    const txt = target.textContent;
    if (!txt) return;
    const words = txt.split(" ");
    words.shift();
    target.textContent = words.join(" ");
  }

  children.forEach((child) => {
    const text = nodeText(child).toLowerCase();

    if (child.matches('[class*="result-primary__PrimaryContainer-sc"]')) {
      removeFirstWord(child);
      primaryRows.push(child);
      return;
    }

    if (text.includes("employee")) {
      removeFirstWord(child);
      empList.appendChild(child);
    } else if (text.includes("employer")) {
      removeFirstWord(child);
      emp2List.appendChild(child);
    } else {
      others.push(child);
    }
  });

  container.innerHTML = "";
  container.appendChild(wrapper);

  wrapper.appendChild(empCol);
  wrapper.appendChild(emp2Col);

  if (others.length) {
    const empPositions = [2, 5, 8, 11, 14];
    const emp2Positions = [2, 5, 8, 11];

    const insertAfterNth = (list, n, node) => {
      const items = Array.from(list.children);
      if (n >= items.length) {
        list.appendChild(node);
      } else {
        const ref = items[n - 1];
        list.insertBefore(node, ref.nextSibling);
      }
    };

    for (let pos of empPositions) {
      if (others.length === 0) break;
      insertAfterNth(empList, pos, others.shift());
    }

    for (let pos of emp2Positions) {
      if (others.length === 0) break;
      insertAfterNth(emp2List, pos, others.shift());
    }
  }

  if (primaryRows.length) {
    const primaryWrapper = document.createElement("div");
    primaryWrapper.className = "result-row";
    primaryRows.forEach((node) => primaryWrapper.appendChild(node));

    const footer = container.querySelector('[class*="footer__Container-sc"]');
    if (footer) {
      container.insertBefore(primaryWrapper, footer);
    } else {
      container.appendChild(primaryWrapper);
    }
  }

  if (others.length) {
    others.forEach((node) => {
      if (node.matches('[class*="footer__Container-sc"]')) {
        container.appendChild(node);
      }
    });
  }
});

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

1 Like

Hi Max - that’s great, just a couple of minor things and think we’re all set:

  1. Could you align the section ‘Total cost’ with ‘Take home pay’ currently its just a couple of pixels below and the lines don’t match

  2. Can you move across ‘Employer saving’ figure into column 2

  3. Is it possible to change the colour of ‘Total employer saving’ from white to #41E2BA

1 Like

Hi there, @ben_wood_tpt :waving_hand:

No problem, our devs will adjust the script for you! I’ll get back to you once it’s done :wink:

Hi there, @ben_wood_tpt :waving_hand:

We’ve moved the Employer saving under the 2nd column and change the color if the Total employer saving by adjusting the script.

As for the Total Cost, I see these calculations are already aligned when checking through the Share link:


If the issue occurs on your website, please send me a link to the page, where your widget is installed :folded_hands:

Hi Max - I’ve been asked to update the headings on the bottom to ‘Annual Saving’ and ‘Annual Saving (per Employee) - marked in red, but when I change the field name it doesn’t appear on published version?

1 Like

Hi there, @ben_wood_tpt :waving_hand:

I’ve asked the devs to look into this. I’ll update you as soon as I hear back from them :slightly_smiling_face:

1 Like

Hi there, @ben_wood_tpt :waving_hand:

Thank you for waiting!

We’ve added the word “annual” to the calculations right in the widget’s settings.

We’ve added “annual” as a 2nd word, since the 1st words (employee) are removed because of the custom script:


I hope this explains things.

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