コンソールに出力する文字列を読みやすくする

以下のコードで元の文字列の各文字の位置を分かりやすくするための、補助的な文字列を生成できる
文字幅(=文字数)は元の文字列と同じとなる

var s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890';
console.log(s);
var t = s.replace(/[\s\S]{1,4}/g, function(m)
	{
		return '^'+new Array(m.length).join(' ')
	});
console.log(t);

出力結果

ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890
^   ^   ^   ^   ^   ^   ^   ^   ^   ^


関数化して、'^'が現れる位置を調整可能にしてみる

var s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890';

console.log(s);
console.log(f(s, 4));
console.log(f(s, 8));

function f(s, width){
	return s.replace(
		new RegExp('[\\s\\S]{1,'+(width || 4)+'}', 'g'), 
		function(m){
			return '^' + new Array(m.length).join(' ');
		});
}

出力結果

ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890
^   ^   ^   ^   ^   ^   ^   ^   ^   ^
^       ^       ^       ^       ^    

Unicode 空白文字等調査

Unicode 'Other, Format'カテゴリ (Cf)

コード 意味 バージョン コメント
U+200B ZERO WIDTH SPACE Unicode 1.1.0 幅の無い空白
U+200C ZERO WIDTH NON-JOINER Unicode 1.1.0
U+200D ZERO WIDTH JOINER Unicode 1.1.0
U+FEFF ZERO WIDTH NO-BREAK SPACE Unicode 1.1.0 幅の無い改行しない空白

Unicode 'Separator, Line'カテゴリ (Zl)

コード 意味 バージョン コメント
U+2028 Line Separator Unicode 1.1.0 LS

Unicode 'Separator, Paragraph'カテゴリ (Zp)

コード 意味 バージョン コメント
U+2029 Paragraph Separator Unicode 1.1.0 PS

Unicode 'Other, Control'カテゴリ (Cc)

コード 意味 バージョン コメント
U+0009 Horizontal Tabulation Unicode 1.1.0 HT, 水平タブ, \t
U+000A Line Feed Unicode 1.1.0 LF, ラインフィード, \n
U+000B Vertical Tabulation Unicode 1.1.0 VT, 垂直タブ, \v
U+000C Form Feed Unicode 1.1.0 FF, 改ページ, \f
U+000D Carriage Return Unicode 1.1.0 CR, キャリッジリターン, \r
U+0085 Next Line Unicode 1.1.0 NEL

Unicode 'Separator, Space'カテゴリ (Zs)

コード 意味 バージョン コメント
U+0020 SPACE Unicode 1.1.0 半角スペース
U+00A0 NO-BREAK SPACE Unicode 1.1.0 改行しない空白
U+1680 OGHAM SPACE MARK Unicode 3.0.0
U+180E MONGOLIAN VOWEL SEPARATOR Unicode 3.0.0
U+2000 EN QUAD Unicode 1.1.0 'n'幅の四角形
U+2001 EM QUAD Unicode 1.1.0 'm'幅の四角形
U+2002 EN SPACE Unicode 1.1.0 'n'幅の空白
U+2003 EM SPACE Unicode 1.1.0 'm'幅の空白
U+2004 THREE-PER-EM SPACE Unicode 1.1.0 1/3'm'幅の空白
U+2005 FOUR-PER-EM SPACE Unicode 1.1.0 1/4'm'幅の空白
U+2006 SIX-PER-EM SPACE Unicode 1.1.0 1/6'm'幅の空白
U+2007 FIGURE SPACE Unicode 1.1.0 フィギュアスペース, 等幅フォントの半分の幅, 数字用空白
U+2008 PUNCTUATION SPACE Unicode 1.1.0 約物スペース, 句読点用, 約物と同幅で横幅が狭い
U+2009 THIN SPACE Unicode 1.1.0 1/5'm'幅の空白, 細い空白
U+200A HAIR SPACE Unicode 1.1.0 ヘアスペース, 非常に細い空白
U+202F NARROW NO-BREAK SPACE Unicode 3.0.0 幅の狭い改行しない空白
U+205F MEDIUM MATHEMATICAL SPACE Unicode 3.0.0 中程度の幅の数学用空白
U+3000 IDEOGRAPHIC SPACE Unicode 1.1.0 和字間隔, 全角スペース


どこかの英語のサイトを参考にしました

タグを生成

追記:Bookmarkletとして実行するとm%60の部分がURLデコードされて構文エラーとなってしまうのを修正(とりあえず%の直後に空白を追加)

(function(){
	
	/* タイムスタンプを取得 */
	javascript:
	var d = new Date(), 
		o = d.getTimezoneOffset(), 
		m = Math.abs(o), 
		s = d.getFullYear() + 
			'-' + ('0' + (d.getMonth()+1)).slice(-2) + 
			'-' + ('0' + d.getDate()).slice(-2) + 
			'T' + ('0' + d.getHours()).slice(-2) + 
			':' + ('0' + d.getMinutes()).slice(-2) + 
			':' + ('0' + d.getSeconds()).slice(-2) + 
			(o < 0 ? '-' : '+') + ('0' + Math.floor(m / 60)).slice(-2) + 
			':' + ('0' + (m % 60)).slice(-2);
	prompt('TimeStamp(ISO 8601)', s);
	
	// 1行にまとめたもの
	javascript:
	var d=new Date,o=d.getTimezoneOffset(),m=Math.abs(o),s=d.getFullYear()+'-'+('0'+(d.getMonth()+1)).slice(-2)+'-'+('0'+d.getDate()).slice(-2)+'T'+('0'+d.getHours()).slice(-2)+':'+('0'+d.getMinutes()).slice(-2)+':'+('0'+d.getSeconds()).slice(-2)+(o<0?'-':'+')+('0'+Math.floor(m/60)).slice(-2)+':'+('0'+(m% 60)).slice(-2);prompt('TimeStamp(ISO 8601)',s)
	
	/* 短縮化 */
	javascript:
	var d = new Date, o = d.getTimezoneOffset(), m = Math.abs(o), s = d.getFullYear();
	with(d){['-','-','T',':',':',o<0?'-':'+',':'].forEach(function(e,i){
		s+=e+('0'+[getMonth()+1,getDate(),getHours(),getMinutes(),getSeconds(),Math.floor(m/60),m% 60][i]).slice(-2)
	})}
	prompt('TimeStamp(ISO 8601)', s);
	
	// 1行にまとめたもの
	javascript:var d=new Date,o=d.getTimezoneOffset(),m=Math.abs(o),s=d.getFullYear();with(d){['-','-','T',':',':',o<0?'-':'+',':'].forEach(function(e,i){s+=e+('0'+[getMonth()+1,getDate(),getHours(),getMinutes(),getSeconds(),Math.floor(m/60),m% 60][i]).slice(-2)})}prompt('TimeStamp(ISO 8601)',s);void(0)
	
	/* <ins>タグを生成 */
	javascript:
	var i = prompt('タグの内容', ''), d = new Date, o = d.getTimezoneOffset(), m = Math.abs(o), s = d.getFullYear();
	with(d){['-','-','T',':',':',o<0?'-':'+',':'].forEach(function(e,i){
		s+=e+('0'+[getMonth()+1,getDate(),getHours(),getMinutes(),getSeconds(),Math.floor(m/60),m% 60][i]).slice(-2)
	})}
	if(i)prompt('TimeStamp(ISO 8601)', '<ins datetime="' + s + '">' + i + '</ins>');
	
	// 1行にまとめたもの
	javascript:var i=prompt('タグの内容',''),d=new Date,o=d.getTimezoneOffset(),m=Math.abs(o),s=d.getFullYear();with(d){['-','-','T',':',':',o<0?'-':'+',':'].forEach(function(e,i){s+=e+('0'+[getMonth()+1,getDate(),getHours(),getMinutes(),getSeconds(),Math.floor(m/60),m% 60][i]).slice(-2)})}if(i)prompt('TimeStamp(ISO 8601)','<ins datetime="'+s+'">'+i+'</ins>');void(0)
	
})();

Bookmarkletで画像ビューア

Bookmarklet用の簡単なビューアVersion0.1(といっても1066文字もある・・・)


機能:

  • 実行すると、ページ内の<img>要素を順番に表示。
  • <img>要素が<a>要素に囲まれている場合は、<a>要素ごと表示。
  • Right, Leftで画像切り替え、Escでビューア終了。ビューア終了後、vで再度実行。
  • Rightで最初の画像より前に戻るか、Leftで最後の画像より先に進むとビューア終了。


テスト環境:Windows Vista SP2, Chrome 7.0.517.44

javascript:(function(a){function $(a,b,c){c=_.createElement(a);c.a=function(a){this.style.cssText=a};if(b)c.a(b);return c}var _=document,b=_.images,c=arguments.callee,d=_.body.appendChild($('div','position:fixed;left:0px;top:0px;width:100%;height:100%;background-color:rgba(0,0,0,.6);z-index:65535')),e=d.appendChild($('div','position:absolute;left:50%;top:50%;z-index:65535')),z='keydown',w=window,g=function(a){w.addEventListener(z,a,!1)},h=function(a){w.removeEventListener(z,a,!1)},j='U+001B';if(b.length==0)return;e.appendChild($('span'));function f(a,c){c=b.item(a);e.style.marginLeft=-c.width/2+'px';e.style.marginTop=-c.height/2+'px';e.replaceChild((/^a$/i.test(c.parentNode.tagName)?c.parentNode:c).cloneNode(true),e.firstElementChild)}f(a);g(function(e,k){k=e.keyIdentifier;if(k=='Left'?--a-a:k=='Right'?++a-a:k==j?0:1)return;e.preventDefault();if(a<0||b.length<=a||k==j){h(arguments.callee);_.body.removeChild(d);g(function(b){if(b.keyIdentifier=='U+0056'){b.preventDefault();h(arguments.callee);setTimeout(function(){c(k==j?a:0)},0)}});return}f(a)})})(0)

変数名・関数名・プロパティ名の短縮化をしてくれるJavaScriptコード圧縮機ってないかな。。。

DOMContentLoadedイベントのイベントターゲットを調べる

document.addEventListener('DOMContentLoaded', ...)という記述と
window.addEventListener('DOMContentLoaded', ...)という記述を見たので、どっちが正しいのだろうと思い、チェック用のHTML+jsを作成。


結果は、(IEを除く)どのブラウザでもdocumentがイベントターゲットとなっていた。IEはそもそもW3C DOMイベントモデルじゃないのでDOMContentLoadedをサポートしておらず問題外。

テスト環境

OS : Windows Vista SP2
Web Browser : Chrome 7.0.517.44 / Opera 10.63 / Firefox 3.6.12 / IE 8.0.6001.18975IC

テスト用コード (HTML+js)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>DOMContentLoaded タイミングチェック</title>
<script type="text/javascript">
<!--
var params = [
	{
		name : 'window', 
		target : window, 
		type : 'load'
	}, {
		name : 'window', 
		target : window, 
		type : 'DOMContentLoaded'
	}, {
		name : 'document', 
		target : document, 
		type : 'load'
	}, {
		name : 'document', 
		target : document, 
		type : 'DOMContentLoaded'
	}
];

var eventPhaseStr = {
	1 : 'CAPTURING_PHASE', 
	2 : 'AT_TARGET', 
	3 : 'BUBBLING_PHASE'
}

/** console.log, console.warnがない場合は適当なログ出力処理で代用 */
if( !window.console ){
	window.console = {};
	if( window.opera ){
		console.log = function(msg){
			window.opera.postError(msg);
		};
		console.warn = function(msg){
			console.log('WARNING: ' + msg);
		};
	}else{
		console.log = function(msg){
			alert(msg);
		};
		console.warn = function(msg){
			console.log('WARNING: ' + msg);
		};
	}
}

function makeListener(name)
{
	return function(e){
		console.log(name + ', ' + e.type + ', ' + eventPhaseStr[e.eventPhase]);
	};
}

function AddEventListener(element, type, listener, useCapture)
{
	if( element.addEventListener ){
		element.addEventListener(type, listener, useCapture);
	}else if( element.attachEvent ){
		console.warn('attachEvent used');
		element.attachEvent('on' + type, listener);
	}else{
		console.warn('event-handler used');
		element['on' + type] = listener;
	}
}

console.log('TARGET, TYPE, EVENT_PHASE');
for( var i=0, l=params.length; i < l; i++ )
{
	var e = params[i];
	AddEventListener(e.target, e.type, makeListener(e.name), false);
	AddEventListener(e.target, e.type, makeListener(e.name), true);
}
//-->
</script>
</head>
<body>
<h1 style="text-align : center">DOMContentLoaded タイミングチェック</h1>
</body>
</html>

テストした全ブラウザでconsole.log, console.warnの両方が使えた。いつからIEOperaには用意されているんだろう・・・

function文とfunction式の違い

console.log(typeof fn1);  // undefined
console.log(typeof fn2);  // function
var fn1 = function(){};
function fn2(){}

varによる変数宣言は、スコープに入ったとき変数の追加だけ行われ、宣言のある行で値の代入が行われる。それに対してfunction式で定義した関数は、スコープに入ったときから使用可能。なので

function Hoge(){}

var Hoge = function(){};

は完全に同じではない。