Welcome to the nuBuilder Forums!

Register and log in to access exclusive forums and content available only to registered users.

Help popup text

Post your ideas & suggestions for new nuBuilder features or other improvements
Post Reply
Uzlander
Posts: 51
Joined: Sat Jul 08, 2023 10:21 am
Has thanked: 7 times
Been thanked: 2 times

Help popup text

Unread post by Uzlander »

Hi there! I just thought it would be cool/helpful to have som kind of help text popping up upon hover (on bigger screens).
I haven't found it with nubuilder but the idea i take from some other (low-code) platforms (say dataexpress[ru], rei3[de]).
My rough imagination's (screenshot attached) an icon on the opposite end from the label, hovering on which short help/hint text pops up.
You do not have the required permissions to view the files attached to this post.
kev1n
nuBuilder Team
Posts: 4416
Joined: Sun Oct 14, 2018 6:43 pm
Has thanked: 74 times
Been thanked: 472 times
Contact:

Re: Help popup text

Unread post by kev1n »

That’s a great idea!
We could also place the icon on the right side of the object.
This way, it won’t interfere with the label when the label is positioned differently (for example, right-aligned, which is the default in nuBuilder).

It might look like this (with an HTML tooltip appearing on mouse-over):

You do not have the required permissions to view the files attached to this post.
Uzlander
Posts: 51
Joined: Sat Jul 08, 2023 10:21 am
Has thanked: 7 times
Been thanked: 2 times

Re: Help popup text

Unread post by Uzlander »

Yeah, to me looks wonderful ))
kev1n
nuBuilder Team
Posts: 4416
Joined: Sun Oct 14, 2018 6:43 pm
Has thanked: 74 times
Been thanked: 472 times
Contact:

Re: Help popup text

Unread post by kev1n »

The following function adds a “?” button to all objects that have a nu-help-text attribute.

Alternatively, add the help text by code, just before calling nuAttachHelpIconsToObjects()

Example:

Code: Select all

$('#sus_first_name').attr('nu-help-text', `
    Enter your <b>legal first name</b> as it appears on official documents.<br>
    ✨ This will be used for identity verification and correspondence.<br>
    <i>Example:</i> John, Maria, Somchai
`.trim());

nuAttachHelpIconsToObjects({
  gapRight: 8,
  iconSize: 32
});
large_help_text.png

And here is an example to set the nu-help-text attribute:
attribute_help.jpg

Code: Select all

nu-help-text="This is a sample <b>hint</b><br>line 2..."

Code: Select all

function nuAttachHelpIconsToObjects({
  selector = 'input[nu-help-text], textarea[nu-help-text], select[nu-help-text]',
  gapRight = 8,                 // px gap outside right edge
  iconSize = 16,                // px
  zIndex = 50,
  iconClasses = 'fa-solid fa-circle-question',   // FA6
  fallbackIconClasses = 'fa fa-question-circle', // FA4/5
  onClick = null,               // optional: (el, helpHTML) => {}
} = {}) {

  // Tooltip container (created once)
  let tooltip = document.getElementById('nu-help-tooltip');
  if (!tooltip) {
    tooltip = document.createElement('div');
    tooltip.id = 'nu-help-tooltip';
    tooltip.style.position = 'absolute';
    tooltip.style.background = 'rgba(50,50,50,0.95)';
    tooltip.style.color = '#fff';
    tooltip.style.padding = '6px 8px';
    tooltip.style.borderRadius = '4px';
    tooltip.style.fontSize = '13px';
    tooltip.style.maxWidth = '250px';
    tooltip.style.zIndex = String(zIndex + 1);
    tooltip.style.pointerEvents = 'none';
    tooltip.style.display = 'none';
    tooltip.style.boxShadow = '0 2px 4px rgba(0,0,0,0.3)';
    document.body.appendChild(tooltip);
  }

  // Overlay for icons
  let overlay = document.getElementById('nu-help-overlay');
  if (!overlay) {
    overlay = document.createElement('div');
    overlay.id = 'nu-help-overlay';
    overlay.style.position = 'absolute';
    overlay.style.left = '0';
    overlay.style.top = '0';
    overlay.style.width = '0';
    overlay.style.height = '0';
    overlay.style.zIndex = String(zIndex);
    overlay.style.pointerEvents = 'none';
    document.body.appendChild(overlay);
  }

  const faLoaded = !!document.querySelector(
    'link[href*="fontawesome"], link[href*="font-awesome"], script[src*="fontawesome"], script[src*="font-awesome"]'
  );

  const ICONS = nuAttachHelpIconsToObjects._icons || new Map();
  nuAttachHelpIconsToObjects._icons = ICONS;

  const fields = Array.from(document.querySelectorAll(selector))
    .filter(el => el.hasAttribute('nu-help-text'));
  const current = new Set(fields);

  fields.forEach((el) => {
    let rec = ICONS.get(el);
    if (!rec) {
      const icon = document.createElement('i');
      icon.className = (faLoaded ? iconClasses : fallbackIconClasses);
      icon.style.position = 'absolute';
      icon.style.fontSize = iconSize + 'px';
      icon.style.lineHeight = '1';
      icon.style.pointerEvents = 'auto';
      icon.style.opacity = '0.95';
      icon.style.cursor = onClick ? 'pointer' : 'help';
      icon.style.color = '#53a1c4'; // icon color

      // Custom HTML tooltip events
      icon.addEventListener('mouseenter', () => {
        tooltip.innerHTML = el.getAttribute('nu-help-text') || '';
        tooltip.style.display = 'block';
        const r = icon.getBoundingClientRect();
        const pageX = window.pageXOffset;
        const pageY = window.pageYOffset;
        tooltip.style.left = (r.left + pageX) + 'px';
        tooltip.style.top = (r.bottom + pageY + 4) + 'px';
      });
      icon.addEventListener('mouseleave', () => {
        tooltip.style.display = 'none';
      });

      if (typeof onClick === 'function') {
        icon.addEventListener('click', (e) => {
          e.preventDefault();
          e.stopPropagation();
          onClick(el, el.getAttribute('nu-help-text') || '');
        });
      }

      overlay.appendChild(icon);

      const ro = new ResizeObserver(() => positionIcon(el, icon));
      ro.observe(el);
      const mo = new MutationObserver(() => {});
      mo.observe(el, { attributes: true, attributeFilter: ['nu-help-text'] });

      rec = { icon, ro, mo };
      ICONS.set(el, rec);
    }

    positionIcon(el, rec.icon);
  });

  // Remove old icons
  ICONS.forEach((rec, el) => {
    if (!current.has(el) || !document.body.contains(el)) {
      try { rec.ro.disconnect(); } catch {}
      try { rec.mo.disconnect(); } catch {}
      if (rec.icon.parentNode === overlay) overlay.removeChild(rec.icon);
      ICONS.delete(el);
    }
  });

  if (!nuAttachHelpIconsToObjects._bound) {
    const refreshAll = () => {
      ICONS.forEach(({ icon }, el) => positionIcon(el, icon));
    };
    window.addEventListener('scroll', refreshAll, { passive: true });
    window.addEventListener('resize', refreshAll);
    nuAttachHelpIconsToObjects._bound = true;
  }

  nuAttachHelpIconsToObjects.refresh = () => {
    ICONS.forEach(({ icon }, el) => positionIcon(el, icon));
  };

  function positionIcon(el, icon) {
    const r = el.getBoundingClientRect();
    const pageX = window.pageXOffset;
    const pageY = window.pageYOffset;
    icon.style.left = (r.right + gapRight + pageX) + 'px';
    icon.style.top  = (r.top + pageY + Math.round(r.height / 2) - Math.round(iconSize / 2)) + 'px';
  }
}

// Example call
nuAttachHelpIconsToObjects({
  gapRight: 8,
  iconSize: 16
});



Could you try it out on your end?
You do not have the required permissions to view the files attached to this post.
kev1n
nuBuilder Team
Posts: 4416
Joined: Sun Oct 14, 2018 6:43 pm
Has thanked: 74 times
Been thanked: 472 times
Contact:

Re: Help popup text

Unread post by kev1n »

Documentation nuAttachHelpIconsToObjects()


Add small “help” icons next to form fields that have a nu-help-text attribute. Hover shows a tooltip with your help text; you can also handle clicks.

Good for
  • Quickly adding inline help to inputs, textareas, and selects
  • Keeping forms clean while still offering guidance
How it works
  1. You add a nu-help-text attribute to any form object.
  2. Call nuAttachHelpIconsToObjects() once after the fields exist in the DOM.
  3. An icon appears to the right; hover to see a custom tooltip. (Click support is optional.)

Call the helper after the fields are in the DOM (e.g. in the form's Custom Code section:

Code: Select all

  nuAttachHelpIconsToObjects(); // use defaults
Basic usage with options

Code: Select all

nuAttachHelpIconsToObjects({
    selector: 'input[nu-help-text], textarea[nu-help-text], select[nu-help-text]', // what to scan
    gapRight: 8, // px gap from the field’s right edge
    iconSize: 16, // px
    zIndex: 50, // stacking order (icons under tooltip)
    iconClasses: 'fa-solid fa-circle-question', // Font Awesome 6 (if loaded)
    fallbackIconClasses: 'fa fa-question-circle', // FA4/FA5 fallback (if FA not detected)
    onClick: null // optional: function(el, helpHTML) {}
});
Options (explained)
  • selector: CSS selector to find fields. Only elements with nu-help-text actually get icons. Default targets input/textarea/select.
  • gapRight: Pixels to place the icon to the right of the field. Default: 8.
  • iconSize: Icon size in pixels. Default: 16.
  • zIndex: Base stacking context for the overlay (tooltip is +1). Default: 50.
  • iconClasses: Classes for Font Awesome 6 icons (used if FA is detected).
  • fallbackIconClasses: Classes for older FA versions (or when FA isn’t detected).
  • onClick: Optional handler to run when the icon is clicked. Receives:
    • el: the field element
    • helpHTML: the help text (inner HTML from nu-help-text)
Example: custom click handler

Code: Select all

nuAttachHelpIconsToObjects({
    onClick: function (el, helpHTML) {
        // You could open a modal, log usage, or focus the field
        alert(helpHTML);
        el.focus();
    }
});
Refreshing (dynamic forms)
If you add or remove fields later, call:

Code: Select all

nuAttachHelpIconsToObjects(); // to attach to any new fields
nuAttachHelpIconsToObjects.refresh(); // to reposition existing icons
What to put in nu-help-text
  • Short, actionable guidance (HTML allowed).
  • Keep it concise; the tooltip wraps at \~250px width.

Code: Select all

<input nu-help-text="<b>Username</b>: 4–20 chars, letters & digits only.">
Styling notes
  • Icon color defaults to #53a1c4. Override via CSS on #nu-help-overlay i.
  • Tooltip is a lightweight custom element (#nu-help-tooltip) with a dark theme; override with CSS.
  • The overlay (#nu-help-overlay) and tooltip are created once per page.
Performance & behavior
  • Icons automatically reposition on window scroll and resize.
  • Each field is watched with ResizeObserver to keep alignment accurate.
  • Changing nu-help-text updates the tooltip content on next hover.
  • Removing a field cleans up its observers and icon automatically.
Requirements
  • Works with or without Font Awesome. If FA is present, uses iconClasses; otherwise uses fallbackIconClasses.
  • Run after your form elements exist (e.g., after page load or after rendering in nuBuilder).
Troubleshooting
  • Icon overlaps another element: increase gapRight or adjust CSS for #nu-help-overlay i.
  • Icon hidden behind other UI: raise zIndex.
  • Icons not showing: make sure your fields actually have nu-help-text. Check your selector if you customized it.
Uzlander
Posts: 51
Joined: Sat Jul 08, 2023 10:21 am
Has thanked: 7 times
Been thanked: 2 times

Re: Help popup text

Unread post by Uzlander »

Pretty good/big job !:)
I think it works on per-form basis, the base function (nuAttachHelpIconsToObjects) should be inserted in the form where we want nu-help-text field attribute working.
But Is it possible to place it some place (say) in the application setup header once and then use "nu-help-text" in all desired field ?
Feeling like i forgot much of web-dev stuff i used to know years ago when actually kept learning))
kev1n
nuBuilder Team
Posts: 4416
Joined: Sun Oct 14, 2018 6:43 pm
Has thanked: 74 times
Been thanked: 472 times
Contact:

Re: Help popup text

Unread post by kev1n »

The function will be built directly into nuBuilder's core files, so in most cases, you won’t need to call it manually.
However, if you want to use different settings (such as icon size, spacing, etc.), you will have the option to customise them.
Once the integration is complete, I will post more information here.
Post Reply