CSS3 Selectors [*|type="toc"]
Asked Answered
T

2

7

I am working with EPUB.JS, which uses the following code to get some information from an ePub file:

var navEl = navHtml.querySelector('nav[*|type="toc"]')

This line of code fails in IE10, as the querySelector returns null. I've never seen an attribute selector in the format [*|attr="val"] before, but what I think they were trying to say was, "Select all nav elements with any attribute or an attribute named 'type' with value 'toc'."

I couldn't find any information on this star-pipe syntax, but I presume it is some sort of logical OR command that works in Webkit/Mozilla but not in IE.

Altering that line to read:

var navEl = navHtml.querySelector('nav')

works, but I still wanted to fully understand why they may have chose that other syntax when I feel like it meaningless, just in case it has an actual purpose that could lead to errors elsewhere.

Is there any explanation for this *|... and is it even necessary?

Truckle answered 6/12, 2013 at 16:5 Comment(1)
Note that querySelector() can only return either zero or one element, not "all of them" (unless there is only one anyway).Erg
D
6

The namespace| syntax applies to type selectors as well as attribute selectors (and possibly others). This essentially says "match nav with type=toc where type is in any namespace (including no namespace)." It would match:

<nav foo:type="toc">

If the selector were just [type=toc], the above element would not be selected because it is in a namespace.

http://www.w3.org/TR/css3-selectors/#attrnmsp

The fact that this doesn't work in IE10 is probably an error on IE's side. To be honest I've never even seen namespaces used in any HTML I've seen, although I'm sure it happens a lot. You can probably get away with just leaving off the *|, but it's important that you understand why it's there before you make that decision.

Detent answered 6/12, 2013 at 16:11 Comment(6)
It is strange indeed - the browser should be able to process this selector because there is no namespace to resolve. See w3.org/TR/selectors-api/#resolving-namespacesErg
This is precisely what I was looking for and, sure enough, some of the sample epubs I'm trying to load have XML like <nav epub:type="toc">, so leaving it off is not really an option. I'll have do some experiments with IE10 to see what is going on. Thank you for the info and the W3 resource, as well.Truckle
@MrSlayer How about trying nav[epub|type=toc], nav[type=toc]?Detent
@Explosion Pills: The first one won't work because epub| needs to be resolved, which can't be done within querySelector(), and the second one won't work as you stated in your own answer.Erg
Yeah, seems like IE10 doesn't understand the namespacing stuff, so that may be out of the question. Might have to resort to looping through getElementsByTagName or something, but I'll experiment a little further before I do that. With 500,000 epub samples to load, I have no idea if other namespaces are being used. Appreciate all the help, folks.Truckle
The only information I can find on this is here: msdn.microsoft.com/en-us/library/cc288326(v=vs.85).aspx#names -- but that is referring to IE8. I believe NSResolver refers to the | syntax. Issue may be carried over to IE10.Detent
T
1

So, I just wanted to post my workaround, in case anyone comes across something similar in the future.

I'm leaving the original querySelector in place:

var navEl = navHtml.querySelector('nav[*|type="toc"]')

However, if that results in a null value for navEl, I wrote a little loop to do a similar "any-namespace attribute selector" using more traditional logic that works in IE10 and presumably lower versions:

if( !navEl )
{
   var navs = navHtml.getElementsByTagName( 'nav' );
   for( var i = 0; i < navs.length; i++ )
   {
      for( var j = 0; j < navs[i].attributes.length; j++ )
      {
         if(
            navs[i].attributes[j].nodeName.match( 'type$' ) == 'type' &&
            navs[i].attributes[j].value == 'toc'
         ) {
            navEl = navs[i];
            break;
         }
      }
   }
}

It's not super-pretty or clean, but it gets the point across. It would be fairly easy to convert this to a function so you can search any attribute/value, instead of hard-coding type and toc, but for my current purposes, this will suffice.

Truckle answered 6/12, 2013 at 17:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.