jQuery Mobileに起票してみました。
Beta -> Alpha版にしたら、同じname属性を持つチェックボックスが排他になっていた。
https://github.com/jquery/jquery-mobile/issues/1944#issuecomment-1540245
2011/07/01
2011/06/12
haskellのリストは便利
haskellのリストでは、閉区間の書き方がとても便利です。
1〜10のリストを作る場合、以下のように書きます。
間隔を指定する場合、以下のように書きます。この場合、3の間隔でリストが作られます。
せっかくなのでjsで実装。
1〜10のリストを作る場合、以下のように書きます。
ghci>[1,3..10]
間隔を指定する場合、以下のように書きます。この場合、3の間隔でリストが作られます。
ghci>[1,3..10] [1,3,5,7,9]
せっかくなのでjsで実装。
var ci = function(arg) {
argList = arg.split(".."),
pivo = argList[0];
// ,で区切られたデータからスタート値と間隔値を取り出す。
if (pivo.length !== 1) {
pivoList = pivo.split(",");
pivo = pivoList[0];
interval = pivoList[1] - pivo;
} else {
interval = 1;
}
pivo = parseInt(pivo);
interval = parseInt(interval);
for (len = argList[1]; pivo < len;pivo = pivo + interval) {
console.log(pivo);
}
};
con("1,3..10");
2011/05/04
jQuery1.6 attrとpropについて
今日、jQuery1.6出ましたね。
jQueryはバージョンが変わるたびに微妙に仕様が変わますね!
話はそれますが、先日も業務で$.ajaxを使っていたところ、1.4からserializeメソッドの挙動が変わったらしく、ものすごーくハマりました(別起票で書きます)。
話はそれましたが…1.6からattrの挙動が変わり、新しくpropメソッドが追加されました。
・1.6からattrメソッドの戻り値が変わる
こんなhtmlがあった場合
1.6より前
1.6以降
ただし、htmlにchecked属性が書かれていない場合(後から画面上でチェックを付けたりしても)
戻り値は、undefinedとなる!
・attrの代わりに、propメソッドを使うと…
propメソッドを使うと、戻り値がブール値で返ってきます。
チェックされてる場合
チェックされてない場合
・その他注意すること
1.セレクタで複数要素取得した場合、each等使い一個一個処理をする!
propメソッドは、「セレクタで複数要素を取得した場合、最初にマッチした要素しか処理しないよ!」とあるので、複数要素を処理したい場合は$.eachとかを使うようにする。
2.IE9より前のバージョンだと、使い方によってメモリーリークが起きるかも問題
詳しくは、ここを参照してください。
DOM要素がdocumentから削除されるより前に、対象のプロパティーが削除(.removeProp()とか使って)されてない場合、DOM要素のプロパティをプリミティブ型(数値、文字列、ブール値)以外にセットするのに.propメソッドを使うとメモリーリークが起きるっぽい
(Macだから試せないけど。誰かWindows使ってる人試してください)。
IEでメモリーリークを引き起こしたくなかったら、dataメソッド(DOM要素にメタデータを持たせるアレです)を使うと安全みたいです。
jQueryはバージョンが変わるたびに微妙に仕様が変わますね!
話はそれますが、先日も業務で$.ajaxを使っていたところ、1.4からserializeメソッドの挙動が変わったらしく、ものすごーくハマりました(別起票で書きます)。
話はそれましたが…1.6からattrの挙動が変わり、新しくpropメソッドが追加されました。
詳しくは本家にありますので、そちらもご参照ください。
※attrでの属性書き換えは、1.6.1になってから後方互換になりました。
なので、1.6.1を使えば問題は起きなさそうです。
・1.6からattrメソッドの戻り値が変わる
こんなhtmlがあった場合
<input type="checkbox" id="hoge1" checked="checked"/>
1.6より前
var hoge = $("#hoge1").attr("checked");
// 戻り値は、ブール値「true」
hoge === true;
1.6以降
var hoge = $("#hoge1").attr("checked");
// 戻り値は、文字列「"checked"」
hoge === "checked";
ただし、htmlにchecked属性が書かれていない場合(後から画面上でチェックを付けたりしても)
戻り値は、undefinedとなる!
<input type="checkbox" id="hoge1" />
var hoge = $("#hoge1").attr("checked");
// 戻り値は、文字列「undefined」
hoge === void(0);
・attrの代わりに、propメソッドを使うと…
propメソッドを使うと、戻り値がブール値で返ってきます。
チェックされてる場合
var hoge = $("#hoge1").prop("checked");
// 戻り値は、ブール値
hoge === true;
チェックされてない場合
var hoge = $("#hoge1").prop("checked");
// 戻り値は、ブール値
hoge === false;
チェック/非チェックの書き換えも簡単にできます
// チェックを付ける
$("#hoge1").prop("checked", true);
$("#hoge1").prop({checked:true});
// チェックを外す
$("#hoge1").prop("checked", false);
$("#hoge1").prop({checked:false});
・その他注意すること
1.セレクタで複数要素取得した場合、each等使い一個一個処理をする!
propメソッドは、「セレクタで複数要素を取得した場合、最初にマッチした要素しか処理しないよ!」とあるので、複数要素を処理したい場合は$.eachとかを使うようにする。
<form method="GET"> <input type="checkbox" id="hoge1" /> <input type="checkbox" id="hoge2" checked="checked"/> <input type="checkbox" id="hoge3" /> </form>
$.each($("input"), function() {
$(this).prop("checked", true);
});
2.IE9より前のバージョンだと、使い方によってメモリーリークが起きるかも問題
詳しくは、ここを参照してください。
DOM要素がdocumentから削除されるより前に、対象のプロパティーが削除(.removeProp()とか使って)されてない場合、DOM要素のプロパティをプリミティブ型(数値、文字列、ブール値)以外にセットするのに.propメソッドを使うとメモリーリークが起きるっぽい
(Macだから試せないけど。誰かWindows使ってる人試してください)。
IEでメモリーリークを引き起こしたくなかったら、dataメソッド(DOM要素にメタデータを持たせるアレです)を使うと安全みたいです。
2011/03/06
Flickrから画像を取得してくるSampleを書いた
Flickrから画像を取得して、表示するモジュールを書いた。
・キーワードを省略するとデフォルト「js」で検索されます。
・件数には整数値を入力してください。
数値チェックはめんどくさいのでやってません。
件数は100くらいがよいと思います(画像問い合わせが重いので)
demo:
http://shinya-api.appspot.com/sandbox/flickr/flickr.html
html:
css:
js:
せっかくなのでinputフォームにデフォルト文字列を埋め込むモジュールを
jQuery plugin形式にしてみました。
・キーワードを省略するとデフォルト「js」で検索されます。
・件数には整数値を入力してください。
数値チェックはめんどくさいのでやってません。
件数は100くらいがよいと思います(画像問い合わせが重いので)
demo:
http://shinya-api.appspot.com/sandbox/flickr/flickr.html
html:
<div id="hoge">
<img id="loading_img" src="img/loadinfo.gif" />
</div>
<div>キーワード : <input type="text" class="in" id="keyword" name="keyword" value="" /></div>
<div>件数 : <input type="text" class="in" id="size" name="size" value="" /></div>
<div><button onclick="flickr.exec();">exec</button></div>
<hr />
<div id="target"></div>
<script type="text/javascript" src="js/flickr.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.js"></script>
<script type="text/javascript" src="/js/shinya/jquery.toggleInputMsg.js"></script>
<script>
// id指定・オプション指定の場合
//$('#keyword').toggleInputMsg({'value':'ほげ','color':'red','inputColor': 'blue'});
// class指定、オプション無しの場合
$('.in').toggleInputMsg();
</script>
css:
body {
background-color:#000000;
color:#00ff00;
margin:0;
padding:0;
}
#hoge {
width:200px;
height:100px;
background-color:#6F6F6F;
opacity:0.8;
position:absolute;
display:none;
}
js:
/**
* JSONPでflickr APIへアクセス
*/
var flickr = (function() {
var B = document.body,
t = document.getElementById('target');
hoge = document.getElementById("hoge") || alert("要素がないよ"),
hst = hoge.style,
limg = document.getElementById("loading_img") || alert("要素がないよ");
limgs = limg.style,
d = document.documentElement;;
return {
/** APIを呼び出す */
exec : function() {
var script = document.createElement('script');
script.src = imageCreator.getApiURL();
B.appendChild(script);
hst.display = "inline";
hst.height = window.innerHeight;
hst.width = window.innerWidth;
limgs.position='absolute';
limgs.top = d.clientHeight / 2 -12;
limgs.left = d.clientWidth/ 2 -12;
},
/** APIのcallback */
callBackFuncForJson : function(data) {
var i,
photo,
photos = data.photos;
hst.display = "none";
for (i = 0; photo = photos.photo[i]; i++) {
var img = document.createElement('img');
img.src = imageCreator.getImageURL(photo);
t.appendChild(img);
}
if (i === 0) { alert('no much!');}
}
}
})();
/**
*creator
*/
var imageCreator = function() {
return {
getImageURL : function (photo) {
return "http://farm" + photo.farm +
".static.flickr.com/" + photo.server +
"/" + photo.id +
"_" + photo.secret +
"_s.jpg";
},
getApiURL : function () {
return "http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=d4009274a471c6b5448e87debe7d38bd"
+ "&format=json&jsoncallback=flickr.callBackFuncForJson&safe_search=1&content_type=1&sort=relevance"
+ "&text=" + (document.getElementById("keyword").value || "js")
+ "&per_page=" + (document.getElementById("size").value || "50");
}
};
}();
flickr.defaultMsgKeyword = "キーワードを入力してください";
flickr.defaultMsgNumber = "取得件数を入力してください";
(function() {
})
せっかくなのでinputフォームにデフォルト文字列を埋め込むモジュールを
jQuery plugin形式にしてみました。
/**
* テキストエリアのデフォルトメッセージを設定する。
* @author shinya
*/
var defaultMsg = "何か入れてください";
(function($) {
$.fn.toggleInputMsg = function(opt) {
var defaults = {
'value' : '入力してください',
'color' : '#696969',
'defaultColor' : '#000000'
}
var setting = $.extend(defaults, opt);
for (var i = 0, len = this.length; i < len; i++) {
this[i].style.color = setting.color;
this[i].value = setting.value;
this[i].addEventListener("focus", function() {
if (this.value == setting.value) {
this.style.color = setting.defaultColor;
this.value="";
}
});
this[i].addEventListener("blur", function() {
if (this.value == "") {
this.style.color = setting.color;
this.value=setting.value;
}
});
}
return this;
};
})(jQuery);
2011/03/02
列挙(Object.keysとObject.getOwnPropertyNames)
一般的な方法
forループの中でhasOwnProperty
オブジェクトのプロパティを列挙するときに一番良く使うのがこの方法だと思います。
これでも全然オッケーと思いますが、実はObject.keysという便利なものがあります。
これを使えば処理がスッキリかける!
Object.keysを使った方法
もし、Object.keysが実装されていないブラウザがあれば以下のような関数を
定義しとくと良いです。
Object.getOwnPropertyNamesを使った方法
Object.keysと似ていますが、Object.getOwnPropertyNameを使うと
コンストラクタを引数にすることもできます。
ちなみに・・・仕様はここにあります。
http://ecma262-5.com/ELS5_HTML.htm#Section_15.2.3.4
これらは新しいJavaScriptの仕様なので
今後活用する場面も増えてくるのではないでしょうか。
forループの中でhasOwnProperty
オブジェクトのプロパティを列挙するときに一番良く使うのがこの方法だと思います。
var exec = function() {
// 何かの処理
}
for (var e in obj) {
obj.hasOwnProperty(e) && exec();
}
これでも全然オッケーと思いますが、実はObject.keysという便利なものがあります。
これを使えば処理がスッキリかける!
Object.keysを使った方法
var hoge = {one:"hoge", two:"moge", three:"fuga"};
// オブジェクトがあれば、exec関数を実行する。
Object.keys(hoge) && exec();
もし、Object.keysが実装されていないブラウザがあれば以下のような関数を
定義しとくと良いです。
if (!typeof Object.keys) {
Object.key = function(obj) {
var prop,
keys = [];
if (typeof obj != "object" && typeof obj != "function") {
// 例外処理する。例えば、TypeErrorを投げる。
throw TypeError("引数にはオブジェクトを渡してください");
}
for (prop in obj) {
obj.hasOwnProperty(prop) && keys.push(prop);
}
return keys;
}
}
Object.getOwnPropertyNamesを使った方法
Object.keysと似ていますが、Object.getOwnPropertyNameを使うと
コンストラクタを引数にすることもできます。
var hoge = {one:"hoge", two:"moge", three:"fuga"};
// オブジェクトがあれば、exec関数を実行する。
Object.getOwnPropertyNames(hoge) && exec();
// オブジェクトがあれば、exec関数を実行する。
Object.getOwnPropertyNames(String) && exec();
Object.getOwnPropertyNames(Math) && exec();
ちなみに・・・仕様はここにあります。
http://ecma262-5.com/ELS5_HTML.htm#Section_15.2.3.4
これらは新しいJavaScriptの仕様なので
今後活用する場面も増えてくるのではないでしょうか。
2011/02/24
jQueryのclckでみる、bindとliveの違い
jQueryを使っていると似たような動きをするメソッドを見かけます。
今回はクリックイベントで呼ばれるbindとliveの違いをメモ。
jQuery1.3からliveが追加されました。
今まではjQueryのafterを使って動的に作られた要素に対してハンドラはバインドされませんでした。liveを使うことで動的に作った要素に対してもハンドラを呼び出すことができます。
HTML
スクリプト
demo :
liveを使うことで、動的に追加されたli要素に対して、自動的にイベントハンドラを
バインドしてくれます。
ちなみに、click()はbindのショートカットなので、bind('click', ハンドラ)と同じ動きをします。
今回はクリックイベントで呼ばれるbindとliveの違いをメモ。
jQuery1.3からliveが追加されました。
今まではjQueryのafterを使って動的に作られた要素に対してハンドラはバインドされませんでした。liveを使うことで動的に作った要素に対してもハンドラを呼び出すことができます。
HTML
<ul id="hoge1">bind("click", ハンドラ)
<li>ここは一回だけ押す</li>
</ul>
<ul id="hoge2">live("click", ハンドラ)
<li>ここは一回だけ押す</li>
</ul>
<ul id="hoge3">click(ハンドラ)
<li>ここは一回だけ押す</li>
</ul>
スクリプト
// イベントハンドラ。動的にli要素を追加する。
var handler = function() {
$(this).after('<li class="nc">ここをクリックして</li>');
}
$(function() {
$("li", "#hoge1").bind("click", handler);
$("li", "#hoge2").live("click", handler);
$("li", "#hoge3").click(handler);
});
demo :
- bind("click", ハンドラ)
- ここは一回だけ押す
- live("click", ハンドラ)
- ここは一回だけ押す
- click(ハンドラ)
- ここは一回だけ押す
liveを使うことで、動的に追加されたli要素に対して、自動的にイベントハンドラを
バインドしてくれます。
ちなみに、click()はbindのショートカットなので、bind('click', ハンドラ)と同じ動きをします。
2011/02/23
テキストボックスのデフォルト値を付けたり/消したりする(jQuery)
以前、テキストボックスのデフォルト値を付けたり/消したりするというネタを書きましたが、実装が雑だった(イベントのバインド方法とか)ので、jQueryで書き直してみました。
demo :
以前に比べるとjQueryっぽいソースになった気がします。
(今回はフラグをみないで、ただバインド/アンバインドをしているので、ロジックは少し変わっています。)
こんな感じのHTMLを用意しておいて…
こんな感じのスクリプトを書いてやります。
やっぱりjQueryで書くとスッキリしますね!
demo :
以前に比べるとjQueryっぽいソースになった気がします。
(今回はフラグをみないで、ただバインド/アンバインドをしているので、ロジックは少し変わっています。)
こんな感じのHTMLを用意しておいて…
<input type="text" name="input2" id="input2" value="" />
こんな感じのスクリプトを書いてやります。
// jQuery版
var defaultMsg = "何か入れてください";
$(function() {
$("#input2").val(defaultMsg)
.focus(function() {
($(this).val() == defaultMsg) && $(this).css("css", "#000000").val("");
})
.blur(function() {
($(this).val() == "") && $(this).css("css", "#696969").val(defaultMsg);
})
});
やっぱりjQueryで書くとスッキリしますね!
2011/02/17
Eclipseでnode.jsのデバッグする
Eclipseでnode.jsの開発をしている方に朗報。
Javaみたいにnode.jsをデバッグ実行できます。
■手順
1.node.jsをインストールしておく。
Terminalで「node」と打つとnode.jsが呼び出されるようになっていればおk。
2.Eclipse for JavaScriptをいれとく。
http://www.eclipse.org/downloads/packages/eclipse-ide-javascript-web-developers/heliossr1
3.Google Chrome Developer Tools for Javaをいれとく。
Eclipseのプライグインです。
http://code.google.com/p/chromedevtools/wiki/HowToInstall
4.EclipseでJavaScriptプロジェクトを作る。
プロジェクト名は何でもおk。
5.Githubにおいてあるサンプルソースをプロジェクトに追加。
https://github.com/ry/node/wiki/using-eclipse-as-node-applications-debugger
にあるdbgtest.jsはオススメ。
6.Terminalを開いて、Eclipseでいじっているファイルのディレクトリまでいく。
Macだとプロジェクトを選んだ状態で、cmd + iでプロジェクトがあるディレクトリを調べられます。
例)
7.node.jsをデバッグ実行する。
デフォルトだと、5858ポートでデバッグを開始します。
例)
8.Eclipseのデバッグの構成(Debug Configuration)を開き、デバッグ実行。
9.dbgtest.jsの関数にブレークポイントをはってみる。

10.ლ(^ω^ლ) デバッグできた!
やったね、たえちゃん!
■その他
ワークスペースから直接node.jsが実行できたら良さげですが、
今のところ、http://www.wickedshell.net/からプライグインをインスコして、シェルスクリプトで実行させる
という方法しかわからないです。
ant実行みたいにお手軽にやる方法があれば良いなぁ。
Javaみたいにnode.jsをデバッグ実行できます。
■手順
1.node.jsをインストールしておく。
Terminalで「node」と打つとnode.jsが呼び出されるようになっていればおk。
2.Eclipse for JavaScriptをいれとく。
http://www.eclipse.org/downloads/packages/eclipse-ide-javascript-web-developers/heliossr1
3.Google Chrome Developer Tools for Javaをいれとく。
Eclipseのプライグインです。
http://code.google.com/p/chromedevtools/wiki/HowToInstall
4.EclipseでJavaScriptプロジェクトを作る。
プロジェクト名は何でもおk。
5.Githubにおいてあるサンプルソースをプロジェクトに追加。
https://github.com/ry/node/wiki/using-eclipse-as-node-applications-debugger
にあるdbgtest.jsはオススメ。
6.Terminalを開いて、Eclipseでいじっているファイルのディレクトリまでいく。
Macだとプロジェクトを選んだ状態で、cmd + iでプロジェクトがあるディレクトリを調べられます。
例)
$ cd /Users/hoge/Documents/fuga/piyo
7.node.jsをデバッグ実行する。
デフォルトだと、5858ポートでデバッグを開始します。
例)
node --debug dbgtest.js
8.Eclipseのデバッグの構成(Debug Configuration)を開き、デバッグ実行。
9.dbgtest.jsの関数にブレークポイントをはってみる。

10.ლ(^ω^ლ) デバッグできた!
やったね、たえちゃん!
■その他
ワークスペースから直接node.jsが実行できたら良さげですが、
今のところ、http://www.wickedshell.net/からプライグインをインスコして、シェルスクリプトで実行させる
という方法しかわからないです。
ant実行みたいにお手軽にやる方法があれば良いなぁ。
2011/02/14
JavaScript Hoisting
JavaScriptの文法でハマりやすいものは色々あります。
先日購入した『JavaScript Pattern』に、昔よくハマってしまっていたhoistingについて書かれていたので、メモ。
hoistingはこんな感じです。
実際の結果は、「undefined」と「inner」が表示されます。
一番目のalert(hoge);でhogeという変数定義を一番近いスコープ(func関数)に探しにいき、そこで見つからなかった場合はグローバルに探しにいきます。
ですが、今回は関数内でhogeを定義しているため、関数内のhogeを参照します。
ただし、一番目のalert(hoge);が実行される時点では、hogeはまだ初期化されていないため
undefinedが表示されてしまいます。
こういうのを防ぐためにも、変数は極力最寄りの関数の先頭で初期化しておきたいですね。
先日購入した『JavaScript Pattern』に、昔よくハマってしまっていたhoistingについて書かれていたので、メモ。
hoistingはこんな感じです。
var hoge = "outer";
var func = function() {
// グローバルなhoge(outer)の表示を想定
alert(hoge);
var hoge = "inner";
// 関数内のhoge(inner)の表示を想定
alert(hoge);
}
func();
コメントに想定している結果が書いてありますが、実際の結果は、「undefined」と「inner」が表示されます。
一番目のalert(hoge);でhogeという変数定義を一番近いスコープ(func関数)に探しにいき、そこで見つからなかった場合はグローバルに探しにいきます。
ですが、今回は関数内でhogeを定義しているため、関数内のhogeを参照します。
ただし、一番目のalert(hoge);が実行される時点では、hogeはまだ初期化されていないため
undefinedが表示されてしまいます。
こういうのを防ぐためにも、変数は極力最寄りの関数の先頭で初期化しておきたいですね。
2011/02/10
JavaScript Patterns
オライリーから出てる『JavaScript Patterns』がすばらしい!
JavaScriptの作法がきちんとまとめられているし、本の厚さもあまりない。
globalな変数(globalへのプロパティ追加)とかは
こういったテクニックは、ライブラリのソースを読むのが一番勉強になりますが、
なかなか長いソースを読むのは大変です。
そこで、こういう本の出番なわけです。
JavaScriptでのこういういったテクニックは、今後どんどん必要になってくると思います。
ちなみに、この本はオライリーのサイトで少し読めますので、ぜひ試してみてはどうでしょう。
ここ
本の内容は、いずれこのブログでも扱っていこうと思います。
蝶本も、もちろんオススメですが、この鳩本(?)もかなりオススメですよ!
もうすぐ日本語版がでるようなので、ぜひ。
JavaScriptの作法がきちんとまとめられているし、本の厚さもあまりない。
globalな変数(globalへのプロパティ追加)とかは
(function ( window, undefined )
{
// jQueryの中身
})(window);
jQueryでは、こんな感じで実装している。こういったテクニックは、ライブラリのソースを読むのが一番勉強になりますが、
なかなか長いソースを読むのは大変です。
そこで、こういう本の出番なわけです。
JavaScriptでのこういういったテクニックは、今後どんどん必要になってくると思います。
ちなみに、この本はオライリーのサイトで少し読めますので、ぜひ試してみてはどうでしょう。
ここ
本の内容は、いずれこのブログでも扱っていこうと思います。
蝶本も、もちろんオススメですが、この鳩本(?)もかなりオススメですよ!
もうすぐ日本語版がでるようなので、ぜひ。
2011/02/02
テキストボックスのデフォルト値を付けたり/消したりする
仕事でテキストボックスのデフォルト値を書き換えるスクリプトを書くことになったので書いてみました。
5分ほど悩んで、やっぱ楽したい!と思ったので、クロージャで実装しました。
こんな感じのコードがあったときに
こんな感じのスクリプトを書いてみる。
一応、OREっていう変数を通してグローバル変数を汚さないようにしたつもりです。
chromeでprofilesを測定しましたが、functionをグローバルで定義しているよりもメモリ効率良く、処理回数も少ないみたいです(?)。だいぶ適当ですが。
書いてて思ったことが2つ。
1つ目は、クロージャーって楽だなと。
楽ばっかりしてると脳みそがふやけそう。
なので、たまにはゴリゴリ系ソース(フラグを沢山使って、配列とかグルグルするソース)を書かないといけないな、と思いました。
2つ目は、jQueryの恩恵に預かろうってことです。
jQueryでこのソースを書けば、きっと3分の1くらいになるんじゃないかなと思います。
けど、まぁ、ちょっとくらいならクロージャもありかなと思ったりしています。
5分ほど悩んで、やっぱ楽したい!と思ったので、クロージャで実装しました。
こんな感じのコードがあったときに
<form method="GET">
<input type="text" name="hogeNm" id="input" value="" />
<input type="submit" value="submit" />
</form>
<button onclick="ORE.toggle(document.getElementById('input'));">GO</button>
こんな感じのスクリプトを書いてみる。
var ORE = function($) {
var _mes = "デフォルトバリュー";
var hoge = document.getElementById("input");
$.onsubmit = function() {
if (hoge.value == _mes || hoge.value == "") {
hoge.value = "同じじゃねーか";
}
};
// フラグが立っていたらイベントをバインド
var bind = function(e) {
e.onfocus = function() {
if (e.value == _mes) {
e.value = "";
}
};
e.onblur = function() {
if (e.value == "") {
e.value = _mes;
}
};
return false;
}
// フラグが立っていなかったらイベントをアンバインド
var unbind = function(e) {
// この関数内でアンバインドしたいイベントにundefinedとかをセットする。
// e.onblur = undefinedとか。void(0)でもいいかも。
// とりあえず、アンバインドされたらアラートを出す処理をいれておきます。
e.onfocus = function() {
alert("アンバインドされた");
};
e.onblur = function() {
alert("アンバインドされた");
};
return true;
}
return {
// OREのメソッドとして関数を定義しときます。
toggle: function () {
var flg = true;
return function(e) {
hoge.value = _mes;
flg = flg ? bind(e) : unbind(e);
};
}()
};
}(window);
一応、OREっていう変数を通してグローバル変数を汚さないようにしたつもりです。
chromeでprofilesを測定しましたが、functionをグローバルで定義しているよりもメモリ効率良く、処理回数も少ないみたいです(?)。だいぶ適当ですが。
書いてて思ったことが2つ。
1つ目は、クロージャーって楽だなと。
楽ばっかりしてると脳みそがふやけそう。
なので、たまにはゴリゴリ系ソース(フラグを沢山使って、配列とかグルグルするソース)を書かないといけないな、と思いました。
2つ目は、jQueryの恩恵に預かろうってことです。
jQueryでこのソースを書けば、きっと3分の1くらいになるんじゃないかなと思います。
けど、まぁ、ちょっとくらいならクロージャもありかなと思ったりしています。
2011/01/23
世界の車窓から.js
昨日、世界の車窓からを見てて、かなり良い曲が流れていた。
The Shores of the Swilly』 by.Phil Coulterって曲です。
世界の車窓からっていつも良い曲を使ってる気がしたので、そんな曲をすぐに調べれるように
「世界の車窓から」を見ながら一覧表を作りました。
Demo:
http://shinya-api.appspot.com/sandbox/shasou.html
shasou.js:
The Shores of the Swilly』 by.Phil Coulterって曲です。
世界の車窓からっていつも良い曲を使ってる気がしたので、そんな曲をすぐに調べれるように
「世界の車窓から」を見ながら一覧表を作りました。
Demo:
http://shinya-api.appspot.com/sandbox/shasou.html
shasou.js:
/**
* created_atの日付がよくわからんことになってるので、
* とりあえずこれはつかわない。
*/
// function makeEtc(e) {
// var date = e.created_at.split(" ");
// console.dir(date);
// return date[2] + "日 " + date[3];
// }
/**
* その他項目を作る
*/
function getMusicNm(al) {
var i;
var buffer = "";
for (i = 4; i < al.length; i++) {
buffer += al[i];
}
return buffer;
}
/**
* テーブルに表示する内容
* いつも決まったフォーマットで呟かれないのが難点
*/
function shasouParser(elem) {
var al = elem.text.split(" ");
if (al.length < 5) {
//return makeEtc(elem);
return "- - - - ";
} else {
return "
" + al[0] + " "+ al[1] + "放送 " + al[2] + " " + al[3] + " " + getMusicNm(al) + " ";
}
}
/**
* JSON取得
*/
$(function() {
$.getJSON("http://api.twitter.com/1/statuses/user_timeline/Sekai_no_Shasou.json?callback=?", function(d) {
var i;
var appendStr = ""; var table = document.getElementById("ta"); for (i = 0; i < d.length; i++) {
var elem = d[i];
appendStr += shasouParser(elem);
}
appendStr += "
";
table.innerHTML =appendStr;
}, "json");
});
こんな感じのスクリプトを、以下のようなHMTLで呼んでやる。 hoge.html:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js"></script>
<style>
body {
background-color: #696969;
}
table {
width: 100%;
border-collapse: collapse;
}
table td {
border: 1px #4cdd09 solid;
}
</style>
<h1>世界の車窓から</h1>
<table>
<thead>
<tr>
<td>放送</td>
<td>シリーズ名</td>
<td>タイトル</td>
<td>その他</td>
</tr>
</thead>
<tbody id="ta">
</tbody>
</table>
<script type="text/javascript" src="shasou.js"></script>
やぱjQueryだと作業効率良い良い(^ω^)
車窓、いいよ車窓♪
2011/01/19
MacのターミナルでJavaScriptを実行する(V8)
V8とは、Googleが開発しているJavaScriptの実行エンジンです。
Google ChromeやAndroid Browserで使われています。
Google Chromeのコンソールからも使えますが、あえてコマンドラインからやりたい場合があります。
Fire Foxなどで採用されているRhinoをコマンドで使う方法は、MacのターミナルでJavaScriptを実行するよ(Rhino)を見てください。
前準備
Terminalを起動します。
/Applications/Utilities/Terminal.app
もしくは、
アプリケーションフォルダ内のユーティリティフォルダの中にTerminalというソフトがあるので、コイツをクリックします。
python版make(?)の「Scons」インストール。
ソースをダウンロードしてきます。
http://www.scons.org/
ダウンロードしたファイルを解凍して、解答したディレクトリ下に移動します。
Sconsをインストールします。
$ pwd
/Users/${user}/Develop/scons-2.0.1
$ sudo python setup.py install
管理者パスワードを聞かれるかもしれないので、入力してあげてください。
ソースをsvnを使用してチェックアウトします(macには元々svnが入ってると思います)
$ svn checkout http://v8.googlecode.com/svn/trunk/ v8-read-only
$ cd v8-read-only/
v8をビルドします
$ scons d8 console=readline
(行での編集を有効にする)オプションを付けたい場合(なくても良い)
$ scons d8 console=readline
これでオッケーです。試しに実行してみます。
./d8
d8> print("hello, world");
hello, world
d8> quit();
便利にアクセスできるように「/usr/local/bin」下にインストールしておきます(なくても良い)
オプションの-mで、アクセス権を設定しています(余談ですが、アクセス権設定はここがオススメです)。
ユーザーには読み書き実行権限を、グループ・その他には読み込み実行権限を付けています。
$ sudo install -m 755 d8 /usr/local/bin
$ d8
d8> print("hello, world");
hello, world
d8> quit();
参考URL
http://code.google.com/intl/ja/apis/v8/build.html
http://diaspar.jp/node/214
これでブラウザを使わなくても、JSができます。
やったねたえちゃん!
2011/01/14
jQueryプラグインの中に出てくるセミコロン「;」
jQueryプラグイン
jQueryプラグインのソースを読んでいると、無名関数の先頭にセミコロン「;」を付けているのを見かけたりします。
たとえば、fancyboxとかがそうです。
;(function($){
..etc
})(jQuery);
jQueryの$関数みたいなものかな?と思いつつ、JSLintとかで文法チェックするとエラーになりますよ。
ただ、なんとなく予想はついていたので、ググってみると英語のフォーラムに書いてありました。
http://markmail.org/message/3gppon7hfmw7jqr7
ざっくり書くと、「セミコロンが先頭にあるプラグインを読み込む前に、セミコロンがちゃんと書かれていないコードがあるとバグッちゃうからつけといたよ!」ということですね。
jsでのセミコロン
jsではセミコロンの自動補完という謎の機能があるため、こんな感じの残念なソースがあります。
var hoge = "hoge";
console.log(hoge)
この例だと、logメソッドの末尾にセミコロンがありません。
イミフwwwうはwwwwおkwwww
ただ、自動でセミコロンが補完されるので「動くことは動きます」。
var hoge = "hoge";
console.log(hoge)
var moge = "moge";
console.log(moge);
ただし、こんな場合はエラーになります。
圧縮ツールとかにかけた場合
var hoge = "hoge";console.log(hoge)var moge = "moge";console.log(moge);
改行が削除されてエラーになります。
無名関数の場合
var hoge = "hoge";
console.log(hoge)
(function() {
var moge = "moge";
console.log(moge);
})();
とかそんな感じ。
なぜ文頭にセミコロンをつけるのか
文末にセミコロンをつけないソースの後ろにコピペしたpluginのソースを貼った場合(もしくはソースをYUI Compressorとかのツールで圧縮した場合)は、無駄な改行が消されて、一行のソースになったりします。
こういう場合に、直前の文でセミコロンがなくても、問題が起きないように文頭にセミコロンを付けています。
var hoge = "hoge";console.log(hoge);;(function() {var moge = "moge";console.log(moge);})();
文末にセミコロンはちゃんと付けましょう。ってことですね。
2011/01/02
グラフを書いてみた
HTML5やらjQueryやら、便利なライブラリがあるのは嬉しい限りです。
ただ、それらってどうやって実装してるんだろう。
APIの使い方を理解している、ライブラリの種類を沢山おぼえている、…本当にそれで良いのだろうか。プログラマとして!
ということで、今年は低レベルAPIの実装とかを意識していけたら良いなぁと思ってます(・ω・)
Demo :
Code:
ドットをひたすらならべたようなグラフになっています。
var anim = function() {
// x,y軸の座標作成カウンタ
var i = 0;
// x軸の最大値
var lim = 650;
// グラフコンテナ
var container = document.getElementById('container');
// 座標関数(X)
var getX = function() {
return i;
}
// 座標関数(Y)サインコサインタンジェント
var getY = function() {
return 100 - 100 * Math.sin(0.01 * i);
}
return function() {
var ten = document.createElement('div');
ten.style.left = getX() + 'px';
ten.style.top = getY() + 'px';
ten.className = 'ten';
container.appendChild(ten);
// yは計算回数減らすために変数にとっちゃう。
// やっぱやめる。リミット値まで描画したら処理をストップする。
document.getElementById("prot").innerHTML = "x:" + getX() + " y:" + getY();
if (i < lim) {
i++;
} else {
clearInterval(timer);
}
};
}();
// タイマーセット!
var timer = setInterval(anim, 10);
2010/12/31
flip tableをやってみる
flipTableっていう、文字を反転させて表示させるのを見かけた。
面白そうなので、自分でも作ってみました。
flipってのは、ひっくり返るってことです。
例えば、pはdにmはwになります。
String.prototype.flipString = function() {
// 変換対象の長さ
var length = this.length;
// 結果文字列を作るための配列
var ar = new Array(length);
// 変換文字用テーブル
var flipTable = {
a : '\u0250',
b : 'q',
c : '\u0254',
d : 'p',
e : '\u01DD',
f : '\u025F',
g : '\u0183',
h : '\u0265',
i : '\u0131',
j : '\u027E',
k : '\u029E',
m : '\u026F',
n : 'u',
r : '\u0279',
t : '\u0287',
v : '\u028C',
w : '\u028D',
y : '\u028E',
'.' : '\u02D9',
'[' : ']',
'(' : ')',
'{' : '}',
'?' : '\u00BF',
'!' : '\u00A1',
"\'" : ',',
'<' : '>',
'_' : '\u203E',
'\u203F' : '\u2040',
'\u2045' : '\u2046',
'\u2234' : '\u2235',
'\r' : '\n'
}
// 処理対象文字列のインデックスカウンタ
var i;
// 処理対象文字
var chara;
// 処理対象文字列
var last = length - 1;
// 変換処理
for (i = 0; i < length; i++) {
chara = this.charAt(i);
ar[last - i] = flipTable[chara] || chara;
}
return ar.join('');
}
こんな感じで呼び出せます。
alert("hoge".flipString());
2010/12/30
canvas要素に感動した
HTML5って今まで避けてきたけど、これ見て感動しました。
リンク先ページで10秒くらい我慢して眺めてみてください!
こんなのが作れるなんて・・・なんて素晴らしいcanvas!
HTML5は来年の春頃からやろうと思ってますが、ちょっとデモを作ってみた。
var canvas = document.createElement('canvas');
document.body.appendChild(canvas);
var anim = function() {
var i = 0;
var canCon= canvas.getContext('2d');
canCon.beginPath();
return function() {
canCon.fillRect(i++, 50, 100, 50);
};
}();
// アニメーション実行
setInterval(anim, 100);
【実行手順】
1.chromeのコンソール画面開いて、↑のソースをペッと貼る。
2.ブログの一番下までスクロールする。そしたら黒い棒みたいのがウネウネ動きますよ!
2010/12/28
http://snipplr.com/に投稿してみた
http://snipplr.com/というサイトを見つけたので
試しに投稿してみた。
何を投稿したら良いか分からないので、適当にurlからファイル名を取得するのを書いたました。
CVS Viewerとかで「ファイル名 + クエリ文字列」が欲しいときに、ワンライナーで使うことを想定。
http://snipplr.com/view/46280/get-current-filename-from-url/
まぁ・・・テスト投稿だからいっか。
英語で書いたコメントからも適当加減が伝わってくるな、これ。
2010/12/27
文字コードテーブルを書いた
とくにネタが思い浮かばなかったので、jsで文字コードテーブルを書いた。
(function() {
// counter
var i;
// limit
var lim = 128;
// strings
var str = '';
var getChar = function(idx) {
var chara = String.fromCharCode(idx);
switch (chara)
{
case '\b' :
return 'バックスペース';
break;
case '\t' :
return 'タブ文字';
break;
case '\n' :
return '改行';
break;
case '\v' :
return '垂直タブ';
break;
case '\f' :
return 'LF 改行ページ';
break;
case '\r':
return 'CR 復帰';
break;
case '\"' :
return 'ダブルクオーテーション';
break;
case '\'' :
return 'シングルクオーテーション';
break;
case '\\' :
return 'バックスラッシュ';
break;
default :
return chara;
}
};
for (i = 0; i < lim; i++) {
str += i + ' : [' + getChar(i) + '], ';
if ((i + 1) % 10 == 0) {
str += '\n';
}
}
console.log(str);
})();
getChar関数の処理で、switch文をオブジェクトリテラルで書き換えると以下のようになります。
var getChar = function(idx) {
var chara = String.fromCharCode(idx);
var escapeChara = {
'\b' : 'バックスペース',
'\t' : 'タブ文字',
'\n' : '改行',
'\v' : '垂直タブ',
'\f' : 'LF 改行ページ',
'\r': 'CR 復帰',
'\"' : 'ダブルクオーテーション',
'\'' : 'シングルクオーテーション',
'\\' : 'バックスラッシュ',
};
return escapeChara[chara] || chara;
};
2010/12/25
無名関数内と無名コンストラクタ内でのthis
JSでthisを使うことってよくありますが、これって便利だけど分かりにくい時ありますね。
無名関数内でのthisはwindowオブジェクトを参照しています。
(function() {
console.log(this === window);
})();
// true
無名コンストラクタ呼び出しの場合、windowオブジェクトではなく
newされたオブジェクトをさします。
new function() {
console.log(this === window);
}();
// false
ちなみに、無名のコンスラクタでnewされたオブジェクトがさしているものを列挙してみます。
new function() {
console.log(this.__proto__.__proto__ === Object.prototype);
}();
// true
new function() {
console.log(this.__proto__.__proto__.constructor === Object);
}();
// true
登録:
投稿 (Atom)




