Page 1 of 1

Tooltip issue on mobile

Posted: 22 June 2021, 20:48
by fafa-fr
Hi,
I'm looking for insight from other developers regarding tooltips on mobile.
There's sometimes a problem on touch devices: when you click on a game element to trigger an action, a tooltip sometimes appears when you don't want it (i.e. without a long press), and it covers a part of the game area, which is annoying for players.

I noticed recently that this happens when there's a div connected to an action that is above a div connected to a tooltip. If you "short-tap" on a div with a tooltip that has no div above it, nothing happens, but as soon as above it there's a div connected to an action, a short-tap triggers the tooltip display in addition to the action connected to the "covering" div. It feels like something is propagating, even if there's a dojo.stopEvent(evt) at the beginning of the triggered method, and even if the "Display tooltips" user preference is set do disable, which prevents using this preference in a workaround.

Do you know why this happens, and if there's a way to prevent that, whithout having to change too much things?
I'd like to find a solution, if possible, that will take me less time to code (and that will imply less change for players) than implementing an "action mode vs tooltip mode" switch. (I think that this solution is a good idea, but I'm running out of time.)

Thanks in advance.

Edit: If you want a live example, you can watch a Dungeon Petz game in progress. At the top right of the main board, there are red / green / blue squares. I don't know if all browsers / devices react the same way (if it doesn't please let me know), but when I short-press on a square without an imp, nothing happens, and when I short-press on a square with an imp, the tooltip is displayed, even when I set tooltips to disabled.

Re: Tooltip issue on mobile

Posted: 22 June 2021, 22:36
by paramesis
I've found this frustrating on mobile devices as well (particularly iPhone), and have never been able to figure out a consistent way to control whether I bring up a tooltip or trigger an action. I would love to see some kind of click-only action mode vs hover-only tooltip mode implemented at the framework level, since it affects almost all games.

Re: Tooltip issue on mobile

Posted: 23 June 2021, 09:42
by Tisaac
paramesis wrote: 22 June 2021, 22:36 I've found this frustrating on mobile devices as well (particularly iPhone), and have never been able to figure out a consistent way to control whether I bring up a tooltip or trigger an action. I would love to see some kind of click-only action mode vs hover-only tooltip mode implemented at the framework level, since it affects almost all games.
I've actually implemented this on Agricola: I have a switch that toggle a "help/safe" mode in which click don't trigger action but trigger tooltips instead.
Here is the js that does all the work automatically :

Code: Select all

    /**********************
     ****** HELP MODE ******
     **********************/
    /**
     * Toggle help mode
     */
    toggleHelpMode(b) {
      if (b) this.activateHelpMode();
      else this.desactivateHelpMode();
    },

    activateHelpMode() {
      this._helpMode = true;
      dojo.addClass('ebd-body', 'help-mode');
      this._displayedTooltip = null;
      document.body.addEventListener('click', this.closeCurrentTooltip.bind(this));
    },

    desactivateHelpMode() {
      this.closeCurrentTooltip();
      this._helpMode = false;
      dojo.removeClass('ebd-body', 'help-mode');
      document.body.removeEventListener('click', this.closeCurrentTooltip.bind(this));
    },

    closeCurrentTooltip() {
      if (!this._helpMode) return;

      if (this._displayedTooltip == null) return;
      else {
        this._displayedTooltip.close();
        this._displayedTooltip = null;
      }
    },

    /*
     * Custom connect that keep track of all the connections
     *  and wrap clicks to make it work with help mode
     */
    connect(node, action, callback) {
      this._connections.push(dojo.connect($(node), action, callback));
    },

    onClick(node, callback) {
      this.connect($(node), 'click', (evt) => {
        if (this._helpMode) return false;
        callback(evt);
      });
      dojo.removeClass(node, 'unselectable');
      dojo.addClass(node, 'selectable');
      this._selectableNodes.push(node);
    },

    /**
     * Tooltip to work with help mode
     */
    addCustomTooltip(id, html, delay) {
      if (this.tooltips[id]) {
        this.tooltips[id].destroy();
      }

      html = '<div class="midSizeDialog">' + html + '</div>';
      delay = delay || 400;
      let tooltip = new dijit.Tooltip({
        //        connectId: [id],
        label: html,
        position: this.defaultTooltipPosition,
        showDelay: delay,
      });
      this.tooltips[id] = tooltip;
      dojo.addClass(id, 'tooltipable');
      dojo.place(
        `
        <div class='help-marker'>
          <svg><use href="#help-marker-svg" /></svg>
        </div>
      `,
        id,
      );

      dojo.connect($(id), 'click', (evt) => {
        if (!this._helpMode) {
          tooltip.close();
        } else {
          evt.stopPropagation();

          if (tooltip.state == 'SHOWING') {
            this.closeCurrentTooltip();
          } else {
            this.closeCurrentTooltip();
            tooltip.open($(id));
            this._displayedTooltip = tooltip;
          }
        }
      });

      tooltip.showTimeout = null;
      dojo.connect($(id), 'mouseenter', () => {
        if (!this._helpMode) {
          if (tooltip.showTimeout != null) clearTimeout(tooltip.showTimeout);

          tooltip.showTimeout = setTimeout(() => tooltip.open($(id)), delay);
        }
      });

      dojo.connect($(id), 'mouseleave', () => {
        if (!this._helpMode) {
          tooltip.close();
          if (tooltip.showTimeout != null) clearTimeout(tooltip.showTimeout);
        }
      });
    },
When you add click listener, simply use this.onClick instead of dojo or whatever else. That will ensure that they will be disabled on the fly in safe/help mode.