Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

md-tooltip throws exception when invoked in SVG context (IE only) #9523

Closed
djfd opened this issue Sep 5, 2016 · 3 comments
Closed

md-tooltip throws exception when invoked in SVG context (IE only) #9523

djfd opened this issue Sep 5, 2016 · 3 comments
Assignees

Comments

@djfd
Copy link

djfd commented Sep 5, 2016

Actual Behavior:

  • What is the issue? *When invoked in SVG context (inside <svg /> graphics) there is exception thrown: TypeError: Object doesn't support property or method 'getElementsByClassName'
  • What is the expected behavior?It is expected to at least do not throw exceptions

CodePen (or steps to reproduce the issue): *

  • CodePen Demo which shows your issue:http://codepen.io/djFD/full/qaBrbL/
  • Details: This only happens when browsing with IE (11/also EMU 10, 9/). Just open console and check. Possible an SVGElement returned by IE does not have such method. Corresponding a code line

As for me, this can be made as simple as

content = angular.element(element[0].firstChild); // or something like this

since we have absolutely trivial template.

there is a markup fragment caused this

<div class="inner" ng-cloak>
  ...
  <svg version="1.1" viewBox="0 0 380 100">
    ...
    <text x="20" y="30" tabindex="-1" ng-mouseover="info.over='line-1'" ng-mouseout="info.over=''">
      <md-tooltip  md-direction="far-away">I am SVG text md-tooltip</md-tooltip>
      md-tooltip: hover on me
    </text>
    ...
  </svg>
  ...
</div>

see stack trace below
Angular Versions: *

  • Angular Version:1.5.7
  • Angular Material Version:1.1.0

Additional Information:

  • Browser Type: *Internet Exlorer only
  • Browser Version: * v11 and v10,v9 in emulation mode (maybe higher versions as well, not tested)
  • OS: *Windows 7, Windows 8
  • Stack Traces:
TypeError: Object doesn't support property or method 'getElementsByClassName'
   at m (https://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.js:12:24758)
   at Anonymous function (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:16:30)
   at Anonymous function (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:80:472)
   at ja (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:81:35)
   at m (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:66:274)
   at g (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:58:481)
   at m (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:66:214)
   at g (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:58:481)
   at g (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:58:498)
   at m (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js:66:214) <md-tooltip md-direction="far-away"
@crisbeto crisbeto self-assigned this Sep 5, 2016
@crisbeto
Copy link
Member

crisbeto commented Sep 5, 2016

Well, at first glance this seemed like an easy replacement of getElementsByClassName to querySelector, however it's more complicated since IE seems to filter out the element's contents completely (e.g. element[0].childNodes is empty), if it's a custom node (as ismd-tooltip`). This seems to be an issue in other places like in Angular 2 and Polymer

The workaround in the Codepen seems like it might work, however it's too much trouble for an edge case like this. Here's another workaround that works without too much trouble:

<svg>
  <foreignObject style="pointer-events: none;">
    <md-tooltip>Some text</md-tooltip>
  </foreignObject>
</svg>

It works by wrapping the tooltip in a foreignObject which is the standard way of including external namespaces into SVG. In addition, the foreignObject is invisible and can't be hovered, which is why we add pointer-events: none that will cause the tooltip to skip it when deciding what element to attach itself to (this can also be added in your external CSS).

As an aside, it's still a good idea to replace getElementsByClassName with querySelector, because it should be slightly faster.

@crisbeto crisbeto closed this as completed Sep 5, 2016
@djfd
Copy link
Author

djfd commented Sep 5, 2016

yeah, you are right, there are not children nodes inside tooltip. possible IE wont mix namespaces. workaround with a foreign object does work, but at least this need to be clearly stated in the docs and even better if tooltip code will be able to detect such situations and move self into HTML namespace

quick question. https://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.js (minified version as well) does not contain any icons (eg md-toggle-arrow, md-menu). Are they excluded from a packaging process and now packaged separately? I cannot find any mention of it in changelogs, thanks

UPD. Even simpler. why to not change tooltip template to be something as you proposed (using 'element' transclusion mode)? at instantiation time we can simply remove these leftovers.

BTW, using ng-transclude in the template consumes an extra scope. Why do not do manual transclusion, using the same scope? And also isolated scope is not required... Currently every tooltip consumes 2 scopes and 0-5 watchers, depending on the options

@crisbeto
Copy link
Member

crisbeto commented Sep 5, 2016

Regarding the icons, they should be available through $$mdSvgRegistry, although they're there mainly for internal use.

As for transclusion, I'm not sure. There's probably a reason for it, but it was done before I joined the team so I can't say.

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

No branches or pull requests

2 participants