riina-k.net

音楽・小説・プログラミングを手がけるリイナの拠点。

カテゴリー ‘ プログラミング

個人的に「これは組込み関数として必要だろ」っていうjavascript関数

// オブジェクトの結合
function merge()
{
	var result = {};
	for( var i=0; i<arguments.length; i++ ){
		var arg = arguments[i];
		for ( var itm in arg ) {
			if ( arg.hasOwnProperty(itm) ) {
				result[itm] = arg[itm];
			}
		}
	}
	return result;
}

// 配列 keys に存在する要素をキーとする値だけをオブジェクト obj から取り出す
function slice(obj, keys)
{
	var result = {};
	for ( var idx in keys ) {
		key = keys[idx];
		result[key] = ( obj.hasOwnProperty(key) ? obj[key] : null );
	}
	return result;
}

// PHPの array_walk() のクローン
function walk(obj, callback, param)
{
	for ( var idx in obj ) {
		var item = obj[idx];
		if ( typeof item != 'undefined' && typeof item != 'function' ) {
			callback(item, idx, param);
		}
	}
}

この3つ。
merge関数は「objectをマージする – javascript:humming bird」を参考に。
slice関数については関数名が適切じゃないかもしれない。
(本来 slice っていうと、配列のi番目からj番目までを切り出すっていう意味っぽいから)

この merge, slice, walk を組み合わせると、こんなことができる。(一応前提としてjQueryを使用、ほかのライブラリでも同様の記述はできるはず)

$(function(){
	// 元のデータを保持するオブジェクトを生成
	var obj = {
		id: 123,
		title: 'rk.tv',
		link: [
			'http://riina-k.net/',
			'http://riina-k.tv'
		]
	};
	// そこにプロパティを追加
	obj = merge( obj, { author: 'Riina K.', param: 'foooo' } );

	// さらに必要なプロパティのみを切り出す
	var target = slice( obj, ['title', 'author'] );

	function printHTML(item, key, jq)
	{
		jq.append( '<dt>' + key + '</dt>' + '<dd>' + item + '</dd>' );
	}

	// 切り出したプロパティそれぞれにコールバック関数を適用し、dlタグを出力
	$('body').append('<dl id="output"/>');
	walk( target, printHTML, $('dl#output') );
});

実行結果

<dl id="output"><dt>title</dt><dd>rk.tv</dd><dt>author</dt><dd>Riina K.</dd></dl>

オブジェクトやコールバック関数を多用するjavascriptだからこそ、こんな関数たちが居てくれると便利。

テーマ「FLAT」のHTML5化

導入しているWordPressテーマ「FLAT」をHTML5に対応させてみる。

……しかし、WordPress本体が直接HTMLを吐き出している箇所が多くあるため、完全なHTML5化は本体を改造しない限り不可能。
そんなわけで、「div id=”header”」を「header」に書き換えるなど、基本的なタグの置き換えに留まる。

と、ここで問題が。
このテーマは常に右下に「ページ最上部に戻るためのボタン」が表示されているが、
リンク先が「#header」だったため、headerタグに置き換えてしまうとリンクが機能しなくなる。
そこで、無条件でスクロールするようjavascriptを書き換えてみた。

scroll.js

	jQuery('a[href*=#header],a[href*=#respond]').click(function() {
		if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
			var $target = jQuery(this.hash);
			$target = $target.length && $target || jQuery('[name=' + this.hash.slice(1) +']');
			if ($target.length) {
				var targetOffset = $target.offset().top;
				jQuery('html,body').animate({ scrollTop: targetOffset }, 1200, 'quart');
				return false;
			}
		}
	});

これを以下のように書き換えて、リンク先が「#header」の場合は無条件でページの先頭までスクロールするように。

	jQuery('a[href*=#header]').click(function() {
		if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
			jQuery('html,body').animate({ scrollTop: 0 }, 1200, 'quart');
			return false;
		}
	});

	jQuery('a[href*=#respond]').click(function() {
		if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
			var $target = jQuery(this.hash);
			$target = $target.length && $target || jQuery('[name=' + this.hash.slice(1) +']');
			if ($target.length) {
				var targetOffset = $target.offset().top;
				jQuery('html,body').animate({ scrollTop: targetOffset }, 1200, 'quart');
				return false;
			}
		}
	});

return top