gpt4 book ai didi

javascript - Gumroad Embedded Widget 在 Angular 导航时中断

转载 作者:行者123 更新时间:2023-12-05 07:28:16 31 4
gpt4 key购买 nike

我想包括 Gumroad's Embed Widgets在我的 Angular 应用程序中。

我尝试过的:

我将此添加到我的 index.html:

<script src="https://gumroad.com/js/gumroad-embed.js"></script>

我将其添加到我的组件模板之一:

<div class="gumroad-product-embed" data-gumroad-product-id="demo"><a href="https://gumroad.com/l/demo">Loading...</a></div>

问题:

假设页面 /buy 上的组件。如果我打开 /buy,就会出现小部件。但是,如果我通过应用程序中的一些 routerLink 导航到 /buy,则不会出现该小部件,它只是一直显示“正在加载...”。

我还通过将 routerLink 更改为 href 来确认这一点并且它有效。也就是说,问题可能与删除和重新添加 div 有关。

无论如何,我的问题是:如何在 Angular 应用程序中正确使用 Gumroad 的 Embed Widget?

注意事项:

1- 查看 gumroad-embed.js 可能会有用。它有类似 MutationObserver 的内容,但我无法跟进。

2- Angular 应用程序在 electronjs 上运行,以防出现差异(由于 MutationObserver 或其他原因)。

最佳答案

在有人想出更好的答案之前,这里有一个特别适用于当前 gumroad-embed.js 的解决方案.将来,它可能会发生变化,答案将过时。无论如何,它在这里:

解决方案

1) 添加文件 edited-gumroad-embed.js在你的/assets下包含以下代码:

function createGumroadEmbed(){window.GumroadEmbed||(window.GumroadEmbed=new GumroadEmbedManager)}function receiveMessage(t){var e={};if(t.data)try{e=JSON.parse(t.data)}catch(r){}if("GumroadEmbedMessage"===e.type&&GumroadEmbed){var i=GumroadEmbed.findEmbed(e.args.id)||GumroadEmbed.findEmbed(e.args.unique_id);i&&("setHeight"===e.action?i.setHeight(e.args.height):"scrollToTop"===e.action&&i.scrollToTop())}}!function(){var n=!1,a=/xyz/.test(function(){})?/\b_super\b/:/.*/;this._GumroadClass=function(){},_GumroadClass.extend=function(t){function e(){!n&&this.init&&this.init.apply(this,arguments)}var o=this.prototype;n=!0;var i=new this;for(var r in n=!1,t)i[r]="function"==typeof t[r]&&"function"==typeof o[r]&&a.test(t[r])?function(i,r){return function(){var t=this._super;this._super=o[i];var e=r.apply(this,arguments);return this._super=t,e}}(r,t[r]):t[r];return e.prototype=i,(e.prototype.constructor=e).extend=arguments.callee,e}}();var GumroadClass=_GumroadClass.extend({setEnvironment:function(){this.environment="production",this.domain="https://gumroad.com",this.isMobile=navigator.userAgent.match(/Mobile[\/; ]/i)||navigator.userAgent.match(/Opera (Mini|Mobi)/i)||navigator.userAgent.match(/IEMobile/i),this[this.environment]=!0,this.origin=window.location.protocol+"//"+window.location.hostname+(window.location.port?":"+window.location.port:"")},startNodeAdditionObserver:function(){MutationObserver&&(this.nodeAdditionObserver=new MutationObserver(function(t){for(var e=0;e<t.length;e++)for(var i=0;i<t[e].addedNodes.length;i++)this.nodeAdditionCallback&&this.nodeAdditionCallback(t[e].addedNodes[i])}.bind(this)),this.nodeAdditionObserver.observe(document.body,{childList:!0,subtree:!0}))}}),GumroadEmbedElement=GumroadClass.extend({init:function(t,e){this.manager=e;var i=t.getAttribute("data-gumroad-product-id");i&&(this.div=t,this.id=i,this.opts={as_embed:"true",referrer:document.referrer,origin:this.manager.origin},this.manager.embeds.push(this),this.show())},buildUrl:function(){var t=(this.manager.domain||"")+"/l/"+this.id+"?";for(var e in this.outboundEmbed&&(this.opts.outbound_embed="true"),this.opts)this.opts.hasOwnProperty(e)&&(t+="&"+e+"="+this.opts[e]);return t},createIframe:function(){this.iframe=document.createElement("iframe"),this.iframe.allowtransparency=!0,this.iframe.setAttribute("allowFullScreen","allowfullscreen"),this.iframe.className="gumroad-embed-iframe",this.iframe.scrolling="no",this.iframe.width="100%",this.iframe.height=0,this.iframe.id="gumroad-embed-iframe-"+this.id,this.iframe.setAttribute("style","display: block !important; border: none !important; margin: 0 auto !important; padding: 0 !important; max-width: 676px !important;"),this.div.parentNode.insertBefore(this.iframe,this.div)},scrollToTop:function(){this.iframe&&this.manager.isMobile&&window.scrollTo(0,this.iframe.offsetTop)},setHeight:function(t){this.div.style.display="none",this.iframe.setAttribute("height",t)},show:function(){this.iframe||this.createIframe();this.id=this.div.getAttribute("data-gumroad-product-id"),this.outboundEmbed=!!this.div.getAttribute("data-outbound-embed"),this.iframe.setAttribute("src",this.buildUrl())}}),GumroadEmbedManager=GumroadClass.extend({init:function(){this.setEnvironment(),this.createEmbeds()},createEmbeds:function(){this.embeds=[];for(var t=document.getElementsByClassName("gumroad-product-embed"),e=0;e<t.length;e++)new GumroadEmbedElement(t[e],this)},findEmbed:function(t){for(var e=0;e<this.embeds.length;e++)if(this.embeds[e].id==t)return this.embeds[e];return!1},gotMessage:function(t){var e={};try{e=JSON.parse(t.data)}catch(i){}this[e.action]&&this[e.action](e.args)},reload:function(){for(var t=0;t<this.embeds.length;t++){var e=this.embeds[t].iframe;e&&e.parentNode&&(e.parentNode.removeChild(e),this.embeds[t].div.style.display="")}this.createEmbeds()},scrollToTop:function(t){var e=this.findEmbed(t);e&&e.scrollToTop()},setHeight:function(t,e){var i=this.findEmbed(t);i&&i.setHeight(e)}});window.addEventListener?(window.addEventListener("message",receiveMessage,!1)/*,window.addEventListener("load",createGumroadEmbed)*/):window.attachEvent&&(window.attachEvent("onmessage",receiveMessage,!1)/*,window.attachEvent("onload",createGumroadEmbed)*/);createGumroadEmbed();

2) 在模板包含<div class="gumroad-product-embed" data-gumroad-product-id="demo"><a href="https://gumroad.com/l/demo">Loading...</a></div>的组件中,添加以下代码:

import {AfterContentInit, Component, OnDestroy} from '@angular/core';

@Component({
selector: 'app-buy',
templateUrl: './buy.component.html'
})
export class BuyComponent implements OnDestroy, AfterContentInit {

readonly scriptNode: HTMLScriptElement;

constructor() {
this.scriptNode = document.createElement('script')
this.scriptNode.setAttribute('src','/assets/edited-gumroad-embed.js')
}

ngAfterContentInit() {
document.getElementsByTagName('head')[0].appendChild(this.scriptNode)
}

ngOnDestroy() {
this.scriptNode.remove()
delete window['GumroadEmbed']
}
}

3) 成功!

解释

通过查看 gumroad-embed.js截至 2018 年 11 月,似乎只是包含另一个文件。这个其他文件的代码是 edited-gumroad-embed.js 的基础基于。 edited-gumroad-embed.js基本上这个文件有 2 个编辑:

  1. 它调用createGumroadEmbed()而不是在 load 上调用它直接事件,因为load似乎只在初始加载文档时触发一次。
  2. 它评论了 load 的事件监听器曾经调用createGumroadEmbed() .

对于组件ts文件,它基本上尽可能地模拟脚本的加载,就好像它是第一次加载一样。通过非彻底查看 gumroad 的代码,似乎要采取行动 window.GumroadEmbed需要是 undefined ;这就是它删除 window['GumroadEmbed'] 的原因.

开放性问题和注意事项

有足够多的开放性问题可以让 Camel 通过。

  1. 如果 Gumroad 的原始代码在 Chrome 而不是 electronjs 上运行,那么所有这些是否都需要或应该成功?
  2. 我没有仔细研究 gumroad 的代码以了解我正在做的事情是否没有副作用。例如,是否有泄漏?是否有应该删除的事件监听器?那MutationObserver呢? (s)?
  3. 我不确定为什么要调用 ngAfterContentInit 中的代码.我试图让它在 div 之后运行已尽可能多地添加到 DOM 中。
  4. 如果组件被重用(例如,在路由中),是否需要重新创建 scriptNode ?由于其他原因,我目前已禁用路由重用。

也就是说,我可能根本不打算使用它,但原因与原始问题无关。原因是我在“网络”选项卡中发现了很多对许多网站(例如 Facebook)的请求,我不知道这对我的客户有什么影响(例如,隐私方面)。再一次:我知道,我不熟悉iframe秒。另外,我有点担心我的解决方案可能有任何泄漏。

我只会添加一个超链接。

关于javascript - Gumroad Embedded Widget 在 Angular 导航时中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53492074/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com