Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix(ngInclude): correctly add non-html namespaced template content #8981

Closed
wants to merge 10 commits into from

Conversation

caitp
Copy link
Contributor

@caitp caitp commented Sep 8, 2014

It is now possible for ngInclude to correctly load SVG content in non-blink
browsers, which do not sort out the namespace when parsing HTML.

/CC @tbosch / @IgorMinar

Closes #7538

@caitp
Copy link
Contributor Author

caitp commented Sep 8, 2014

hmm, jenkins doesn't like it :(

@@ -590,6 +590,27 @@ describe('ngInclude and transcludes', function() {
expect(root[0]).toBe(element[0]);
});
});


it('should correctly work with SVG content', function() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is a terrible test name, will come up with something better

@caitp
Copy link
Contributor Author

caitp commented Sep 8, 2014

It's hard to debug the failures unfortunately, ddescribe is no longer working, and it's not reproducible with iit

@caitp caitp force-pushed the issue-7538 branch 3 times, most recently from 28dbcbe to a2922ec Compare September 8, 2014 20:29
// If there's no namespace, and no futureParentElement, then we're probably compiling
// nodes in-place, so we should use the $compileNode's parent element in order to figure
// out the namespace.
if (isUndefined(futureParentElement) && isUndefined(cloneConnectFn)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!futureParentElement && !cloneConnectFn

@tbosch
Copy link
Contributor

tbosch commented Sep 8, 2014

The approach seems ok!

@caitp caitp force-pushed the issue-7538 branch 3 times, most recently from ec59785 to 8d5e11d Compare September 8, 2014 20:54
@caitp
Copy link
Contributor Author

caitp commented Sep 8, 2014

So there's a problem, Safari seems to have problems with this --- it doesn't create childNodes at all when setting innerHTML of an SVG element =( (it's possible that it's not parsing immediately or something)

// Safari 7 debugger:
> $element[0].innerHTML
< "<rect></rect>"
> $element[0].childNodes
< []

(repro at http://jsfiddle.net/hp2rm4yc/)

@caitp
Copy link
Contributor Author

caitp commented Sep 8, 2014

There's a bug filed on this already for webkit https://bugs.webkit.org/show_bug.cgi?id=135698 --- I don't mind fixing it in the browser, so after my little conference talk I can spend a few hours on that maybe. But unfortunately that doesn't do much good for fixing this in angular for the legacy Webkit browsers

@IgorMinar
Copy link
Contributor

I agree. overall it looks good.

@caitp
Copy link
Contributor Author

caitp commented Sep 8, 2014

As a short-term solution to the safari/webkit problem, we could also abandon the test if (!'innerHTML' in SVGElement.prototype). sgty?

@@ -268,7 +268,17 @@ var ngIncludeFillContentDirective = ['$compile',
require: 'ngInclude',
link: function(scope, $element, $attr, ctrl) {
$element.html(ctrl.template);
$compile($element.contents())(scope);
if (!$element.contents().length && ctrl.template.length) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a blank line above this line

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we simplify the check to !$element[0].childNodes.length && ctrl.template.length

@caitp
Copy link
Contributor Author

caitp commented Sep 8, 2014

The fix as-is doesn't really work well enough anyways (works for Safari now, but not for Chrome/Firefox) --- I think we want to take the SVG path for both chrome and FF --- so we need to tell the directive that it's supposed to be an SVG node.

I guess a quick SVG test for the toString()'d name of the template would be good enough

// WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
// support innerHTML, so detect this here and try to generate the contents
// specially.
$element.append(jqLite(jqLiteBuildFragment(ctrl.template, document).childNodes));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT we don't need to call jqLite here.

@caitp caitp force-pushed the issue-7538 branch 2 times, most recently from e336b80 to 0471aa8 Compare September 8, 2014 23:48
@caitp
Copy link
Contributor Author

caitp commented Sep 8, 2014

with the latest fix, (I think) this works correctly --- it's not quite right yet, I'll try to get it ready to land tonight and merge before release

@@ -124,6 +124,8 @@
"jqLiteAddNodes": false,
"jqLiteController": false,
"jqLiteInheritedData": false,
"jqLiteBuildFragment": false,
"jqLiteParseHTML": false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the jqLiteParseHTML addition doesn't matter much, but I don't think it's bad to have it

This makes sure that the linked element is empty before adding the content.
@caitp
Copy link
Contributor Author

caitp commented Sep 9, 2014

From local tests, the current iteration is working well on Safari, FF31 and Chrome --- I think it's ready to squash and land --- @IgorMinar can you take a last look at it (the diff is smaller due to the removal of revert of petes commit)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ngInclude doesn't work for SVG in Safari or Firefox (5263)
4 participants