IE の getAttribute / setAttribute2005年10月29日 04時29分

DOM の getAttribute / setAttribute メソッドは DOM Level 1 から定義されているメソッドで、MSDN Library によれば IE はバージョン 4 からサポートしています。しかし、IE での element.getAttribute(name) / element.setAttribute(name, value) というのは、基本的には JavaScript における element[name] / element[name] = value のシンタックスシュガーでしかありません。ですから、element.setAttribute("innerHTML", "foo") とすると、element の属性には何の変化もないが element の内容が書き換えられるという事態になります。

この (手抜き) 実装が原因で、getAttribute / setAttribute で class 、style 、イベント属性などを操作できないというバグが IE にはあります。具体的には無理やり getAttribute / setAttribute メソッドを使おうとするなら以下のようにしなくてはいけません。

// NG
element.getAttribute("class");
element.setAttribute("style", "background-color: #fff; color: #000;");
element.setAttribute("onclick", "clickHandler(event);");

// OK
element.getAttribute("className");
element.style.cssText = "background-color: #fff; color: #000;";
element.setAttribute("onclick", new Function("clickHandler(event);"));

また、デフォルトで getAttribute は大文字小文字を区別せずプロパティ名を検索しますが、setAttribute は大文字小文字を区別します。この動作は IE 独自の引数 iFlags を設定することで変更可能です。(0: 大文字小文字を区別しない、1: 大文字小文字を区別する)

input.setAttribute("maxLength", 10);
input.setAttribute("maxlength", 20);
alert(input.getAttribute("MAXLENGTH")); // 10
input.setAttribute("maxlength", 30, 0);
alert(input.getAttribute("MaxLength")); // 30
alert(input.getAttribute("maxlength", 1)); // 20

ちなみに、このことを利用すればほぼ確実に IE かどうかを判別できると思われます。document.all を実装するブラウザはいくつもありますが、こんな奇妙な動作を実装するブラウザはほかにはないでしょう。(あったら教えてください。)

var isIE = (document.documentElement.getAttribute("style") ==
            document.documentElement.style);

ただし、手元に環境がないため、Mac IE 5 でも同じ動作をするのかは不明です。もしどなたか試してくださった際にはぜひ報告していただければ幸いです。

なお、これはあくまでも HTML (MSHTML) に関しての話であり、XML (MSXML) に関しては IE もちゃんと仕様どおりの動作をします。

参考

コメント

_ オムスビ ― 2005年11月06日 02時44分

はじめまして。
Mac IE 5.2.3で「p.style == p.getAttribute("style")」を試したら、「true」になりました。
Safari 2.0.2の場合は、「false」になりました。

どちらもMac OS X 10.4.3上で確認。

_ nanto_vi ― 2005年11月06日 12時52分

おお、ありがとうございます。
Mac IEでも同じ実装なのですね。
判別の手間が省けると思いつつもちょっと残念です。

_ nao ― 2006年02月26日 00時57分

_ nao ― 2006年02月26日 01時05分

element.setAttribute("onclick","newHandler()")で属性変えても、newHander()がどうして呼ばれないのかさんざん悩みました。
助かりました。
前の投稿、記事が消えてしまいましたが、こんどはちゃんとかきこめるだろうか。

_ hal* ― 2006年09月15日 16時23分

助かりましたーヾ(・◇・)ノ

_ brazil ― 2006年11月07日 23時22分

MochiKit.DOM.updateNodeAttributesによると、以下の属性も変換の必要があるそうです。

checked -> defaultChecked
usemap -> useMap
for -> htmlFor
readonly -> readOnly
colspan -> colSpan
bgcolor -> bgColor

_ nanto_vi ― 2006年11月09日 20時29分

情報ありがとうございます。
defaultChecked はちょっと特殊 (動的に生成した input 要素を文書ツリーに挿入する前に設定した checked 属性は反映されず、defaultChecked だと反映される) ですがあとは DOM HTML と同じ変換ですね。
実際に試したわけではありませんが DOM HTML 仕様から抜き出す限りでは以下も当てはまりそうです。
http-equiv -> httpEquiv
tabindex -> tabIndex
accesskey -> accessKey
accept-charset -> acceptCharset
datetime -> dateTime
ismap -> isMap
longdesc -> longDesc
codebase -> codeBase
codetype -> codeType
valuetype -> valueType
nohref -> noHref
cellpadding -> cellPadding
cellspacing -> cellSpacing
char -> ch
charoff -> chOff
rowspan -> rowSpan

_ F.D ― 2007年04月13日 17時39分

if(document.all){
}
IEの場合はdocument.allがTrueになりました。

_ NMT ― 2007年09月21日 16時42分

助かりました。
ありがとうございます。

_ PIN ― 2007年10月13日 22時16分

こんばんわ。
今作成しているものにこのsetAttributeの動作が必要なのですが、
onClickを入れようとして属性値にfunction名("値")を入れているのですが、FireFoxで実行した時に値が変数だとそのまま変数名が入ってしまいます。

FireFoxの場合変数の中身を代入することはできないのでしょうか?

説明が下手で申し訳ございませんが、ご教授願えたらと思います。

_ nanto_vi ― 2007年10月14日 23時24分

function f() {
var a = 42;
element.setAttribute("onclick", "alert('a');");
}
としたら、42 と表示してほしいのに a と表示されてしまったということでしょうか?
もしそうなら、以下のようにクロージャを使うことで解決できます (ブラウザによってはクロージャの使用がメモリリークの原因となることもありますが)。
function f() {
var a = 42;
element.addEventListener("click", function () { alert(a); }, false);
}

_ otn ― 2007年12月11日 20時16分

PINさんの質問がnaotoさんの想像通りなら、
element.setAttribute("onclick", "alert('"+a+"');");
でいいんじゃないですか?
aの値がsetAttribute時点とclick時点で異なるならダメですが。

_ nanto_vi ― 2007年12月12日 01時19分

a の値が単純な数値などならそれでもかまいませんね。PIN さんがどのような状況を想定しているのかにもよりますが。

_ nanto_vi ― 2009年08月27日 23時47分

誤って kubota さんのコメントを削除してしまいました。
大変申し訳ありません。

_ Ghost X ― 2011年03月06日 21時44分

var CSS={
getAttribute:function(element,name){
var browser=getBrowserName();
if(browser=='InternetExplorer'){
switch(name){
case 'class':
name='className';
break;
case 'checked':
name='defaultChecked';
break;
case 'usemap':
name='useMap';
break;
case 'for':
name='htmlFor';
break;
case 'readonly'
name='readOnly';
break;
case 'colspan':
name='colSpan';
break;
case 'bgcolor':
name='bgColor';
break;
case 'http-equiv':
name='httpEquiv';
break;
case 'tabindex':
name='tabIndex';
break;
case 'accesskey':
name='accessKey';
break;
case 'accept-charset':
name='acceptCharset';
break;
case 'datetime':
name='dateTime';
break;
case 'ismap':
name='isMap';
break;
case 'longdesc':
name='longDesc';
break;
case 'codebase':
name='codeBase';
break;
case 'codetype':
name='codeType';
break;
case 'valuetype':
name='valueType';
break;
case 'nohref':
name='noHref';
break;
case 'cellpadding':
name='cellPadding';
break;
case 'cellspacing':
name='cellSpacing';
break;
case 'char':
name='ch';
break;
case 'charoff':
name='chOff';
break;
case 'rowspan':
name='rowSpan';
break;
}
}
return element.getAttribute(name);
}
};

_ Ghost X ― 2011年03月06日 21時48分

function getBrowserName(){
if(/*@cc_on!@*/false){
return true;
}
return false;
}

皆さんの意見を参考に、
CSS.getAttribute(element,name,value);
を作ってみました。

ただ、あまりにも長いというか、処理が多くなってしまいます;
もっと、軽く書ける方法をご存知の方は書いてください><;

_ Ghost X ― 2011年03月06日 21時51分

上記、getBrowserName関数にミスがありました;
正しくは、
function getBrowserName(){
if(/*@cc_on!@*/false){
return 'InternetExplorer';
}
return null;
}
です。

_ Ghost X ― 2011年03月07日 03時09分

おっと;
CSS.getAttribute関数のswitch文内に、以下の記述を追加して下さい^^;
case 'style':
return element.style.cssText+';';
break;

連投すみませんm(_ _)m

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※投稿には管理者が設定した質問に答える必要があります。

名前:
メールアドレス:
URL:
次の質問に答えてください:
「ハイパーテキストマークアップ言語」をアルファベット4文字でいうと?

コメント:

トラックバック

このエントリのトラックバックURL: http://nanto.asablo.jp/blog/2005/10/29/123294/tb

_ BUZZ LIVEYEAR - 2005年12月28日 09時44分

 JavaScriptでDOMを使用してコンテンツを動的に書き換える技があるのだ...

_ Blog::Trapple::Net - 2006年04月21日 17時23分

Domにおいて、エレメントの属性値を取得するメソッドはgetAttribute(...

_ Junnama Online - 2006年06月18日 14時18分

イベントハンドラは装置に依存しないよう論理イベントをあわせて指定する。 WCAG

_ A Better Project@はてなダイアリー - 2006年10月24日 10時03分

過去エントリであるIEでDOMで生成したbutton(input要素)のイベントハンドラ(onClick)が正常に動作しないの続きです。半年前のエントリですが。 この問題に関しては、IE の getAttribute / setAttribute: Days on the Moonでも解説されているのですが、初心者にはさっぱり

_ 神保町のウェブ制作者のつぶやき - 2006年10月24日 23時02分

週末ITの総合展示会の「WPC 2006 TOKYO」に行ってきました、

_ ひきこもり生活記 - 2007年04月04日 21時11分

非常に再現性の低い現象だと思うのですが。 特定の環境でのみ発生するIEのJavaScriptまわりの謎な挙動です。 とりあえずこのテストを試してください。 もちろんJavaScriptはonにしておいてくださいね。 内容は、JavaScriptで作ったボタンからJavaScriptを呼び出すことがで..

_ cefa::blog - 2007年07月05日 15時11分

MT4 beta4: mt.jsを思いっきり改修してみた (cefa::blog) の続きです。

_ KK企画研究所 - 2008年03月05日 13時34分

仕事が立て込んでしまって、ブログの更新大分ご無沙汰になっていました。
今回は、InternetExplorer(以下IE)でsetAttribute()メソッドを使ったスクリプトを書いていてハマッテしまったので、その解決策を忘れないうちに記します。

= IEと非IE系ブラウザの差異 =
現在あるDOMに対して、動的に属性などを設定する場合、モダンブラウザ繁栄の時代でもあるので、やはり DOM.setAttribute()メソッドを使いたくなります。
そこで、id="text...

_ 覚え書きみたいなもの - 2008年09月01日 14時59分

IE の getAttribute / setAttribute


JavaScriptにて、elementオブジェクトから、
setAttributeメソッドにて class 、style 、onclick等のイベント属性の設定を行うことができない。
(getでの取得もできない。)

それぞれ、


【クラス】
キー指定を"class"で....

_ progress - 2009年06月05日 19時14分

前回の記事で、IEで動作しない問題を抱えておりました「JavaScriptイミディエイトウィンドウ」ですが、試行錯誤の末、ようやく動作するようになりました。
#というか、何でIEってこんな...