クロスドメインをやってみる
ことの発端
地図タイル画像を出している某サイトで、地名についてSVGで出すようになりました ("Access-Control-Allow-Origin: *
"が付いています)。
IE10以上、FireFox等ではimg要素から画像として取得できますが、スタイルが決定されてしまっている状態です。
インラインSVGの場合は、JavaScriptからCSSルールを操作できるので、SVG文書を取得して無理やりインラインSVGにする方法をまずは考えましたが、インラインSVGでなくHTML要素を直接書き込んでやればCSSルールの操作は効くし、IE9以下でも見れるしでいいことずくめだろう、と考えました。
しかしこれが泥沼だったとは最初は知る由も無かったのであった、ときたもんだ。
IE 6について
無視します。
XMLHttpRequest2 とAccess-Control-Allow-Origin
FireFox, Opera, Chrome, IE 10 らについては、XMLHttpRequest2 の Cross-Origin Resource Sharingが有効です。
CORSが有効な場合には、サーバ側の返却コンテントのヘッダに
Access-Control-Allow-Origin: (許可サイト)
があって、呼び出し元ページが許可サイトにマッチしている場合には、得られたコンテントを使いまわすことができます。
そうでない場合は許可されずに、responseXMLにアクセスしようとすると、ブラウザに止められます。
また、ヘッダに
Access-Control-Allow-Origin: *
がある場合は、呼び出し元ページがどのドメインにいようとも得られたコンテントを使いまわせます。
var svg = xhr.responseXML.getElementsByTagName("svg")[0];
でsvg要素が得られます。
IE 7,8,9ではXDomainRequestで
XDomainRequestを使います。
ただし、XMLHttpRequestとプロパティが若干異なります…この若干でも違うのが以下略
また、XDomainRequestで得られたコンテントはresponseTextから得られます。
これをXML化するには、次のようなかんじにしました。
var doc = document.createElement("doc"); doc.innerHTML = xhr.responseText; var svg = doc.getElementsByTagName("svg")[0];
IEのローカルページからのアクセス
IE 7,8,9 の XDomainRequest, XMLHttpRequestは、呼び出し元がローカルの場合には、リモートへのアクセスが禁止されます。open()時点でアウト。
IE10は、XMLHttpRequestでローカルページからリモートコンテントを取ることはできますが、ローカルコンテントが拾えません。
ここで、ActiveXの登場です。
if( location.protocol == "file:" ) { var xhr = new ActiveXObject("Msxml2.XMLHTTP");
で、あとは XMLHttpRequest と同じです。
じゃあ最初からMsxml2.XMLHTTPを使えばいいじゃない、と思うかもしれませんが、呼び出し元がリモートのページの場合にクロスドメインが効かないのです。
条件分岐はIEのバージョンで
IE 7,8,9,10 は XDomainRequest も XMLHttpRequest も両方持っています。
typeof XDOmainRequest != "undefined" などのやり方は通用しません。
バージョンを導いてから判定します。
ここまでのまとめ
クラスの使い分けは次の通りです。
- IEでない場合はXMLHttpRequest
- IEの場合は
- ローカルページなら ActiveX
- リモートページなら
- IE 7,8,9 なら XDomainRequest
- IE 10 なら XMLHttpRequest
IE7のクラス名をJavaScript DOMから得る
さて無事
IE7は、クラス名を得る属性名は "className" です。IE8以上、IE以外は "class" です。
e.getAttribute("class") || e.getAttribute("className");
こんなかんじ。
おわりに
IEは穴があったり、穴がふさがってたり、独自仕様があったりと、いろいろ注意が必要ですね(白目