どうしても名前空間を汚染したい時のjquery拡張

jsonpとかフラッシュから関数呼びたい時とかグローバルな名前空間汚したい時ってありますよね?
他と名前ぶつからないようにするの大変ですよね?
(注意:jquery.ajaxjsonp呼び出す時はjqueryが内部で同じような事をしています)

作り方

jquery.makeNS.jsとか適当に名前をつけて保存します。

/* (C) makoto@2ch.to */
if(typeof jQuery === 'function' && typeof jQuery.makeNS === 'undefined' ) jQuery.makeNS = function($_){
	var $			= jQuery;
	var $default	= {
		top			: window,
		prefix		: 'jQuery_',
		object		: {}
	};
	$_ = $.extend($default,typeof $_ === 'function' ? {object:$_} : $_);
	var $c	= $.now();
	var $ns	= null;
	while( typeof $_['top'][ $ns = $_['prefix'] + $c ] !== 'undefined' ) $c++;
	$_['top'][$ns] = $_['object'];
	return $ns;
};

準備

〜の中でjQueryと先ほど作ったjquery.makeNS.jsをロードします。

<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.min.js"></script>
<script type="text/javascript" src="./jquery.makeNS.js"></script>

使い方

//window[$ns]に空のオブジェクトがセットされます。
var $ns = $.makeNS();
//window[$ns]に関数がセットされます。
var $ns = $.makeNS(function($_){console.log($_)});
//引数topで渡したオブジェクトの$nsに引数object(関数でも定数でも良い)で渡したオブジェクトがセットされます。
var $ns	= $.makeNS({
	top    : window, //TOPのオブジェクト(省略可能)
	prefix : 'jQuery_', //名前空間の先頭文字(省略可能)
	object : {}, //名前空間にセットするオブジェクト(省略可能)
});

formに値を渡すjquery拡張

formに値入れるのにいちいち
$(':input[name=name1]').val('value1');
$(':input[name=name2]').val('value1');
 :
…って書くのがめんどくさいのでまとめて渡す拡張

作り方

jquery.fillInForm.jsとか適当に名前をつけて保存します。

/* (C) makoto@2ch.to */
(function($){
	$.fn.extend({
		fillInForm : function($_){
			var $self = this;
			if( typeof $_ === 'string' ){
				if( typeof $.parse === 'undefined' ) throw 'please install jQuery parse plugin';
				$_ = $.parse($_);
			}
			$.each($_,function($k,$v){
				$(':input[name='+$k+']',$self).val($v);
			});
		}
	});
})(jQuery)

準備

〜の中でjQueryと先ほど作ったjquery.fillInForm.jsをロードします。

<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.min.js"></script>
<script type="text/javascript" src="./jquery.fillInForm.js"></script>
<!-- ↓なくても動きますがロードしてあるとテキストも渡せるようになります -->
<script type="text/javascript" src="./jquery.parse.js"></script>

使い方

オブジェクトを渡すだけです。idではなくnameですのでご注意ください。

//基本的な使い方
$('form').fillInForm({
  name1 :'value1',
  name2 : value2'
});

jquery.parse.jsと連動します。

//jquery.parse.jsがロードしてあればqueryっぽい文字列が渡せます
$('form').fillInForm('name1=value1&name2=value2');

//もちろんparseメソッドの返り値をそのまま渡してもOK
var $query = $.parse();
$('form').fillInForm($query);

jQueryにquery parserを追加する拡張

query_string(location.search)をパースしてオブジェクトを返す拡張

作り方

jquery.parse.jsとか適当に名前を付けて保存します。

jquery pluginはjQuery.fn.extend(object)を利用するのが作法ですがjQuery.parse()みたいな呼び出し出来なくなるので強引に拡張しています。
jquery pluginとしては非常にお行儀の悪い書き方ですので真似しないでください。
コメントによるとこの拡張方法で問題無いみたいです

if(typeof jQuery === 'function' && typeof jQuery.parse === 'undefined' ) jQuery.parse = function($_){
	var i,$R = {};
	$_	= arguments.length === 0 ? location.search : new String($_);
	if( (i = $_.indexOf('?')) != -1 ) $_ = $_.substring(i+1);
	if( (i = $_.indexOf('#')) != -1 ) $_ = $_.substring(0,i);
	jQuery.each( $_.split('&') ,function(){
		var $_  = this.split('=');
		if( typeof $_[0] === 'undefined ' || $_[0] === '') return;
		var $k	= decodeURIComponent($_[0]);
		var $v	= $_.length === 1 ? true : decodeURIComponent($_[1]);
		if( $k.match(/(.+)\[\]$/) ){
			$k = RegExp.$1;
			if( !jQuery.isArray($R[$k]) ) $R[$k] = [];
			$R[$k].push($v);
		}else{
			$R[ $k ] = $v;
		}
	});
	return $R;
};

準備

〜の中でjQueryと先ほど作ったjquery.parse.jsをロードします。

<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.min.js"></script>
<script type="text/javascript" src="./jquery.parse.js"></script>

使い方

どちらもオブジェクトが返ります。

//引数が無い場合location.searchを解析します。
var $query = $.parse();
console.log($query);

//文字列を渡すと渡した文字列を解析します。
var $query = $.parse('test.html?key1=value1&key2=value2_1&key2=value2_2&key3&key4=&key5[]=value5_1&key5[]=value5_2#hash');
console.log( $query );

console.log( 'key' in $query               );//keyが存在するか調べる
console.log( $query['key1'] === 'value1'   );//右辺がそのまま値になる
console.log( $query['key2'] === 'value2_2' );//同じ名前が2回存在する場合後からの値で上書きされる
console.log( $query['key5']                );//ただしkeyが[]で終わる場合配列になる
console.log( $query['key3'] === true       );//=が無い場合trueになる
console.log( $query['key4'] === ''         );//=の右辺が無い場合空文字になる

某ニュースサイトに紹介してもらった

「やばいサーバ負荷耐えれるかな?」とか浮かれてたのですがamazonってやっぱすごいですね。
まったく落ちる/不安定になるとか無しに1ドル程度で処理できちゃいました。

せっかくなので今回の構成の詳細を書いて行きたいと思います。

DNSサーバ

value-domainを利用しています。
(時々ポカをしてる気がしますが)無料で利用できるし名前解決が遅いということも無くそこそこ安心して利用してます。

WEB(静的コンテンツ)サーバ

ドメイン名のbacketを作成するとCNAMEレコードを設定するだけで、そのまま独自ドメインの(静的コンテンツ)サーバに出来ます。
最近はディレクトリーインデックスやエラードキュメントも設定できるのでめちゃくちゃ便利です。
注意点は
CGIやサーバサイドインクルード(SSI)は利用できないし別のサービスと組み合わせないとSSLも利用できないのと
「アップロードするときにpublicにするのを忘れないように!」<これ大切

今回はHTML,CSS,JSは全部S3にお任せしました。
エラードキュメントで特定のHTMLを呼び出してHTMLからJSでAPIを叩くという仕組みにしてるのでほとんどのアクセスはS3が処理してます。

APIサーバ

CRUD(今回はUに該当する処理はありません)はEC2のmicro instanceを利用しました。
個人のサービスのほとんどを置いてるサーバですが大部分はS3においたHTMLとJSが面倒みてくれてるので
APIは最低限のチェックとS3の操作だけで済むので普段と負荷は変わりませんでした。

細かい話だと、完全に設計ミスで取得処理がJSだけでは出来ずphp呼び出してるのが気になってしょうがないので今後のアップデートで対応したいと思っています。

DBサーバ

S3でコンテンツと同じバケット使ってます。
今回はプライマリーキーのみなので、普通のサーバだとinodeがきになりますがS3使ってるとまったく気にしなくていいのでがんがんファイルアウトしてます。

IE対策>見た目>コード

「技術者仲間には作るの早かったね」って言われるのですがこのサービス作るのにコードは200行前後しか書いておらず
IEが動かなかったり、他と違う挙動していて調査や調整にほとんどの時間割いていて最低限の動作だけなら3時間くらいで出来ちゃってます。

今必要な技術って適切なライブラリ/モジュールを見つけられる事なんだなと思いました。

アクセス量やら負荷やら

作ったサービスが技術者向けなせいか、二番煎じだったせいか、紹介当日で1000人/日〜翌日は300人/日くらいで
紹介してくれた記事が大手ポータルサイトに転載されてたのでもっと期待してたのですがアクセスしにくい状況以前でサーバが暇すぎて困るくらいでした。

確かに紹介無かったよりは増えてるのですがSEOスパムの実験した時のほうがアクセス量は増えますorz
yahooに記事載った!とかだとまた違うのかな?

大きいサイトに紹介してもらうとアクセス数増えるんですね!って言いたかったのになぁってのが率直なところでした。

二番煎じで作っちゃいました。一度だけアクセス可能なURLを生成するネットサービス

一度だけアクセス可能なURLを生成するネットサービスα

gigazine.netさんでOne Time SecretというWEBサービスを紹介していましたが
日本語を入力するとエラーになるみたいで、twitterを見ていると日本語対応しないかな〜?とささやかれてたので作っちゃいました

技術的には

ブラウザサイドで、パスフレーズを使ってテキストを可逆暗号化(blowfish)し、パスフレーズは非可逆暗号化(MD5)し
サーバサイドには暗号化された情報しか渡ってこないので非常にセキュアです。(その為SSLも必要ない)
もちろん取り出し時も入力されたパスフレーズを非可逆暗号化(MD5)し
URLのキーとMD5が一致した場合のみ可逆暗号化されたデータを返すようになっており、複合はブラウザサイドで行っています。
もちろん漏えいしないに越したことはないですが、万が一データファイルが漏えいしても解読は非常に困難な仕組みになっています。
ただし、大部分をブラウザサイドで行っているのでJavaScriptは必須です。

インフラは…

・html,javascript等はAmazon S3に配置してバーチャルホスト設定
・アルプリケーション(保存と取り出し)はAmazon EC2(Apache+PHP)
・データファイルはAmazon S3に保存
と、AWSにべったりな構成になっています。

最後に…

感想、要望、不具合報告は、この記事にコメントいただくか、twitterにお願いします。
また、はてぶ、twitterでの拡散大歓迎ですのでよろしくお願いします。

一度だけアクセス可能なURLを生成するネットサービスα

formをajaxで呼び出すjquery拡張

formに入力させてsubmitされたらajaxphp呼び出して〜って良くある処理を簡略化する拡張

jQureryを拡張する。

jquery.ajaxFrom.jsとか適当に名前を付けて保存します。
〜内にではさんで書いても大丈夫。

/* (C) makoto@2ch.to */
if(jQuery) jQuery.fn.extend({
	ajaxForm	: function($_){
		var $opt = {};
		if( typeof $_ === 'function' ) $opt.success = $_;
		if( typeof $_ === 'object'   ) $opt = $.extend($opt,$_);
		return $(this).submit(function(event){
			event.preventDefault();
			return jQuery.ajax($.extend({
				url			: jQuery(this).attr('action'),
				type		: jQuery(this).attr('method'),
				data		: jQuery(this).serialize(),
				dataType	: jQuery(this).attr('data-type') || 'json',
			},$opt) );
		});
	}
});

jqueryjquery.ajaxForm.jsを呼び出す

jQueryの後にロードしないとダメ

<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.min.js"></script>
<script type="text/javascript" src="./ajaxForm.js"></script>

使い方は二通り

関数を渡す

submitが押されてajax通信がsuccessだった時の処理を関数で渡します。

var $opt = jQuery('#form').ajaxForm(function($_){
	console.log($_);
});
オブジェクトを渡す

jQuery.ajaxが受け付けるパラメータならなんでも書けます。

var $opt = {
	success:function($_){
		console.log($_);
	},
	error: function(){
		//エラー処理
	}
};
jQuery(form).ajaxForm($opt);
その他

デフォルトだとactionの実行結果はjsonを期待しています。
htmlやtextが変える場合formにdata-typeエレメントを定義することで変更することができます。

<form action="login.php" method="post" data-type="html">
<input type="text" name="i">
<input type="password" name="p">
</form>

お気に入りのエロ画像

お気に入りのエロ画像

最近ガラケーからスマートフォンに変更したのでjquery mobileを試してみたくなったので
jquery mobileとgoogle ajax apiを利用してスマートフォン向けエロ画像サイト作ってみました。
RSSやWEB APIを利用していますがphpは使わずにHTMLとJavaScriptのみで実装しています。
(refererを見て画像へのアクセスを禁止するサイトがあるのでサーバサイドでちょっと小技を使っています。)

エロい人はいいました「エロは技術力を上げる為の燃料になる!! 」

お気に入りのエロ画像