Discourse 注册重定向到 URL 而不是模态

Discourse Sign Up redirect to URL instead of modal

我目前一直在尝试更改我的话语安装中用户注册的登录页面。

我正在尝试通过他们的管理面板在编辑 Html/css 中进行自定义,特别是在 </head> 部分中,我也尝试将其放入 </body>

出于某种原因,这段代码没有停止默认操作,也没有在点击时重定向用户

<script>
    var thingy = document.getElementsByClassName("sign-up-button")
    thingy.onclick ="return false;"
    thingy.onclick = function() {
        window.location.href = "https://join.domain.com";
    };
</script>

当我尝试这样做时

<script>
    var thingy = document.getElementsByClassName("sign-up-button");
    console.log(thingy.length);
    console.log(thingy)
    for (var i = 0; i < thingy.length; i++) {
            console.log('print this');
    };
</script>

它显示 thingy 的长度为 0,但随后它继续打印 html 元素,但从不迭代,因为长度为 0

getElementsByClassName 返回零到多个对象的集合。你会想要选择一个,遍历它们,或者使用 jQuery.

如果您只想 return 第一个按钮,此方法有效。 ( thingy[0]. )

<script>
    var thingy = document.getElementsByClassName("sign-up-button")
    //thingy.onclick ="return false;"
    thingy[0].onclick = function() {
        window.location.href = "https://www.google.com";
        //return false;
    };

</script>

不需要 "return false",因为您要替换 onclick 事件。

更好的选择是给按钮一个 ID,然后使用 getElementById 来检索它。

问题似乎是 Discourse 使用 Ember。 Ember 作为 client-side 框架没有任何问题,但它似乎在脚本运行后向 DOM 添加元素。当您的脚本尝试添加事件侦听器后添加元素时,您的脚本不会做太多事情(如您所见)。

我查看了一个 Discourse 网页,我可以看到该按钮经常被添加和从 DOM 中删除。这可能是因为 the button is only supposed to appear when the user is at the top of the page.

一种策略是做一些事情来延迟您的脚本 — 例如 async deferrequestAnimationFramesetTimeout — 这样当您的脚本运行时该元素就已经存在了。因为我没有独立的页面来测试,所以我无法对此发表评论。

我要演示的是如何在将元素添加到 DOM 时附加事件处理程序。在过去,你会使用 mutation events, as shown in most of the answers to this question. Since those events are now deprecated, you must use Mutation Observers (which seem to be fairly well supported).

MutationObserver.observe() 有两个参数:一个目标元素和一个选项对象。目标元素是您在其上侦听突变事件的元素。从在页面上使用 view-source 开始,似乎 body 内部没有太多用处,所以我们将关闭 body。至于选项对象,我们对 childList 突变和 subtree 感兴趣,因为该按钮不是 body.

的直接后代

回调函数(构造函数的唯一参数)将在事件发生时触发。这是您应该查找按钮并附加点击事件处理程序的时间点。为了保持清洁,您可能需要检查按钮是否真的在附近,如果在,则断开 MutationObserver。无需继续附加活动。

为了完整起见,我还喜欢调用函数来立即附加事件,以防万一该元素恰好已经存在。

请注意,即使当您向上和向下滚动时从 DOM 中删除和添加元素,您也只需要附加一次事件。它似乎是同一个元素,所以事件侦听器仍然附加。

您还在评论中提到了有关在附加侦听器后模态框仍然显示的内容。您可以使用 .stopPropagation().

停止它

顺便说一句,这种传播与您不能进行简单 $(window).on('click', '.sign-up-button', ...) 的原因有些相关。这适用于大多数动态创建的元素,但在这种情况下,底层应用程序也在监听点击事件,显然会阻止事件冒泡。

我的代码如下。我正在使用 jQuery 因为我看到它出现在 Discourse 的页面上。

var targetNode = $('body')[0];

var attachEvent = function () {
  var $button = $('.sign-up-button');

  $button.on('click', function (e) {
    e.stopPropagation();

    // Do the redirect here
    console.log('gotcha');
  });

  if ($button.length) {
    console.log('hit');
    observer.disconnect();
  }
};

var callback = function() {
  console.log('mutation');
  attachEvent();
};

var observer = new MutationObserver(callback);

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

// Just in case...
attachEvent();

多亏了之前的所有回答,我才让它在我的话语论坛上工作。

首先我必须找到在哪里包含这段代码,那就是自定义主题的头部。 URL 可能是 https://yourdiscourse.com/admin/customize/themes/1/common/head_tag/edit

在那之后包括脚本几乎对我有用,但前提是稍后使用 window.onload 或 document.onload 加载并且我在事件中做了 stopPropagation

<script>
window.onload = (event) => {
      var signUpButton = document.getElementsByClassName("sign-up-button")[0]
      if (typeof signUpButton !== 'undefined') {
          signUpButton.onclick = function(e) {
            e.stopPropagation();
            window.location.href = "https://www.google.com";
          };
      }
};

</script>