javascript - example - ¿Es posible usar HTML.querySelector() para seleccionar por atributo xlink en un SVG?
xlink href#user (3)
El selector de consultas puede manejar espacios de nombres, pero se vuelve complicado porque
La sintaxis para especificar espacios de nombres en los selectores de CSS es diferente de html;
La API de querySelector no tiene ningún método para asignar un prefijo de espacio de nombres (como
xlink
) a un espacio de nombre real (como"http://www.w3.org/1999/xlink"
).
En el primer punto, la parte relevante de las especificaciones de CSS le permite especificar ningún espacio de nombres (el predeterminado), un espacio de nombres específico o cualquier espacio de nombres:
@namespace foo "http://www.example.com"; [foo|att=val] { color: blue } [*|att] { color: yellow } [|att] { color: green } [att] { color: green }
La primera regla coincidirá solo con elementos con el atributo
att
en el espacio de nombres " http://www.example.com " con el valor "val".La segunda regla solo coincidirá con los elementos con el atributo
att
independientemente del espacio de nombres del atributo (incluido el espacio de nombres).Las dos últimas reglas son equivalentes y coincidirán solo con elementos con el atributo
att
donde el atributo no está en un espacio de nombres.
Mira este violín, prestando atención a los estilos de relleno (por defecto, hover y activo):
https://jsfiddle.net/eg43L/
La API de Selectores adopta la sintaxis del selector CSS, pero no tiene equivalente a la regla @namespace
para definir un espacio de nombres. Como resultado, los selectores con espacios de nombres no son válidos, pero el token de espacio de nombres comodín es válido :
Si el grupo de selectores incluye prefijos de espacio de nombres que deben resolverse, la implementación debe generar una excepción SYNTAX_ERR ([DOM-LEVEL-3-CORE], sección 1.4).
Esta especificación no proporciona soporte para resolver prefijos de espacio de nombres arbitrarios. Sin embargo, el soporte para un mecanismo de resolución de prefijo de espacio de nombre puede considerarse para su inclusión en una versión futura de esta especificación.
Un prefijo de espacio de nombres debe resolverse si el componente de espacio de nombres no está vacío (por ejemplo,
|div
), representa el espacio de nombres nulo, o un asterisco (por ejemplo,*|div
), que representa cualquier espacio de nombres. Como no es necesario resolver el asterisco o el prefijo de espacio de nombres vacío, las implementaciones que admiten la sintaxis del espacio de nombres en Selectores deben admitirlas.
(negrita agregada)
Mira https://jsfiddle.net/eg43L/ nuevo, esta vez prestando atención a la salida de la consola. El comando document.querySelector(''[*|href="#url"]'')
devuelve el elemento que desea.
Una última advertencia: MDN me dice que IE8- no es compatible con espacios de nombres CSS, por lo que podría no funcionar para ellos.
Actualización 2015-01-31:
Como señaló @ Netsi1964 en los comentarios, esto no funciona para los atributos de espacio de nombres personalizados en los documentos HTML 5, ya que HTML no admite espacios de nombres XML. (Funcionaría en un SVG autónomo u otro documento XML, incluido XHTML).
Cuando el analizador HTML5 encuentra un atributo como data:myAttribute="value"
lo trata como una sola cadena para el nombre del atributo, que incluye :
Para hacer las cosas más confusas, auto-minúsculas la cadena.
Para que querySelector
seleccione estos atributos, debe incluir los data:
como parte de la cadena de atributos. Sin embargo, dado que :
tiene un significado especial en los selectores de CSS, debe escapar con un /
carácter. Y dado que necesita el /
para pasar a través como parte del selector, necesita escapar en su JavaScript.
La llamada exitosa por lo tanto se ve así:
document.querySelector(''[data//:myattribute="value"]'');
Para hacer las cosas un poco más lógicas, recomendaría usar minúsculas para los nombres de tus atributos, ya que el analizador HTML 5 los convertirá de todos modos. El buscador Blink / Webkit activará los selectores en minúsculas y pasará querySelector
, pero en realidad es un error muy problemático (es decir, nunca puede seleccionar elementos SVG con nombres de etiquetas mixtas).
Pero, ¿funciona la misma solución para xlink:href
? ¡No! El analizador HTML 5 reconoce xlink:href
en el marcado SVG, y lo analiza correctamente como un atributo de espacio de nombres.
Aquí está el violín actualizado con pruebas adicionales . De nuevo, mira la salida de la consola para ver los resultados. Probado en Chrome 40, Firefox 35 e IE 11; la única diferencia en el comportamiento es que Chrome coincide con el selector de mayúsculas y minúsculas.
Dado:
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<a xlink:href="url"></a>
</svg>
</body>
¿Es posible usar el HTML DOM''s .querySelector()
o .querySelectorAll()
para seleccionar el enlace dentro de SVG por los contenidos de su atributo xlink:href
?
Esto funciona:
document.querySelector(''a'') // <a xlink:href="url"/>
Estos no:
document.querySelector(''[href="url"]'') // null
document.querySelector(''[xlink:href="url"]'') // Error: not a valid selector
document.querySelector(''[xlink/:href="url"]'') // Error: not a valid selector
document.querySelector(''[xlink//:href="url"]'') // null
¿Hay alguna manera de escribir ese selector de atributos para que ''vea'' el xlink:href
?
Lamentablemente no.
querySelector
no maneja espacios de nombres XML, por lo que no hay una manera fácil de hacerlo de esa manera. Sin embargo, puede usar una consulta XPath
.
var result = document.evaluate(
// Search for all nodes with an href attribute in the xlink namespace.
''//*[@xlink:href="url"]'',
document,
function(prefix){
return {
xlink: "http://www.w3.org/1999/xlink"
}[prefix] || null;
},
XPathResult.ORDERED_NODE_ITERATOR_TYPE
);
var element = result.iterateNext();
Si necesita compatibilidad completa con varios navegadores, como IE, que no tiene un document.evaluate
. Evaluar, puede rellenarlo con wicked-good-xpath .
Por supuesto, dependiendo de su uso, puede ser más fácil hacer esto (que creo que funcionará en IE):
var element = Array.prototype.filter.call(document.querySelectorAll(''a''),
function(el){
return el.getAttributeNS(''http://www.w3.org/1999/xlink'', ''href'') === ''url'';
})[0] || null;
[*|href]
coincidirá con href
y svg xlink:href
, luego use :not([href])
para excluir html href
.
document.querySelectorAll(''[*|href]:not([href])'')
probado en cromo