ゆるめ

ゆるめなのは公開範囲です。

IE8 でチェックを反映させた印刷プレビューを表示する

うっかりプラスを継続させたままにしてしまいました。もったいないので今日調べたけど回答するまで至らなかった質問の事について書きます。

IE8での現象です。下記のラジオボタンをチェックしても、印刷プレビューにチェックがでてきません。 でも、最初のDOCTYPE を削除すると印刷プレビューにチェックがでてきます。この現象について、解説しているページの紹介お願いします。 http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">http://www.w3.org/1999/xhtml">1 2
IE 8 だとラジオボタンのチェックが印刷プレビューに反映されないらしいです。

IE8 モードだと HTML の checked が移動しない

とりあえず以下のような HTML を書いて、ちまちまいじくってリアクションを見てみました。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="ja">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="Content-Style-Type" content="text/css">
    <meta http-equiv="Content-Script-Type" content="text/javascript">
    <meta http-equiv="X-UA-Compatible" content="IE=8">
    <title>ラジオボタンのチェック具合テスト</title>
  </head>
  <body>
    <form action="#">
      <p>
        <label><input type="radio" name="chk0" value="1">1</label>
        <label><input type="radio" name="chk0" value="2" checked>2</label>
      </p>
    </form>
    <script type="text/javascript">

// ここに色々書いて調べてた

    </script>
  </body>
</html>

確かに「1」の方にラジオボタンのチェックを移しても、プレビューでは初期状態の「2」の方にチェックされていました。ラジオボタンの他、チェックボックスでも同じように初期状態でプレビューされました。

X-UA-Compatible を IE=7 にしたらチェックが反映されるようになったので、IE8 になってからあえてそうするようにしたというところまでは予測できました。

htmlinputelementObject.checked

boolean

要素の type 属性が値 "radio" または "checkbox" であるとき, これはインタラクティブなユーザーエージェントにおけるフォームコントロールの現在の状態を現す。このプロパティの変更はフォームコントロールの状態を変更するが、 HTML の INPUT 要素の checked 属性の値は変更しない。

This Document has Moved

多分この辺の標準に従ったのではないかと踏んでいます。*1
X-UA-Compatible を IE=7 にして、「1」の方をチェックした後、ラジオボタンの outerHTML を表示したら、以下のようになりました。

<INPUT value=1 CHECKED type=radio name=chk0>

初期状態では付いていなかった checked 属性が付きました。
そして、X-UA-Compatible を IE=8 に戻して、同じように「1」の方をチェックした後、ラジオボタンの outerHTML を表示したら、以下のようになりました。

<INPUT value=1 type=radio name=chk0>

checked 属性は付きませんでした。多分 HTML の INPUT 要素の checked 属性の値は変更しないようにしたのだと思います。ちなみに Fx とか Chrome もこんな感じの checked 属性が付かない HTML を保持していました。
ためしに setAttribute や removeAttribute で checked 属性を付けたり取っ払ったりしてみたら、印刷プレビューにも反映されるようになりました。

"checked" コンテンツ属性に関する解析操作は、常に"checked" および "defaultChecked" DOM 属性に影響を与えます。 ( たとえば、removeAttribute('checked') にすると、"checked" と "defaultChecked" は false に設定され、setAttribute('checked', 'checked') に設定すると、両方の DOM 属性が true に設定されます。

2008/4/10 - IE8 Beta 1 における HTML 標準および DOM 標準準拠

と公式サイトで書かれているので、多分仕様通りなのだと思います。

多分 IEJavaScript で取れる HTML と同じものを印刷に使っている

IE8 に限らず IE は innerHTML とか outerHTML で取れる HTML を、多分そのまま印刷に使い回しています。印刷プレビューが崩れている様子*2を見る限り、基本的に innerHTML にクォートが付かないみたいなので、そういう推測に至りました。

二つの原因からくるあわせ技

そんな訳で、IE8 はチェックしても checked 属性が移動しない内部 HTML を印刷に使っているので、ラジオボタンのチェックが初期値のままになるのではないかと思います。
他のブラウザではどういう風に印刷用の HTML を保持しているのかは分かりませんでしたが、チェックはしっかり反映されていたので、少なくとも JavaScript で取れる HTML そのままではないのだと思います。

姑息な対処法

以下のような JavaScript を書いておけば、とりあえず印刷にチェックが反映されるようになります。思想的にやって良いことなのかどうかは分かりません。

if (document.documentMode > 7 && window.attachEvent)
 window.attachEvent("onbeforeprint", function() {

	var inputs = document.getElementsByTagName("input");
	for (var i = 0; i < inputs.length; i++)
	 if (/^(radio|checkbox)$/i.test(inputs[i].type))
	 inputs[i].defaultChecked = inputs[i].checked;

});

ちなみに select (option) 要素は黙ってても印刷に選んだものが反映されていました。selected 属性も HTML 内で移動しまくってました。

私のできることはここまで

とりあえず自分の中ではもういいやおなかいっぱいと思える程度に調べて、結論と対処法も出たのですが、どこもかしこも「多分」ばっかりなのと、肝心の解説しているページが見つからなかったので、答えるまでには至りませんでした。
この日記を見て下さった方で、これ詳しく知ってる!と思い当たった方は、この日記のコメント欄ではなく、元質問の方に答えた方が、割とみんながハッピーになれると思います。

*1:英語がさらっと読める方は原文をどうぞ。私はさらっと読めないので、邦訳の方を引用しました。

*2:本題は違う記事です