「あれこれトリックあうと」 と読みます。
Arekore-Trick-Old-UserAgent-Trouble の略です。
どうでもいいですが。
標準に準拠していないような古いタイプのブラウザ
(主にIE)
で使いたいのに使えなかった機能を、
ちょっとだけ、それなりに、一部だけ、使えるようにして、
そのブラウザをだましだまし使ってしまおう、
そしたら
HTMLとかJavaScriptも
ちょっとは標準っぽく
(けして標準で書けるというわけでわない)
書けたり見れたりするかも知れないね、
・・・といったツールです。
機能としては以下な感じ。
いずれも初期設定で使うか使わないかのスイッチはできます。
それぞれの詳しい説明は、
「仕組みについて」
のところで説明してるので、そちらを参考に。
上のアンカーからでも飛べます。
JSファイルを読み込むだけです。
「対象をファイルに保存」でよろしく。
置き方は、 HTMLファイル のどこかに、下記のように。
<script type="text/javascript"
src="ArekoreTrick.js"></script>
外部JSファイルが複数ある場合は、一番最初に読み込んだほうがいいかも。
JSファイルを開けば、 一番上あたりに設定があります。
何を使うようにするか、どう使うかは、
そこでスイッチしたりそれなりに設定したりできるので、
いろいろいじってみてください。
自由に入力できるのは
listener : 1,
などの数字やnull(未定義に)と
'Q' : ['"'],
などの文字列
(シングルクオーテーションで囲まれた部分)です。
他の露出してるスクリプト部分はなるべくいじらないでください。
<ABBR> は IE だとちゃんと要素として認識してくれない ( <ABBR>と</ABBR>という 2つの空要素として認識されている ) ので、要素として再構成させます。
q:before, q:after { content:'"'; } も使えないのに、 Q要素の前後に最初からマークがつかないなんておかしい! ってことでマークがつくようにしちゃいます。
ソースのイメージとしては、例えば、 このヘアースタイルが<q>サザエさんみてェー</q>だとォ? とあったとすると、 このヘアースタイルが <q> <span class="mark">"</span> サザエさんみてェー <span class="mark">"</span> </q> だとォ? という風になります
マークやマークを代入する要素などは、JSの中で設定してください。
em.memo の前後に (~)カッコを挿入、みたいな。
スタイルシートでその文字部分を扱いたいときは、
q:before, q:after { content:'"'; }
q:before, q:after, q .mark { font-weight:bold; }
みたいにしてください。
CSSライクに、以下のような書き方に対応しました。
IDとクラスと属性はいくつでも連結できるハズです。
ただ、単に * とか .class だと、 ほぼ全ての要素にアクセスして判断するため、処理が非常にアホくさいです。 なるべく要素を指定したり、IDを指定して使うようにしませう。
ちょっとした専門用語を使うなら、
全称セレクタ,
タイプセレクタ,
IDセレクタ,
クラスセレクタ,
子孫セレクタ,
属性セレクタの一部,
が使えます。
子供セレクタ,
隣接セレクタ,
擬似クラス,
には対応してません。
(たかだかIEで :before, :after
するためにそこまで必要だとは思えないし/笑)
属性セレクタの一部
というのは、基本的な
A[title]
A[target="_blank"]
などはできて、ちょっと高度な
A[rel~="help"]
というスペースで区切られた値のリストでのマッチ、
Q[lang|="en"]
というハイフンで区切られた値のリストのマッチ、
などはできない、ってことです。
…や、スクリプトの仕様とかじゃなく、
単にたいして使いそうもないのに
そこまで対応させるのは無駄だし面倒だと思っただけです。
ごめん。
IEでは、スタイルシートで、
#banner { position:fixed; bottom:0; right:0; }
とやっても固定されず、仕方なく
#banner { position:absolute; bottom:0; right:0; }
としても、画面をスクロールしたらすごくカッコ悪いことになります。
対応策として、IEと他のブラウザで場合わけして、こんな真似をしたり。↓
#banner { /* not IE */ position:fixed !important; top:auto !important; bottom:0 !important; left:auto !important; right:0 !important; /* IE */ position:absolute; top:0; bottom:auto; left:0; right:auto; }
・・・と、するのもいいのですが、
ちゃんとできるに越したことはないので、
JSに値を設定することでそれなりに動くようにしてみました。
設定できる値は[px]での数値のみです。
([em]とかは使えません)
IEの場合、 <OBJECT>要素使うとなんか変なときがあるらしいので、 (メソッドを書き換えようとしたり、 for (key in object) したりするとIEが死にますw) 比較的安定に使える <IFRAME>要素に変換します。
MIMEタイプが なし, text/html, application/xhtml+xml, application/xml, text/xml, のいずれかのときだけ変換されます。
属性は
data,
id,
name,
class,
title,
width,
height,
border,
のそれぞれが適当に保持されます。
他の値は消えます。
<IFRAME>要素に変換します。
などとは言ってますが、実際は要素を新しく作って、
<OBJECT>要素を消してるだけなので注意。
<IFRAME>に変換すると
name属性が効かなくなる問題に対処しましたw
くわしくは、過去日記の
OBJECT→IFRAME
を参考に。
getElementsByTagNameNS や
createElementNS,
createAttributeNS
などはまだIEなどでは未定義で使えません。
なので、それぞれ
getElementsByTagName,
createElement,
createAttribute
によりオブジェクトを返すようにしてみました。
ただ、別に名前空間をサポートするわけじゃないので、 単に「エラーがでなくなる」という応急処置に過ぎません。 あしからず。
だいたい、バグなのか何なのかわからないけど、
Gecko や Opera でも、
ちゃんとXHTMLの名前空間指定したって
var ps = document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'P');
で要素とれないし。
当然
var ps = document.getElementsByTagNameNS(null, 'P');
ならとれるけど。
HTML, XHTML に限るなら、普通に
var ps = document.getElementsByTagName('P');
ってやったほうがいいのカモ。
とりあえず、過去日記の
JavaScriptのイベントのthis
を参考に。
IEでも
element.addEventListener
を使えるようにします。
IE以外の使えなさそうなブラウザでも、大丈夫なはず。たぶん。おそらく。
Opera7.5では
window.addEventListener
だけ何故か使えないので、そのときだけ
window.attachEvents
が使われます。
イベントの発生する順序も、登録した順になります。
その他、これによるイベントのあれこれについては、 下の 要素に追加されるメソッドについて の項で解説します。
IEでは
element.setAttribute('class', '*');
や
var clas = element.getAttribute('class');
では、classの値を取得・変更できず、
element.className = '*';
や
var clas = element.className;
とやらねばならないので、
setAttribute、getAttribute
をオーバーロードさせて、
class属性のときでも
setAttribute、getAttribute
で属性を取得・変更できるようにしました。
これも、他のスクリプトで新しく要素を追加する場合は、 下の 要素に追加されるメソッドについて の項の、 他のスクリプト内で新しく要素を作る場合 の部分を参考に。
ここからは、この
仮想 addEventListener
などを使って実際にスクリプトを作るときに注意することをまとめます。
一般に使う分には、あまり関係ないです。
addEventListener で発生させた要素のオブジェクトは、次のようにすると楽に取得できるかと。
function func(e) {
var obj = this; // element-object
if (!obj.nodeType && e && e.srcElement)
obj = e.target || e.srcElement; // IE
...
}
windowオブジェクトの場合は e.srcElementがない(null)ので、 だいたいこれでいけると思います。
window と window.document に
addEventListener を関連付けるのは、
このJSファイルを読み込んでいるときですが、
ドキュメント内にある全ての要素に
addEventListener や
setAttribute,
getAttribute
などを関連付けするのは、
ドキュメントを読み終わったとき(onload時)になります。
そのため、スクリプト中で行われる、
document.createElement('DIV')
とかには自動では関連付けされません。
(
document.createElement.prototype.addEventListener
とかできたらいいのに...
)
その場合、次のように書くと結構シアワセになります。
var obj = document.createElement('DIV');
if (window.addElementMethod) addElementMethod(obj);