2008年9月30日火曜日

seekAttention: ページ内の特定要素をハイライトするjQueryプラグイン

「ほら、ここを見てください」と指をさして知らせるように、ページ内の特定部分をハイライトできるjQueryのプラグインです。

seekAttention
(http://enhance.qd-creative.co.uk)

HTMLでマークアップできる要素なら、たいていはハイライト表示できるようです。

リンク


パラグラフ


INPUTフィールド


画像


とても魅力的なプラグインなのですが、いくつか問題を含んでいるとホームページで注意を喚起しています。
実際に使用する際は十分にテストするのをお忘れなく。

2008年9月29日月曜日

あなたのコードでもぜひ使うべきRubyの21の小技

知っていると非常に便利そうなRubyの小技集

21 Ruby Tricks You Should Be Using In Your Own Code
(http://www.rubyinside.com/21-ruby-tricks-902.html)

Rubyビギナーには目がクラクラしそうなコードが並んでるけど、こういうのを自然に使いこなせたらできる人に見えるかも。

サンプルとしてふたつほど抜粋

and と or を使って処理をグループ化する

queue = []
%w{hello x world}.each do |word|
queue << word and puts "Added to queue" unless word.length < 2
end
puts queue.inspect

# Output:
# Added to queue
# Added to queue
# ["hello", "world"]

今まではこんな風に書いてました...
queue = []
%w{hello x world}.each do |word|
unless word.length < 2
queue << word
puts "Added to queue"
end


文字列やシンボル以外をハッシュのキーに使う
does = is = { true => 'Yes', false => 'No' }
does[10 == 50] # => "No"
is[10 > 5] # => "Yes"

今まではこんな風に書いてました...とうか真偽値をキーに使えるなんて知りませんでしたよ。
does = is = { true => 'Yes', false => 'No' }
bool1 = 10 == 50
does[bool1] # => "No"
bool2 = 10 > 5
is[bool2] # => "Yes"


可読性とのかねあいもあるけど、短くワンラインで書けるならそっちの方がいいように個人的には思います。

2008年9月27日土曜日

jQuery Context Menu Plugin: コンテキストメニュー(右クリックメニュー)を操作するプラグイン


特定の要素の上で右クリックすると、準備しておいたメニューが現れるというjQueryのプラグイン。
方法によっては非常に強力な使い方ができそうです。

jQuery Context Menu Plugin
(http://abeautifulsite.net)
デモ

デモのコンテクストメニューは Edit, Cut, Copyなどが用意されています。
HTMLは下のような感じ。

<ul id="myMenu" class="contextMenu">
<li class="edit">
<a href="#edit">Edit</a>
</li>
<li class="cut separator">
<a href="#cut">Cut</a>
</li>
<li class="copy">
<a href="#copy">Copy</a>
</li>
<li class="paste">
<a href="#paste">Paste</a>
</li>
<li class="delete">
<a href="#delete">Delete</a>
</li>
<li class="quit separator">
<a href="#quit">Quit</a>
</li>
</ul>

Editの場合、Aタグのhref属性に #edit と指定されていますが、#をのぞいた edit がメニューの選択時にactionとして引数に渡されてきます。
Aタグにclassを指定することもできますが、class名とaction名がかぶるとうまく動かないようなので注意。


$(document).ready( function() {
$("#selector").contextMenu({
menu: 'myMenu'
},
function(action, el, pos) {
alert(
'Action: ' + action + 'nn' +
'Element ID: ' + $(el).attr('id') + 'nn' +
'X: ' + pos.x + ' Y: ' + pos.y + ' (relative to element)nn' +
'X: ' + pos.docX + ' Y: ' + pos.docY+ ' (relative to document)'
);
});
});

第1引数はプラグインのオプション。
menu は使用するメニューのID名です。

ドキュメントには書かれていませんが
inSpeed, outSpeed というオプションも指定できるようです。
これはメニューの出現/消滅時の fadeIn/fadeOutの引数に渡されています。
(指定しない場合は inSpeed=150, outSpeed=75)


第2引数はコールバック関数。
メニューが選択された時に呼び出されます。
actionはメニューで指定したAタグのhref属性です。 (href="#[action]")



メソッドが5つ用意されています。

disableContextMenu() / enableContextMenu()
コンテクストメニューの解除/適用
$('#selector').disableContextMenu(); //#selectorのメニューを解除
$('#selector').enableContextMenu(); //#selectorにメニューを再適用


disableContextMenuItems(expr) / enableContextMenuItems(expr)
$('#myMenu').disableContextMenuItems('#cut,#copy'); //cutとcopyだけメニューから解除
$('#myMenu').enableContextMenuItems('#cut,#copy'); //cutとcopyを再適用


destroyContextMenu
マッチする要素をプラグインから外します。

jQueryでJSONP

jQuryだとJSONPを行うのに余計なライブラリを読み込んだり、DOM操作でSCRIPTタグをああだこうだする必要ないので簡単。
普通にAJAXの処理を書く延長で対応できます。


jQuery.getJSON( url, [data], [callback] )

一番シンプルな書き方。

$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?",
function(data){
$.each(data.items, function(i,item){
$("").attr("src", item.media.m).appendTo("#images");
if ( i == 3 ) return false;
});
});

コールバック関数を jsoncallback=? のように書くのがポイント。
こうすると引数の関数がコールバックで呼び出されます。

jQuery.getJSONのドキュメント
http://docs.jquery.com/Ajax/jQuery.getJSON



jQuery.ajax( options )

ちょっと複雑な処理 (例えばJSONPの 開始と終了時(註1) 終了時に何かを行うとか) をしたい時には jQuery.ajax を使うのが無難です。
$.ajax({
url : 'http://api.flickr.com/services/feeds/photos_public.gne',
data : {
tags : 'cat',
tagmode : 'any',
format : 'json'
},
dataType : 'jsonp',
jsonp : 'jsoncallback',
complete : function(){
//通信終了時の処理

},
success : function(data, status){
//通信が成功した場合の処理 (JSONPのコールバック関数はこれが呼ばれます)

},
beforeSend : function(){
//通信開始時の処理

},

error : function(){
//通信が失敗した場合の処理

}

});

基本的にはAJAXの処理と書き方は同じです。

特徴的なのは dataType に jsonp を指定すること。
これだけでクロスドメインの通信が可能に。

そして、jsonpオプションでコールバック関数のパラメーター名を指定しています
これはどういうことなのかというと、jQueryはデフォルトでコールバック関数名をcallback というパラメーター名で補完します。
http://api.flickr.com…&callback=?

ただ、Flickrがそうであるようにパラメーター名は普通独自の名前を持っています。(Flickrの場合はjsoncallback)
jsonpオプションはこのパラメーター名を指定するためのオプションです。
{jsonp : 'jsoncallback'}
http://api.flickr.com…&jsoncallback=?


jQuery.ajaxのドキュメント
http://docs.jquery.com/Ajax/jQuery.ajax

※ 註1

Note: All remote (not on the same domain) requests should be specified as GET when 'script' or 'jsonp' is the dataType (because it loads script using a DOM script tag). Ajax options that require an XMLHttpRequest object are not available for these requests. The complete and success functions are called on completion, but do not receive an XHR object; the beforeSend and dataFilter functions are not called.

$.ajax では jsonpで beforeSend などコールバック関数もコールされると思っていましたが、勘違いでした。
実際にコールされるのはsuccess complete だけですのでご注意を。


追記:

上記の制限を解決してくれるプラグインがあるようです。

Google Code: jquery-jsonp
http://code.google.com/p/jquery-jsonp/

エラーハンドリング、キャッシング、タイムアウトなど、デフォルトでは対応できない機能が使えるようになるみたいなので、必要な方は使ってみてはどうでしょうか。

2008年9月25日木曜日

Google App EngineのDjangoヘルパーで認証してみる

Djangoヘルパーを使えばApp Engine上でも簡単に独自の認証システムを導入できると思ってたら、どうやらそうじゃないみたい。
あくまでUsers API前提の仕様みたいです。

それでもデコレーターとかタグとか色々便利そうなので使ってみることにしました。


モデル

user という UserProperty が入っているのがDjangoオリジナルと違う所。
もうひとつ違う点は get_djangouser_for_user というクラスメソッドが追加されています。

appengine_django.auth.models

class User(BaseModel):
user = db.UserProperty(required=True)
username = db.StringProperty(required=True)
first_name = db.StringProperty()
last_name = db.StringProperty()
email = db.EmailProperty()
password = db.StringProperty()
is_staff = db.BooleanProperty(default=False, required=True)
is_active = db.BooleanProperty(default=True, required=True)
is_superuser = db.BooleanProperty(default=False, required=True)
last_login = db.DateTimeProperty(auto_now_add=True, required=True)
date_joined = db.DateTimeProperty(auto_now_add=True, required=True)
groups = EmptyManager()
user_permissions = EmptyManager()

@classmethod
def get_djangouser_for_user(cls, user):
query = cls.all().filter("user =", user)
if query.count() == 0:
django_user = cls(user=user, email=user.email(), username=user.nickname())
django_user.save()
else:
django_user = query.get()
return django_user


初回ログイン時に自動的にDatastoreにユーザー情報が放り込まれるようです。

あとは普通のDjangoの認証システムとあまり変わりません。
viewで request.user.is_authenticated() のようなメソッドが使えます。


デコレーター
from appengine_django.auth.decorators import login_required

@login_required
def index(request):
・・・

これだけでログインしていないユーザーを弾くことができます。


テンプレート

{% auth_login_url %} => ログインのURL
{% auth_logout_url %} => ログアウトのURL


Google App Engine Helper for Django
(http://code.google.com/p/google-app-engine-django/)

jQuery Autocomplete: 入力値をAjaxで補完するjQueryプラグイン


フォームに文字の一部を入力するとマッチする結果をAjaxで返してくれるオートコンプリート。
例えば、appleのホームページの検索ボックスは、"ip" と入力するとiphoneやipodを自動で表示してくれます。

jQuery Autocompleteはオートコンプリート機能を手軽に実装できるjQueryのプラグインです。

jQuery Autocomplete Mod
(http://www.pengoworks.com)

使い方はいたってシンプルです。
まずはjQuery Autocompleteからjavascriptファイルとcssファイルをダウンロード。

<script type="text/javascript" src="/javascripts/jquery.autocomplete.js"></script>
<link rel="stylesheet" type="text/css" href="/stylesheets/jquery.autocomplete.css" />
パスは自分の環境に合わせてください


id_name というidを持つinput要素にjQuery Autocompleteを適用します。(もちろんid名はなんでもかまいません)
<input type="text" name="name" value="" id="id_name" />

<script type="text/javascript">
$(document).ready(function(){
$('#id_name').autocomplete('autocomplete_ajax.php');
});
</script>

オートコンプリートはAjaxで通信しますので、サーバー側で検索処理などを行うスクリプトを置いておく必要があります。(上の例では autocomplete_ajax.php)

では、jQuery Autocompleteは具体的にどうやって通信しているのでしょうか?

Ajax云々の処理は、プラグインが内部的にやってくれるので特に気にする必要はありません。

例えば、id_nameというフィールドが国名を期待するものであるなら、
"A" と一文字入力すると Afghanistan, Argentina, Australia などの国名のリストをサーバーが返してくるようにスクリプトを書くだけです。

"A"が入力されると...

クライアント -> サーバー
autocomplete_ajax.php?q=A というリクエストが送信されます

サーバー
qというキーを持つGETパラメータを利用して、データベースなどから目的のリストを取得します。
取得したリストを\n区切りにしてクライアントに返します。
Afghanistan\nArgentina\nAustralia...

あとはjQuery Autocompleteが\n区切りを解析してULタグの中に放り込んでくれます。



jQuery Autocompleteは第2引数でオプションを指定することができます。
くわしくはドキュメントを参照してください。

ここでは jQuery Autocompleteのデモを参考に、コールバック関係のオプションのサンプルをまとめておきます。
<script type="text/javascript">
function findValue(li) {
if( li == null ) return alert("No match!");

// if coming from an AJAX call, let's use the CityId as the value
if( !!li.extra ) var sValue = li.extra[0];

// otherwise, let's just display the value in the text box
else var sValue = li.selectValue;

alert("The value you selected was: " + sValue);
}

function selectItem(li) {
findValue(li);
}

function formatItem(row) {
return row[0] + " (id: " + row[1] + ")";
}

$(document).ready(function(){
$('#id_name').autocomplete('autocomplete_ajax.php', {
onItemSelect : selectItem,
onFindValue : findValue,
formatItem : formatItem
});
});
</script>

2008年9月21日日曜日

Timer: 繰り返し処理を行うためのjQueryプラグイン

javascriptで決まった処理を繰り返し行いたい時に便利なjQueryのプラグイン。

Timer
(http://plugins.jquery.com/project/Timer)

Prototype.jsには繰り返し処理用に PeriodicalExecuter という大変便利な機能があって、jQueryにも似たようなのがあるんだろう思ってドキュメントを探していたのですが、どうやらないようなのでプラグインを探しました。

このTImerはコードが30行ほどと非常にシンプル!
setIntervalとsetIntervalを駆使してタイマーを実装しています。

コードに付属しているサンプルを見れば使い方は一目瞭然。

var second = false;
$.timer(1000, function (timer) {
if (!second) {
alert('First time!');
second = true;
timer.reset(3000);
} else {
alert('Second time');
timer.stop();
}
});

上のサンプルではページを表示した1秒後に "Fist time!" というアラートが出て、その3秒後に "Second time"というアラーが出ます。さらに、その時点でタイマーをストップしています。

この例を応用すれば繰り返しに関するある程度の処理はOKなのではないでしょうか。
とても便利です。