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 <[email protected]> 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 [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---