jQuery 3 не має цієї проблеми
Однією із змін, перелічених у версії jQuery 3.0, є:
додати маніпуляцію класом SVG ( # 2199 , 20aaed3 )
Одним із варіантів вирішення цієї проблеми було б оновлення до jQuery 3. Чудово працює:
var flip = true;
setInterval(function() {
// Could use toggleClass, but demonstrating addClass.
if (flip) {
$('svg circle').addClass('green');
}
else {
$('svg circle').removeClass('green');
}
flip = !flip;
}, 1000);
svg circle {
fill: red;
stroke: black;
stroke-width: 5;
}
svg circle.green {
fill: green;
}
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<svg>
<circle cx="50" cy="50" r="25" />
</svg>
Проблема:
Причина, що функції маніпулювання класом jQuery не працюють з елементами SVG, полягає в тому, що версії jQuery до версії 3.0 використовують className
властивість для цих функцій.
cur = elem.nodeType === 1 && ( elem.className ?
( " " + elem.className + " " ).replace( rclass, " " ) :
" "
);
Це поводиться так, як очікувалося для елементів HTML, але для елементів SVG className
дещо інше. Для елемента SVG - className
це не рядок, а екземпляр SVGAnimatedString
.
Розглянемо наступний код:
var test_div = document.getElementById('test-div');
var test_svg = document.getElementById('test-svg');
console.log(test_div.className);
console.log(test_svg.className);
#test-div {
width: 200px;
height: 50px;
background: blue;
}
<div class="test div" id="test-div"></div>
<svg width="200" height="50" viewBox="0 0 200 50">
<rect width="200" height="50" fill="green" class="test svg" id="test-svg" />
</svg>
Якщо ви запустите цей код, ви побачите щось подібне на консолі розробника.
test div
SVGAnimatedString { baseVal="test svg", animVal="test svg"}
Якби ми кидали цей SVGAnimatedString
об’єкт на рядок, як це робиться jQuery, у нас би це було [object SVGAnimatedString]
, де jQuery виходить з ладу.
Як плагін jQuery SVG справляється з цим:
Плагін jQuery SVG працює над цим шляхом, виправляючи відповідні функції, щоб додати підтримку SVG.
function getClassNames(elem) {
return (!$.svg.isSVGElem(elem) ? elem.className :
(elem.className ? elem.className.baseVal : elem.getAttribute('class'))) || '';
}
Ця функція буде визначати, чи є елемент SVG, і якщо він є, він використовуватиме baseVal
властивість SVGAnimatedString
об'єкта, якщо він доступний, перед тим, як повернутися назад на class
атрибут.
Історична позиція jQuery щодо цього питання:
jQuery наразі перераховує цю проблему на їхній сторінці Won't Fix . Ось відповідні частини.
Помилки елементів SVG / VML або елементів з простором імен
jQuery - це перш за все бібліотека для HTML DOM, тому більшість проблем, пов’язаних із SVG / VML-документами або елементами, розміщеними в іменах, виходять за межі сфери. Ми намагаємося вирішити проблеми, які "кровоточать" у документах HTML, таких як події, які випливають із SVG.
Очевидно, jQuery вважає повну підтримку SVG поза межами ядра jQuery і краще підходить для плагінів.