David -

It'd be good to file a ticket on the issue and add in your patch and a
link back to this discussion:
http://dev.jquery.com/newticket

How well have you tested the change across browsers? Does changing
.className to .getAttribute/setAttribute("class") have any other
ramifications? It's definitely something that we can look in to for
another release.

--John



On Sat, May 30, 2009 at 10:27 AM, David Baird <dhba...@gmail.com> wrote:
>
> Anyone have advice on how to proceed?
>
> The fundamental goal is to add support for selectors like this:
>
>    $("#my-svg-element .my-class") // this currently won't work
>
> The reason this doesn't work right now is because jQuery's class name
> selection relies on the .className member of the HTML DOM.  The SVG
> DOM also has .className, but it is of an incompatible type
> ("SVGAnimatedString").  (This is explained in more detail in the
> original post).
>
> I'm a newbie to jQuery development, so any pointers would be much
> appreciated.
>
> Thanks in advance,
> David
>
> On May 26, 11:01 pm, David Baird <dhba...@gmail.com> wrote:
>> Overview of the problem: The HTML and SVG DOM extensions have
>> differing interface definitions for "className".  For the HTML DOM,
>> className is a DOMString [1].  For SVG, className is defined as type
>> SVGAnimatedString [2] (instead of good old DOMString) in SVGStylable
>> [3].  (Furthermore, not all SVG elements inherit from SVGStylable - a
>> fact which some Mozilla devs think is ridiculous, and I'd tend to
>> agree, and they plan to add support for class everywhere in spite of
>> the W3C recommendation [4]).  To access the class value of an SVG
>> element, you must call elem.className.baseVal (or elem.getAttribute
>> ("class")).
>>
>> So, I'd like to tackle this problem as either a modification of jQuery
>> or a plugin to jQuery.  The following jQuery interfaces would need to
>> be changed:
>>
>> - addClass/hasClass/removeClass/toggleClass
>>
>> - Selection: The Sizzle backend for allowing selection based on class
>> would need to be changed a little
>>
>> Keith Wood has provided a jQuery plugin which solves part of this
>> problem by creating a wrapper around addClass, et al. [5].  But his
>> plugin doesn't address selection of SVG elements by class name (e.g. $
>> (".my-svg-class")).
>>
>> My question for the devs: is a modification to jQuery itself
>> necessitated or can/should I factor this out into a separate plugin?
>> It seems that I have to drill to the bottom layers of Sizzle, which
>> makes me think a plugin is not ideal, and I would appreciate any
>> suggestions.
>>
>> Here's a patch I came up with (alternatively, it should be available
>> here for a month:http://pastebin.com/m24bdbbd9):
>>
>> --- jquery-1.3.2.js     2009-05-25 12:00:43.667854804 -0600
>> +++ jquery-1.3.2-modified-selectors.js  2009-05-26 22:52:33.748668152
>> -0600
>> @@ -707,27 +707,54 @@
>>         },
>>
>>         className: {
>> +
>> +               get: function( elem ) {
>> +                       //var classNames = elem.className.baseVal || 
>> elem.className ||
>> elem.getAttribute("class");
>> +                       var classNames = elem.getAttribute("class");
>> +                       classNames = classNames ? classNames : "";
>> +                       return classNames
>> +               },
>> +
>> +               set: function( elem, value ) {
>> +                       elem.setAttribute("class", value);
>> +               },
>> +
>> +
>>                 // internal only, use addClass("class")
>>                 add: function( elem, classNames ) {
>>                         jQuery.each((classNames || "").split(/\s+/), 
>> function(i, className)
>> {
>> -                               if ( elem.nodeType == 1 && 
>> !jQuery.className.has( elem.className,
>> className ) )
>> -                                       elem.className += (elem.className ? 
>> " " : "") + className;
>> +                               var curClassName = 
>> jQuery.className.get(elem);
>> +                               if ( elem.nodeType == 1 && 
>> !jQuery.className.has( curClassName,
>> className ) )
>> +                               jQuery.className.set(elem, curClassName + 
>> (curClassName ? " " :
>> "") + className);
>>                         });
>>                 },
>>
>>                 // internal only, use removeClass("class")
>>                 remove: function( elem, classNames ) {
>>                         if (elem.nodeType == 1)
>> -                               elem.className = classNames !== undefined ?
>> -                                       
>> jQuery.grep(elem.className.split(/\s+/), function(className){
>> +                               jQuery.className.set(elem, classNames !== 
>> undefined ?
>> +                                       
>> jQuery.grep(jQuery.className.get(elem).split(/\s+/), function
>> (className){
>>                                                 return 
>> !jQuery.className.has( classNames, className );
>>                                         }).join(" ") :
>> -                                       "";
>> +                                       ""
>> +                               );
>>                 },
>>
>>                 // internal only, use hasClass("class")
>>                 has: function( elem, className ) {
>> -                       return elem && jQuery.inArray( className, 
>> (elem.className ||
>> elem).toString().split(/\s+/) ) > -1;
>> +                       var classNames = "";
>> +                       if (elem)
>> +                               {
>> +                                       if (elem.getAttribute)
>> +                                               {
>> +                                                       classNames = 
>> elem.jQuery.className.get(elem);
>> +                                               }
>> +                                       else
>> +                                               {
>> +                                                       classNames = elem; 
>> // <-- ???
>> +                                               }
>> +                               }
>> +                       return elem && jQuery.inArray( className, 
>> classNames.toString
>> ().split(/\s+/) ) > -1;
>>                 }
>>         },
>>
>> @@ -1779,7 +1806,8 @@
>>
>>                         for ( var i = 0, elem; (elem = curLoop[i]) != null; 
>> i++ ) {
>>                                 if ( elem ) {
>> -                                       if ( not ^ (elem.className && (" " + 
>> elem.className + "
>> ").indexOf(match) >= 0) ) {
>> +                                       var className = 
>> jQuery.className.get(elem);
>> +                                       if ( not ^ (className && (" " + 
>> className + " ").indexOf(match)>= 0) ) {
>>
>>                                                 if ( !inplace )
>>                                                         result.push( elem );
>>                                         } else if ( inplace ) {
>> @@ -2005,7 +2033,8 @@
>>                         return (match === "*" && elem.nodeType === 1) || 
>> elem.nodeName ===
>> match;
>>                 },
>>                 CLASS: function(elem, match){
>> -                       return (" " + (elem.className || 
>> elem.getAttribute("class")) + "
>> ")
>> +                       var className = jQuery.className.get(elem);
>> +                       return (" " + (className) + " ")
>>                                 .indexOf( match ) > -1;
>>                 },
>>                 ATTR: function(elem, match){
>> @@ -2207,7 +2236,7 @@
>>         if ( div.querySelectorAll && div.querySelectorAll(".TEST").length
>> === 0 ) {
>>                 return;
>>         }
>> -
>> +
>>         Sizzle = function(query, context, extra, seed){
>>                 context = context || document;
>>
>> [1]http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-58190037
>> "Interface HTMLElement"
>> [2]http://www.w3.org/TR/SVG/types.html#InterfaceSVGAnimatedString
>> [3]http://www.w3.org/TR/SVG/types.html#InterfaceSVGStylable
>> [4]https://developer.mozilla.org/en/SVG/Specification_Deviations
>> [5]http://keith-wood.name/svg.html
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"jQuery Development" group.
To post to this group, send email to jquery-dev@googlegroups.com
To unsubscribe from this group, send email to 
jquery-dev+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to