2013-07-24 22 views
20

Mam zestaw elementów SVG z klasami node i link. Mój program powinien wykryć, czy element zawiera klasę node lub klasę link po najechaniu kursorem na dowolny z elementów SVG. Jednak z jakiegoś powodu, .hasClass() nie wydają się działać:Metoda jQuery .hasClass() kończy się niepowodzeniem dla elementów SVG

$(".node").hover(function(evt){ 
    console.log($(this).attr("class")); //returns "node" 
    console.log($(this).hasClass('node')); //returns false 
}, function(){console.log("Done");}); 

więc element I unosił się na ma klasę node i jQuery wykryje, że zbyt, jak pokazano przez console.log($(this).attr("class"));, ale z jakiegoś powodu rzeczywista .hasClass() kończy się niepowodzeniem. Dlaczego to? Czy to nie z powodu SVG?

+1

tylko marginesie, jesteś brakuje ')' w końcu :) i [wydaje się działać dla mnie] (http://jsfiddle.net/hungerpain/V4BNT /) – krishgopinath

+0

Interesujące ... spróbuj ustawić zmienną równą '$ (this) .attr (" class ")' następnie użyj 'hasClass' z tym var. Wciąż fałszywe? – tymeJV

+5

Elementy wewnątrz SVG nie są tak naprawdę HTML i jako takie nie ma właściwości z tych elementów, dlatego uzyskanie atrybutu działa, ale użycie hasClass, które prawdopodobnie sprawdza właściwość className, nie działa. – adeneo

Odpowiedz

11

Atrybut klasy dla elementu HTML nie ma takiego samego znaczenia w SVG.

$("<b></b>").addClass($(this).attr("class")).hasClass("node") 

Albo

/(^|\s)node(\s|$)/.test($(this).attr("class")) 

elementów SVG.

EDIT .hasClass wydaje się działać dobrze (przynajmniej w IE9 i FF) http://jsfiddle.net/X6BPX/1/

więc problem może być dowolną kombinacją następujących: błąd składni przy użyciu przestarzałej przeglądarki, korzystając przestarzała wersja jQuery.

+0

Co jeszcze może oznaczać "klasa" w SVG? – Bergi

+0

@Bergi - Jest to zwykły atrybut zamiast specjalnego atrybutu stylizacji, tak jak w elementach HTML z haczykami specyficznymi dla przeglądarki, takimi jak className vs class. –

+0

http://www.w3.org/TR/SVG/styling.html#ClassAttribute – Bergi

-4

Działa. Ale pamiętaj, aby zamknąć funkcję

$(".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/

+0

Dziękuję Rick, ale wyjaśniłem w komentarzach, że brakujący nawias był literówką. Funkcja, którą mam na moim komputerze, jest zamknięta. –

+0

im sry. Nie przeczytałem tego. ale działa :) –

+0

@Rick: jak to "działa", gdy 'hasClass ('node')' zwraca fałsz ?! – Tom

5

Jak Bergi zauważył w komentarzach, jQuery dyskretnie nie powiedzie się na elementach SVG z tytułu className powracających obiekt SVGAnimatedString zamiast normalnego DOMString.

Aby porównać, zobacz this JSFiddle.

Kusiło mnie, aby złożyć wniosek ciągnij tego, ale tak szybkie wyszukiwanie projektu, a pozornie projekt stanowisko w kwestiach jQuery SVG jest WONTFIX: https://github.com/jquery/jquery/pull/1511

Jeśli używasz D3, można użyć d3.select(this).classed('node') . Zwróć uwagę, że D3 poprawnie zwraca zarówno elementy HTML, jak i elementy SVG.

2

To nie jest najszybsza opcja w historii, ale jest to możliwe rozwiązanie. Zamiast używać jQuery w wersji hasClass, możesz zamiast tego uzyskać atrybut class jako ciąg i użyć go do przeszukiwania go przez indexOf. Prawdopodobnie są przypadki, w których to się nie powiedzie, więc nie polecałbym tego, z wyjątkiem bardzo prostych projektów.

przykład robocza:

var s = $(this).attr('class'); 
if(s.indexOf('node')!==-1){ 
    // do something 
} 

Pamiętaj: indexOf powraca -1 gdy nie mogę znaleźć nic, nie 0. 0 jest zwracana, gdy substring zaczyna się od indeksu 0.

0

To jest hack dla metod jQuery addClass, removeClass, hasClass dla wersji 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; 
    } 
}); 

Wykorzystanie:

$('.svg-element').addSVGClass('selected'); 
Powiązane problemy