Can someone please explain to me how the User Card pop-up works?

Guys, i’m trying to work out how the code for User Card works.

How does it create a pop-up and then escalate to a new page?

<a href="/u/postinguser" data-user-card="postinguser" class=""><img alt="" src="/letter_avatar_proxy/v2/letter/m/bbce88/50.png" class="avatar" title="User - Frequent Poster" width="25" height="25"></a>

I can see how it is constructed from the .hbs template file, but not how the action of clicking it causes the user card to appear …

<a href="{{poster.user.path}}" data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" imageSize="small"}}</a>

But how does the javascript fit together?

What code is causing the user card to load instead of going to the user route?

I see:

/app/assets/javascripts/discourse/widgets/poster-name.js.es6

and specifically:

export default createWidget("poster-name", {
  tagName: "div.names.trigger-user-card",

  settings: {
    showNameAndGroup: true,
    showGlyph: true
  },

  // TODO: Allow extensibility
  posterGlyph(attrs) {
    if (attrs.moderator) {
      return iconNode("shield", { title: I18n.t("user.moderator_tooltip") });
    }
  },

  userLink(attrs, text) {
    return h(
      "a",
      {
        attributes: {
          href: attrs.usernameUrl,
          "data-user-card": attrs.username
        }
      },
      formatUsername(text)
    );
  },

  html(attrs) {
    const username = attrs.username;
    const name = attrs.name;
    const nameFirst =
      this.siteSettings.display_name_on_posts &&
      !this.siteSettings.prioritize_username_in_ux &&
      name &&
      name.trim().length > 0;
    const classNames = nameFirst
      ? ["first", "full-name"]
      : ["first", "username"];

    if (attrs.staff) {
      classNames.push("staff");
    }
    if (attrs.admin) {
      classNames.push("admin");
    }
    if (attrs.moderator) {
      classNames.push("moderator");
    }
    if (attrs.new_user) {
      classNames.push("new-user");
    }

    let afterNameContents =
      applyDecorators(this, "after-name", attrs, this.state) || [];

    const primaryGroupName = attrs.primary_group_name;
    if (primaryGroupName && primaryGroupName.length) {
      classNames.push(primaryGroupName);
    }
    let nameContents = [this.userLink(attrs, nameFirst ? name : username)];

    if (this.settings.showGlyph) {
      const glyph = this.posterGlyph(attrs);
      if (glyph) {
        nameContents.push(glyph);
      }
    }
    nameContents = nameContents.concat(afterNameContents);

    const contents = [
      h("span", { className: classNames.join(" ") }, nameContents)
    ];

    if (!this.settings.showNameAndGroup) {
      return contents;
    }

    if (
      name &&
      this.siteSettings.display_name_on_posts &&
      sanitizeName(name) !== sanitizeName(username)
    ) {
      contents.push(
        h(
          "span.second." + (nameFirst ? "username" : "full-name"),
          [this.userLink(attrs, nameFirst ? username : name)].concat(
            afterNameContents
          )
        )
      );
    }

    const title = attrs.user_title;
    if (title && title.length) {
      contents.push(
        this.attach("poster-name-title", { title, primaryGroupName })
      );
    }

    return contents;
  }

Can someone talk me through this latter code wrt to launching the user card in a state which will permit a further click to the user’s profile?

1 „Gefällt mir“

I think you’re looking for card-contents-base.js.es6, which defines a series of events which point to the _show method.

# card-contents-base.js.es6#103
$("#main-outlet").on(clickDataExpand, `[data-${id}]`, e => {});

$("#main-outlet").on(clickMention, `a.${triggeringLinkClass}`, e => {});

this.appEvents.on(previewClickEvent, $target => {});
# card-contents-base.js.es6#20
_show(username, $target) {}
6 „Gefällt mir“

Thanks James! I’ll have a read through that code … head spinning already though … :slight_smile:

1 „Gefällt mir“

What is the thing that you’re trying to do?

1 „Gefällt mir“

Trying to understand how the user card is wired in so I can ultimately code the same behaviour in a plug-in.

2 „Gefällt mir“

@merefield Konntest du das jemals herausfinden?

Ich versuche herauszufinden, wie ich eine Themenkomponente erstellen kann, um die Benutzerkarte des Standorte-Plugins zu modifizieren, sodass sie beim Klicken die Profilkarte anzeigt, anstatt direkt zur Profilseite zu gehen, aber ich habe auch keine Ahnung, wo ich anfangen oder suchen soll.

oooh das ist 5 Jahre alt … ich kann mich nicht erinnern :sweat_smile: … ich stelle mir vor, der Code ist jetzt ganz anders.

Ich würde diese Funktionalität als PR für Locations akzeptieren, da sie schon oft gewünscht wurde.

2 „Gefällt mir“

haha ja, das ergibt Sinn. Ich werde mich bald damit beschäftigen und wenn ich herausfinde, wie man Plugins als PR einreicht, werde ich es hochladen :folded_hands:t2:

1 „Gefällt mir“