KanjiVG / kanjivg

Kanji vector graphics
http://kanjivg.tagaini.net
Other
1.06k stars 181 forks source link

Can't grab selectors with colons in them using JavaScript (or CSS)...? #426

Closed Kaji01 closed 8 months ago

Kaji01 commented 10 months ago

I've been trying to figure out how to get this to work for a couple hours now and I'm a bit stuck. Help?

Here's how I'm including the SVG file:

        <div id="svg-container"></div>
        <script>
            jQuery(document).ready(function() {
                // Load SVG file and insert it into the container
                jQuery.ajax({
                    url: "img/kanjivg/<?php echo str_pad($kanji->ucs, 5, '0', STR_PAD_LEFT);?>.svg",
                    dataType: "xml",
                    success: function(data) {
                        jQuery("#svg-container").html(data.documentElement);

                        // Modify SVG properties
                        jQuery("[kvg\\:radical]").css("stroke", "red");
                    }
                });
            });
        </script>

It loads fine, but everything is black. I tried putting the jQuery("[kvg\\:radical]").css("stroke", "red"); line into the console to see if it would work, and it keeps selecting nothing, even though I've opened the file and confirmed the presence of said attribute.

I tried working around this with CSS as follows:

[kvg\:radical] {
    display: none;
}

But it's still showing up. Yet if I just tell it to do something to svg, svg g, or svg text, it works fine—it's when I try to access selectors with colons in them that it develops a blind spot.

Can anyone offer insights into how to work around this?

Kaji01 commented 10 months ago

Apparently when I tried asking on SO someone was able to demonstrate things working in a JSfiddle—I could even create one there that got it to work—but for some reason the systems I'm using refuse to respond to the selectors. Initially I was doing dev on a XAMPP install locally, but I've since uploaded it to Plesk, where the same issue is occurring (as can be verified by pulling up the browser's console and testing the selectors from the initial post). Here's a link to the page I've been using in testing: link

Trying to reverse engineer it, I had the console dump the attributes for the node in question using the following:

jQuery('#kvg\\:04ee4-g1').each(function(){
    jQuery.each(this.attributes, function(){
        if(this.specified){
            console.log(this.name, this.value);
        }
    });
});

Which produced the following output:

[Log] id – "kvg:04ee4-g1"
[Log] kvg:element – "人"
[Log] kvg:position – "top"
[Log] kvg:radical – "general"

So it knows it exists; it just doesn't seem to be letting me access it for some reason.

Are there any environmental issues that could be causing this? Using PHP 8.2 and jQuery 3.6.0.

EDIT: That said, as can be seen in the JS functions written for the buttons on the linked page, we're able to select IDs with colons in them no problem...

EDIT 2: Figured out a workaround for now, using the following:

function highlight_svg_radical() {
let ucs = '<?php echo str_pad($kanji->ucs, 5, '0', STR_PAD_LEFT);?>';

jQuery('[id^=kvg\\:' + ucs + '-g]').each(function(){
    let element_id = this.id.replace(':', '\\:');

    jQuery.each(this.attributes, function(){
        if(this.specified){
            // console.log(this);
            if (this.name.endsWith('radical')) {
                console.log('#' + element_id + ' path');
                jQuery('#' + element_id + ' path').css('stroke', 'green');
                console.log(element_id, this.name, this.value);
            }
        }
    });
});
}
SlugFiller commented 9 months ago

This isn't really related to KanjiVG, is it? At least, it's not something that can be fixed in this repo, since the issue is with your own code.

There are two primary flaws I see with your code. First, is the use of JQuery.html to embed the SVG document into the div. This would transform the document to text, and then back to SVG, wasting resources on parsing. Instead, you should use JQuery.append.

Second, and more to the point, trying to select based on namespaced attributes with a CSS query, when you should be using XPath. It might take some effort to turn the XPathResult to a set of elements so you can pass it to JQuery(). But not a lot:

function mapns(ns) {
  if (ns === 'kvg') {
    return 'http://kanjivg.tagaini.net';
  }
  if (ns === 'svg') {
    return 'http://www.w3.org/2000/svg';
  }
  return '';
}
const result = document.evaluate('.//*[@kvg:radical]', jQuery("#svg-container")[0], mapns, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
const nodes = [];
let node = null;
while ((node = result.iterateNext())) {
  nodes.push(node);
}
JQuery(nodes).css('stroke', 'red');

Still, this is an issue tracker, not StackOverflow. And this is not an issue with KanjiVG.

benkasminbullock commented 8 months ago

I don't think this is a problem we can solve by modifying KanjiVG's code, so let's close this.