A Day in the Life

要素の横幅が0の時、再計算させてちゃんとした値を入れる

要素の横幅が0の時、再計算させてちゃんとした値を入れる

ちゃんと HTML に要素は描画されてるはずなんだけど、offsetWidth や getBoundingClientRect で取得した横幅が0の時があってなんで??って地味にはまりまくった。具体的には capybara-webkit だと基本的に 0 で値がとれるため死ねます。capybara-webkit は headless browser で実際にはレンダリングしてないため要素のサイズ計算が行われないからなのかなぁ。

ただ jQuery ではうまく取れるのでコード読んだら、offsetWidth が 0 の場合は一時的に style を変更してそのタイミングで offsetWidth を一度叩いて reflow させてるぽくてちゃんととれてた。一度描画(計算)させちゃえば、その後 DOM からきちんと扱えるようになるっぽいのでそれを jQuery 使わずやるには以下の感じのコードで。

var reflow = function(element, force) {
      if (force || element.offsetWidth === 0) {
        var prop, oldStyle = {}, newStyle = {position: "absolute", visibility : "hidden", display: "block" };
        for (prop in newStyle)  {
          oldStyle[prop] = element.style[prop];
          element.style[prop] = newStyle[prop];
        }
        element.offsetWidth, element.offsetHeight; // force reflow
        for (prop in oldStyle)
          element.style[prop] = oldStyle[prop];
      }
    };

ニッチな嵌り方だけど全然情報無かったので誰かのためになれば。

そうえばそろそろ capybara-webkit 良い感じになってきてる。utf8 な文字列がうまく扱えない問題もパッチ書いたので pull request 取り込まれてちゃんと使えるようになったし、selenium 以外の driver じゃ pass してないと思われる javascript driver のテストも pass しました。こっちも pull request が取り込まれたら反映されると思う。

なので Rack で JS コミのエンドツーエンドテストしてる人はそろそろ capybara-webkit 使い出しても良い頃じゃないかなぁ。