Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

The zoom property of css changed by brower/W3C and JqueryUI component is affected #2292

Open
wesoft2020 opened this issue Sep 11, 2024 · 13 comments

Comments

@wesoft2020
Copy link

wesoft2020 commented Sep 11, 2024

Description

Steps to reproduce the problem

testJquery.zip
1.write the code like "document.body.style.zoom=1.2" in javascript.
2.create a date component of jqueryUI like $( "#datepicker" ).datepicker({});
3.open the html and focus in the date component, the popup is Misplaced
image

Cause estimation

https://drafts.csswg.org/css-viewport/#zoom-om
The W3C standard for the Zoom attribute has been changed so that the getBoundingClientRect, getClientRects, and IntersectionObserver APIs return rects with scaled lengths by browser, which returned rects with unscaled lengths before.
So the offset() method developed on getBoundingClientRect also changed, return rects with scaled lengths now.

Please let us know will jquery or jqueryUI Do some correspondence.
We did this temporarily.
var originalOffset = $.fn.offset;
$.fn.offset = function() {

var originalResult = originalOffset.apply(this, arguments);
originalResult.top = originalResult.top / document.body.style.zoom;
originalResult.left = originalResult.left / document.body.style.zoom;
return originalResult;

@mgol mgol transferred this issue from jquery/jquery Sep 13, 2024
@mgol
Copy link
Member

mgol commented Sep 13, 2024

I moved the issue to the jQuery UI repo as that's where jQuery UI issues should be reported.

Thanks for the report. Does the issue you describe exist when jQuery UI 1.12.1 is used or only with jQuery UI 1.13.0 or newer?

@mgol
Copy link
Member

mgol commented Sep 13, 2024

OK, I checked myself in the template, it's reproducible in jQuery UI 1.12.1 as well.

Since the issue is already in 1.12, given limited team resources it's not likely to be fixed by the UI team; see the project status at https://blog.jqueryui.com/2021/10/jquery-maintainers-update-and-transition-jquery-ui-as-part-of-overall-modernization-efforts/. PRs are welcome if they're not too complex and contain tests.

@wesoft2020
Copy link
Author

Thank you very much for your response! However, this issue isn't confined to the datetimepicker; other jQuery UI controls like autocomplete also exhibit similar problems. Additionally, other UI frameworks built on jQuery, such as jQuery Bootstrap Datetimepicker JA, face the same issue.

The root cause appears to be the use of jQuery's offset() method. The coordinates returned by this method now include zoom attributes in the latest browsers, which wasn't previously the case.

Therefore, I believe the problem doesn't lie with the UI framework itself but with the jQuery offset() method. I suggest we move away from using getBoundingClientRect() for HTML controls and instead use the offsetTop attribute. We have temporarily corrected this in our web application.

I welcome further discussion on this approach.

@mgol
Copy link
Member

mgol commented Sep 13, 2024

@wesoft2020 can you prepare an isolated test case that just uses jQuery, without jQuery UI or other libraries? Then it will be clearer what the issue with jQuery is and we’ll be able to open a new jQuery issue about it.

@markvantilburg
Copy link
Contributor

When i zoom the browser with ctrl-scroll it works fine. But the javascript zoom does something strange.

I created this fiddle: https://jsfiddle.net/geovd7L6/

@wesoft2020
Copy link
Author

wesoft2020 commented Sep 17, 2024

@mgol I created a page that displays the offset length using jQuery and the browser. The browser has updated its API for the W3C zoom property, while jQuery continues to use the same API as before, I think.
OffsetLengthTest.zip

Install old chrome version:
npx @puppeteer/browsers install chrome@127
https://developer.chrome.com/blog/chrome-for-testing?hl=ja

@markvantilburg Thanks for the discussion! This issue is only affected by the Computed Style APIs, so the browser's zoom works fine.

@jacekzwroclawia
Copy link

jacekzwroclawia commented Sep 25, 2024

I'm really happy that I'm not the only one facing this issue. A lot of libraries using jQuery like Primeface facing the same problem. We need to disable zoom completely in our application waiting for some solutions. So how do you see next steps with that issue? Implementation of offset() is going to be changed in jQuery?
image

@wesoft2020
Copy link
Author

wesoft2020 commented Sep 26, 2024

@jacekzwroclawia
Thank you for your comment.
We can't disable the zoom in our application, so for now we're overwriting the offset method in Jquery like this and it works fine,I hope this helps.

var isNewRectAPI = false; // for old browser versions
var originalOffset = $.fn.offset;
$.fn.offset = function() {
var originalResult = originalOffset.apply(this, arguments);
// TR excluded for bootstrap data-reorderable-rows which works fine in latest chrome.
if($(this).prop("tagName") == "TR" || !isNewRectAPI) {
return originalResult;
}
originalResult.top = originalResult.top / document.body.style.zoom;
originalResult.left = originalResult.left / document.body.style.zoom;
return originalResult;
}

// Set isNewRectAPI based on a specific value, not according to multiple browser versions.
var originTop = $("#some element whose position is held").prop("offsetTop");
var boundingClientRectTop = document.getElementById("#some element whose position is held").getBoundingClientRect().top;
isNewRectAPI = Math.abs(originTop - boundingClientRectTop) > Math.abs(originTop*document.body.style.zoom - boundingClientRectTop)

@mgol
Copy link
Member

mgol commented Sep 26, 2024

I submitted a jQuery issue based on the discussion above: jquery/jquery#5561.

@DanielP1976
Copy link

DanielP1976 commented Nov 1, 2024

you can fix the code in jquery.min.js / jquery.js
something like this:

offset: function (t)
{
if (arguments.length) return void 0 === t ? this : this.each(function (e) { S.offset.setOffset(this, t, e) });
var e, n, r = this[0];

var zoom = 1;
var isChromium = !!window.chrome;
var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
var isEdgeChromium = isChrome && (navigator.userAgent.indexOf("Edg") != -1);                
if (isChromium || isChrome || isEdgeChromium)
{
    var chromeVersion = /Chrome\/([0-9.]+)/.exec(navigator.userAgent)[1];
    if (chromeVersion >= "128.0.0.0")
     {                        
           if (document.body.style.zoom.indexOf('%') >= 0) {
              zoom = parseFloat(document.body.style.zoom) / 100;
           }
           else {
             zoom = document.body.style.zoom;
           }
 }

}
return r ? r.getClientRects().length ? (e = r.getBoundingClientRect(), n = r.ownerDocument.defaultView, { top: (e.top + n.pageYOffset) / zoom, left: (e.left + n.pageXOffset) / zoom }) : { top: 0, left: 0 } : void 0
},

@bit-mschwingenschloegl
Copy link

Based on the comments of @wesoft2020 and @DanielP1976 I created a workaround for this error. (Because I needed a short-term solution for my project) Maybe it will also help others until the adjustment is officially available.

//Workaround JQuery Issue 2292
//https://github.com/jquery/jquery-ui/issues/2292
$.fn.offset = (function (_super) {
  return function () {
    // Call base function
    var originalResult = _super.apply(this, arguments);
    //Define default value
    var zoom = 1;
    try {
      //Use `currentCSSZoom` of HTML element
      //https://caniuse.com/?search=currentCSSZoom
      //https://developer.mozilla.org/de/docs/Web/API/Element/currentCSSZoom
      if (this && this[0] && this[0].currentCSSZoom) {
        zoom = this[0].currentCSSZoom;
      }
    } catch {
      //Fallback for unexpected errors
      zoom = 1;
    }
    //Modify result
    originalResult.top = originalResult.top / zoom;
    originalResult.left = originalResult.left / zoom;
    //Return result
    return originalResult;
  };
})($.fn.offset);

@TheWitness
Copy link

Is there a plan to merge this? I've been noting this warning as well.

@bit-mschwingenschloegl
Copy link

bit-mschwingenschloegl commented Nov 14, 2024

Is there a plan to merge this? I've been noting this warning as well.

It is only a workaround (redefinition) which cannot be merged as it does not modify the original JQuery source. The code can be simply added as a separate JavaScript file after the include of JQuery.

# for free to join this conversation on GitHub. Already have an account? # to comment
Development

No branches or pull requests

7 participants