いろいろためしたけど、以下が一番楽
// 変更 element.runtimeStyle.cssText = ' width: 100%; height: 100%'; // 戻す element.runtimeStyle.cssText = '';
// 変更 element.runtimeStyle.cssText = ' width: 100%; height: 100%'; // 戻す element.runtimeStyle.cssText = '';
element.uniqueID
というのがある。
これは、要素に固有の番号を付けたものだ。
これが結構便利で、
var seen = {}; for (var i = 0; i < elemenets.length; i ++) { if (seen[elements[i].uniqueID]) elements.splice(i, 1); else seen[elements[i].uniqueID] = true; }
みたいな感じで、使うことができる。
他のブラウザにはこれがないので、結構不便。
で、 getter で出来るじゃんって思ってググってみたら。
Dean Edwards さんがもう作ってた。さすが
http://dean.edwards.name/moz-behaviors/src/
HTMLElement.prototype.__defineGetter__("uniqueID", function() { // a global counter is stored privately as a property of this getter function. // initialise the counter if (!arguments.callee.count) arguments.callee.count = 0; // create the id and increment the counter var $uniqueID = "moz_id" + arguments.callee.count++; // creating a unique id, creates a global reference window[$uniqueID] = this; // we don't want to increment next time, so redefine the getter this.__defineGetter__("uniqueID", function(){return $uniqueID}); return $uniqueID; });
ちょっとだけ自分用にカスタマイズ
(function() { var nextUniqueID = 1; HTMLElement.prototype.__defineGetter__('uniqueID', function() { var uniqueID = 'id' + nextUniqueID++ this.__defineGetter__("uniqueID", function(){return uniqueID}); return uniqueID; }); })();
↑ id:javascripter さんの指摘で直しました><ありがとうございます><
(Dean Edwards)++
以下の方法で判定することができるようです。
// リクエストオブジェクトを作る var req = new ActiveXObject('Microsoft.XMLHTTP'); // フラグの準備 var sended = false; // readystatechange イベントを待つ req.onreadystatechange = function() { if (req.readyState == 4) { // キャッシュに存在しない場合 if (sended) { alert('loaded'); } // キャッシュに存在する場合 else { alert('cached'); } } }; // 通信開始 req.open('GET', 'hoge'); req.send(); // フラグを立てる sended = true;
ということです
これで試してみると、コンテンツ中で読み込まれたファイル (css とか js とか) は Ajax でアクセスしたときにキャッシュされているようです。
ということは、逆に言ってしまうと js とか css とかの生のテキストが欲しい場合は、非同期ではない Ajax でアクセスしてしまってもなんら問題ない訳ですね。(実際には同期して、キャッシュから読んでいるので)
あと、キャッシュされているなら以下の二つのコードは全く同じということですね
var req = new ActiveXObject('Microsoft.XMLHTTP'); // 非同期通信でも req.open('GET', 'hoge'); req.send(); var text = req.responseText;
var req = new ActiveXObject('Microsoft.XMLHTTP'); // 同期通信でも req.open('GET', 'hoge', false); req.send(); var text = req.responseText;
ということは、以下のようにすればキャッシュにある場合だけ使うということができるということですね!
これは使えるかも!
var req = new ActiveXObject('Microsoft.XMLHTTP'); // 非同期通信するが、 onreadystatechange は使わない。 req.open('GET', 'hoge'); req.send(); var text = null; try { text = req.responseText } catch(e) { // キャッシュにない場合はここにくる req.abort(); }
IE 限定ですが、キャッシュから取得されたか通信が行われたかを判定できることが分かりました。
http://amachang.art-code.org/ierendering/014.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <title>IE Rendering Test</title> <script type="text/javascript"> document.attachEvent('onreadystatechange', function() { var $ = function(id) { return document.getElementById(id) }; var log = function(message) { $('log').appendChild(document.createTextNode(message)); $('log').appendChild(document.createElement('br')); } if (document.readyState == 'complete') { // 基本的には、直近の layout を持った祖先要素が offsetParent になる log($('e000') == $('e001').offsetParent && $('e000').currentStyle.hasLayout); log($('e000') == $('e002').offsetParent && $('e000').currentStyle.hasLayout); log($('e000') == $('e003').offsetParent && $('e000').currentStyle.hasLayout); log($('e003') == $('e004').offsetParent && $('e003').currentStyle.hasLayout); // tagName のない無名の layout を持った要素が $('e005') と $('e004') の間に生成されている log($('e005').offsetParent.tagName == ''); log($('e005').offsetParent.currentStyle.hasLayout); log($('e005').offsetParent.offsetParent == $('e004')); // td を作ると無名の要素はできない log($('e007').offsetParent == $('e006') && $('e006').currentStyle.hasLayout); log($('e008').offsetParent == $('e007') && $('e007').currentStyle.hasLayout); // tr 要素は layout を持つのに td 要素の offsetParent は table 要素になる log($('e010').offsetParent == $('e009') && $('e009').currentStyle.hasLayout); log($('e011').offsetParent == $('e009') && $('e009').currentStyle.hasLayout); log($('e010').currentStyle.hasLayout); log($('e012').offsetParent == $('e011') && $('e011').currentStyle.hasLayout); } }); </script> <style type="text/css"> .LAYOUT { zoom: 1 } .RELATIVE { position: relative } </style> </head> <body id="e000"> <div id="e001"> <div id="e002"> <div class="LAYOUT" id="e003"> <table id="e004"> <div id="e005">HOGE</div> </table> <table id="e006"> <td id="e007"> <div id="e008">HOGE</div> </td> </table> <table id="e009"> <tr id="e010"> <td id="e011"> <div id="e012">HOGE</div> </td> </tr> </table> </div> </div> </div> <div id="log"></div> </body> </html>
table が evil なだけなのかどうなのか。そこが問題だ
逃げちゃダメだ、逃げちゃダメだ
今までは出来ないと思っていたのですが、今日いろいろ試していて出来る方法が分かりました。
ですので、ちょっと紹介したいと思います。今のところアイデアなので、実用性は?です。
HTML に以下の style 要素を挿入することで実現することができます。
<style type="text/css"> * { display: expression(function() { if (!this.__mark) { this.__mark = true; alert('inserted node: ' + this.tagName); } return ''; }.apply(this)); } </style>
http://amachang.art-code.org/ieexpression/000.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <title>IE Rendering Test</title> <style type="text/css"> * { display: expression(function() { if (!this.__mark) { this.__mark = true; alert('inserted node: ' + this.tagName); } return ''; }.apply(this)); } </style> </head> <body> <input type="button" value="appendChild" onclick="document.body.appendChild(document.createElement('div'))" /> <input type="button" value="innerHTML" onclick="document.body.innerHTML += 'aaa<br />'" /> </body> </html>
という仕組みです。
http://amachang.art-code.org/ierendering/000.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <title>IE Rendering Test</title> </head> <body> <!-- border-left と padding-bottom を持つ layout を持たないブロックレベル要素 --> <div style="border-left: 1em solid blue; padding-bottom: 1px;"> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <!-- この要素の最後に layout を持たないブロックレベル要素 --> <div>layout を持たないブロックレベル要素</div> </div> <!-- この要素が 2em (ボーダーの幅 x 2)だけずらされる --> <div>ずれてますか?</div> </body> </html>
http://amachang.art-code.org/ierendering/001.html
<body> <div style="border-left: 1em solid blue; padding-bottom: 1px;"> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <!-- この最後の要素をインライン要素にする --> <span>layout を持たないブロックレベル要素</span> </div> <!-- ずれない --> <div>ずれてますか?</div> </body>
http://amachang.art-code.org/ierendering/002.html
<body> <div style="border-left: 1em solid blue; padding-bottom: 1px;"> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <!-- この最後のノードをテキストノードにする --> テキストノード </div> <!-- ずれない --> <div>ずれてますか?</div> </body>
http://amachang.art-code.org/ierendering/003.html
<body> <div style="border-left: 1em solid blue; padding-bottom: 1px;"> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <!-- border-bottom を付ける --> <div style="border-bottom: 1px solid blue;">layout を持たないブロックレベル要素</div> </div> <!-- 2em ではなくて 1em しかずれない --> <div>ずれてますか?</div> </body>
http://amachang.art-code.org/ierendering/004.html
<body> <div style="border-left: 1em solid blue; padding-bottom: 1px;"> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <!-- padding-bottom を付ける --> <div style="padding-bottom: 1px;">layout を持たないブロックレベル要素</div> </div> <!-- 2em ではなくて 1em しかずれない --> <div>ずれてますか?</div> </body>
http://amachang.art-code.org/ierendering/005.html
<body> <!-- border-bottom を追加 --> <div style="border-left: 1em solid blue; border-bottom: 1px solid blue; padding-bottom: 1px;"> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>layout を持たないブロックレベル要素</div> </div> <!-- ずれない --> <div>ずれてますか?</div> </body>
http://amachang.art-code.org/ierendering/006.html
<body> <!-- layout を与える --> <div style="zoom: 1; border-left: 1em solid blue; padding-bottom: 1px;"> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>layout を持たないブロックレベル要素</div> </div> <!-- ずれない --> <div>ずれてますか?</div> </body>
http://amachang.art-code.org/ierendering/007.html
<body> <div style="border-left: 1em solid blue; padding-bottom: 1px;"> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <div>ほげほげほげほ</div> <!-- layout を与える --> <div style="zoom: 1">layout を持つブロックレベル要素</div> </div> <!-- ずれない --> <div>ずれてますか?</div> </body>
http://amachang.art-code.org/ierendering/008.html
<body> <div style="border-left: 1em solid blue; padding-bottom: 1px;"> <!-- からっぽ --> </div> <!-- 1em ずれる --> <div>ずれてますか?</div> </body>
http://cssbug.at.infoseek.co.jp/detail/winie/b025.html
http://cssbug.at.infoseek.co.jp/detail/winie/b041.html
http://cssbug.at.infoseek.co.jp/detail/winie/b046.html
http://amachang.art-code.org/ierendering/009.html
<body> <div style="zoom:1; border: 1px solid blue; margin: 2em;"> あああ <div style="border: 1px solid red">端っこ見えてます?</div> あああ <div style="margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div> あああ <div style="zoom: 1; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div> あああ <div style="position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div> あああ <div style="zoom: 1; position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div> あああ </div> <div style="zoom:1; border: 1px solid blue; margin: 2em;"> あああ <div style="margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div> </div> <div style="zoom:1; border: 1px solid blue; margin: 2em;"> あああ <div style="zoom: 1; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div> </div> <div style="zoom:1; border: 1px solid blue; margin: 2em;"> あああ <div style="position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div> </div> <div style="zoom:1; border: 1px solid blue; margin: 2em;"> あああ <div style="zoom: 1; position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div> </div> <div style="border: 1px solid blue; margin: 2em;"> あああ <div style="border: 1px solid red">端っこ見えてます?</div> あああ <div style="margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div> あああ <div style="zoom: 1; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div> あああ <div style="position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div> あああ <div style="zoom: 1; position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div> あああ </div> <div style="border: 1px solid blue; margin: 2em;"> あああ <div style="margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div> </div> <div style="border: 1px solid blue; margin: 2em;"> あああ <div style="zoom: 1; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div> </div> <div style="border: 1px solid blue; margin: 2em;"> あああ <div style="position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div> </div> <div style="border: 1px solid blue; margin: 2em;"> あああ <div style="zoom: 1; position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div> </div> </body>
layout を持たない親要素の中で float を clear すると背景が margin 領域まで広がる。そして、自分の兄要素の layout を持たないものが消える(消えると言っても実際に消えるわけではなく、「再描画」が伝搬しなくなる。スクロールによって出現する)
この消え方を Peek-a-boo というらしい
http://amachang.art-code.org/ierendering/010.html
<body> <div style="margin: 1em; background: gray;"> <div>あああ</div> <div style="position: relative">いいい</div> <div style="zoom: 1">ううう</div> <div style="zoom: 1; position: relative">えええ</div> <div style="float: right">おおお</div> <div style="clear: right">かかか</div> <div>あああ</div> <div style="position: relative">いいい</div> <div style="zoom: 1">ううう</div> <div style="zoom: 1; position: relative">えええ</div> <div style="float: right">おおお</div> <div style="clear: right">かかか</div> <div>あああ</div> <div style="position: relative">いいい</div> <div style="zoom: 1">ううう</div> <div style="zoom: 1; position: relative">えええ</div> </div> <div style="margin: 1em; zoom: 1; background: gray;"> <div>あああ</div> <div style="position: relative">いいい</div> <div style="zoom: 1">ううう</div> <div style="zoom: 1; position: relative">えええ</div> <div style="float: right">おおお</div> <div style="clear: right">かかか</div> <div>あああ</div> <div style="position: relative">いいい</div> <div style="zoom: 1">ううう</div> <div style="zoom: 1; position: relative">えええ</div> <div style="float: right">おおお</div> <div style="clear: right">かかか</div> <div>あああ</div> <div style="position: relative">いいい</div> <div style="zoom: 1">ううう</div> <div style="zoom: 1; position: relative">えええ</div> </div> <div style="margin: 2em; background: gray;"> <div>あああ</div> <div style="position: relative">いいい</div> <div style="zoom: 1">ううう</div> <div style="zoom: 1; position: relative">えええ</div> <div style="float: right">おおお</div> <div style="clear: right"></div> </div> <div style="zoom:1; margin: 2em; background: gray;"> <div>あああ</div> <div style="position: relative">いいい</div> <div style="zoom: 1">ううう</div> <div style="zoom: 1; position: relative">えええ</div> <div style="float: right">おおお</div> <div style="clear: right"></div> </div> <div style="margin: 2em; background: gray;"> <div>あああ</div> <div style="position: relative">いいい</div> <div style="zoom: 1">ううう</div> <div style="zoom: 1; position: relative">えええ</div> <div style="float: right">おおお</div> <div style="clear: right"></div> </div> </body>
http://www.positioniseverything.net/explorer/peekaboo.html
http://amachang.art-code.org/ierendering/011.html
<body> <div style="background: gray"> <div style="height: 20em; float: left"> <br /> <span> Float <br /><br /> <a href="#"> test link </a> </span> </div> This is bare text. <a href="#">Test link</a> <div style="border: 3px solid #f00; background: #dde;">This is text inside a div. <a href="#">Test link</a></div> This is bare text. <a href="#">Test link</a> <div style="border: 3px solid #0c0; background: #dde;">This is text inside a div. <a href="#">Test link</a></div> This is bare text. <a href="#">Test link</a> <div style="border: 3px solid #00f; background: #dde;">This is text inside a div. <a href="#">Test link</a></div> This is bare text. <a href="#">Test link</a> <div style="clear: left">Clearing div</div> <div style="border: 3px solid #00f; background: #dde;">This div is after the cleared div. (purple box) If cleared div does not touch float, bug is not triggered. <a href="#">Test link</a></div> </div> </body>
float というよりもボックス内で clearance マージンが設定されたかどうかで発生するかが決まる。
たとえば、コンテンツを文字で満たして float 要素を囲み、 clearance マージンの設定が必要のない状態にするとこの問題は発生しない。( clear を指定した要素の margin-top を clearance よりも大きくしてもこの問題は発生しない)
あと、 clearance マージンより下方向にコンテンツがない場合は、 Peek-a-boo は起きない。
重要なことは、 clearance マージンと non-layout なブロックの背景。