Closed SokratisVidros closed 7 years ago
Hi @SokratisVidros
I've opened an issue on Polymer about this https://github.com/Polymer/polymer/issues/4086 (It's not a Polymer specific issue, but that's where I ran into it first)
The basic gist is that each Hosted Fields iframe requires access to window.parent.frames
, but when an iframe is added to the shadow dom, it is not added to window.frames
, so the Hosted Fields iframes cannot initialize.
We're looking into possible solutions for this, but at this time, Hosted Fields is incompatible with the shadow dom.
Hi @crookedneighbor.
Thanks for the quick reply. I guess a fix should be applied at src/hosted-fields/internal/assemble-iframes.js
. Currently, i am planning to use it only in Chrome so the following patch might work:
...
const iframes = document.querySelectorAll('html /deep/ iframe');
const iWindows = iframes.map(f => f.contentWindow);
...
The above patch is not a cross-browser solution. Nonetheless, If we take into account the current shadow DOM support, i believe that it can be part of the official library.
Lastly, an alternate, coarse-grained approach could be the following:
...
const allNodes = document.getElementsByTagName('*');
for (let i = 0, l = allNodes.length; i < l; i++) {
if (allNodes[i].shadowRoot) {
// Get all the shadow iframes recursively
}
}
...
That script for assemble-iframes
occurs within the iframe itself and is hosted by braintree. So the iframe does not have access to the parent's document
, so neither of those approaches will work for this. 😞
You are absolutely right.
I attempted to use the above tricks and overwrite window.frames but it didn't work.
Have you tried enclosing the shadow form in an iframe to encapsulate Braintree-web lib?
Le 25 oct. 2016 à 17:25, Blade Barringer notifications@github.com a écrit :
Hi @SokratisVidros
I've opened an issue on Polymer about this Polymer/polymer#4086 (It's not a Polymer specific issue, but that's where I ran into it first)
The basic gist is that each Hosted Fields iframe requires access to window.parent.frames, but when an iframe is added to the shadow dom, it is not added to window.frames, so the Hosted Fields iframes cannot initialize.
We're looking into possible solutions for this, but at this time, Hosted Fields is incompatible with the shadow dom.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
Hi @SokratisVidros,
We will be considering how to best support the Shadow DOM use case moving forward, but it will take some time to refactor Hosted Fields and make it compatible. I'll leave this issue open to provide updates on our progress. Thanks for opening this!
Thanks a lot.
Here's a codepen that illustrates how to use Hosted Fields with the shadow DOM: http://codepen.io/braintree/pen/NbqPVO
The trick is that you need to set up the Hosted Fields divs in the normal DOM (so that the iframes can find each other) and then inject them into the shadow DOM.
Hope this helps!
👍
@crookedneighbor Just in case you're wondering and for anyone else out there...
You CAN use braintree and polymer 2 together, you just have to put the form outside the shadow dom and use <slot> to tell polymer where it should end up
. This way the braintree lib can find the elements to bind the iframes to, and you still get your form showing up where you want it.
Example:
In index.html add your braintree-fields inside your app container <my-app>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- Load webcomponents-loader.js to check and load any polyfills your browser needs -->
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
<!-- Load redux library -->
<script src="/redux/dist/redux.js"></script>
<!-- Load the Client component -->
<script src="https://js.braintreegateway.com/web/3.12.0/js/client.min.js"></script>
<!-- Load the Hosted Fields component -->
<script src="https://js.braintreegateway.com/web/3.12.0/js/hosted-fields.min.js"></script>
<!-- Load your application shell -->
<link rel="import" href="/src/my-app.html">
<!-- Add any global styles for body, document, etc. -->
<style>
body {
margin: 0;
font-family: 'Roboto', 'Noto', sans-serif;
line-height: 1.5;
min-height: 100vh;
background-color: #eeeeee;
}
</style>
</head>
<body>
<my-app>
<div id="braintree-fields">
<div class="field" id="card-number-container">
<label for="card-number">Card Number</label>
<div id="card-number"></div>
</div>
<div id="cvv-container">
<label for="cvv">CVV</label>
<div id="cvv"></div>
</div>
<div id="expiration-date-container">
<label for="expiration-date">Expiration Date</label>
<div id="expiration-date"></div>
</div>
</div>
</my-app>
</body>
</html>
then in <my-app>
<slot id="#braintree-fields">
where you want to put it.
<iron-pages
selected="[[page]]"
attr-for-selected="name"
fallback-selection="view404"
role="main">
<my-home name="home"></my-home>
<my-give name="give"></my-give>
<my-checkout name="checkout">
<slot id="#braintree-fields"></slot>
</my-checkout>
<my-view404 name="view404"></my-view404>
</iron-pages>
Finally, in <my-checkout>
just slot in any content (which should be only the #braintree-fields
)
<iron-form id="giveForm" on-iron-form-presubmit="_giveFormSubmitted">
<slot></slot>
</iron-form>
If anyone is interested in trying a beta release that adds official support for the shadow DOM, you can try it out here:
https://js.braintreegateway.com/web/3.64.0-beta.1/js/client.min.js https://js.braintreegateway.com/web/3.64.0-beta.1/js/hosted-fields.min.js
The fix was to check if the container being passed existed in the shadow DOM, and if it does, add slot
elements into the container and the iframes in divs referencing those slots on the main page. This allows the iframes to communicate with each other even when inside the shadow DOM.
Is there a beta version for Dropin UI that supports shadow DOM too? Trying to get it working with Flutter Web but experiencing the perpetual spinner issue with version 1.25
@paulhulatt please jump in on the issue in the Drop-in repo: https://github.com/braintree/braintree-web-drop-in/issues/296
Hi there,
I am trying to setup hosted fields inside a shadow container. The iframe loads as it should,
<script>braintree.hostedFields.create();</script>
is injected but no label or input is rendered.At the moment, I am tracing the issue but i'd appreciate more useful insights from the contributors.
My init code looks like:
Thanks in advance, Sokratis