Jsdom: offsetWidth, offsetHeight, offsetTop, dan offsetLeft

Dibuat pada 1 Feb 2011  ·  32Komentar  ·  Sumber: jsdom/jsdom

Saya mencoba menerapkan penyaji sisi server untuk HighCharts. Semuanya tampak berfungsi dengan baik kecuali markup SVG yang dihasilkan tidak memiliki nilai x, y, lebar, dan tinggi di semua tempat. Melalui beberapa debugging, saya yakin saya telah menunjukkan masalah dengan fakta bahwa offsetWidth, offsetHeight, offsetTop dan offsetLeft semuanya tidak terdefinisi untuk setiap elemen.

Apakah properti ini dijadwalkan untuk disertakan dalam rilis mendatang? Juga, apakah ada solusi yang bisa saya terapkan saat ini?

css feature layout needs tests

Komentar yang paling membantu

Saya menggunakan cuplikan ini untuk dukungan, yang berfungsi untuk kasus saya. Perlu diingat itu jauh dari implementasi yang tepat. Perhatikan bahwa window harus menjadi document.parentWindow .

Jika Anda membutuhkan implementasi yang lebih baik, perluas kode menggunakan spesifikasi:
http://dev.w3.org/csswg/cssom-view/#dom -htmlelement-offsetleft

Object.defineProperties(window.HTMLElement.prototype, {
  offsetLeft: {
    get: function() { return parseFloat(window.getComputedStyle(this).marginLeft) || 0; }
  },
  offsetTop: {
    get: function() { return parseFloat(window.getComputedStyle(this).marginTop) || 0; }
  },
  offsetHeight: {
    get: function() { return parseFloat(window.getComputedStyle(this).height) || 0; }
  },
  offsetWidth: {
    get: function() { return parseFloat(window.getComputedStyle(this).width) || 0; }
  }
});

Semua 32 komentar

Saya pikir http://www.w3.org/TR/cssom-view/ , perlu diimplementasikan.

kami telah mulai mengintegrasikan cssom yang seharusnya menyelesaikan beberapa masalah SVG.

Memang akan sangat bagus jika kita dapat mengakses properti offset*, yang akan membutuhkannya untuk proyek yang berhubungan dengan kanvas.

Bagaimana perkembangan masalah ini? saya juga akan menghargai fitur seperti itu untuk rendering backend sag dengan Highcharts.

Saya juga ingin memiliki ini :)

Apakah kalian memiliki siklus cadangan untuk membantu? Secara pribadi saya tidak membutuhkan svg 1.1 tetapi saya akan bersedia membantu mendaratkannya jika kalian cukup bersemangat untuk mengerjakannya juga.

@tmpvar : Saya ingin membantu, tetapi saya cukup baru dalam hal-hal JS sisi server itu.
Mungkin Anda bisa memberi tahu saya di mana untuk memulai dan saya bisa mencoba yang terbaik untuk mendapatkan sesuatu :)

Saya juga sangat tertarik dengan SVG 1.1, untuk mengaktifkan grafik tinggi di server. Saya ingin menawarkan bantuan, tetapi pertama-tama saya perlu mengenal SVG 1.0 dan implementasinya saat ini di jsdom, yang mungkin memakan waktu cukup lama;)

Saya pikir langkah pertama di sini adalah mengambil salinan test suite ( http://www.w3.org/Graphics/SVG/WG/wiki/Test_Suite_Overview ) dan mengubahnya menjadi headless (yang mungkin cukup sulit)

Kemudian kita dapat menambahkan level2/svg.js dan mulai mengimplementasikannya.

Saya mungkin akan menyelesaikan ini pada akhirnya, tetapi ini tidak tinggi dalam daftar prioritas jsdom saya sekarang.

@href implementasi svg 1.0 cukup sederhana. Itu lulus tes di level1/core tetapi tidak benar-benar mengimplementasikan apa pun yang spesifik svg.

Saya pikir, getBoundingCLientRect tidak diimplementasikan dengan benar.

Saya memiliki kode ini untuk menghitung elemen svg tertentu:

var html = '<!DOCTYPE html><html><head><title></title></head><body style="margin: 0; padding: 0;"><svg id="svg" xmlns="http://www.w3.org/2000/svg" version="1.1" style="margin: 0; padding: 0;"><rect style="" x="10" y="10" width="100" height="100" rx="0" ry="0"/></svg></body></html>';

        jsdom.env({
            html : html,
            src: [jquery],
            done: function (errors, window) {
                var $ = window.$;
                var clientBox = $("#svg").find(type)[0].getBoundingClientRect();
                console.log(clientBox);
            }
        });

Dan hasilnya adalah:

{ bottom: 0, height: 0, left: 0, right: 0, top: 0, width: 0 }

Tapi, jika saya menguji html yang sama di browser web, hasilnya adalah ini:

{ bottom: 110, height: 100, left: 10, right: 110, top: 10, width: 100 }

@throrin19 : Baca sampai #653.

Jadi tidak mungkin tercapai? Sejauh ini saya berhasil melewati masalah ini melalui phantomJS tetapi sangat lambat dan jika saya memiliki SVG besar, itu macet.

Maksud saya, itu bukan tidak mungkin, tetapi kita harus menulis seluruh mesin tata letak, dan tidak ada yang punya waktu untuk melakukannya.

Saya sudah memikirkannya, tetapi kemudian otak saya kejang dan saya harus pergi.

Apakah ada tes di luar asam yang bisa diikuti?

+1 untuk menemukan ini fitur yang sangat diinginkan

Saya menggunakan cuplikan ini untuk dukungan, yang berfungsi untuk kasus saya. Perlu diingat itu jauh dari implementasi yang tepat. Perhatikan bahwa window harus menjadi document.parentWindow .

Jika Anda membutuhkan implementasi yang lebih baik, perluas kode menggunakan spesifikasi:
http://dev.w3.org/csswg/cssom-view/#dom -htmlelement-offsetleft

Object.defineProperties(window.HTMLElement.prototype, {
  offsetLeft: {
    get: function() { return parseFloat(window.getComputedStyle(this).marginLeft) || 0; }
  },
  offsetTop: {
    get: function() { return parseFloat(window.getComputedStyle(this).marginTop) || 0; }
  },
  offsetHeight: {
    get: function() { return parseFloat(window.getComputedStyle(this).height) || 0; }
  },
  offsetWidth: {
    get: function() { return parseFloat(window.getComputedStyle(this).width) || 0; }
  }
});

Adakah orang lain yang berhasil dengan apa yang disarankan tobyhinloopen?

@tobyhinloopen : Latar belakang grafik, sumbu, dan label saya muncul (walaupun miring) tetapi sisanya masih sangat kacau. Apakah Anda bisa mendapatkan grafik yang lengkap?

Saya memiliki kasus penggunaan yang berbeda di mana implementasi yang saya sarankan berfungsi. Jika tidak berhasil untuk Anda, perpanjang. Kemungkinan OffsetHeight/width juga harus menyertakan padding. Saya akan menyarankan beberapa perbaikan terbaru untuk membuatnya berfungsi, karena implementasi yang sempurna sulit untuk diterapkan.

Solusi yang diusulkan oleh @tobyhinloopen tampaknya baik-baik saja tetapi ketika saya menggunakannya saya mendapatkan "tidak dapat memperbaiki properti offsetLeft"

@zallek Saya pikir Anda sudah memiliki dukungan offsetLeft :) Apa window.HTMLElement.prototype.offsetLeft kembali? Jika itu tidak terdefinisi, solusi saya tidak akan berfungsi

Hanya ingin mengucapkan terima kasih @tobyhinloopen , solusi Anda sangat berguna bagi saya. :)

@tobyhinloopen Terima kasih banyak telah memposting solusinya! Ini sangat membantu dan berfungsi selama saya menggunakan variabel untuk mengatur nilai offset dan mengecualikan this . this keluar tidak terdefinisi, yang mana masuk akal mengingat konteksnya bukan kelas yang sebenarnya. Apakah itu yang Anda harapkan?

@jordantomax ini terikat ke elemen saat fungsi dipanggil, bukan saat fungsi didefinisikan. 'ini' harus menjadi elemen saat Anda memanggilnya dari elemen html mana pun.

Jika tidak, saya ingin melihat contoh.

@tobyhinloopen Terima kasih atas tanggapan cepatnya. Itulah yang saya harapkan. Ketika saya mencoba mereproduksi masalah saya di kode dan kotak menggunakan lingkungan browser nyata, itu berfungsi dengan benar. Tetapi ketika menggunakan lelucon, saya melihat this sebagai tidak terdefinisi. Saya membuat repo sampel kecil untuk menunjukkan kepada Anda apa yang saya alami, mungkin pengaturan saya salah.

https://github.com/jordantomax/jest-htmlelement-prototype-sandbox

Terkait, saya juga mengalami masalah saat mengganti metode seperti scrollIntoView menggunakan lelucon dan jsdom. Apakah ada cara yang disarankan untuk melakukannya?

Terima kasih banyak atas bantuan Anda!

Saya pikir itu karena Anda menggunakan get: () => {} - Sintaks fungsi () => {} mengacaukan this . Jika Anda menggunakan get() {} (disarankan) atau get: function() {} (alternatif), itu akan berfungsi. @jordantomax

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this

Anda juga menggunakan => di it / describe test suite Anda. Saya tidak tahu tentang JEST, tetapi di MOCHA tidak disarankan, karena this di it / test / describe memiliki semua jenis utilitas yang tidak dapat Anda akses jika Anda menggunakan fungsi panah. Misalnya, moka memiliki hal-hal seperti this.slow() , this.timeout(4000) dll.

https://mochajs.org/#arrow -functions

Terkait, saya juga mengalami masalah saat mengganti metode seperti scrollIntoView menggunakan lelucon dan jsdom. Apakah ada cara yang disarankan untuk melakukannya?

Biasanya ada beberapa jenis polyfill yang tersedia di MDN. Jika tidak, coba saja implementasikan berdasarkan spesifikasi dengan cara yang sesuai dengan kebutuhan Anda. Jika semuanya gagal, gunakan saja lingkungan pengujian yang berbeda. JSDom memiliki tempatnya, tetapi pada titik tertentu Anda mungkin ingin mempertimbangkan browser yang sebenarnya. Banyak lingkungan pengujian memungkinkan pengujian di browser nyata (bahkan beberapa pada saat yang sama) sementara juga melaporkan kembali secara realtime ke mesin pengembangan Anda. IIRC Karma melakukan ini -> https://karma-runner.github.io/latest/index.html

Saya telah membuka beberapa browser (firefox chrome safari internet explorer edge + yang seluler di simulator) sekaligus di mesin saya, dan semuanya melaporkan kembali secara realtime menggunakan Karma + Mocha.

@tobyhinloopen Benar, Anda ada di semua akun! Terima kasih!! Saya masih sedikit tidak jelas tentang mengapa getComputedStyle diperlukan, dan apakah mungkin untuk menulis setter dengan metode itu. Bagi saya ini sepertinya berhasil:

Object.defineProperties(window.HTMLElement.prototype, {
  offsetTop: {
    get () {
      return this.marginTop
    },
    set (offset) {
      this.marginTop = offset
    }
  }
})

Terima kasih kembali 🙏

@jordantomax getComputedStyle mengambil gaya yang dihitung sebenarnya untuk semua properti CSS, di mana pun itu diterapkan (stylesheet, atribut style atau dari JS). Saya tidak yakin apakah this.marginTop melakukan hal yang sama, tetapi saya kira begitu (tetapi jelas hanya untuk margin, tidak untuk semua alat peraga CSS)

@tobyhinloopen Ah, mengerti. Terima kasih!

Terima kasih @tobyhinloopen . Saya menggunakan versi yang lebih pendek. Saya pikir getComputedStyle tidak benar-benar diperlukan karena saya pribadi tidak pernah menambahkan css ke unit test saya kecuali inline, itulah sebabnya .style cukup baik dan lebih cepat.

Object.defineProperties(window.HTMLElement.prototype, {
  offsetLeft: {
    get () { return parseFloat(this.style.marginLeft) || 0 }
  },
  offsetTop: {
    get () { return parseFloat(this.style.marginTop) || 0 }
  },
  offsetHeight: {
    get () { return parseFloat(this.style.height) || 0 }
  },
  offsetWidth: {
    get () { return parseFloat(this.style.width) || 0 }
  }
})

Apakah ini sudah diperbaiki, saya mendapatkan offsetWidth = 0

   const dom = new JSDOM(`<!DOCTYPE html><body></body>`);
    let document = dom.window.document
    let span = document.createElement("span");
    span.innerHtml = 'test
    span.style.fontSize = 150 + 'px';
    span.style.fontFamily = 'Arial'
    document.body.appendChild(span)
    console.log(span.offsetWidth) // 0

Apakah ini sudah diperbaiki, saya mendapatkan offsetWidth = 0

@petran tidak realistis untuk mengharapkan jsdom menghitung lebar SPAN Anda, karena itu membutuhkan pengetahuan tentang ukuran font Anda dan semua properti CSS yang diwarisi. Saya tidak berpikir itu tujuan JSDOM. Jika Anda menginginkan simulasi browser yang lebih akurat, pertimbangkan untuk menggunakan browser yang sebenarnya.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat