広告

この広告は30日以上更新がないブログに表示されております。
新規記事の投稿を行うことで、非表示にすることが可能です。
posted by fanblog
「ここにブログの名前を入れます」は更新を終了しました。記事はすべて新ブログ「Big Bang」に移転済みです。記事のタイトルをクリックすると新ブログの該当記事に移動します。そちらでお楽しみください。

カテゴリー別アーカイブ  :  

appendChildやinsertBeforeでノードを移動させる

DOMのappendChildは子ノードの追加、insertBeforeはノードの挿入のためのメソッドですが、これを使ってノードの場所を変更できます。

appendChildで移動する

たとえば、次のようなHTMLがあったとします。

<div id="outer">
<p id="morning">おはよう</p>
<p>こんにちは</p>
<p id="night">こんばんは</p>
</div>

ここで、下のコードを実行すると「おはよう」が「こんばんは」の後に移動します。

document.querySelector('#outer').appendChild(document.querySelector('#morning'));

実行例

おはよう

こんにちは

こんばんは

実行すると「おはよう」が「idがouterであるdiv」に追加されます。その結果、元の位置から最後にずれます。「おはよう」の位置がずれたので、「こんにちは」が先頭になります。

insertBeforeで移動する

上の例のHTMLに今度は次のスクリプトを適用してみます。すると最後の「こんばんは」が先頭にある「おはよう」の前に移動します。

var outer=document.querySelector('#outer');
var night=outer.querySelector('#night');
var morning=outer.querySelector('#morning');

outer.insertBefore(night,morning);

実行例

おはよう

こんにちは

こんばんは

これを知っていると、すごく便利だと思います。このブログのコメント欄の改造はこのメソッドを多用して実現しました。

新ブログ「Big Bang」で続きを読む

Google Analyticsのイベント トラッキングはaddEventListenerやattachEventでは計測されない

先日書いた記事「Google Analyticsでクリック数を計測するスクリプト」で、どこへのリンクがクリックされたのかのログをonclickイベントで拾うコードを書きました。ちゃんと動いていたんですが、Tweetボタンやmixiボタンが動作しなくなっていたので修正しました。

動かなくなった理由はonclickを上書きしていたからです。普通のaタグはonclickがnullなので、書いたコードで問題なかったんですが、Tweetボタンやmixiボタンはhref="javascript:void(0);"でリンクを無効にして、onclickで作動していたからです。そのスクリプトを消してしまっていたから、ボタンを押しても動作しませんでした。正確に言えばボタンを押すと、違う動きになった。つまりGoogle Analytics用のデータ作成に使われるようになったということです。

そこで、addEventListener 或いは attachEventを使って、アクションを「上書き」ではなく「追加」したんですが、それではログが記録されていないことに気がつきました。

Google Analyticsのイベント トラッキングはonclickでなくては計測されない

確認するために丸一日、下のコードで置いておきました。その結果計測されたイベントはゼロです。ただ、そのコードはすでに消してしまっていたので、下のコードは記憶を元に書いています。元のソースでは_gaq.pushのところをalertに変えてテストしましたが、意図どおりに動いていました。

<script type="text/javascript">
<!--
var add_ga=function(elem){
	type=(-1==elem.href.indexOf('/ayzfqir5/')&&elem.href.match(/^https?\:\/\//))?'Out':'In';
	_gaq.push(['_trackEvent',type+'bound Link','click',elem.href]);
};

set_event=(function(){
	if(document.addEventListener){
		return function(elem,func){
			elem.addEventListener('click',func,false);
		};
	}

	if(document.attachEvent){
		return function(elem,func){
			elem.attachEvent('onclick',func);
		};
	}

	return null;
})();

if('function'==typeof set_event){
	a=document.querySelectorAll('a');

	for(var i=0;i<a.length;i++){
		set_event(a[i],(function(elem){
			return function(){add_ga(elem);};
		})(a[i]));
	}
}

delete set_event;
// -->
</script>

対処として、上のコードを次のものに変更したところ、addEventListenerのfirefoxでもattachEventのIEでも計測されるようになりました。滅多に押されないところを自分でクリックして記録されているかどうかを見たのですが、偶然誰かが他のブラウザでクリックしていないのならaddEventListenerでもattachEventでも記録されているのだと思います。

<script type="text/javascript">
<!--
var add_ga=function(elem){
	type=(-1==elem.href.indexOf('/ayzfqir5/')&&elem.href.match(/^https?\:\/\//))?'Out':'In';
	_gaq.push(['_trackEvent',type+'bound Link','click',elem.href]);
};

set_event=(function(){
	if(document.addEventListener){
		return function(elem){
			if(null!==elem.onclick){
				elem.addEventListener('click',elem.onclick,false);
			}

			elem.onclick=function(){add_ga(elem);};
		};
	}

	if(document.attachEvent){
		return function(elem){
			if(null!==elem.onclick){
				elem.attachEvent('onclick',elem.onclick);
			}

			elem.onclick=function(){add_ga(elem);};
		};
	}

	return null;
})();

if('function'==typeof set_event){
	a=document.querySelectorAll('a');

	for(var i=0;i<a.length;i++){
		set_event(a[i]);
	}
}

delete set_event;
// -->
</script>

元々のonclickの内容をelem.addEventListener('click',elem.onclick,false);elem.attachEvent('onclick',elem.onclick);という形でコピーしてから、elem.onclick=function(){add_ga(elem);};で新しいonclickに_gaq.pushする関数を上書きするという内容です。正直、これで動くか心配だったんですが、出来るんですね。

結論として、addEventListenerattachEventではダメで、onclickでなくてはイベントは計測されないようです。

ただ、検索してみるとaddEventListenerでうまくいっていると言う記事がたくさんあったのですが、他の方は動いてるんでしょうか?

新ブログ「Big Bang」で続きを読む

querySelectorとquerySelectorAll

スタイルシートのセレクタを使ってDOMにアクセス出来る2つのメソッドが超便利な件。

querySelectorquerySelectorAllの2つ。

どちらも同じで、document.querySelector('div.entry p')のようにセレクタでアクセスできる。

この2つのメソッドの違いは、querySelectorの場合、指定条件にあった最初の1個だけを抽出する。
一方、querySelectorAllの時は、指定条件にあうすべての要素を抽出する。

たとえば、次のようなHTMLがあったとする。

<div class="entry">
<p class="hoge">こんにちは。<br />
今日はとっても天気がいいですね!</p>
<p>これはペンです。</p>
<p class="hoge">さようなら。</p>
</div>

これに対してpタグを見つけたい場合

document.querySelector('div.entry p')だと、最初の
<p class="hoge">こんにちは。<br />
今日はとっても天気がいいですね!</p>

だけを抽出する。

一方、document.querySelectorAll('div.entry p')なら<div class="entry">〜</div>の中にある、
すべてのpタグをまとめて抽出してくれる。

そして、querySelectorAllは、配列のように添字でアクセスできる。

var p=document.querySelector('div.entry p');
p.style.color='#ff0000';

とすると、
こんにちは。
今日はとっても天気がいいですね!

というように、最初のpタグだけが赤くなる。

一方

var p=document.querySelectorAll('div.entry p');

for(var i=0;i<p.length;i++){
	p[i].style.color='#ff0000';
}

とすれば、すべてのpタグが赤くなる。

querySelectorAllには、lengthがあるが、querySelectorには、lengthがないので注意。

セレクタでアクセス出来るので、var p=document.querySelectorAll('div.entry p.hoge');と指定すれば、
hogeクラスのpタグだけが抽出される。

CSSのセレクタに関しては次のページが参考になります。
意外と知らない!?CSSセレクタ20個のおさらい|Webpark

本当にこれは便利です!
実際にこのメソッドを使ってソースを書いてみました。下がその記事です。

新ブログ「Big Bang」で続きを読む

onpasteはペースト直前に実行される

JavaScriptで右クリックからペーストを選択した時に、それをトリガーにして何かを実行したいとする。たとえば、textareaに文字列を入力すると、入力結果をプレビュー欄に表示させる、というような場合。

ctrl+Vならonkeyupでいい。だけどマウスの右クリックでペーストすると、それではダメだ。キーボードは叩いていないんだからイベントが発生しない。

onmouseupでいけるだろうと思ったが、うまくいかない。少なくともFirefoxでは反応しなかった。

どのボタンでクリックされたか判別する【JavaScript】 - Programming Magicという記事を拝見したところ、Firefoxではマウスの右クリックは拾えないようだ。

ならば、ということでonpasteというイベントを使ってみた。実はこのイベントを使ったのは初めてなんだけど、ペーストした追加部分がプレビューに含まれていない。

調べてみたら、onpasteはペーストする直前のタイミングで処理を行なうらしい。
うーん。としばらく考えたけど、setTimeout関数を使って実現できた。

<textarea name="ta" id="ta" onclick="clear_value(this);" onkeyup="preview();" onpaste="setTimeout(preview,10);">
ここにご記入ください。
</textarea>

<div id="pv"></div>

<script type="text/javascript">
<!--
var flag={"ta":0};
var ta=document.getElementById('ta');
var pv=document.getElementById('pv');

var clear_value=function(elem){
	if(!flag[elem.name]){
		elem.value='';
		flag[elem.name]++;
	}
}

var preview=function(){
	pv.innerHTML=ta.value;
}
// -->
</script>

setTimeoutなし (続けて2回右クリックでペーストするとわかる)


setTimeoutあり (狙いどおりの動作)

新ブログ「Big Bang」で続きを読む

年齢計算フォーム

別のサイトで下のような選択フォームを作りました

1月、3月、5月、7月、8月、10月、12月は日付を31日まで選択できますが、
4月、6月、9月、11月は30日まで、2月は年によって28日か29日になります。
(西暦は大正元年にあたる1912年まで対応)

誤入力を防止するため、存在しない日付は表示しません。

たとえば、今年、今月を選択すれば、1日から今日の日付までしか選べません。

昭和64年は1月7日までなので、昭和64年1月を選べば7日まで、平成元年1月を選べば
8日からの表示となります。

元号年から西暦への変換も出来ます。
たとえば平成1年を選択した後に、西暦を押すと1989年と表示されます。

これを実現するのに以下のソースを書いてFirefoxで試したらうまくいきました。
ところが、IE(インターネット エクスプローラー)ではset_select関数が動きません。

Internet ExplorerではselectタグのinnerHTMLへの挿入はサポートしていないそうです。

新ブログ「Big Bang」で続きを読む

addEventListenerとattachEvent

addEventListenerattachEventはオブジェクトにイベントを追加する関数です。

この2つは起動時に、window.onloadと併用しても使えます。

window.onloadは、複数書くと最後の1個だけが作動しますが(前にあるwindow.onloadは上書きされて消えてしまう)この関数を使うことで起動時の関数を複数動作させられます。

新ブログ「Big Bang」で続きを読む

DOMでIEのstyleタグやscriptタグに書込む法

Internet ExplorerのDOM操作で下のように、styleタグやscriptタグにtextNode
appendChildしようとするとエラーになります。そういう時の対処法です。

var css=document.createElement('style');
css.setAttribute('type','text/css');

var str=document.createTextNode('div.entryInfo{clear:both}'); css.appendChild(str);
var head=document.getElementsByTagName('head'); head[0].appendChild(css);

新ブログ「Big Bang」で続きを読む