Jsdom: `element.getBoundingClientRect` рдФрд░ `element.getClientRects` рд▓рд╛рдЧреВ рдХрд░реЗрдВ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 5 рдЬреБрд▓ре░ 2013  ┬╖  18рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: jsdom/jsdom

#61 рдФрд░ #135 рд╕реЗ рд╕рдВрдмрдВрдзрд┐рддред

рдЙрди рдореБрджреНрджреЛрдВ рдкрд░ рдЕрдм рддрдХ рдЪрд░реНрдЪрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рд╕реЛрдЪрд╛ рдХрд┐ рдореИрдВ рдЗрд╕реЗ рд╡рд╣рд╛рдВ рдлреЗрдВрдХ рджреВрдВрдЧрд╛ред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рддрддреНрд╡реЛрдВ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдкреНрд░рддрд┐ рдЙрджрд╛рд╣рд░рдг рдУрд╡рд░рд░рд╛рдЗрдб рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЙрджрд╛рд╣рд░рдг:

function createMockDiv (width, height) {
  const div = document.createElement("div");
  Object.assign(div.style, {
    width: width+"px",
    height: height+"px",
  });
  // we have to mock this for jsdom.
  div.getBoundingClientRect = () => ({
    width,
    height,
    top: 0,
    left: 0,
    right: width,
    bottom: height,
  });
  return div;
}

рд╕рднреА 18 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ getBoundingClientRect рдХреЛ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдбрдореА рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд▓реМрдЯрд╛рддрд╛ рд╣реИред

рдпрд╣ рдЙрдЪрд┐рдд рд▓рдЧрддрд╛ рд╣реИ; рд╕рдм рдХреБрдЫ рдФрд░ рд╡рд╣ рд╕рдм рдХреЗ рд▓рд┐рдП рд╢реВрдиреНрдпред рдкреИрдЪ рд╕реНрд╡рд╛рдЧрдд рд╣реИред

рдзрдиреНрдпрд╡рд╛рдж, @F1LT3R рдФрд░ @domenic! (рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕ рдмреАрдЪ, рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдиреЛрдбреБрдирд┐рдЯ рд╕реЗ рдЙрдкрдпреБрдХреНрдд рд╡реЗрдм-рдЖрдзрд╛рд░рд┐рдд рдврд╛рдВрдЪреЗ рдореЗрдВ рдкреЛрд░реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝ рдЪреБрдХрд╛ рд╣реВрдВ: рдХреНрд╡рд┐рдирд┐рдЯ)ред :+1:

рдХреНрдпрд╛ getClientRects jsdom рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ? рдЗрд╕ jQuery рдЯрд┐рдХрдЯ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдпрд╣ рдирд╣реАрдВ рд╣реИ

getClientRects рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИ, рдХреЗрд╡рд▓ getBoundingClientRect рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред рдПрдХ рдкреАрдЖрд░ getClientRects() рдЬреЛ рд╣рдореЗрд╢рд╛ рдПрдХ рдЦрд╛рд▓реА рд╕рд░рдгреА рджреЗрддрд╛ рд╣реИ (рдпрд╛ рд╢рд╛рдпрдж рдЕрдкрдиреЗ рд╕рднреА рдореВрд▓реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╢реВрдиреНрдп рдХреЗ рд╕рд╛рде рдПрдХ рд░реЗрдХреНрдЯ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд░рдгреА ??) рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред

рд╣рд╛рдБ jQuery 1.12.0 getClientRects рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрднреА рдЕрдкрдиреЗ рдореВрд▓ рд╕реНрдЯрд╛рдЗрд▓ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рд╣реИред рд╣рдо рдПрдХ рд╣реА рдореБрджреНрджреЗ рдореЗрдВ рднрд╛рдЧреЗред рдореИрдВ рдЗрд╕реЗ рд╕реЛрдорд╡рд╛рд░ рдХреЛ рдЬреЛрдбрд╝рдХрд░ рдПрдХ рдкреАрдЖрд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛ рд╕рдХрддрд╛ рд╣реВрдВред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ .height() рдлрд╝рдВрдХреНрд╢рди рдерд╛ рдЬреЛ рдЕрдм рдлреЗрдВрдХ рд░рд╣рд╛ рд╣реИред

рдореИрдВ el.getBoundingClientRect() рд╕реЗ рд╕рд╣реА рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реВрдВред рд▓реМрдЯрд╛рдИ рдЧрдИ рд╡рд╕реНрддреБ рдореЗрдВ рд╕рднреА рд╕рд╣реА рдХреБрдВрдЬрд┐рдпрд╛рдВ (рдКрдВрдЪрд╛рдИ, рдЪреМрдбрд╝рд╛рдИ, рд╢реАрд░реНрд╖, рдЖрджрд┐) рд╣реЛрддреА рд╣реИрдВ, рд▓реЗрдХрд┐рди рдкреНрд░рддреНрдпреЗрдХ рдорд╛рди рд╣рдореЗрд╢рд╛ 0 рд╣реЛрддрд╛ рд╣реИред рдореБрдЭреЗ рдпрд╣ рдЬрд╛рдирдиреЗ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ рдФрд░ рдЗрд╕рдХрд╛ рдЕрдиреБрднрд╡ рдХрд░ рд░рд╣рд╛ рд╣реИред

рдпрд╣ рд╣рдореЗрд╢рд╛ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ:

    it('getBoundingClientRect produces correct height', () => {
      container.style.height = '300px'
      expect(container.getBoundingClientRect().height).eql(300)
    })

рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрд░рд╛ рд╕рдорд╛рдзрд╛рди (рдЬреЛ рдПрдХ рдРрд╕рд╛ рд╡рд╛рдХреНрдпрд╛рдВрд╢ рд╣реИ рдЬреЛ рдореБрдЭреЗ рдХрд╣рдиреЗ рдХреЗ рд▓рд┐рдП рдкреАрдбрд╝рд╛ рджреЗрддрд╛ рд╣реИ) рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╣реИ:

getComputedElHeight(el) {
    return Number(window.getComputedStyle(el).height.split('px')[0])
  }

рдореИрдВрдиреЗ рд╕реЛрдЪрд╛ рдерд╛ рдХрд┐ рдЬрдм рддрдХ рдпрд╣ рдореБрджреНрджрд╛ рдЦреБрд▓рд╛ рд░рд╣реЗрдЧрд╛, рдореИрдВ рдЗрд╕реЗ рд╕рд╛рдЭрд╛ рдХрд░реВрдВрдЧрд╛ред

рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдЗрд╕реЗ рд╕рд╣реА рдореВрд▓реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдерд╛
рдХреЗрд╡рд▓ рд╕рд╣реА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ред
рдорд╛рд░реНрдЪ 14, рд╡рд░реНрд╖ 2016 9:02 рдмрдЬреЗ, "lushfuture" [email protected] рд▓рд┐рдЦрд╛ рд╣реИ:

рдореИрдВ рд╕реЗ рд╕рд╣реА рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реВрдБ
el.getBoundingClientRect ()ред рдЬреЛ рд╡рд╕реНрддреБ рд╡рд╛рдкрд╕ рдорд┐рд▓рддреА рд╣реИ, рдЙрд╕рдореЗрдВ рд╕рдм рдХреБрдЫ рд╣реЛрддрд╛ рд╣реИ
рд╕рд╣реА рдХреБрдВрдЬрд┐рдпрд╛рдБ (рдКрдБрдЪрд╛рдИ, рдЪреМрдбрд╝рд╛рдИ, рдКрдкрд░, рдЖрджрд┐) рд▓реЗрдХрд┐рди рд╣рд░ рдорд╛рди рд╣рдореЗрд╢рд╛ 0 рд╣реЛрддрд╛ рд╣реИред рдореИрдВ рд╣реВрдБ
рдпрд╣ рдЬрд╛рдирдиреЗ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИ рдХрд┐ рдХреЛрдИ рдФрд░ рдЗрд╕рдХрд╛ рдЕрдиреБрднрд╡ рдХрд░ рд░рд╣рд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред

рдпрд╣ рд╣рдореЗрд╢рд╛ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ:

it('getBoundingClientRect produces correct height', () => {
  container.style.height = '300px'
  expect(container.getBoundingClientRect().height).eql(300)
})

рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрд░рд╛ рд╕рдорд╛рдзрд╛рди (рдЬреЛ рдПрдХ рдРрд╕рд╛ рд╡рд╛рдХреНрдпрд╛рдВрд╢ рд╣реИ рдЬреЛ рдореБрдЭреЗ рдкреАрдбрд╝рд╛ рджреЗрддрд╛ рд╣реИ
рдХрд╣рддреЗ рд╣реИрдВ) рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╣реИ:

getComputedElHeight (рдПрд▓) {
рд╡рд╛рдкрд╕реА рд╕рдВрдЦреНрдпрд╛ (window.getComputedStyle(el).height.split('px')[0])
}

рдореИрдВрдиреЗ рд╕реЛрдЪрд╛ рдерд╛ рдХрд┐ рдЬрдм рддрдХ рдпрд╣ рдореБрджреНрджрд╛ рдЦреБрд▓рд╛ рд░рд╣реЗрдЧрд╛, рдореИрдВ рдЗрд╕реЗ рд╕рд╛рдЭрд╛ рдХрд░реВрдВрдЧрд╛ред

-
рдЗрд╕ рдИрдореЗрд▓ рдХрд╛ рд╕реАрдзреЗ рдЙрддреНрддрд░ рджреЗрдВ рдпрд╛ рдЗрд╕реЗ GitHub рдкрд░ рджреЗрдЦреЗрдВ
https://github.com/tmpvar/jsdom/issues/653#issuecomment -196300151ред

рд╣рд╛рдВ, рдЗрд╕реЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдореВрд▓реНрдпреЛрдВ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдПрдХ рд╕рдВрдкреВрд░реНрдг рд▓реЗрдЖрдЙрдЯ рдЗрдВрдЬрди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдЬреЛ рдПрдХ рдмрдбрд╝рд╛ рдЙрдкрдХреНрд░рдо рд╣реЛрдЧрд╛ред рдЕрдВрдХ #1322 рдЙрд╕ рд╡рд┐рд╖рдп рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рддрд╛ рд╣реИред

рдХреНрдпрд╛ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдЙрд╕ рд╡рд┐рдзрд┐ (рд╕рднреА рддрддреНрд╡реЛрдВ рдХреЗ рд▓рд┐рдП) рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ рддрд╛рдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╕рдордп рдкреНрд░рдпреЛрдЧ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рд╣реЛ рд╕рдХреЗ?

рд╣рд╛рдБ, рдареАрдХ рдЙрд╕реА рддрд░рд╣ рдЬреИрд╕реЗ рдЖрдк рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдХрд░рддреЗ рд╣реИрдВ: Element.prototype.getBoundingClientRect = function () { ... }

рдореИрдВрдиреЗ рдХрд░рдирд╛ рд╕рдорд╛рдкреНрдд рдХрд░ рджрд┐рдпрд╛
рд╡рд┐рдВрдбреЛ._рдХреЛрд░. HTMLDivElement.prototype.getBoundingClientRect

рдЬреЛ рдареАрдХ рдХрд╛рдо рдХрд┐рдпрд╛ред

рдпрд╣ jsdom рдХреЗ рднрд╡рд┐рд╖реНрдп рдХреЗ рд░рд┐рд▓реАрдЬ рдореЗрдВ рдЯреВрдЯ рдЬрд╛рдПрдЧрд╛ (рдмрд╣реБрдд рдЬрд▓реНрдж, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ)ред рдмрд╕ ._core рд╣рдЯрд╛ рджреЗрдВред

рдзрдиреНрдпрд╡рд╛рдж рдореИрдВ рдХреЛрд╢рд┐рд╢ рдХрд░реВрдБрдЧрд╛ рдХрд┐
2 рд╕рд┐рддрдВрдмрд░ 2016 рдХреЛ рд░рд╛рдд 9:03 рдмрдЬреЗ, "рдбреЛрдореЗрдирд┐рдХ рдбреЗрдирд┐рдХреЛрд▓рд╛" рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди @github.com рдиреЗ рд▓рд┐рдЦрд╛:

рдпрд╣ jsdom рдХреЗ рднрд╡рд┐рд╖реНрдп рдХреЗ рд░рд┐рд▓реАрдЬ рдореЗрдВ рдЯреВрдЯ рдЬрд╛рдПрдЧрд╛ (рдмрд╣реБрдд рдЬрд▓реНрдж, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ)ред рдЕрднреА - рдЕрднреА
_рдХреЛрд░ рдХреЛ рд╣рдЯрд╛ рджреЗрдВред

-
рдЖрдк рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдиреЗ рдЯрд┐рдкреНрдкрдгреА рдХреА рдереАред
рдЗрд╕ рдИрдореЗрд▓ рдХрд╛ рд╕реАрдзреЗ рдЙрддреНрддрд░ рджреЗрдВ, рдЗрд╕реЗ GitHub рдкрд░ рджреЗрдЦреЗрдВ
https://github.com/tmpvar/jsdom/issues/653#issuecomment -244520584, рдпрд╛ рдореНрдпреВрдЯ рдХрд░реЗрдВ
рд╕реВрддреНрд░
https://github.com/notifications/unsubscribe-auth/AEtD9luz1uJWmJ3JlgdwuO1i5MP04_BXks5qmNWCgaJpZM4Ayv3U
.

рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рддрддреНрд╡реЛрдВ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдкреНрд░рддрд┐ рдЙрджрд╛рд╣рд░рдг рдУрд╡рд░рд░рд╛рдЗрдб рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЙрджрд╛рд╣рд░рдг:

function createMockDiv (width, height) {
  const div = document.createElement("div");
  Object.assign(div.style, {
    width: width+"px",
    height: height+"px",
  });
  // we have to mock this for jsdom.
  div.getBoundingClientRect = () => ({
    width,
    height,
    top: 0,
    left: 0,
    right: width,
    bottom: height,
  });
  return div;
}

рдХрд░реНрдо рдХреЛрдб рдХреИрд╕реЗ рд▓рд┐рдЦреЗрдВ рдпрджрд┐ getboundingclientrect() рд╡рд┐рдзрд┐ ts рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЕрдиреНрдп рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реИред
рдХреНрдпрд╛ рдХреЛрдИ рдХреГрдкрдпрд╛ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИред

window.HTMLElement.prototype.getBoundingClientRect = function () {
  return {
    width: parseFloat(this.style.width) || 0,
    height: parseFloat(this.style.height) || 0,
    top: parseFloat(this.style.marginTop) || 0,
    left: parseFloat(this.style.marginLeft) || 0
  }
}

рдФрд░ рдпрд╣ рднреА рдСрдлрд╕реЗрдЯ рдХреЗ рд▓рд┐рдП

Object.defineProperties(window.HTMLElement.prototype, {
  offsetWidth: {
    get () { return parseFloat(this.style.width) || 0 }
  },
  offsetHeight: {
    get () { return parseFloat(this.style.height) || 0 }
  },
  offsetTop: {
    get () { return parseFloat(this.style.marginTop) || 0 }
  },
  offsetLeft: {
    get () { return parseFloat(this.style.marginLeft) || 0 }
  }
})
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

philipwalton picture philipwalton  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Progyan1997 picture Progyan1997  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

eszthoff picture eszthoff  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

domenic picture domenic  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

jhegedus42 picture jhegedus42  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ