Метод jQuery.hasClass() не работает для элементов SVG
У меня есть набор элементов SVG с классами node
и link
. Моя программа должна определить, имеет ли элемент класс node
или класс link
при зависании над любым элементом SVG. Однако по какой-то причине .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?
Ответы
Ответ 1
Атрибут класса для элемента HTML не имеет такого же значения в 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/ p >
Таким образом, проблема может быть любой комбинацией следующего: синтаксическая ошибка с использованием устаревшего браузера с использованием устаревшей версии jQuery.
Ответ 2
Как отмечал Берги в комментариях, jQuery бесшумно терпит неудачу в SVG-элементах за счет className
возвращает объект SVGAnimatedString
вместо обычного DOMString
.
См. этот JSFiddle для сравнения.
У меня возникло соблазн представить запрос на перенос, но сделал быстрый поиск по проекту, и, по-видимому, позиция проекта jQuery в вопросах SVG - это wontfix: https://github.com/jquery/jquery/pull/1511
Если вы используете D3
, вы можете использовать d3.select(this).classed('node')
. Обратите внимание, что D3 правильно возвращает как для HTML-элементов, так и для элементов SVG.
Ответ 3
Это не самый быстрый вариант, но это возможное решение. Вместо использования jQuery hasClass
вместо этого вы можете получить атрибут class
в качестве строки и использовать indexOf
для поиска по нему. Вероятно, есть случаи, когда это не удастся, поэтому я бы не рекомендовал этого, кроме супер простых проектов.
Рабочий пример:
var s = $(this).attr('class');
if( s.indexOf('node')!==-1 ){
// do something
}
Помните: indexOf
возвращает -1
, когда он ничего не может найти, а не 0
. 0
возвращается, когда подстрока начинается с индекса 0
.
Ответ 4
Это взломать методы addClass, removeClass, hasClass jquery перед версиями jquery 3.x.x.
$.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');
Ответ 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/