2009年8月18日火曜日

COLSPAN属性およびROWSPAN属性とIE

引き続きInternetExplorerのDOM実装と格闘していて気がついたこと。

■COLSPANとROWSPANは静的な値である?

jQueryが、IE6やIE7において、内部的にどのようにこの2つの属性を読み書きしているのかはわからないが、
( {jQuery} tdElement ).attr( 'colspan', {Number} colspanValue )
( {jQuery} tdElement ).attr( 'rowspan', {Number} rowspanValue )

という呼び出しで、DOMのTD要素に両属性を書き込みしても、ブラウザの画面内で表示されているTD要素にその効果──すなわち複数のセルを結合した大セルの表示と、それにともなう右隣、下隣のセルの適切な位置への移動──は行われない。

FirfoxやOpera、Safariで同じことをすれば、セルのサイズが変更される。つまり両属性を書き込んだ時点でそのTD要素を内包するTABLE要素の再レンダリングが行われて、前述の「効果」が現れる。(「効果」によって右や下方に押し出されてしまう余分なセルは削除すれば、きれいなテーブルになる)。

IEでは──すくなくともjQuery1.3.2を使用している場合──このような親切は期待できない。上記のattrメソッドで属性を書き込んだあと、TABLE要素に対して、

({jQuery} tableElement).html( ({jQuery} tableElement).html() )

などとすこしばかばかしい処理(TABLE要素内のHTMLソースコードを取り出して、それをそのまままた元のTABLE要素内に注入する)をして、手動でTABLEの再レンダリングを引き起こす必要がある。

※TABLE要素内の要素にイベントリスナなど後天的・動的に付加された情報がある場合、それらの情報は上記の処理では棄却されてしまう。これを回避するにはもっと面倒な処理を行う必要がある。

■COLSPANとROWSPANは別待遇

これはFirefoxでもそうなのだが、COLSPANとROWSPANはブラウザ内部では値の扱い方が違うらしい。FirefoxではCOLSPANやROWSPANが指定されていない要素に対して、たとえば
var td = $('<td></td>');
td.attr('colspan'); // undefined を返す
td.attr('rospan'); // 1 を返す
とattrメソッドを呼び出した場合、二つの属性で返される値が異なる。
これは標準と照らしてどうなのかわからないが、わかりづらい動作であることは確かであろうと思う。

IEではこれがさらに怪しげになる。

"colSpan"属性や"rowSpan"属性(なぜかSが大文字)が存在する。どういうときにこれらの属性値が出現するのかわからない。たぶん、
td.attr('colspan', {Number} colspanValue);
td.attr('rowspan', {Number} rowspanValue);
などとすると、(TABLE要素のinnerHTMLプロパティなどにアクセスするとわかるのだが)、TD要素に、この謎の属性が出現する。そしてなぜかこの謎の属性のほうが、"colspan"や"rowspan"(もちろんすべて小文字!)よりも効果が優先される。仕方なく、
if($.browser.msie){
td.attr('colSpan', {Number} colspanValue);
td.attr('rowSpan', {Number} rowspanValue);
}
などとすると、うまくいく。($.browserつまりjQuery.browserオブジェクトは、jQuery1.3ではすでにサポート対象外宣告を受けているのだけど、こうしてしばしば立派に活躍していることを考えると、なぜサポート対象外?と疑問を感じる)

■そもそもIEでは、"colSpan"や"rowSpan"は存在しても、"colspan"や"rowspan"は存在しない?

さらに恐ろしいのは、IEで
td.removeAttr('colspan');
td.removeAttr('rowspan');

などとすると、エラーでJavaScriptの実行が停止してしまうこと。
おそらく「そんな名前の属性は存在しません」とでも訴えているのである。これにはかなりムカっとくる。

0 件のコメント: