# 谁能向我解释一下用户卡片弹窗是如何工作的？

**URL:** https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479
**Category:** Development
**Created:** [2018年七月30日 14:24 UTC](https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479 "2018-07-30T14:24:47Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2018年七月30日 14:24 UTC](https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479/1 "2018-07-30T14:24:47Z")

</div>

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:

```plaintext
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?

---

<div class="post-metadata">

### Author: ![gdpelican](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/gdpelican/32/81308_2.png) [@gdpelican](https://meta.discourse.org/u/gdpelican)
#### Post date: [2018年七月30日 14:53 UTC](https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479/2 "2018-07-30T14:53:32Z")

</div>

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

```plaintext
# 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 => {});

```

```plaintext
# card-contents-base.js.es6#20
_show(username, $target) {}

```

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2018年七月30日 15:00 UTC](https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479/3 "2018-07-30T15:00:18Z")

</div>

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

---

<div class="post-metadata">

### Author: ![gdpelican](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/gdpelican/32/81308_2.png) [@gdpelican](https://meta.discourse.org/u/gdpelican)
#### Post date: [2018年七月30日 15:02 UTC](https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479/4 "2018-07-30T15:02:11Z")

</div>

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

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2018年七月30日 15:06 UTC](https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479/5 "2018-07-30T15:06:01Z")

</div>

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

---

<div class="post-metadata">

### Author: ![jimkleiber](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jimkleiber/32/121814_2.png) [@jimkleiber](https://meta.discourse.org/u/jimkleiber)
#### Post date: [2023年十月24日 08:43 UTC](https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479/6 "2023-10-24T08:43:27Z")

</div>

@merefield 你有没有办法解决这个问题？

我正在尝试创建一个主题组件来修改 Locations 插件的用户地图，以便在点击时显示个人资料卡而不是直接跳转到个人资料页面，但我也不知道从哪里开始或往哪里看。

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2023年十月24日 09:35 UTC](https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479/7 "2023-10-24T09:35:53Z")

</div>

哦，这已经是 5 年前的了……我不记得了 😅 ……我想现在的代码肯定大不相同了。

我接受将此功能作为 PR 合并到 Locations，因为它之前已经被请求过很多次了。

---

<div class="post-metadata">

### Author: ![jimkleiber](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jimkleiber/32/121814_2.png) [@jimkleiber](https://meta.discourse.org/u/jimkleiber)
#### Post date: [2023年十月24日 09:50 UTC](https://meta.discourse.org/t/can-someone-please-explain-to-me-how-the-user-card-pop-up-works/93479/8 "2023-10-24T09:50:28Z")

</div>

哈哈，是的，这说得通。我可能很快就会深入研究一下，如果我弄明白了如何提交插件的拉取请求，我会把它放上去的 🙏🏻
