SVG 元素的 jQuery .hasClass() 方法失败
Posted
技术标签:
【中文标题】SVG 元素的 jQuery .hasClass() 方法失败【英文标题】:jQuery .hasClass() method fails for SVG elements 【发布时间】:2013-07-24 08:11:22 【问题描述】:我有一组带有 node
和 link
类的 SVG 元素。我的程序应该在悬停在任何 SVG 元素上时检测元素是否具有 node
类或 link
类。但是,由于某种原因,.hasClass()
似乎不起作用:
$(".node").hover(function(evt)
console.log($(this).attr("class")); //returns "node"
console.log($(this).hasClass('node')); //returns false
, function()console.log("Done"););
所以我悬停的元素有 node
类,jQuery 也检测到这一点,如 console.log($(this).attr("class"));
所示,但由于某种原因,实际的 .hasClass()
失败了。为什么是这样?是否因为 SVG 而失败?
【问题讨论】:
只是一个旁注,你最后错过了);
:) 和seems to work for me
SVG 中的元素并不是真正的 html,因此这些元素中缺少属性,这就是获取属性有效的原因,但使用可能检查 className 属性的 hasClass 不起作用。
其实不太一样,但只要其他类都不包含字符串“node”就可以了。
请记住,在使用 SVG 时,元素没有 className、innerHTML 等内容,因此并非 jQuery 中的所有内容都适用于这些元素。
jQuery 2.2.0 修复了这个问题 - 你可以在这里看到我的帖子:***.com/a/34698009/3885376 包含一些细节 + 一个小例子,现在是 hasClass()
、addClass()
和removeClass()
工作。
【参考方案1】:
这是针对之前 jquery 3.x.x 版本的 addClass、removeClass、hasClass jquery 方法的 hack。
$.fn.extend(
addSVGClass: function (cls)
return this.each(function ()
var classList = $(this).attr('class');
if (classList)
var classListArr = classList.split(" ");
if (classListArr.indexOf(cls) === -1)
classListArr.push(cls);
classList = classListArr.join(" ").trim();
$(this).attr('class', classList);
else
$(this).attr('class', cls);
);
,
removeSVGClass: function (cls)
return this.each(function ()
var classList = $(this).attr('class');
if (classList)
var classListArr = classList.split(" ");
if (classListArr.indexOf(cls) !== -1)
delete classListArr[classListArr.indexOf(cls)];
classList = classListArr.join(" ").trim();
$(this).attr('class', classList);
);
,
hasSVGClass: function (cls)
var el = this[0];
var classList = $(el).attr('class');
if (classList)
var classListArr = classList.split(" ");
if (classListArr.indexOf(cls) !== -1)
return true;
else
return false;
return false;
);
用法:
$('.svg-element').addSVGClass('selected');
【讨论】:
【参考方案2】:这不是有史以来最快的选择,但它是一个可能的解决方案。除了使用 jQuery 的 hasClass
之外,您还可以获取 class
属性作为字符串并使用 indexOf
搜索它。这可能会在某些用例中失败,因此我不建议这样做,除非是超级简单的项目。
工作示例:
var s = $(this).attr('class');
if( s.indexOf('node')!==-1 )
// do something
记住:indexOf
在找不到任何东西时返回-1
,而不是0
。当子字符串从索引0
开始时返回0
。
【讨论】:
【参考方案3】:正如 Bergi 在 cmets 中指出的那样,由于 className
返回一个 SVGAnimatedString
对象而不是普通的 DOMString
对象,jQuery 在 SVG 元素上静默失败。
请参阅this JSFiddle 进行比较。
我很想就此提交一个拉取请求,但做了一个快速的项目搜索,显然 jQuery 项目对 SVG 问题的立场是不会修复的:https://github.com/jquery/jquery/pull/1511
如果您使用的是D3
,则可以使用d3.select(this).classed('node')
。请注意,D3 正确返回 HTML 元素和 SVG 元素。
【讨论】:
如果 jQuery 的文档说明缺乏支持(或意外结果),那就太好了。 hasClass() API doc 表示 “从 jQuery 1.12/2.2 开始,此方法支持 XML 文档,包括 SVG”【参考方案4】:HTML 元素的 class 属性在 SVG 中的含义不同。
$("<b></b>").addClass($(this).attr("class")).hasClass("node")
或者
/(^|\s)node(\s|$)/.test($(this).attr("class"))
用于 SVG 元素。
EDIT .hasClass 似乎工作得很好(至少在 IE9 和 FF 中)http://jsfiddle.net/X6BPX/1/
所以问题可能是以下任意组合:语法错误、使用过时的浏览器、使用过时的 jQuery 版本。
【讨论】:
class
在 SVG 中还有什么含义?
@Bergi - 它只是一个常规属性,而不是像 HTML 元素中的特殊样式属性,具有浏览器特定的钩子,如 className vs class。
@Bergi - jsfiddle.net/TRKF6 注意 elm.class、elm.className、elm.getAttribute('class')、elm.getAttribute('className') 与标准 HTML 元素的响应方式不同。旧版本的 jQuery 可能无法解释这些差异。
不,只有className
属性产生不同的值。检查jsfiddle.net/TRKF6/1 进行比较。如果你得到其他属性的不同值,你可能应该更新你的浏览器。
我不确定链接(编辑)JSFiddle 打算证明什么,因为它使用的是 div。正如问题所暗示的那样,这是一个失败的 SVG:jsfiddle.net/Mm3TE【参考方案5】:
有效。但一定要关闭功能
$(".node").hover(function(evt)
console.log($(this).attr("class")); //returns "node"
console.log($(this).hasClass('node')); //returns false
, function()console.log("Done"););
http://jsfiddle.net/X6BPX/
【讨论】:
谢谢 Rick,但我确实在 cmets 中澄清了缺少的括号是一个错字。我电脑上的功能已关闭。 @Rick:当hasClass('node')
返回 false 时,这是如何“工作”的?!
完全没用的小提琴 - 它表明它适用于 HTML 元素。没有人对此提出质疑。手头的问题是它不适用于 SVG 元素。 (也就是说,jQuery .hasClass() 没有。)
这是更正后的 Fiddle,它表明 .hasClass() 不适用于内联 SVG 元素。 jsfiddle.net/X6BPX/8以上是关于SVG 元素的 jQuery .hasClass() 方法失败的主要内容,如果未能解决你的问题,请参考以下文章