Ads

リンク

考察

気づいたこととか

input タグで貼り付けを出来ないようにする。

メールアドレスやパスワードをミス防止で2回入力させるときに貼り付けされるとイヤーンなときに使う。

onKeyDown="if(event.ctrlKey==true && event.keyCode==86)return false;"

コンテキストメニューを表示させないようにする。

右クリックメニューを出させたくないときに使う。素人にはソース見られたくないとか、input タグで貼り付けを防止するとか。

onContextMenu="return false;"

実体参照の罠

次の HTML だが、どっちが正しく動くと思います?ちなみに ' は ' (シングルクオート)です。

<span onclick="alert('&#039;')">ほげ</span>
<span onclick="alert('&#039;)">ふが</span>

「ほげ」の方をクリックするとエラーで、「ふが」の方は空文字の alert が出ます。 要は javascript が解釈される前に実体参照が展開されて、ブラウザから見たら次のように書いてあるのと同じなわけです。

<span onclick="alert(''')">ほげ</span>
<span onclick="alert('')">ふが</span>

さて、ここで次の例です。これはどう動くでしょうか?

<script>alert('ほげ&#039;')</script>
<script>alert('ふが&#039;)</script>

正解は「ふが&amp;#039;」がポップアップされます。 さっきの例と逆、…というか script タグの中では実体参照の展開は行われないようです。 ちなみに script タグの中を <!-- --> で囲っても結果は同じでした。

この2つの例はどちらも、IE と Firefox で試しましたがどちらもこの挙動のようです。HTML4ではscript要素がCDATAとされているからではないでしょうか。

OperaのgetAttributeのバグ?

Opera の eleemnt.getAttribute って foo:bar="hoge" ってのが取れないのかな?<span foo:bar="hoge" abc="1"> で elm.getAttribute("abc") は 1 が取れるのに、elm.getAttribute("foo:bar") だと null になってしまう。でも、elm.setAttribute("foo:bar2", "123"); elm.getAttribute("foo:bar2"); て感じで JavaScript でつけた場合はちゃんと 123 が取れるんだよな、最初から付いてる foo:bar 的な属性だけが取れないぽい。

elm.attributes を for で回して if(elm.attribute[i].name == "foo:bar") alert(elm.attribute[i].value) とかすればなんとか foo:bar の値が取れるな。

微妙だ…。

強引だが、例えば↓こんなコードをonloadあたりで一発やっとけばOperaでも elm.getAttribute("foo:bar") がマトモに使えるようになりそうかも。

// Opera だったら getAttribute のバグ対応の為にネームスペースつきの属性を setAttribute しなおす。
if(navigator.userAgent.indexOf("Opera", 0)) {
  var elms = document.all || document.getElementsByTagName("*");
  for(var i = 0; i < elements.length; i++) {
    var elm = elems[i];
    for(var j = 0; j < elm.attributes.length; j++) {
      var attr = elm.attributes[j];
      if(attr.name.match(/:/)) {
        return elm.setAttribute(attr.name, attr.value);
      }
    }
  }
}

Tips

document.getElementsByClassName クラス名でエレメントを検索

document.getElementsByClassName = function(className) {
	var elementsAll = document.getElementsByTagName('*') || document.all;
	var elements = new Array();
	for(var i = 0; i < elementsAll.length; i++) {
		var classNames = elementsAll[i].className.split(' ');
		for(var j = 0; j < classNames.length; j++) {
			if (classNames[j] == className) {
				elements[elements.length] = elementsAll[i];
				break;
			}
		}
	}
	return elements;
}

既存のスタイルシートを全部無効にして指定のCSSを適用するブックマークレット

javascript:(function() {
	var sheet = 'http://example.com/foo.css';
	var s = document.styleSheets;
	for (var i = 0; i < s.length; i++)
		s[i].disabled = true;
	var link = document.createElement('LINK');
	link.setAttribute('href', sheet);
	link.setAttribute('rel', 'stylesheet');
	link.setAttribute('type', 'text/css');
	document.getElementsByTagName('HEAD')[0].appendChild(link);
})()

イベントリスナーの使い方

onclick イベントを JavaScript で追加するときに以下のよく様なコードを書くことがある。

function foo(event) {
  alert("bar");
}
obj.onclick = foo;

でも、このやり方はいくつかの問題点をはらんでいる。

  • 例えばイベントを一つの関数しか設定できない。onclick+=";func1()"; onclick+="func2()" などすればよいのかもしれないがスマートさに欠ける。
  • それにイベントを削除することも出来ない。仮に onclick="" とすれば自分のあずかり知らないところで onclick が改変されている場合も全て消えてしまう。

答えはイベントリスナーにある。IEの場合は attachEvent、Firefox や Opera の場合は DOM の addEventListener メソッドで素敵に解決できる。 マルチブラウザを考えて以下のような関数を作っておくと良い。

function addEventListener(target, type, func) {
  if(target.attachEvent) {
    target.attachEvent("on" + type, func);
  } else if(target.addEventListener) {
    target.addEventListener(type, func, true);
  } else {
    //イベントリスナが使えない場合は on○○ 属性を上書きで妥協(今時あんまし無いと思うが
    target["on" + type] = func;
  }
}

これを使って、

addEventListner(obj, 'click', func1);
addEventListner(obj, 'click', func2);
addEventListner(obj, 'click', func3);

とかやれば click に複数のイベントが設定できて、かつ onclick 属性も汚染されない。 しかも obj.removeEventListener とかで狙ったイベントだけを外すことも出来る。

CSSクラスのスタイルシートを取得や設定する方法

  • スタイルシートのアクセスパス
    • IEの場合
      • document.styleSheets[i].rules[j].style
    • Firefox,Operaの場合
      • document.styleSheets[i].cssRules[j].style
  • 手順
    • 全ての document.styleSheets[i].cssRules[j].selectorText を回してチェックして、目的の selectorText を持つルールの style を集めて順番的に最後のものを取得する
      • 同じselectorTextが複数のスタイルシートやルールで設定されることができるので、その場合ブラウザの見た目に適用されるのは最後のものを使う
      • この手順では !important には未対応です
  • メモ
    • rulesの分割?
      • 例えば以下のような複数のセレクタを同時に設定したルールがある場合
        a, .hoge {
          color: red;
        }
      • IEの場合は rules に selectorText が 'a' のルールと selectorText が '.hoge' の二つのルールに分割されたものにアクセスする。
      • FirefoxやOperaでは cssRules には selectorText が 'a, .hoge' という一つのルールとしてアクセスする。
      • なので selectorText をカンマで分割したものを自分で回して目的のセレクタにマッチするルールを探す必要がある。
  • クロスドメイン上のCSSファイル
    • IEやOperaでは問題ないが、Firefoxでは別ドメイン上にあるcssファイルの document.styleSheets[i].cssRules にアクセス(cssRulesプロパティがあるかどうかチェック)するだけで例外が発生する

上記を踏まえて、CSS アクセス用のユーティリティ関数とその実行デモを作ってみた。 IE6-7,Firefox,Opera,Safariで正常に動作することは確認出来た。

デモページ


添付ファイル: fileCssValue.html 885件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2008-05-26 (月) 09:39:57 (2925d)