The latest version of jquery v3.3.1 bugs and solutions (what doesn't matter, how to solve the problem is important)

Source: Internet
Author: User
Discover problems

In the latest version of Fineuipro v5.2.0, we've upgraded the built-in jquery v1.12.4 to the jquery v3.3.1 to see the upgrade history:

+ Upgrade to jquery v3.3.1.
-jquery v3.x supported browsers: chrome,edge,firefox,safari,ie9+.
-Added type Jslibrary enumeration value JQV1, used to introduce jquery v1.x.
-If you need to support IE8, add the configuration item jslibrary=jqv1 in Web. config.
-IE8 limited support and complex pages may have performance issues, it is recommended that you actively guide users to use modern browsers.

The reason for this upgrade is to consider the following factors:

1. IE8 's market share is shrinking, consider putting IE8 's support in a secondary position

2. Through the full configuration parameters Jslibrary=jqv1 introduced the old version of the JQuery v1.12.4, so that old customers can still support IE8

3. Using jquery v3.3.1 By default, keeping up with the jquery version means better performance and security, as well as the ability to solve problems in a timely manner

4. Given the development of jQuery for so many years, stability should not be a problem

The entire upgrade process is still very smooth, no major changes.

The only thing that gives me a headache is that the position of the node in the table is always calculated incorrectly, such as when the table cell is edited, and if the table does not have a scrollbar, the correct edit box is displayed:

However, when the table scroll bar appears, the edit box is misplaced:

And this problem, when using jQuery v1.12.4 is not there!

Analyze problems

After a period of debugging, finally determined that this is the latest version of the JQuery v3.3.1 a bug, this problem should meet the following conditions:

1. Quoting the latest version of JQuery v3.3.1

2. Error in calculating the relative position of the form TR or TD, for example: $ (' Table Tr:eq (1) TD (0) '). Position ()

To illustrate the problem more visually, I have written an example where the HTML code block:

<Divclass= "Container">  <Table>    <TR>      <TD>Row-1</TD>    </TR>    <TR>      <TDID= "thetd">Row-2</TD>    </TR>  </Table></Div><DivID= "Result"></Div>

CSS code blocks:

. Container{Background-color:LightGreen;padding:50px;position:relative;}Table{width:100%;Border-collapse:collapse;border-spacing:0;Background-color:Green;}Table TD{padding:0;Height:50px;Color:#fff;vertical-align:Top;}

To more visually describe the problem, we use different background colors to identify the outer container (. container) and the Internal table (table).

JavaScript code block:

$ (function() {    var tdposition = $ (' #theTD '). Position ();    $ (' #result '). HTML (' top: ' + Tdposition.top + ' Left: ' + tdposition.left);});

According to the normal mode of thinking, the relative position of the above thetd should be relative. Container offset (because. Container is the first encountered relative positioning parent element of TD).

Because. Container sets the padding for 50px, and the height of each row of the table is 50px, so thetd distance. The vertical height of the container should be 100px.

So we expect the output to be:

top:100 left:50

But did the results really? I created two examples of examples of jquery v1.9.1 and references to jquery v3.3.1, and the results are as follows:

It can be seen that in JQuery v3.3.1, getting the relative position (position) of the TD node in the table is not what we want. What exactly is this value?

Top:50 left:0

Solve the problem

After careful analysis, I think this value is the offset of the TD relative to the External table node, not the position relative to the first floating parent node (position:relative/absolute).

Once I doubted the exact meaning of position () and offset (), did I get it wrong? Later found that my understanding is no problem:

. OffsetParent () is supposed to return the nearest positioned element, where "positioned" means it has a CSS position Attri Bute of "relative", "absolute", or "fixed".

I relied on position computation in many places, and it was a mistake when JQuery computed the offsetParent node:

Open the browser's debug window, I enter the following code:

$ (' #theTD '). OffsetParent ()

As you can see, it is still the. container that is obtained through jQuery, and this method returns no problem.

No way, since the problem, had to first in their own code fixed.

First attempt

Since the relative position of the TD is relative to the table, it is better to use table to do a relay, calculate the table of the position plus to go on the line, as follows:

$ (function() {    var tdposition = $ (' #theTD '). Position ();    var tableposition = $ (' #theTD '). Parents (' table '). Position ();      $ (' #result '). HTML (' top: ' +       + tableposition.top) + ' left: ' +       +  tableposition.left);    });

It looked as if it was correct, and later the test found that the nested table was not going to be a problem, as in the following example:

<Divclass= "Container"><Tableclass= "Table-outer">  <TR>    <TD>Table1-row1</TD>  </TR>  <TR>      <TD>        <Table>          <TR>            <TD>Row-1</TD>          </TR>          <TR>            <TDID= "thetd">Row-2</TD>          </TR>        </Table>    </TD>   </TR> </Table></Div><DivID= "Result"></Div>
. Container{Background-color:LightGreen;padding:50px;position:relative;}. Table-outer{Background-color:Blue;}Table{width:100%;Border-collapse:collapse;border-spacing:0;Background-color:Green;}Table TD{padding:0;Height:50px;Color:#fff;vertical-align:Top;}

Second attempt

One count does not, regenerate a count. Since the table position problem, then the div position should be normal. This time I'll be here. How about creating a div node dynamically in TD?

$ (function() {  var tmpdiv = $ (' <div style= "position:relative; /> '). Prependto ($ (' #theTD '));   var tdposition = tmpdiv.position ();  Tmpdiv.remove ();      $ (' #result '). HTML (' top: ' + Tdposition.top + ' Left: ' + tdposition.left);});

Look like there is no problem, can still problem, when set TD Vertical-align:middle, the problem is exposed, because at this time the div inside the TD is centered display:

Third attempt

As I helpless, I suddenly thought of the offsetParent () function in front of it, which can get the correct parent node. Since the position () function has a problem, why don't I try the offset () function.

1. Jquery.position (): Gets the offset of the element relative to the parent element (Position:relative/absolute)

2. Jquery.offset (): Gets the offset of the element relative to the viewport

$ (function() {    var tdoffset = $ (' #theTD '). offset ();     var tdparentoffset = $ (' #theTD '). OffsetParent (). offset ();    $ (' #result '). HTML (' top: ' + (tdoffset.top  -tdparentoffset.top) + ' Left: ' + (Tdoffset.left-  Tdparentoffset.left);});

This time subtracting the current element from the offset of the relative parent element, will the result be what we need?

Yes, that's exactly what we need. Because this logic is simple to judge, and whether the table nesting does not matter, so test the first attempt to fail the situation:

Bingo! Everything is fine. This issue is resolved satisfactorily!

Is it really a jquery bug?

It is inconceivable that a public JavaScript that is used by users around the world has such a bug, and no one can find out about it?

Online search for a lap, it seems I worry about, long ago the user raised this question:

github.com/jquery/api.jquery.com/issues/1081

Per the spec, an offsetParent are defined as an element with a position which is non-static or is a table, th, or T D element. Since 3.3.0, position started using the native property offsetParent which started respected table, TH, and TD as offset parents, BU T the .offsetParent() method is left unchanged. We'll fix this in a upcoming release, but we'll need to note the special behavior for those 3 elements in the docs.

This is the answer given by the JQuery core development team to the effect that offsetParent this node attribute refers to a parent node:

1. Node is non-static, that is, has position:relative/absolute/fixed style

2. node is table, th or TD

Ha, after all these years, I actually heard the first time that OffsetParent has a relative to td,th,table, although this td,th,table node is position:static, use the code to verify:

$ (function() {    var tdposition = $ (' #theTD '). Position ();   var offsetParent = $ (' #theTD '). OffsetParent () [0].tagname;   var nativeoffsetparent = $ (' #theTD ') [0].offsetparent.tagname;    $ (' #result '). HTML (' top: ' + Tdposition.top + ' Left: ' + tdposition.left +            ' <br>offsetparent (): ' + OffsetParent +       ' <br>native offsetParent: ' + nativeoffsetparent);});

View the results separately in different browsers.

Chrome:

Firefox:

Edge:

IE11 (because IE11 cannot open the Jsfiddle site, we created a separate page):

Even IE9 is the same:

Well, it looks like I'm a know.

JQuery starts with the second case in v3.3.0, but the definition of jquery.offsetparent () does not change. This inconsistency itself is a bug.

Instead of being compatible with previous JQuery v1.x, v2.x and v3.3.0 versions, it should be a bug for a widely used public library, or at least a way to provide compatibility.

Consider another more realistic question: In practical applications, why should we get TD, Table position ()?

Not to get the value to update other TD or Table Top/left Properties!

Instead of the Top/left property of the other related div node, the position () of the DIV node is relative to the position:relative/absolute/fixed parent node, not the TD, Table node, This is bound to be a problem.

So, we still believe that this is a bug.

But the official jQuery does not seem to have fixed the problem, but it may change the definition of jquery.offsetparent () in future versions:

But jquery, are you doing this really well, it's been more than 10 years since you didn't obey the standard, suddenly a small version is called the Support standard, and the previous code is incompatible, you let the previous code sentiment why!

Anyway, we have our own solution.

Summary

This article describes a problem that we encountered in our Fineuipro product update, eventually locating the problem to the jquery.position () function, although jQuery is done in accordance with the HTML specification, but jquery.offsetparent () and Jquery.position () Two functions have a conflict, and will cause the previous jquery plugin error, it should be considered a bug.

Fortunately, this article gives a remedial method, if the method here can enlighten you or help, give a recommendation Bai.

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.