AngularJS - Duplicate Source Files in IE11 - angularjs

My company has created a generic application that launches custom applications within an iframe. The parent window allows end users to click on an item within a worklist, and depending on what they've clicked on, we navigate to a launch controller which will build up a url to the product associated with the task. We then load that product application into an iframe within the launch view.
We are seeing duplicate static content files (js and partial templates) existing inside IE's developer tools.
Image of dev tools
Bundled js as well
We end up seeing additional copies of the file after every load the iframe. Since we're an SPA the assumption was that these files would be cached (which they are in all browsers except for IE). Each file is served up from the same web server. We even notice that if we dont set a breakpoint in the correct instance of the js file it wont get hit.
We have tried numerous things including removal of the iframe in the destroy event within the launch controller (since the frame gets added to the window object, we figured it was living on forever). We've ensured that the iframe has a valid ng-src tag as well as using $sce for the dynamically created url.
Since we require the iframe to be loaded via a POST from a form, we're doing something like this which is a super hacky way of submitting a POST. The snippet wont run as is but i wanted to include info on how we're populating our iframe.
function launch() {
//return launchService.launch(vm.url, buildLaunchRequest()).then(success, error);
$timeout(function() {
$("#productForm").submit().remove();
}, 1);
}
launch();
<div id="launch" class="container-fluid ss-container">
<iframe name="productFrame" id="productFrame" data-ng-src="{{vm.url}}" resize-frame />
</div>
<form id="productForm" role="form" method="post" action="{{vm.url}}" name="productForm" target="productFrame">
<input type="hidden" name="user" ng-value="vm.user" id="user" />
<input type="hidden" name="authToken" ng-value="vm.authToken" id="authToken" />
<input type="hidden" data-ng-repeat="(k,v) in vm.styles" name="{{k}}" value="{{v}}" />
</form>
Im sure there is a better way to submit a form with the target being an iframe but at the moment nothing seems to have worked for us.
If anyone has seen this duplicate source file issue and/or knows the proper way to submit a form with generated inputs automatically when the controller is loaded please help us out!
Thanks,
Jake

Turns out it was some weird issue with how IE caches the iframe if you dont clear out the src tag on the iframe that causes this.
This question helped identify the issue:
IE8 reloads dynamic iframe content from cache into the wrong iframe
It somehow would add a clone of the iframe to the parent window every time the angular view was loaded regardless of the src being the same. Clearing the src tag out on $destroy of our angular controller seems to kick IE into actually removing the node from the dom. We even tried $("#productFrame").remove() without any luck. Removing the src attrib didnt work as well.
What worked was $("#productFrame").attr("src", "").remove();

Related

How do I target the reCAPTCHA element within an iframe to show it, and nothing else (Gatsby/React)?

LSS, I can't use jQuery or extra CSS files. Right now I'm loading in an iframe from shopify to handle a contact form submit. Everything is working great, except I have set the iframe to "display: none" so that I can add my own styled contact form. The only issue is the iframe contains the reCAPTCHA ("you are not a robot" thing) I need to complete the form submission.
Is there an easy way to target the reCAPTCHA in the .js file so I can keep the reCAPTCHA, put it where I need it to go when it is called upon, but hide every other part of the iframe?
Right now the HTML looks like this inside my JSX.
<iframe
width='100%'
height='100%'
css={{ display: 'none' }}
src='https://shop.examplestore.com/pages/contact-store'
/>
Provided that the iframe is in a different origin, then no, you cannot access the contents of the iframe.
The same-origin policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. It helps isolate potentially malicious documents, reducing possible attack vectors.
Learn more about the same-origin policy here
If the document is part of the same origin, you could ostensibly manipulate the DOM of the child iframe in order to hide any content other than the captcha, and then you could also submit the form from that frame, using el.contentWindow (where el is a reference to the relevant iframe node in the DOM).

Chrome/Webkit reflow bug with ng-repeat

I'm pretty new to angularjs and I've stumbled upon a strange bug.
I made a timeline using CSS and HTML, and then used ng-repeat to dynamically generate it. However, on Webkit browsers, the timeline isn't displayed correctly.
Unfortunately I can't embed images in my post because my account is new, so I uploaded them here :
Webkit render
http://i.imgur.com/Gdt2h5F.png
However, if I resize the window, open the console or change any CSS properties, the timeline now looks fine :
http://i.imgur.com/5yCXSfs.png
It also works flawlessly on Firefox or Safari with no reflow needed.
I've looked into $scope.$apply, but that doesn't work because I'm using angular to generate the values, so I can't call it and it should be called automatically by angular anyway.
Please note that if I create the <ul><li></li></ul> manually, the timeline displays correctly.
Here's the code sample :
<h1>Relevés</h1>
<ul>
<li ng-repeat="batch in batches track by batch.id">
<span class="date" ng-bind="batch.createdAt | amDateFormat: 'DD/MM/YY'"></span>
</li>
</ul>
Also, when this bug occurs, I can see artefacts of the timeline on other partial views when changing pages, and this occurs only on Chrome (without any extension).

ng-show and ng-hide doesn't work in chrome extension

I made a little chrome extension with angularjs and bootstrap. I have a alert like this:
<div class="alert alert-danger" role="alert" ng-show="errorMailZR">error</div>
and in angularjs controller :
$scope.errorMailZR = false;
i put it to false because i see the alert by default, it's not hidden :/ but in single web page when i go on it with browser, everything is ok. So, what i need for it's works in chrome extension ?
ng-show="false" doesn't work too in chrome extension...
UPDATE:
https://docs.angularjs.org/api/ng/directive/ngCsp#!
In order to run angular on an extension page, you have to use the ng-csp directive, or satisfy the ng-csp policies. I'm assuming you've done this, or nothing would be working at all.
Doing so turns off inline style insertion, this line in particular in angular.js (showing for reference, not for modification!):
!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend('<style type="text/css">#charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
To get directives that rely on classes like ng-hide, ng-animate, ng-cloak, to work, manually link to the classes using:
<link rel="stylesheet" href="path/to/angular/angular-csp.css">
That's all there is to it.
OLD HACKY STUFF
Immediate fix, add this to your document head:
<style type="text/css">#charset "UTF-8";[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>
Ng-show and hide work by angular adding the class ng-hide to items that are hidden and removing it when they are shown.
Why doesn't it work in extensions?
Good question. For whatever reason (will update when I find the reason) chrome extensions prevent that style tag from being added to the head. It's probably some kind of security thingy, and there's probably a way to turn off that security bit, I'll update when I find out more.
You can debug chrome extension in chrome, just click right on extension popup. my guess is that angularjs isn't loaded or bootstraped in your extension, from my experience you should rather load angular from local files rather than CDN

Parsley Validation

I'm using parlsey validation and all is good. The problem is that if you partially load the website or load the website and click on "send" before everything is loaded, then parsley validation does not work.
Its not working because it hasn't been loaded. However, the validation script for parsley is in the header of the document? Is there a way to load a script before the website is loaded at all?
No that's not possible. If you place the JavaScript src in the head of the HTML document that's moste likely the only thing you can do. But that's not a good idea at all. JavaScript has to be placed before the closing body tag - at least until all Browsers and Servers are using SPDY.
The problem you are facing is caused by the way parsley works. While loading the page it will "scan" the HTML markup and search for parsley validation informations and apply bindings to them. It seems that this is not fully done.
What you can do is trying to avoid hitting a submit or what you use for submitting a form before the domready event is available. You could eg. set a submitt button for the form to disabled ...

mailto: links gobbled in a route

I'm using the jquery linkify plugin on a relatively simple Backbone view. Links to web pages outside this app work properly and using browser view source, I see the mailto links are properly generated. But clicking a mailto link appends /mailto:q#example.com to the current URL (e.g., http://example-acme.staging.myservername.com/mailto:q#example.com).
If I copy the generated HTML using Inspector and paste it into the source of arbitrary pages (not in this app), the mailto links function as expected, opening a new message window from my mail client. Problem is the same in Chrome and Firefox.
Have you seen and fixed this issue?
Just for closure: I added an event handler in the handler use window.location.assign(mailto) and that gets the job done. Not necessarily 'correct' but practical. #Brad, thanks for chiming in!

Resources