2007年04月20日

FlashLite1.1の限界と携帯版Gmailで添付ファイルを見る方法

Mobile File Viewer -携帯でPCのドキュメントが無料で見られるツール-
これはすごい。

FlashLite1.1の限界に近いと思う。
FlashLite1.1って、webでリッチな表現をしようと思った時に、
htmlの次に、リーチが広いプログラミング言語だと思うんですよね。
PCと携帯の台数を含めて考えて。


さて、携帯版Gmailが始まって普通に使い始めたけど、
添付ファイルを開いてみたいなって思う。

メールを転送、
あて先を mfv あっと kayac.com にして、
本文に自分のメアドをコピペして、
送ると閲覧用のurlが送られてきますー

2007年02月27日

javascript開発者のためのproxomitronローカルプロキシのすすめ

設定の備忘録。

javascriptの開発で、Firebugの次に大事な開発ツール。
ローカルプロキシ。

最速の人は
萌ディタとSleipnirとWEBrickを使って人のサイトのCSSをリアルタイム編集するデモ
WEBrick使うようですが、ruby(まだ)よくわからない私は、
proxomitron
さくっとローカルプロキシ環境を入れられます。
ダウンロードはこちら

使い方としては、
ローカルにapache立てておいて、リモートのjsファイルを全部ローカルのapacheに302リダイレクト。
それ以外は全部スルー。
完成度あがってきたらチェックイン。

設定はこんな感じ。
proxomitron.gif

proxomitron2.gif

proxomitron3.gif

設定がちゃんとしてると、Firebugで見るとこんな感じ。
firebug.gif

javascript開発者だけじゃなく、CSSやFlash開発者にもいいかもしれません。

Firefoxで、ツールバーから簡単にプロキシを変更できる拡張も必須
SwitchProxy 1.3
ここにproxomitron追加しておいて、開発時だけプロキシ変更する。

あとはエディタの保存と同時にFirefoxにリロード送れば完璧。

2007年02月02日

QステアとUSB赤外線学習リモコン

Qステア QSS11 フェアレディZ(Z33) (C/D)
タカラトミー (2006/12/28)
売り上げランキング: 951
おすすめ度の平均: 5.0
5 大人テイスト

Zかわいい!

届いたけどまだ開けてないです。
開けるのは、いっしょに買ったUSB赤外線学習リモコンが届いてから。
キーボードのテンキーで動かすのが待ち遠しいです。
動くかな~

技術者っぽい楽しみ方?
きっとその先にもっと楽しいことが待っている。
結果レポートはします。

2007年01月03日

[iCalMobile] Ver.1.03 省電力化 待ち受け起動時, 2分無操作でSleep

またバージョンアップです。

Ver.1.03 省電力化 待ち受け起動時, 2分無操作でSleep

携帯「iCalビューアー」としてはだんだん満足してきました。

関連:
[iCalMobile] Ver.1.02 定例イベント限定対応, 複数iCal対応
PC向けiCalMobile紹介ページへ
NTTDoCoMo携帯電話向けiCalMobile紹介、ダウンロードページへ

2007年01月02日

[iCalMobile] Ver.1.02 定例イベント限定対応, 複数iCal対応

バージョンアップです。

Ver.1.01 -> Ver.1.02 定例イベント限定対応, 複数iCal対応

[定例イベント限定対応]

携帯で日本の休日を見たいなと思ったので。
iCalの定例イベントの仕様が複雑なので、
Google CalendarのJapanese Holidays[Google HTML] Japanese Holidays[Google iCal]
だけ見れればいいかな、という意味で限定対応です。
Yearlyの定例イベントは対応してます。
それより間隔の短い定例イベントはスルーしてます。ご了承ください。


[複数iCal対応]

Google Calendarをプライベート/仕事で「マイカレンダー」を使い分けてたりするので、
さらに日本の休日も含めて携帯で見たいな、と。
3つまでokです。

新しいスクリーンショットはこんな。


PC向けiCalMobile紹介ページへ
NTTDoCoMo携帯電話向けiCalMobile紹介、ダウンロードページへ

2006年12月14日

[iCalMobile] Ver.1.01 省電力化

早速バージョンアップです。
一日常駐アプリにしておくと電池無くなってたので。。

Ver.1.0 -> Ver.1.01 折りたたみ携帯を閉じるとSleep


PC向けiCalMobile紹介ページへ
NTTDoCoMo携帯電話向けiCalMobile紹介、ダウンロードページへ

[iCalMobile] 携帯iCalビューアーiアプリ GoogleCalendarを携帯で表示

iCalMobile
GoogleCalendarのスケジュールを表示するには。

GoogleCalendarでカレンダーの設定画面を開く
googlecalendar1.gif

googlecalendar2.gif

設定画面のiCalボタンを右クリック、リンクをコピーして携帯電話へメールで送り、iCalMobileの設定画面へ貼りつけ
googlecalendar3.gif

2006年12月13日

[iCalMobile] 携帯iCalビューアーiアプリ スクリーンショット

PC向けiCalMobile紹介ページへ

NTTDoCoMo携帯電話向けiCalMobile紹介、ダウンロードページへ

待受け画面


通常画面


スケジュール詳細画面


設定画面


HELP

[iCalMobile] 携帯iCalビューアーiアプリαリリース

[iCalMobile] 携帯iCalビューアーiアプリαリリース
です。

iアプリをダウンロード(NTTDoCoMoの携帯電話用ページ)

スクリーンショット

iCalMobileは、
・iCalendarフォーマットのカレンダー、スケジュールを携帯電話で軽快に操作、表示するためのiアプリです。
・フリーのiアプリです。

参考: iCalendarフォーマットは、GoogleCalendar等メジャーなオンラインカレンダーツールで採用されているカレンダー、スケジュール用のファイルフォーマットです。

関連:
[iCalMobile] Ver.1.02 定例イベント限定対応, 複数iCal対応

2006年12月12日

携帯iアプリ開発ではまったところ

ひさびさにNTTDoCoMo向けiアプリをつくってました。
もうすぐα版出そうと思うので、はまったところのノウハウ紹介。

JavaSDKは、最新版ではだめ
「サポートされていないエンコーディングです: SJIS_i」
とかってエラーが出ます。
j2sdk-1_4_2_12-windows-i586-p.exe
これで開発できてます。

一番はまったのが、iαppliTool for DoJa-4.0(FOMA) って
携帯電話のJava環境の、PC上で動くエミュレータでは問題無く動くのに、
携帯にダウンロードして動かすと、
「αエラーが発生しました」
ってエラーが出て落ちる時がありました。。

開発環境と実機で動きが違う故のバグって、
実機では落ちる時の情報も取れないので厄介なもの。

現象は、ネットにつなごうとするときに落ちる。
地道に切り分けていきます。。

結局、原因はサーバの返すHTTPヘッダの「Content-Length」が間違っていたこと。
iアプリは携帯からアクセスできるサーバが、
そのiアプリをダウンロードしたサーバに限定されるので、
サーバ側も自分で開発していたのですが、それがバグってた。。

ご参考までにiアプリ側のJavaコードはこんな感じ

try {
 String param = com.nttdocomo.net.URLEncoder.encode( param_unencoded );
 String url = url_base+param;
 HttpConnection conn = (HttpConnection)Connector.open(url,Connector.READ);
 conn.setRequestMethod(HttpConnection.GET);
 conn.connect();
 if(conn.getResponseCode() == HttpConnection.HTTP_OK){
  InputStream in = conn.openInputStream();
  InputStreamReader isr = new InputStreamReader(in);

  int contentLength = (int)conn.getLength();
  char[] data = new char[contentLength];
  isr.read( data, 0, contentLength );
  ret = new String(data);
  // retを使ってごにょごにょ

PC上のエミュレータでは、誤ったContent-Lengthでも動いちゃってたものが、
携帯実機上では許されなかった、と。

よく考えると、ネットワーク関連の機能って、
PC上のエミュレータと携帯とでは実装が異なるはずです。
エミュレータはPCのネットワークを使ってるし、携帯は自力でDoCoMoのネットワークにつなげる。
ネットワーク関連は全部HttpConnectionってクラスに抽象化されてるのですが、
そこの設計がしょぼいのかもしれませんね。

入出力系、注意。

2006年09月01日

Javascript Linker - Janitorで未使用関数を除去する

batファイルでjavascriptコード圧縮

それより、ライブラリのうち未使用の関数を省くようなの、欲しいな。

と言いましたが、そう思ってる方は他にも多くいらっしゃるようです。


8/30 JS Linker in Dojo
The JS Linker was just committed to the Dojo repository.

Javascript Linkerとは、

The purpose of JavaScript Linker is to process HTML/JavaScript code base to prepare code for deployment by reducing file size, create source code documentation, obfuscate source code to protect intellectual property, and help gather source code metrics for source code analysis & improvements.

JavaScript Linker (JSL) - Alpha 1 : Readme より
JavascriptLinkerは、HTML/JavaScriptのファイルサイズ削減やコードのドキュメント、知的財産を守るためのコード難読化、ソースコード解析のためのメトリクス収集、のためのプリプロセスを行うことを目的とする。


インストールが少しめんどう。
2.0 Requirements
1. JDK 1.5.x installed with JAVA_HOME pointing to that JDK.
2. You will need Apache Ant 1.6.x installed with ANT_HOME set.


お目当ての

Janitor - unused function removal via dependency analysis
Janitor task is used to strip out unused functions from the JavaScript source code. Janitor performs a static code analysis constructing a function call graph for all global functions. Entry points are also calculated from all source files that have imported after processing the Dojo require statements. Every function not reachable from the graph is considered unused and gets removed.

コードの静的解析をして全グローバル関数の呼び出し関係をグラフ化して、呼び出されないものを削除する?
う~ん。


こんな感じで対象のファイルを解析、ファイルサイズ削減する。

java -Xms8m -Xmx200m -cp jsl.jar;sisc.jar;bcel.jar org.dojo.jsl.top.Top --verbose --prj jsl.prj --sources ../tests/test_Colorspace.html


使って見た感じも、期待していたようなコード削減効果は無し。
まだ、タブやコメントを削除してくれるくらい。

javascriptファイル単位で、使っているものを抜き出してくれるので、DojoとかYUIとかのライブラリから使っているjsファイルのみを抜き出す、みたいな用途では使えそう。


期待としては、
例えばprototype.jsをscriptタグで呼び出しているのに$関数しか使って無かったら、prototype.jsのファイルサイズがめっちゃ減って欲しい。

静的解析じゃ厳しいのではないかしら。
全部のイベントをシミュレーションしてDOM構造に影響を与えたところをバックトレースしていく、みたいなアプローチがいいのかな~

Janitor task will be improved incrementally in the later releases.
なので期待して待ちましょう。

2006年08月30日

batファイルでjavascriptコード圧縮

javascriptを書いてると、圧縮してあげたくなります。

Makeを利用したJavaScriptファイルの結合・圧縮
がとってもスマートなのだけれど、Windows環境だしMakefile手書きしたこと無いので、
bat(バッチ)ファイルで。

set u=union.js
set c=comp.js
del %u%
del %c%
copy *.js %u% /B
java -jar custom_rhino.jar -c %u% > %c% 2>&1
1. これをjsファイルのあるフォルダに保存して compressjs.bat とかって名前付けて保存

2. custom_rhino.jarをダウンロードして同じフォルダに保存(JavaRuntimeは入れておく)

3. batファイルをダブルクリック

4. フォルダ内の.jsファイルを union.js にまとめた後、圧縮してできた comp.js が最終的なコード。

jsファイルのあるフォルダがちらばってる場合には、こんな感じ('+'区切りでパスをつなぐ)。

copy *.js %u% /B
↓
copy js1\\myjs.js+js2\\myjs2.js %u% /B

さらに、CSSファイルを保存すると同時にブラウザをリロード にならって秀丸の保存にフック(?)できると快適!


javascript圧縮エンジンは Dojo’s Compressor


日本語について。
Makeを利用したJavaScriptファイルの結合・圧縮 では

Dojo's Compressorでは日本語文字列はうまく扱えないようなので、日本語文字列は別ファイルに記述する必要がある。

って書いてあるけれど改善されたのか、問題無し(圧縮前はUTF-8で保存した状態で確認)。
ただし、「\u7e3a\uff7e\u7e3a\ufffd」になって日本語は逆に容量増えちゃいますが。


いまいちコード削減量が大した事無かったのと、
使わせてもらっているjavascriptライブラリの権利周りをそのままにしておきたいので、
とりあえず未採用...

それより、ライブラリのうち未使用の関数を省くようなの、欲しいな。

2006年08月27日

ブロック要素の中で滑らかスクロールする方法(javascript)2

昨日の ブロック要素の中で滑らかスクロールする方法(javascript) はつくってて楽しかった♪
Flashアプリとかつくる人にとっては当たり前な気がしますが。

usage:
http://slightlyblue.com/lab/t20060827/smoothscroll.js を読み込んで、
SmoothScroll.scrollTo( 'target id', 'parent id', options);
'parent id' はスクロールしようとしているブロック要素のid
'target id' は 'parent id'ブロック内にあるスクロール目標(=スクロール後にブロックの一番上に表示させたい行)のid
options は { time : 500, unit : 50 } 等と指定する
options.time は スクロール完了までの時間
options.unit は スクロール完了までに何ms単位で細かくスクロールするか
映画のフレームレート:24fps(40ms/frame)が映像を滑らかに見せるぎりぎりのラインだと思うので、それくらいを目安に。


point1:
滑らかなスクロールは、
$('parent id').scrollTop を options.unit 毎に更新することで実現します。
更新毎の移動量は、線形に漸減する方式になっています。

目標の距離に対して、options.time / options.unit 回に分けてスクロールするので、
目標の距離 / ( options.time / options.unit ) だけ一度に動かすと、速度変化は起きません。

線形に漸減させるためには、
一回の移動量 = 目標の距離 / ( options.time / options.unit ) * 2
x2すればいいのです。
この三角形を意識すれば簡単。

4分の1円形状に速度が落ちていったらかっこいいかな、なんて考えたりすると楽しい。。


point2:
もうひとつのポイントは、IE/Firefoxの違い
MSDN Home > 連載コラム > DHTML Dude > 配置と編集
HTML要素のサイズや位置を取得する
この辺りが詳しい。
offsetTopを使って、スクロールの目標を決めているのだけれど、
offsetTopがどこ基準のオフセットなのか、ブラウザ依存。
ここでは、'parent id'のwidth,heightを絶対値指定して、'parent id'ブロックをその内側にある'target id'のoffsetParentにしている。


もし万が一使うことがありそうだったらコメントいただけたらうれしいです。

ブロック要素の中で滑らかスクロールする方法(javascript)

ブロック要素の中で滑らかスクロールする方法(javascript)
IE,Firefoxのみで動作確認(IE追加@2006/08/27)

気持ちいいインターフェース。
Scriptaculous.Effects.ScrollTo をHackする方法もあるけれど、重いので自前で。

明日解説するかも。

a
b
c
d
e
f
g
h
[i]
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
[z]








コード:

javascript:
var SmoothScroll = {};
SmoothScroll = {
	targetScrollTop : 0,	// we're gonna make the $(parentid).scrollTop -> targetScrollTop
	dist : 0,
	timer : 0,
	count : 0,
	parentid : 0,
	lastDist : 0,
	//speedStore : [],		// for debug
	options : {},
	defaultOptions : {
		time : 1*1000,	// [ms]
		unit : 50			// [ms]
	},
	scrollTo : function( element, parent, options ){
		this.options.time = this.defaultOptions.time;
		this.options.unit = this.defaultOptions.unit;
		if( options ){
			this.options.time = ( options.time ) ? options.time : this.options.time;
			this.options.unit = ( options.unit ) ? options.unit : this.options.unit;
		}
		clearInterval( this.timer );
		this.parentid = parent;

		this.scrollTopMax = this.$(parent).scrollHeight - this.$(parent).offsetHeight + parseInt(this.$(parent).style.borderTopWidth) + parseInt(this.$(parent).style.borderBottomWidth);

		if( navigator.userAgent.match( "MSIE" ) ){
			this.targetScrollTop = ( element ) ? this.$(element).offsetTop : 0;
		}else{
			var targetOffsetTop = ( element ) ? this.$(element).offsetTop : this.$(parent).offsetTop;
			this.targetScrollTop = targetOffsetTop - this.$(parent).offsetTop;
		}
		this.targetScrollTop = ( this.targetScrollTop > this.scrollTopMax ) ? this.scrollTopMax : this.targetScrollTop;

		this.dist = this.targetScrollTop - this.$(parent).scrollTop;
		this.lastDist = 0;
		this.timer = setInterval('SmoothScroll.update()', this.options.unit );
		this.count = 0;
		//this.speedStore = [];
		this.update();
	},
	update : function(){
		var dist = this.targetScrollTop - this.$(this.parentid).scrollTop;
		var speed = 2 * dist * this.options.unit / ( this.options.time - this.options.unit * this.count );
		//this.speedStore.push( speed );
		speed = ( speed > 0 ) ? Math.ceil( speed ) : Math.floor( speed );
		if( Math.abs(dist) <= Math.abs(speed) ){
			// got there
			clearInterval( this.timer );
			this.$(this.parentid).scrollTop = this.targetScrollTop;
			return;
		}else if( this.lastDist == dist ){
			// stuck
			clearInterval( this.timer );
			this.$(this.parentid).scrollTop = this.targetScrollTop;
			return;
		}
		var scrollTop = this.$(this.parentid).scrollTop + speed;
		this.$(this.parentid).scrollTop = scrollTop;
		this.lastDist = dist;
		this.count++;
		if( this.count == this.options.time / this.options.unit ){
			// timeout
			clearInterval( this.timer );
			this.$(this.parentid).scrollTop = this.targetScrollTop;
		}
	},
	$ : function(id) {
		return document.getElementById(id);
	}
}
function gototop(){
	document.getElementById('scroll20060827').scrollTop = 0;
}

html:
<div id="scroll20060827" style="width: 100px; height: 100px; overflow-y: scroll; border: 2px black dotted;">
a<br />b<br />c<br />d<br />e<br />f<br />g<br />h<br />
<span id="t20060827i" style="color: red"><b>[i]</b><br />
</span>j<br />k<br />l<br />m<br />n<br />o<br />p<br />q<br />r<br />s<br />t<br />u<br />v<br />w<br />x<br />y<br /><span id="t20060827z" style="color: blue"><b>[z]</b></span><br />
</div>
<input type="button" value="go to top (normal)" onclick="gototop();"/>
<input type="button" value="go to top smoothly" onclick="SmoothScroll.scrollTo(0,'scroll20060827');"/>
<input type="button" value="go to [i] smoothly" onclick="SmoothScroll.scrollTo('t20060827i','scroll20060827');"/>
<input type="button" value="go to [z] smoothly" onclick="SmoothScroll.scrollTo('t20060827z','scroll20060827');"/>
<input type="button" value="go to [i] smoothly, but FAST" onclick="SmoothScroll.scrollTo('t20060827i','scroll20060827',{time: 500});"/>
<input type="button" value="go to [z] smoothly, but FAST" onclick="SmoothScroll.scrollTo('t20060827z','scroll20060827',{time: 500});"/>
<input type="button" value="go to [i] smoothly, but SLOW" onclick="SmoothScroll.scrollTo('t20060827i','scroll20060827',{time: 2000});"/>
<input type="button" value="go to [z] smoothly, but SLOW" onclick="SmoothScroll.scrollTo('t20060827z','scroll20060827',{time: 2000});"/>

2006年08月21日

GoogleMaps "a has no properties" ってjavascriptエラーが出たら

Google Maps で遊んでいたら、

Firefox の Firebug の Console画面に"a has no properties"ってエラーがGoogleのjavascriptコードの中で起こっていましたよ。
そのエラーが起こった後は、拡大縮小やらをしてもマーカーがその縮尺に応じた位置に表示されなかったり、悪影響大。

再現性があったので、いろいろ発生パターンを出していたらわかりました。

marker.openInfoWindowHtmlで info window を登録して開いたまま、
map.setCenter で縮尺変更と地図センター変更を行うと、いけないようです。

map.setCenter の前に map.closeInfoWindow をすればok。
頼むよgoogle。


しかし、再現する不具合は簡単だなー。

2006年08月18日

GoogleMapsの上に半透明のフォームを重ねる

GoogleMapsいじってると、地図の上にいろいろ重ねたくなっちゃいます(かっこよさげだから)。

半透明のフォームのっけてみました。

Google Maps API Version 2 Class Reference (意訳とサンプル) GOverlay
をベースに。
地図全面にGOverlayを貼り付けるところと、半透明なブロックをつくるCSS

javascript:
TestOvy.prototype.redraw = function(force) {
  //再描画
  if (!force) return;  //forceがfalseなら(つまり地図が動いていなければ)動作しません
  this._div.style.width = map.getSize().width + "px";
  this._div.style.height = map.getSize().height + "px";
}
css:
#content{
background: white;
text-align: center;
padding-top: 100px;
filter: alpha(opacity=85);
-moz-opacity:0.85;
opacity:0.85;
position: relative;
left: 0px;
top: 0px;
}

フォームでtext入力する時の使い勝手が悪いのでアウト..

2006年08月15日

GoogleMaps IEでマーカー画像の読み込みが異常に遅い現象の対策

引き続き、、GoogleMapsAPIいじり中

IEでマーカーや縮尺等の画像読み込み(特にpoweredby.png)が異常に遅い現象が起ったら。

IEでは、透明PNGファイルがサポートされていないので普通に表示すると

こんなふうに背景が透過されません。。

その対策として、filter:progid:DXImageTransform.Microsoft.AlphaImageLoader
というのを使います。

例えば今使おうとしているYUIでは

<!--[if gte IE 5.5000]>
<script type="text/javascript">
function correctPNG() // correctly handle PNG transparency in Win IE 5.5 or higher.
{
  for(var i=0; i<document.images.length; i++)
  {
    var img = document.images[i]
    var imgName = img.src.toUpperCase()
    if (imgName.substring(imgName.length-3, imgName.length) == "PNG")
    {
      var imgID = (img.id) ? "id='" + img.id + "' " : ""
      var imgClass = (img.className) ? "class='" + img.className + "' " : ""
      var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' "
      var imgStyle = "display:inline-block;" + img.style.cssText
      if (img.align == "left") imgStyle = "float:left;" + imgStyle
      if (img.align == "right") imgStyle = "float:right;" + imgStyle
      if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle
      var strNewHTML = "<span " + imgID + imgClass + imgTitle
      + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
      + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
      + "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>"
      img.outerHTML = strNewHTML
      i = i-1
    }
  }
}
YAHOO.util.Event.addListener(window, "load", correctPNG);
</script>
<![endif]-->

onloadイベントで、.pngファイルをsrcとするimgを、スタイルを保持したspanに置き換えています。

こいつが悪さしてました。
onloadでimgを書き換えてしまうので、GoogleMaps上に描かれるpngファイルが読み込み中に読み込み元を失ってまずいことになったっぽい(?)。

before:
if (imgName.substring(imgName.length-3, imgName.length) == "PNG")
after:
if (imgName.substring(imgName.length-3, imgName.length) == "PNG" && img.className == "png"){
imgタグにclassを指定して、透過処理して欲しいヤツだけ指定することで回避。

IEの透明PNG対策はこの辺にいろいろあります
I want to make transparent png graphics work in IE
PNG alpha transparency, fast and easy

2006年08月12日

GoogleMaps全部のGMarker(マーカー/ピン)が一画面に収まるような縮尺を自動計算する方法

引き続き、、GoogleMaps調査中。。

マーカーを複数立てた時に、全部のマーカーが一画面に収まるような縮尺を自動計算したいものです。

Google Maps APIについてのGoogleGroupにも過去にその議論はあって

1.各ズームサイズにおける縮尺(というか経度緯度とドットとの関係)の計算の仕方
全国ロケ地図(http://saya.s145.xrea.com/x/lmap.html)を作っているときに、全てのマーカーを表示したいとか、マーカーを重ならないように引き出し線等で表示したい(印刷用)という要望がありました。
前者は、全マーカの中心に移動しズームアウトしていき、表示範囲を取得(getBoundsLatLng)して全て入ったところでやめるというかなり無理矢理な-やり方をしています。
後者も表示範囲(getSpanLatLng)から経度緯度とドットの関係を計算して、うまく配置するしかないのでしょうか?

その議論の中で紹介されていなかった、smartな解法を見つけた(その後GoogleMapsAPIに追加された?)ので御紹介。

Google Maps API Version 2 Referenceを見ると、GLatLngBoundsというクラスがあります。

class GLatLngBounds
A GLatLngBounds instance represents a rectangle in geographical coordinates, including one that crosses the 180 degrees meridian.

そのひとつのmethod、extendが使えます。

extend(latlng)
Enlarges this rectangle such that it contains the given point. In longitude direction, it is enlarged in the smaller of the two possible ways. If both are equal, it is enlarged at the eastern boundary.

さらにGMap2のgetBoundsZoomLevelってmethod。

getBoundsZoomLevel(bounds)
Returns the zoom level at which the given rectangular region fits in the map view. The zoom level is computed for the currently selected map type. If no map type is selected yet, the first on the list of map types is used.

javascriptコードはこんな。

List[0] = self.createMarker( 0, new GLatLng( 35.678084480, 139.76313114 ) );
List[1] = self.createMarker( 1, new GLatLng( 35.66278800541137 , 139.7543442249298  ) );
List[2] = self.createMarker( 2, new GLatLng( 35.67073730876408 , 139.76759433746338	) );
List[3] = self.createMarker( 3, new GLatLng( 35.65085384825412 , 139.7745680809021  ) );
List[4] = self.createMarker( 4, new GLatLng( 35.668497289125376 , 139.75984811782837  ) );
self.initZoom();

中略

createMarker : function( num, point ) {
  var letter = Letter.getNext();
  var ic = new GIcon(baseIcon);
  ic.image = "img/icons/icon"+letter+".png";
  var marker = new GMarker(point, { icon: ic});
  map.addOverlay( marker );
  return marker;
},
initZoom : function(){
  var gb;
  var first = 1;
  for( var index in List ){
    var marker = List[index];
    if( first ){
      gb = new GLatLngBounds( marker.getPoint(), marker.getPoint() );
      first = 0;
    }else{
      var point = marker.getPoint();
      gb.extend( point );
    }
  }
  map.setCenter( gb.getCenter(), map.getBoundsZoomLevel( gb ) );
}


デモ:Google Maps API 全部のGMarkerが含まれるような縮尺を自動算出

2006年08月08日

GoogleMapsマーカーのアイコンをカスタマイズ!

GoogleMapsのAPIでつくりたいものがあって調査中・・・

ピン(マーカー)を立てた時のアイコンをカスタマイズしたいところ。
こういうやつ

まとめサイトを見つけました。
その中でもおすすめは
Google Maps API Tutorial :: Google Earth Icons
PHP script which uses the webhues package posted above to make colored, numbered markers on the fly (http://www.csail.mit.edu/~alexgru/markers/numbered_markers.tar.gz)
特に後者、任意の色を背景に、任意のテキストを貼り付けたアイコン画像を動的生成するスクリプトも配布しています!

http://slightlyblue.com/lab/t20060808/numbered_marker.php?image=pushpins/webhues/087.png&text=99
http://slightlyblue.com/lab/t20060808/numbered_marker.php?image=pushpins/webhues/007.png&text=A
引数に色とテキストを指定してあげればその場でつくってくれます。
Script by Ali Mohammad and Alex Gruenstein とのこと。Good Job

自分のところに設置して、こんなコードで0~99までの番号付きのマーカー画像を作れます。

use strict;
use LWP::Simple;

my @alpha = ("A" .. "Z");
#my @alpha = (0..99);

foreach (@alpha){
  my $imageurl = "http://path.to/numbered_marker.php?image=pushpins/webhues/007.png&text=$_";
  my $localimage = "icon$_.png";
  print "$imageurl,$localimage\n";
  my $ret = getstore( $imageurl, $localimage );
}


そして..
気になるスクリプトを発見: XMaps Library - A Google Maps API Extension
Google Maps APIをさらに使いやすく拡張するライブラリ。
正式リリースはまだのようだけれど、マーカー(と影も)を動的生成して張り付けたりってことが楽にできそう。
期待(重そうだけど)。
マーカー動的生成のデモ

前回:GoogleMapsブラウザリサイズ時のイベント処理でcheckResizeする!

2006年08月02日

B.F.R. Download

Becky! 用の Feed Reader plugin をつくっています。

V1.08betaのダウンロードはこちらから。
V1.07のダウンロードはこちらから。

v1.07 → v1.08 は、パーサーが落ちる不具合修正と、一部読めないATOMフィードがあったのを読めるように修正いたしました。
評価ができていないのでbetaとしておきます。

--追記
2004/06/26 : v1.01 にVUPしました。
2004/10/10 : v1.02 にVUPしました。
2004/11/19 : v1.03 にVUPしました。お待たせした方、すみませんでした....
2004/11/28 : v1.04 にVUPしました。
2004/12/12 : v1.05 にVUPしました。
2005/03/21 : v1.06 にVUPしました。
2005/08/27 : v1.07 にVUPしました。
2006/08/02 : v1.08betaにVUPしました。

GoogleMapsブラウザリサイズ時のイベント処理でcheckResizeする!

今更感がありますがGoogleMapsAPIを使ったアプリで作りたいものができました。
サンプルコードで含めたい機能の実現性確認中。。。

ちょっとはまったのが、
ブラウザのリサイズ時に地図のセンターを変更したい(もしくは変更したくない)場合の話。

GoogleMapsデフォルトの動作では、例えばブラウザウィンドウの右端をつかんで左方向へドラッグ&ドロップすると、表示されている地図の左端(西)は変わらずにウィンドウが狭くなった分右側が狭くなり、結果的に地図のセンター位置がより西側に動いてしまう(地図はスクロールせず)。

地図のセンター位置を変えたくなければ、同じ操作をした時に、地図が左にスクロールすればよい。

ということで、bodyのonresizeイベントで、リサイズ前のセンター位置がセンターに来るようにsetCenterとかpanToで動かしたいと思うのでした。

ところがIEではうまくいくのに、Firefoxでリサイズ後にsetCenterとかを行うと、おかしな位置にセンターを持っていったりする。

どうやら、GoogleMaps自体もonresizeでいろいろ計算しているらしく、自分の登録したonresizeイベントの処理されるタイミングとGoogleMaps自体の処理タイミングがブラウザによって異なるらしい。
つまり同一イベントに対して複数のイベントハンドルがある場合に、ブラウザによって処理順番が異なるらしい。

GoogleMapsAPIGroupに聞いてみたところ、あっという間に対策できました♪
自分のsetCenterやpanToの前にcheckResizeを呼ぶことで、GoogleMapsの方のイベント処理を確実に完了させられるみたいです。

→ ブラウザをリサイズしても地図のセンター位置が変わらないGoogleMaps(Firefox,IEで動作確認済み)

<script type="text/javascript">
//<![CDATA[
var map;
var center = new GLatLng(37.2, 135.8);
function load() {
	resize();
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById("map"));
		map.addControl( new GLargeMapControl() );
		map.addControl(new GScaleControl());
		map.addControl( new GMapTypeControl() );
		new GKeyboardHandler(map);
		map.setCenter(center, 5);
		document.getElementById("message").innerHTML = center.toString();

		var point = new GLatLng(35.65855154020906,139.70184803009033);
		var marker = new GMarker(point);
		map.addOverlay(marker);

		map.openInfoWindow(map.getCenter(),
									 document.createTextNode("Hello, world"));

		GEvent.addListener(map, "click", function(marker, point) {
			if (marker) {
				map.removeOverlay(marker);
			} else {
				map.addOverlay(new GMarker(point));
			}
		});

	}
}

function resize(){
	var map_obj=document.getElementById("map");
	var disp=getDispSize();
	map_obj.style.width=(disp.width-100)+"px";
	map_obj.style.height=(disp.height-100)+"px";
	if( map ){
		map.checkResize();
		map.panTo(center);
	}
}
function getDispSize(){
 if(document.all){
	 if(window.opera){
		 return {width:document.body.clientWidth,height:document.body.clientHeight};
	 }else{
		 return {width:document.documentElement.clientWidth,height:document.documentElement.clientHeight};
	 }
 }
 else if(document.layers || document.getElementById){
	 return {width:window.innerWidth,height:window.innerHeight};
 }
}
//]]>
</script>
</head>
<body onresize="resize();" onload="load()" onunload="GUnload()">

2006年07月30日

factio Blog Parts Generator beta

factio Blog Parts Generator beta
factio ブログ パーツ ジェネレーター ベータ

つくりました。

↓こういうものがお手軽につくれるツールです。

タップTシャツ。
価格: 2,625円(税125円)

  • factioの商品ページの縮小版をBlogに貼り付けるためのツールです
  • 黒点線の内側(点線を含まない)までが本ブログパーツのhtmlコードで表現されています
  • htmlコードをコピーし、ブログのサイドバー等にはりつけてください
  • htmlコードは自由に編集して使っていただいてokです
  • "AD by slightlyblue"は残しておいていただけるとうれしいです
  • 写真や商品説明文の転載許可はデザイナーさんから得てくださいね
  • factio officialが登場するまでのbetaです

工夫としては、
マウスオーバー時の画像拡大(縮小表示→等倍表示)を行わせるjavascriptも生成してブログパーツに含めていること、かな。

実装としては、
factioサイトをGETして、HTML::TokeParserで解析して(Lolipopインストール済だったから....)、JSONでブラウザに返して、Lyase_viewテンプレート[javascriptテンプレートエンジンまとめ][inforno::埋め込みjavascriptを実装してみました。]でレンダリングしてます。


factioデザイナーの方、ファンの方、どうぞお使いください。
ちなみにslightlyblueデザインのTシャツは、このブログパーツでスタイルを変更しなかった場合に限り転載可とします。

2006年07月16日

Flickr Color Selectr

Flickr Color Selectr
color_20060716.jpg

つくってみました。

Flickrから、CreativeCommonsのライセンスの付いた、色の似た画像をとってきます。
これは楽しいです。

既出なのは承知で。画像を使ったWEBアプリの練習台。

AJAX的な画面遷移、星を使ったレイティング辺り、今風の王道かしら。
YUIのスライダー+LyaseView Javascriptテンプレート+Prototypeフレームワーク+FlickrAPI+MySQL+Perl+Image::Magick+私。

どうぞ。

2006年07月05日

タップダンスTシャツ第一弾

タップダンスTシャツつくりました。
1637695_o1.jpg

1637695_o2.jpg

1637695_o3.jpg

タップダンスっていまやメジャースポーツなのに(ぉ
タップを題材にしたTシャツって見かけないですよね。

これからの時期、必要なのでつくっちゃいました。

factioさん、いいですよ。
2500円で自作Tシャツ買えちゃうって価格破壊。
これからリアルの店舗でTシャツ買うことは無くなりそうな。

まー1枚どうぞ。
Tシャツのサイズ表記はここで。

2006年06月29日

Becky!でGTD?ToDo管理?

なにつくろうか、ということで、
Becky!でGTD、というかToDo管理できたらうれしいですかね?

メールって返信を期待されている点ToDoリストに近い。
メールとは関係ないToDoをメーラーで管理できたらうれしいかな。

そもそもToDoに求められる要件ってなんだろう?
・ToDoリストを一望できること
・一望できる範囲に内容、〆切、重要度、状態が含まれること
・重要度順、〆切順などで並べ替え、見栄えの区別ができること
・ToDo項目毎に詳細を書き込めること
・完了後に完了済としてどこかに保存できること
・How to make it doneを書き込めること
・どこからでもアクセスできること
こんなもん?

最後のを除けば(最後のも工夫次第だが)
メーラーのインターフェースってわりとよいのでは。

いしなおさんも過去に
IMAPを使ってGTDを管理できないか
考えたことがあるようですが、今このアイディアはどうなっちゃったんでしょう?

今、BMemoのメモメールでToDo管理しているが、、
それより便利だろうか・・・
しばし想像してみよー
ほしい人います?

AJAXのローディング中画像

ajaxload
ローディング中・・・ の画像をつくれるサイト
ajaxload_20060629.jpg
Ceekz Logsさんより

ためしに作ったのはこれ。

旬レシピで使ってみました。
かわいーなー

ソースはこんな。
htmlには...

<div id="loading"></div>

javascriptには..
prototypeフレームワークを使っているので
Ajax.Request を呼び出す前に

$('loading').style.display = 'block';

onCompleteイベントで
$('loading').style.display = 'none';

cssには

#loading {
	position:absolute;
	left:0;
	top:0;
	width:32px;
	height:32px;
	display:none;
	<strong>background-image: url(ajax-loader.gif);</strong>
	background-repeat: no-repeat;
}

旬レシピも落ち着いちゃったので、次なにつくろう?

2006年06月23日

AJAX的 旬レシピ検索

素材が料理の限界を規定する。
なので、その時最もおいしい素材を求めることは、おいしさの探求者として、一料理人として当然のこと。

というわけで、
旬レシピ http://slightlyblue.com/recipe/
recipe_20060623.jpg

公開です。

今日なにを作ろうか。
レシピを決めるまでには、2つのステップがあると思う。
1. なに食べようか。
2. どうやってつくろうか。
世の中には、両方詰め込んでごちゃごちゃしてるレシピサイトが山ほどあるように感じます。
旬レシピは、1.の方に重点を置いています。

シンプルな、直感的なインターフェースで、
食感をそそるレシピを見つけてください!


ゆっくりと調べてきたいくつかの技術を寄せ集めてつくっています。
複数月選択インターフェース by Javascript,CSS
javascriptテンプレートエンジンまとめ::lyase_view
Prototype Window Class
prototypeフレームワーク

2006年06月04日

複数月選択インターフェース by Javascript,CSS

今つくっているなにかのために、
月を選択するインターフェースが必要なので、作ってみました。
滑らかで自然かな、と。

・単月の選択も
・複数月の選択も
・年を越えた複数月の選択も
できる直感的なI/Fかな、と。

複数月選択インターフェースdemo

prototype.js と、以下の3ファイルを同フォルダに入れれば動作します。
index.html
selectmonth.js
selectmonth.css

lightbox v2.02を参考にして初Javascriptライブラリをつくってみました。

2006年05月30日

Lyase_Viewで405MethodNotAllowedと言われたら


javascriptテンプレートエンジンまとめのうち、Lyase_Viewを使って遊んでいます。

ちょっとはまった話。

	var rendered = Lyase.View.render({file:"./images.jhtml"}, yresult );

こんなふうにテンプレート使ってみてたら、
"405 Method Not Allowed"
というhttpエラーが。

そんなエラー見たこと無かったので調べてみると、
images.jhtml に対してPOSTメソッド使っちゃだめですよ、という感じらしい。
lolipopのapacheの設定でしょう、拡張子で制限かけてそうです。

回避はこんな。
88行目を

before:
    template = (new Ajax.Request(options.file,{asynchronous : false})).transport.responseText;
after:
    template = (new Ajax.Request(options.file,{asynchronous : false, method:'get'})).transport.responseText;

prototype.js のAjax.RequestってデフォルトPOSTメソッド使うんですね。知りませんでした。

2006年05月16日

javascriptテンプレートエンジンまとめ

ちょっとjavascriptのテンプレートエンジンの調査・・・

ご紹介とテンプレートのコーディングスタイル:

ajax pages

<html>
<body>
<% for ( i=0; i<5; i++ ) { %>
    Hello World <br>
<% } %>
</body>
</html>

TrimPath

  <textarea id="cart_jst" style="display:none;">
    Hello ${customer.first} ${customer.last}.<br/>
    Your shopping cart has ${products.length} item(s):
    <table>
     <tr><td>Name</td><td>Description</td>
         <td>Price</td><td>Quantity & Alert</td></tr>
     {for p in products}
         <tr><td>${p.name|capitalize}</td><td>${p.desc}</td>
             <td>$${p.price}</td><td>${p.quantity} : ${p.alert|default:""|capitalize}</td>
             </tr>
     {forelse}
         <tr><td colspan="4">No products in your cart.</tr>
     {/for}
    </table>
    {if customer.level == "gold"}
      We love you!  Please check out our Gold Customer specials!
    {else}
      Become a Gold Customer by buying more stuff here.
    {/if}
  </textarea>

JKL.Hina

<table border="1">
  <tr><th>name</th><th>author</th></tr>
  <tr title="@foreach line1 [/table1]">
	<td>[/line1/name]</td>
	<td>[/line1/author]</td>
  </tr>
</table>

Jamritas.Template

<p tid="time">It's <em tid="hours">hour</em> :
                   <em tid="minutes">minute/em> :
                   <em tid="seconds">second</em> now.</p>

lyase_view

<textarea id="template" style="display:none">
 <% context.list.each(function(pair){%>
  The value of <%= pair.name %> is: <%= pair.value%>
 <% }) %>
</textarea>

選びがたいですが、
simple is best. ということでlyase_viewでちょっと遊んでみようと思います。




2006/07/29 追記
lyase_view使って遊んで見た結果、こんなものできました。
javascriptテンプレートエンジン使用例:
旬レシピ
Flickr Color Selectr

両方とも、サーバのperlスクリプトから返ってきたJSONをevalしてlyase_viewのテンプレートでhtmlコードをレンダリングしている感じです。
viewを、htmlとjavascriptコードとjavascriptテンプレートとに分離して実装している点が気持ち悪いです..


ちょっとしたwebアプリは誰にでも書けるようになっている今日この頃、
腕のあるソフトウェアエンジニアは、
よりチャレンジングな、○○フレームワークの開発、に挑んでいるようですね。


一昔前までは、手書きでhtmlを書いていたのが、
今ではhtmlをなにも意識しなくてもブログを更新できる。

紙がどんな素材でできているかなんて一般人は気にする必要はない。
活版印刷が普及した時、なにが起こったっけ?

歴史は繰り返す。

キリスト教が普及したな・・・

2006年05月08日

lolipopのインストール済みperlモジュール

lolipopのレンタルサーバを借りてから、perlでごにょごにょ始めてます。

そんな時に便利だったのが、
サーバーアナライザー

お使いのサーバの仕様って分かってますか?意外と、サービス事業者のページは技術的に細かいことまでは掲載されていないことが多いですよね。サーバアナライザーは、サーバの仕様を自動的に調査し、ブラウザー上に表示します。どんな Perl モジュールが使えるのか、このコマンドのパスは?等などの疑問が解消できるでしょう。

lolipop検討中の方へ、調査結果から一部参照してお届け。

続きを読む "lolipopのインストール済みperlモジュール" »

2006年05月04日

Lightbox JS v2.02のコメント/タイトル欄

またまたLightboxJSv2.02ねた。

ギリシャ&ドイツ写真@2003秋http://slightlyblue.com/blog/2006/05/2003.html
で、初めてLightboxでオーバーラップ表示した画像の下にある
コメント(タイトル?)欄を使ってみました。

書式が小さなフォントのboldだったので、
見やすくなるようにいじってみました。

lightbox.css のline.68辺り

pre:
#imageData #caption{ font-weight: bold;	}

aft:
#imageData #caption{
	font-size: x-small;
}


ちなみにMovable Typeのエントリー投稿画面での入力の仕方memo

ギリシャ&ドイツ写真@2003秋http://slightlyblue.com/blog/2006/05/2003.html
のエントリーは以下のように書いてます。

<a href="http://slightlyblue.com/blog/photo/g2/01.jpg" title="1/32

成田発アエロフロート便モスクワ経由アテネ着早朝

そのまま朝の便でミコノス島へ

フェリーを降りて拉致られるようにして着いた宿が
ここ

部屋の窓からの景色。

Oh, yeah!
" rel="lightbox[g2]"><img src="http://slightlyblue.com/blog/photo/g2/01.jpg" width=100></a>
1/32

成田発アエロフロート便モスクワ経由アテネ着早朝

そのまま朝の便でミコノス島へ

フェリーを降りて拉致られるようにして着いた宿が
ここ

部屋の窓からの景色。

Oh, yeah!



2006年05月03日

AJAX + Lightbox JS v2.02

AJAXでもLightbox JS v2.02を使えるようにしてみた。

ポイントは、
AJAX.RequestがonCompleteするときに呼ぶ
myLightbox.initialize();

Loading...
Tab 1
Tab 2
Tab 3
initial value


サーバサイドソースはこちら
- process.php

Lightboxは、ページが読み込まれた時に、
ページ内の全部のアンカータグを探して、
条件に合うもの(relタグだとか)があったら、
onclick イベントを登録するようだ。

AJAXで途中から読み込まれたものには、
onclickイベントを登録しなおさないといけない。

ということで、
initialize を呼びなおしてみました。

dirty, but works.

rel属性無しでLightbox JS v2.02

Lightbox2.02お試しでも使ったLightbox JS v2.02の小技をご紹介。

Lightbox JS v2.02は、

Lightbox JS is a simple, unobtrusive script used to overlay images on the current page. It's a snap to setup and works on all modern browsers.

写真を綺麗な見栄えで見せてくれるツールです。

ただ、使うためには、画像にrel属性を入れないといけません。
↓こんなふうに。
<a href="image.jpg" rel="lightbox"><img alt="image.jpg" src="image.jpg" /></a>

めんどくさいです。

回避方法はいろいろあり、
Lightbox JS の rel 属性を自動付与するに詳しいのですが、

今回は Lightbox Plusに対する同様の変更 : Lightbox Plus で画像を同一画面にオーバーレイして表示を参考に、
Lightbox JS v2.02のrel属性いらない版をつくりましたので公開です。

使い勝手が少し変わりました。
[従来]
・rel="lightbox" を入れると、単品画像のLightbox化
・rel="lightbox[hoge]" を複数の画像に入れると、グループ化

[変更後]
・画像の拡張子がjpg,gif,png,bmpなら単品画像のLightbox化
・rel="lightbox[hoge]" を複数の画像に入れると、グループ化 (従来どおり)

ソース
line.180辺りを

prev:
if (anchor.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox')))

aft:
if (anchor.getAttribute('href') &&
 ( (relAttribute.toLowerCase().match('lightbox'))
 || (anchor.getAttribute('href').match(/.+(jpg|gif|png)$/i)) ) )

line.330辺りを

prev:
// if image is NOT part of a set..
if((imageLink.getAttribute('rel') == 'lightbox'))
{
	// add single image to imageArray
	imageArray.push(new Array(imageLink.getAttribute('href'), imageLink.getAttribute('titl')));
} else{
	// if image is part of a set..
	// loop through anchors, find other images in set, and add them to imageArray
	for (var i=0; i<anchors.length; i++){
		var anchor = anchors[i];
		if (anchor.getAttribute('href') && (anchor.getAttribute('rel') == imageLink.getAttribute('rel')))
		{
			imageArray.push(new Array(anchor.getAttribute('href'), anchor.getAttribute('title')));
		}
	}
	imageArray.removeDuplicates();
	while(imageArray[imageNum][0] != imageLink.getAttribute('href')) { imageNum++;}
}

aft:
// if image is part of a set..
if( (imageLink.getAttribute('rel') != null) && (imageLink.getAttribute('rel') != 'lightbox' ) && (imageLink.getAttribute('rel').toLowerCase().match('lightbox')) )
{
	// loop through anchors, find other images in set, and add them to imageArray
	for (var i=0; i<anchors.length; i++)
	{
		var anchor = anchors[i];
		if (anchor.getAttribute('href') && (anchor.getAttribute('rel') == imageLink.getAttribute('rel')))
		{
			imageArray.push(new Array(anchor.getAttribute('href'), anchor.getAttribute('title')));
		}
	}
	imageArray.removeDuplicates();
	while(imageArray[imageNum][0] != imageLink.getAttribute('href')) { imageNum++;}
}
else
{
	// if image is NOT part of a set..
	// add single image to imageArray
	imageArray.push(new Array(imageLink.getAttribute('href'), imageLink.getAttribute('title')));
}

ダウンロードは download modified Lightbox JS v2.02

added 2006/05/08 23:45
Firefoxでrel属性無し版が動作しない不具合を修正いたしました!


javascriptはC言語likeで安心します。

2005年12月27日

タップダンスTシャツ

タップダンスTシャツつくろうとしています。

white_front2.jpg

よろしければ。

2005年08月12日

Google Maps APIで遊んでみました


前から、
お気に入りの店をDoCoMoのiエリア使って近い順に並べる・・・
ジャンルや店名で検索・・・
なんかしてグルメを育ててましたよ。

それをGoogle Maps API使って、もう少し便利にしてみました!
http://mxo.k1.xrea.com/gourmet_gmap/select_g_gmap.php

MySQLに当たって店情報とってきて、
Google Maps表示させて、
お店のマークをつけて、詳細情