The jQuery .hasClass() function does not work properly with SVG elements

I am working with a group of SVG elements that are assigned the classes node and link. My goal is to determine whether an element contains either the node or link class when hovering over any of the SVG components. However, I am encountering an issue where the .hasClass() method does not seem to be functioning correctly:

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

Even though the element being hovered on possesses the class node, as evidenced by

console.log($(this).attr("class"));
, the .hasClass() evaluation fails inexplicably. What could be causing this discrepancy? Could it be related to the use of SVG?

Answer №1

In SVG, the class attribute of HTML elements has a different interpretation.

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

Alternatively,

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

can be used for SVG elements.

UPDATE .hasClass appears to be functioning correctly (at least in IE9 and FF) http://jsfiddle.net/X6BPX/1/

The issue could potentially stem from a syntax error, utilization of an outdated browser, or working with an older version of jQuery.

Answer №2

In the discussions, Bergi highlighted that jQuery has a silent failure when it comes to SVG elements due to the fact that className returns an SVGAnimatedString object instead of a regular DOMString.

To see a comparison, check out this JSFiddle link.

I thought about submitting a pull request for this issue, but after searching through the project, it seems that the jQuery team's position on SVG problems is "won't fix": https://github.com/jquery/jquery/pull/1511

If you are using D3, you can utilize d3.select(this).classed('node'). It's worth noting that D3 handles both HTML and SVG elements correctly.

Answer №3

While not the quickest option available, this method presents a viable solution. Rather than utilizing jQuery's hasClass, one could extract the class attribute as a string and utilize indexOf to search within it. It is worth noting that there may be scenarios where this approach may fall short, thus it is advisable to use it primarily for straightforward projects.

Below is a functional demonstration:

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

It is important to keep in mind that indexOf yields a result of -1 when no match is found, rather than 0. The latter value is only returned when the substring commences at index 0.

Answer №4

In order to extend the functionalities of addClass, removeClass, and hasClass jQuery methods for versions prior to 3.x.x, this hack can be used.

$.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;
    }
});

Example usage:

$('.svg-element').addSVGClass('selected');

Answer №5

Make sure to remember to close the function properly

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

http://jsfiddle.net/X6BPX/

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The AJAX functionality is not functioning properly on the remote server, although it is working fine on localhost within the MVC.NET framework

While everything seems to work fine on localhost, the deployment version is encountering issues. I am utilizing jQuery for deletion from the controller: I have tried using type: delete, as well as get and POST methods but still face difficulties. $("#btn ...

Mapping an array of objects within another array of objects

I have a collection of objects that I looped through to extract the content: const teamSliderContent = [ { Description1: 'Chef. Mordy Wenk', Title: 'Head of the Chief staff.', id: 1, }, { Desc ...

Speed of scrolling on a biquadratic Bezier curve

I recently came across a fascinating website called that showcases a unique scrolling behavior. It gives the illusion of moving between slides (screens) with snappy scrolling, when in reality, the website actually scrolls continuously. The transitions bet ...

A guide on transforming Jonatas Walker's TimePicker into a custom JavaScript class or a versatile jQuery plugin

I came across a timepicker solution on this Stack Overflow answer that I really liked. However, I encountered difficulties trying to implement it in a project where input elements are dynamically created. It seemed like the timepicker required specific han ...

Delete the HTML line break

I need some help figuring out how to eliminate the line break in HTML. Essentially, I want to display two "Hello World" lines next to each other instead of stacked on top of each other. <p>Hello World</p> <p>Hello World</p> ...

The error you are seeing is a result of your application code and not generated by Cypress

I attempted to test the following simple code snippet: type Website = string; it('loads examples', () => { const website: Website = 'https://www.ebay.com/'; cy.visit(website); cy.get('input[type="text"]').type(& ...

Adjust the size of CSS boxes based on the window dimensions

I am facing an issue with two divs placed side by side. They appear fine when the page is viewed in full-screen mode. However, upon resizing the window, the right div overlaps the left one and causes a messy layout. . -I want to prevent these boxes fro ...

Retrieve the element (node) responsible for initiating the event

Is there a way to identify which element triggered the event currently being handled? In the following code snippet, event.target is only returning the innermost child node of #xScrollPane, with both event.currentTarget and event.fromElement being null. A ...

Unable to adjust table, row, and cell heights in Outlook template due to HTML/CSS formatting issues

I'm struggling to make the height of the leftmost (commented) nested table adjust automatically based on the content in the right section. It displays correctly in Chrome, but does not stretch in Word/Outlook. Any ideas on how to fix this for Word/Ou ...

Setting up a retrieval callback in mongoose and storing it in a global variable

Is there a way to set the value of db as a global variable? I am having trouble with getting the console output of name outside of the findOne function, it keeps showing me undefined. Any suggestions on how to fix this issue? var name; schema.findone({na ...

What is the best way to change an int32 to a float32 in Deeplearn.js?

In December 2017, this code did the job perfectly. However, after updating Deeplearn.js to the latest version, it no longer functions as expected: math.scope(function(keep, track) { var i = track(dl.Array3D.fromPixels(rawImageData, 4)); i = math.multi ...

Ways to display and conceal a div when hovering over another div

Currently, I have 4 divs grouped under the class "menubut." I am attempting to create a small overlay that appears when hovering over the menubut classes. Additionally, I want another div called "red" to show up about one-tenth of the size of the menubut ...

Obtaining output values from a POST request

When making a GET request through Ajax using jQuery, the URL displayed in the Chrome console is script.php?param=1. $.ajax({ type : "POST", url : "script.php", data : { q : "save", query : query // a variable }, succe ...

Display a list of records retrieved from a Firebase query using ngFor to iterate through each instance

I'm currently using firebase and angular to work on a billing list project. The list contains data showing information for a specific month, you can refer to the imagehttps://i.stack.imgur.com/ZR4BE.png While querying the list was smooth, I encounte ...

Tips for capturing the Three.js model file content and assigning it to a variable

After exporting a model from Blender to Three.js, the resulting file contains JSON data. There are two methods I know of for loading this model: var loader = new THREE.JSONLoader() var material = new THREE.MeshPhongMaterial({color: '#8080a0'}) ...

What is the best way to replicate tags in selenium when an element has multiple class names?

Extracting information from a webpage where a significant amount of text was concealed behind the "see more" tab. Using selenium to click on all such buttons and then extracting data with beautifulsoup. However, some of these buttons have additional space ...

Experiencing Difficulty Retaining Checkbox State Using LocalStorage Upon Page Reload

At the moment, I have a script that automatically clicks on a random checkbox whenever the page loads or refreshes. Through localStorage, I can also view the value of the input assigned to the randomly selected checkbox. However, I'm facing an issue ...

Having trouble with Next.js getStaticProps? Getting a TypeError that says "Cannot read properties of undefined (reading 'map')"?

My latest project was built using create-next-app as a base. In the Blog.js page, I attempted to fetch data from https://jsonplaceholder.typicode.com/posts by utilizing the getStaticProps() function. I followed the instructions provided in this guide: htt ...

Place the outcome of the function into the div element's attribute

As a newcomer to HTML and JavaScript, I recently dove into using 3Dmol.js. Following a tutorial, I was able to create this code snippet that actually works: <script src="http://3Dmol.csb.pitt.edu/build/3Dmol-min.js"></script> <div id="el ...

Is it possible to scroll the grid horizontally?

I have a grid that scrolls vertically, with columns adjusting their width automatically. .grid { display: grid; overflow-y: auto; grid-template-columns: repeat(auto-fit, minmax($min-column-width, 1fr)); } Now, I'm attempting to create a horizon ...