A bug in the QWrap selector: Case sensitivity of tagName

Source: Internet
Author: User

Selector is a must for modern Web Front-ends. For standard browsers, querySelector is available, while for IE8 standard mode, a Selector engine is required.

Because this project uses QWrap in the Code, although some of the code I write does not use QWrap, it is better to use QWrap as a Selector engine.

The result is a tragedy.

I use the html5-shim/shiv library to make IE parse the new HTML5 tag correctly. However, the QWrap engine cannot correctly select html5 elements.

I tried to make a human choice and found that it was okay,That is, the Selector of QWrap has a bug.

After arduous struggles, we finally found that the problem lies in the 2nd rows of this function:

 
 
  1. Function (){
  2. SFun. push ('El. tagName = "'+ a. toUpperCase () + '"');
  3. Return '';
  4. }). Replace (/([\ [(]. *) | # ([\ w \-] +) | \. ([\ w \-] +)/g, // id scaling method // className Scaling Method

QWrap uses the Code Generation Technology to assemble the corresponding functions for the selector. This is a very tricky and advanced technology.

It is not hard to see that a tag match is generated here. The code generated for matching "nav" should be: el. tagName = "nav". toUpperCase ().

Generally, when a browser calls a tagName for all HTML elements, all uppercase letters are returned.

No.: Why in upper case?

Hax answer: This is a habit inherited from the HTML ancestor SGML. For people who wrote SGML/HTML in the early days, the easiest way to distinguish between tags and body content is to use uppercase tags.

However, according to the famous tattoo hacker in the circle, the reason why HTML is capitalized is that the technology was outdated at that time, the storage was too tight, and the full capital was less storage space ...... (In this case, I cannot remember the details. Ask Winter for help from gossip personnel)

/Out of number]

Unfortunately, html5-shim and almost all similar libraries I know use all lowercase letters. This is because the mainstream of modern Web standards is full lower case.

No.] Why is it in lower case?

Hax answer: this is because it does not hurt your eyes or hands.

/Out of number]

Although IE is case-insensitive to the HTML elements it can recognize, it regards new elements generated through the createElement neural knife as XML-like elements, that is, it is case sensitive, so the tagName attribute will return the originally set case format.

How to fix this problem?

One easy way to think of is to change the tag list in the html5-shim to uppercase. However, this method does not work. Because the tagName returns the initial value, that is, if you write

..., The returned result is SECTION. If you write ... The returned result is SECtion (that is, the case of the start tag). If you write document. createElement ('region'), the returned result is sEcTion.

Obviously, QWrap Selector (or any general script Library) should not depend on how the Web author writes it. Therefore, this problem must be solved by QW.

In addition, the library should not assume that the tagName must return uppercase letters. Although the specification stipulates that the tagName of the HTML element should always return uppercase letters, the library must consider compatibility (IE mentioned here ).

In addition, the general script library should be proactive. For example, the Selector engine is used to select XML elements. Currently, various pure JS selector engines are not namespace-aware, So XML elements cannot be selected. However, the HTML specification allows you to directly mix MathML and SVG in HTML. New browsers are also supported.

For example, you can try to view the following code in FireFox:

 
 
  1. <body>  
  2. <div id="test"><math>  
  3.     <mi>x</mi>  
  4.     <mo>=</mo>  
  5.     <mfrac>  
  6.      <mrow>  
  7.       <mo form="prefix">−</mo> <mi>b</mi>  
  8.       <mo>±</mo>  
  9.       <msqrt>  
  10.        <msup> <mi>b</mi> <mn>2</mn> </msup>  
  11.        <mo>−</mo>  
  12.        <mn>4</mn> <mo>⁢</mo> <mi>a</mi> <mo>⁢</mo> <mi>c</mi>  
  13.       </msqrt>  
  14.      </mrow>  
  15.      <mrow>  
  16.       <mn>2</mn> <mo>⁢</mo> <mi>a</mi>  
  17.      </mrow>  
  18.     </mfrac>  
  19.    </math></div>  
  20. </body>  

You can see that $ ('test'). firstChild. tagName returns "math" instead of "MATH ". Document. querySelector ('# test math') can also select this element correctly.

However, QW Selector cannot select the math element.

Extension]

What happens if you insert document. createElement ('Math') in this document?

Note that you do not insert a MathML element, you need to use createElementNS, plus the appropriate namespace (http://www.w3.org/1998/Math/MathML. You insert an HTML element named "math". The tagName of this element returns a full-capital "MATH ".

In this case, the two elements are returned using getElementsByTagName ('Math') or document. querySelectorAll ('Math. While getElementsByTagName ('Math') or document. querySelectorAll ('Math') Only returns the HTML element exactly called "MATH" without returning the MATH element of the actual MathML. Note: The FF behavior is so, and currently Chrome returns both. This should be a WebKit bug.

/Extension]

Although the main purpose of the pure JS Selector engine is forward compatibility, it is better to achieve backward compatibility. QW Selector fails in both aspects due to this small case sensitivity problem.

Fortunately, it is easy to correct it.

SFun. push ('El. tagName = "'+ a. toUpperCase () + '"');

Change

SFun. push ('El. tagName. toLowerCase () = "'+ a. toLowerCase () + '"');

You can.

Someone may ask, why are all switched to toLowerCase ()?

Have you ever said anything about UPPERCASE!

Seriously, toLowerCase () is used because the behavior specified by the standard is like this. Although toUpperCase () does not seem to be the same.

The results of the above Code are consistent with the current Chrome behavior, that is, even if it is a non-HTML namespace element, it is also case insensitive. If you want to follow the FF behavior, you can change it:

'Ishtmlelement (el )? TagName. toLowerCase () = "{a. toLowerCase ()}": tagName = "{}"'

The above isHTMLElement checks whether an element is an HTML element. Check the standard for the logic. {A} The template syntax is used here to make everyone better understand. I also save a lot of effort to put quotation marks and the plus sign.

Original article: http://hax.iteye.com/blog/1126134

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.