Пока кто-то не придумает лучшего ответа, вот решение, которое работает , в частности с текущим 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 , чтобы просто включить другой файл.Код этого другого файла является основой, на которой основан edited-gumroad-embed.js
.edited-gumroad-embed.js
- это, в основном, этот файл с двумя правками:
- Он вызывает
createGumroadEmbed()
вместо прямого вызова события load
, потому что load
запускается один раз только при начальной загрузкеdocument. - Он комментирует прослушиватель событий для
load
, который раньше вызывал createGumroadEmbed()
.
Для файла компонента ts он в основном пытается симулировать загрузку скриптакак можно больше, как если бы это была первая загрузка.При неполном взгляде на код gumroad, кажется, что для выполнения действий window.GumroadEmbed
должно быть undefined
;вот почему он удаляет window['GumroadEmbed']
.
Открытые вопросы и предостережения
Там достаточно открытых вопросов, чтобы пропустить верблюда.
- Все это даже нужноили должен был бы быть успешным исходный код Gumroad, если бы он запускался на Chrome вместо electronicjs?
- Я недостаточно изучил код gumroad, чтобы узнать, не имеет ли то, что я делаю, побочные эффекты.Например, есть ли утечки?есть слушатели событий, которые должны быть удалены?Как насчет
MutationObserver
(s)? - Я не уверен, почему я вызываю код в
ngAfterContentInit
.Я пытаюсь заставить его работать после того, как div
было добавлено в DOM, насколько это возможно. - Если компонент используется повторно (например, в маршрутизации), нужно ли его заново создавать
scriptNode
?В настоящее время у меня в любом случае отключено повторное использование маршрутизации по другим причинам.
Тем не менее, я, вероятно, не собираюсь его использовать в конце концов, но причина не связана с первоначальным вопросом.Причина в том, что я нашел много запросов на вкладке «Сеть» ко многим веб-сайтам (например, Facebook), и я не знаю, как это влияет на моих клиентов (например, в отношении конфиденциальности).Опять же: я не знаю, я не знаком с iframe
s.Кроме того, я немного боюсь, что в моем решении могут быть утечки.
Я просто добавлю гиперссылку.