riina-k.net

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

【Keyアレンジ】 ハリウッド・デカはこうしてお星様になったのであった

先日開催されたオンラインKeyアレンジイベント Thanks, Key 3 に投稿した2曲目です。

原曲は「Angel Beats!」より「theme of SSS」、「planetarian」より「Gentle Jena」です。どちらも超名曲です。よりにもよって混ぜちゃいました。
タイトルでお気付きの方、さすがです。さらに他のなにかが混ざってます。

試聴は以下のリンクからよろしくです。
Thanks, Key 3 内のページ(mp3, 128kbps)
rk.tv 内のページ(mp3, 96kbps)

続きを読む

【Keyアレンジ】 Trampoline Girl (More Higher)

先日開催されたオンラインKeyアレンジイベント Thanks, Key 3 に投稿した1曲目です。

原曲はつい先日PC全年齢対象版も発売された「クドわふたー」より氷室先輩のテーマ「Trampoline Girl」。アレンジアルバムでボーカル化も果たした名曲です。
破天荒な行動に定評のある氷室先輩ですが、私のアレンジも破天荒で何をし始めるか分かりません

試聴は以下のリンクからよろしくです。
Thanks, Key 3 内のページ(mp3, 128kbps)
rk.tv 内のページ(mp3, 96kbps)

続きを読む

Thanks, Key 3 に2曲投稿しました!

Thanks, Key 3

Keyアレンジのオンラインイベント「Thanks, Key 3」に今回も2曲投稿しました。いまのところ皆勤!

1曲目:クドわふたー「Trampoline Girl」
2曲目:Angel Beats!「theme of SSS」 + planetarian「Gentle Jena」

楽曲の詳しい情報は公開され次第追記しようと思います。

2013/07/02追記
楽曲が公開されたので、個別記事を作成しました。
1曲目:「Trampoline Girl (More Higher)」
2曲目:「ハリウッド・デカはこうしてお星様になったのであった」

docomo GALAXY SIII α にMNP → 即root化 → IIJmioで運用してるGALAXY NoteとSIMを入れ替えてみた

auを裏切って突然のMNP!!

GALAXY S III α 最高です。空きメモリ普通に1ギガ超えてサクサク。
でもやっぱりroot取らないと遊び込めないよね!
ってことで。

GALAXY S III α と GALAXY Note のroot取った
これでAndroid端末5台のうちrootを取ってないのはEVO3Dだけとなりました。

ここでひとつ、以前からの疑問を解消すべく、両者のSIMを差し替える実験。
「GALAXY Note がLTEを掴まないのは回線の問題か端末の問題か」

まず、microSIMを抜くのに苦労した。コツを掴んでしまえば、爪先でSIMの端っこを片側ずつ押して、あとは上から指で押さえて小刻みに左右に動かしながら押し抜く感じ。

GALAXY S III α にIIJmioのSIM差して「やべえ通信できない!」ってなってたら単純にAPNの設定忘れてただけでした。
APN: iijmio.jp
ユーザー名: mio@iij
パスワード: iij
認証タイプ: PAPまたはCHAP
お馴染みのコレを設定したら……LTE掴んだ!!

一方、docomo純正SIMを差した GALAXY Note のほうは、APNの設定画面に入ろうとすると落ちる。
こりゃ完全に端末側の問題っすね。root取ったばっかりだけどファクトリーリセットかけてみますか。

ちなみに GALAXY S III α はIIJmio公式の動作確認バージョンが「SC03EOMAMA6」となってますが、最新の「SC03EOMAMC3」でもちゃんと動作するようです。
https://www.iijmio.jp/guide/outline/hdd/devices.jsp

カテゴリごとにTwitterウィジェットを切り替えるプラグイン作ってみた

ごぶさたーーーー!

ここ最近、TwitterクライアントとかRuby on RailsとかWordPressとかいろんなものを触る機会が増えた。
触るだけで成果が見えないのももったいないので、軽くWordPressプラグインを作ってみた。

TwitterPerCategory

名前のまんま。
私のようにジャンルごとにTwitterアカウントを使い分けてる人が多いか少ないかは分からないけど、
私の場合
 プログラミング → @Riina_Kw_pg
 音楽 → @Riina_Kw_m
 小説 → @Riina_Kw_nv
と、3ジャンルに分けてて、このWordPressも同様のカテゴリ分けをしてる。

ここで困ったことが。
世に出回ってるTwitterプラグインは複垢に対応してない!

てことで、自分で作ってみた。(地産地消)

現時点では「とりあえず公式ウィジェットの貼り付け」だけだけど、いずれはカテゴリごとのデザイン変更とか該当カテゴリへの投稿時にTwitterに自動投稿とかも実装したい。

05/09 追記:
データの持ち方にバグがあるようで、いまウィジェットが表示されてません。もう一度調べなおしてみます。

Javascript の prototype を学び始めた

既に存在するオブジェクトの振る舞いを変えてしまう prototype。
どう上手く扱えばいいのか、少しずつ勉強を始めてみた。

まず書いてみたのが、textarea から入力文字列を受け取る際、改行コードを統一する関数。

String.prototype.replaceAll = function (org, dest)
{
	return this.split(org).join(dest);
}

String.prototype.uniformLF = function()
{
	return this.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
}

正規表現を必要としない簡単な全置換が定義されていないため、replaceAll 関数を定義したのち、それを利用して改行コードを全置換。

これがうまく行ったので、以前の記事個人的に「これは組込み関数として必要だろ」っていうjavascript関数で作った関数を改造してみた。

Object.prototype.merge = function(arg)
{
	for ( var idx in arg ) {
		if ( arg.hasOwnProperty(idx) && typeof arg[idx] != 'undefined' && typeof arg[idx] != 'function' ) {
			this[idx] = arg[idx];
		}
	}
	return this;
}

Object.prototype.sliceKeys = function(keys)
{
	var result = {};
	for ( var idx in keys ) {
		var key = keys[idx];
		var item = this[key];
		if ( typeof item != 'undefined' && typeof item != 'function' ) {
			result[key] = ( this.hasOwnProperty(key) ? item : null );
		}
	}
	return result;
}

Object.prototype.walk = function(cb, param)
{
	if ( !cb ) {
		return;
	}
	for ( var idx in this ) {
		if ( this.hasOwnProperty(idx) ) {
			var item = this[idx];
			if ( typeof item != 'undefined' && typeof item != 'function' ) {
				cb(item, idx, param);
			}
		}
	}
}

for( … in …… ) の構文だと、プロパティやメソッド、prototype で指定したメソッドまで現れてしまうので、this.hasOwnProperty() 関数を多用するハメに。

しかしこれのおかげで、前の記事で書いたサンプルコードがこんな感じに豹変。

// 元のデータを保持するオブジェクトを生成
var obj = {
	id: 123,
	title: 'rk.tv',
	link: [
		'http://riina-k.net/',
		'http://riina-k.tv'
	]
};

function printHTML(item, key, jq)
{
	alert( '<dt>' + key + '</dt>' + '<dd>' + item + '</dd>' );
}
$('body').append('<dl id="output"/>');
	
// そこにプロパティを追加、切り出したプロパティそれぞれにコールバック関数を適用し、dlタグを出力
obj.merge({ author: 'Riina K.', param: 'foooo' }).sliceKeys(['title', 'author']).walk( printHTML, $('dl#output') );

追加したメソッドの戻り値のおかげで、メソッドチェーンを使って複雑な処理も1行で書けるようになった! これは便利。

遅延ロードのライブラリをクロスブラウザ対応

先日の記事「遅延ロードをライブラリ化してみた」がIEで動作しなかった原因が分かったので、一部書き直し。

delayload.js

変更点は2箇所。ひとつは「オブジェクトのプロパティとして class という名前は使用できない」という制約があるため、これを「target」というプロパティ名に変更。
もう一つは、img要素を生成する際、先にwidth, heightを設定してからsrcを設定してしまうと、IEでは先に設定したサイズを無視してオリジナルサイズでwidth, heightを上書きしてしまうため、srcを設定してからwidth, heightを設定という順番に変更。

var DelayLoad = {
	target: "delay",
	error: "error",
	retry: 1,
	init: function(params)
	{
		if ( params && params.hasOwnProperty("target") ) {
			this.target = params.target;
		}
		if ( params && params.hasOwnProperty("retry") ) {
			this.retry = params.retry;
		}
		if ( params && params.hasOwnProperty("error") ) {
			this.error = params.error;
		}
		
		// 対象のjQueryオブジェクトにパラメータを設定
		var jqTarget = jQuery( "*[class^='" + this.target + "']" );
		for ( i=0; i<jqTarget.length; ++i ) {
			jQuery.data( jqTarget.get(i), "retry", this.retry );
			jQuery.data( jqTarget.get(i), "error", this.error );
		}
		jqTarget.each(function(){
			// 引数をパース
			var paramsString = this.className.split(";")[1];
			var arrParams = paramsString.match(/^params=\{(.*?)\}$/)[1].match(/([a-z]+):('(.*?)'|[0-9]+)/g);
			var objParams = {};
			for ( i=0; i<arrParams.length; ++i ) {
				var tmp = arrParams[i].split(":");
				if ( tmp[1].match(/^'(.*?)'$/) ) {
					objParams[ tmp[0] ] = RegExp.$1;
				} else {
					objParams[ tmp[0] ] = tmp[1];
				}
			}
			if ( !objParams.hasOwnProperty("url") ) {
				throw "DelayLoad: url required";
			}
			if ( !objParams.hasOwnProperty("title") ) {
				objParams.title = "";
			}
			if ( !objParams.hasOwnProperty("retry") ) {
				objParams.retry = jQuery.data( this, "retry" );
			}
			objParams.error = jQuery.data( this, "error" );
			
			var jqImg = jQuery("<img />");
			// エラー時のイベントハンドラ
			jqImg.bind("error", function(e){
				// 再試行回数だけリロード
				var retry = jQuery.data( this, "retry" );
				if ( --retry > 0 ) {
					jQuery.data( this, "retry", retry );
					this.src = this.src;
				} else {
					// 試行回数切れ
					var target = jQuery.data( this, "target" );
					var error = jQuery.data( this, "error" );
					target.replaceWith(error);
					// 後始末
					jQuery.removeData( this, "retry" );
					jQuery.removeData( this, "error" );
					jQuery.removeData( this, "target" );
				}
			});
			// ロード時のイベントハンドラ
			jqImg.bind("load", function(e){
				var target = jQuery.data( this, "target" );
				target.replaceWith( jQuery(this) );
				// 後始末
				jQuery.removeData( this, "retry" );
				jQuery.removeData( this, "error" );
				jQuery.removeData( this, "target" );
			});
			// 再試行回数を設定
			jQuery.data( jqImg.get(0), "retry", objParams.retry );
			// エラーHTMLを設定
			jQuery.data( jqImg.get(0), "error", objParams.error );
			// 画像置換対象
			jQuery.data( jqImg.get(0), "target", jQuery(this) );
			// 読み込み
			jqImg.attr("src", objParams.url);
			if ( objParams.hasOwnProperty("width") ) {
				jqImg.attr("width", objParams.width);
			}
			if ( objParams.hasOwnProperty("height") ) {
				jqImg.attr("height", objParams.height);
			}
			if ( objParams.hasOwnProperty("title") ) {
				jqImg.attr("alt", objParams.title);
			}
		});
	}
};

DelayLoad デモ

現時点では、以下のブラウザで動作を確認。

  • [Windows XP] IE 8.0
  • [Windows XP] Firefox 13.0.1
  • [Windows XP] Opera 11.64
  • [Windows 7] Opera 23.0

クロスブラウザ対応がとりあえずできたということで、今回をもって「DelayLoad ver 1.0」としますか。
前回書いたものはβ版ってことで。

デモファイルは http://riina-k.net/delayload/1.0/ 以下にあるので、欲しい人はソース漁ってください 要望があればzipにまとめてDLできるようにしますかねー。

遅延ロードをライブラリ化してみた

先ほどのエントリー「画像ロード時のエラー制御で試行錯誤」で組んだjavascript、エラー制御というより「読み込み中」的な意味で使い回しができそうなので汎用性を持たせてライブラリ化。

delayload.js

DelayLoad = {
	class: "delay",
	error: "error",
	retry: 1,
	init: function(params)
	{
		if ( params && params.hasOwnProperty("class") ) {
			this.class = params.class;
		}
		if ( params && params.hasOwnProperty("retry") ) {
			this.retry = params.retry;
		}
		if ( params && params.hasOwnProperty("error") ) {
			this.error = params.error;
		}
		
		// 対象のjQueryオブジェクトにパラメータを設定
		var jqTarget = jQuery( "*[class^='" + this.class + "']" );
		for ( i=0; i<jqTarget.length; ++i ) {
			jQuery.data( jqTarget.get(i), "retry", this.retry );
			jQuery.data( jqTarget.get(i), "error", this.error );
		}
		jqTarget.each(function(){
			// 引数をパース
			var paramsString = this.className.split(";")[1];
			var arrParams = paramsString.match(/^params=\{(.*?)\}$/)[1].match(/([a-z]+):('(.*?)'|[0-9]+)/g);
			var objParams = {};
			for ( i=0; i<arrParams.length; ++i ) {
				var tmp = arrParams[i].split(":");
				if ( tmp[1].match(/^'(.*?)'$/) ) {
					objParams[ tmp[0] ] = RegExp.$1;
				} else {
					objParams[ tmp[0] ] = tmp[1];
				}
			}
			if ( !objParams.hasOwnProperty("url") ) {
				throw "DelayLoad: url required";
			}
			if ( !objParams.hasOwnProperty("title") ) {
				objParams.title = "";
			}
			if ( !objParams.hasOwnProperty("retry") ) {
				objParams.retry = jQuery.data( this, "retry" );
			}
			objParams.error = jQuery.data( this, "error" );
			
			var jqImg = jQuery("<img />");
			// エラー時のイベントハンドラ
			jqImg.bind("error", function(e){
				// 再試行回数だけリロード
				var retry = jQuery.data( this, "retry" );
				if ( --retry > 0 ) {
					jQuery.data( this, "retry", retry );
					this.src = this.src;
				} else {
					// 試行回数切れ
					var target = jQuery.data( this, "target" );
					var error = jQuery.data( this, "error" );
					target.replaceWith(error);
					// 後始末
					jQuery.removeData( this, "retry" );
					jQuery.removeData( this, "error" );
					jQuery.removeData( this, "target" );
				}
			});
			// ロード時のイベントハンドラ
			jqImg.bind("load", function(e){
				var target = jQuery.data( this, "target" );
				target.replaceWith( jQuery(this) );
				// 後始末
				jQuery.removeData( this, "retry" );
				jQuery.removeData( this, "error" );
				jQuery.removeData( this, "target" );
			});
			// 再試行回数を設定
			jQuery.data( jqImg.get(0), "retry", objParams.retry );
			// エラーHTMLを設定
			jQuery.data( jqImg.get(0), "error", objParams.error );
			// 画像置換対象
			jQuery.data( jqImg.get(0), "target", jQuery(this) );
			// 読み込み
			if ( objParams.hasOwnProperty("width") ) {
				jqImg.attr("width", objParams.width);
			}
			if ( objParams.hasOwnProperty("height") ) {
				jqImg.attr("height", objParams.height);
			}
			if ( objParams.hasOwnProperty("title") ) {
				jqImg.attr("alt", objParams.title);
			}
			jqImg.attr("src", objParams.url);
		});
	}
};

使い方はこんな感じ。

<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/delayload.js"></script>
<script type="text/javascript">
	jQuery(function(){
		DelayLoad.init({
			error: "<strong style='color:red;'>読み込みに失敗しました</strong>"
		});
	});
</script>
<body>
	<strong>画像直リン</strong>
	<img class="delay;params={url:'images/ongakuji.jpg',width:480,height:270,title:'音楽寺'}" src="images/loading.gif" width="16" height="16" />
	<strong>意図的に2秒待たせるPHP</strong>
	<img class="delay;params={url:'wait2seconds.php',width:480,height:270,title:'音楽寺(2秒遅れ)'}" src="images/loading.gif" width="16" height="16" />
	<strong>存在しないリンクを3回再試行</strong>
	<img class="delay;params={url:'no_longer_exists',width:480,height:270,title:'存在しないURL',retry:3}" src="images/loading.gif" width="16" height="16" />
</body>

実行結果はこんな感じ。DelayLoad デモ

軽く解説。
あらかじめjQueryがロードされていることが条件。
DOMのロードが終わった状態で、DelayLoad.init()関数を実行する。
このとき引数として置換対象クラスclass、エラー時に表示されるHTMLerror、再試行回数retryをパラメータとするオブジェクトを渡すことができる。
値を省略した場合、対象クラスは「delay」、エラーメッセージは「error」、再試行回数は1回。

DelayLoad.init({class:"mydelay",retry:3});

HTMLでは、置換パラメータをクラス指定の中に記述する。
最終的にはクラス指定した要素が画像で置き換わるので、クラス指定をするのはimgタグである必要はない。
パラメータの指定方法は 「init関数で指定したクラス名;params={……}」、前記のとおり、クラス名のデフォルトは「delay」。
paramsにはいくつかのパラメータを書くことができる。
url : 必須、読み込む画像のURL。
width : 画像を表示する横幅、省略した場合はimgタグでwidthを書かなかったときと同じ動作。
height : 画像を表示する縦幅、省略した場合はimgタグでheightを書かなかったときと同じ動作。
title : 画像のaltに設定される画像のタイトル。省略した場合はaltが出力されない。
retry : エラー時の再試行回数。init関数での指定よりも優先される。省略した場合はinit関数の設定またはデフォルト値。

<img class="delay;params={url:'images/ongakuji.jpg',width:480,height:270,title:'音楽寺'}" src="material/loading.gif" width="16" height="16" />

現時点ではIEには対応してません。
要望があればバージョンアップしたいなー。

return top