Firefoxでの擬似window.event

category-icon

Follow-Up 2006-7-6

 Firefoxでもwindow.eventを有効にするやり方のエントリーはこちらLink  

 Gecko系のブラウザでは、これはNetscape4.x時代からずっとそうなんだけど、イベントは、イベントハンドラーにargumentとして渡されるので、この手の記述には必ず引数(ひきすう)を書く必要がある。一方、IEでは(Operaもか?)、イベントモデルには、最後に生じたイベントをキャプチャーするwindow.eventという属性があり、これはどこからでも自由にアクセスすることが出来る。以上のことをまとめると、イベントに関してクロスブラウザーな記述をしようと思えば、例えば以下のような感じになる。

function getEventType(e){
 var e = e || window.event;
 alert("Event Type is:" + e.type);
}

 で、ここで引数に使用している"e" であるが、これはGecko系のためだけに必須である。window.event であれば、この引数は不要だ。で、自分は常々、この"e"を追放できないかなと思っていた。何しろ、イベントを絡ませるような関数に必ずついて回るからだ。スクリプトの記述はシンプルなのが良いのに、この"e" のために余計に引数が増えてしまう。

 ppBlogでは数箇所に、この"e" が出てくるので、こいつを追放してやろうと決心した。そして色々弄った結果、これならOKかなというのを見つけたのでメモしておく。もちろん、ppBlogにも反映される。

 まず、最初にやったことは、ppBlogのjs/lib.jsに記述してある、ページ内でのマウスイベントX座標をゲットする以下の関数において、Firefoxでイベントがどんな風に呼び出されるのかだ。

function getEventPageX(e){
 var e = e ||window.event;
 if(e.pageX){
  return e.pageX;
 } else if(e.clientX){
  if(d.documentElement && typeof d.documentElement.scrollLeft != "undefined"){
   return d.documentElement.scrollLeft + e.clientX;
  } else if(d.body && typeof d.body.scrollLeft != "undefined"){
   return d.body.scrollLeft + e.clientX;
  }
 }
 return 0;
}

 実行している関数自身は、arguments.calleeで参照出来る。そして、この関数が何によって呼び出されているかは、callerプロパティーを参照すればいい。これらを使って、上の関数に、

 alert(arguments.callee.caller);

を付け足してみると、Firefoxでは、

function onclick(event){
  getEventPageX(event);
}

というのが返ってくる。→デモ1。Link ほほう。ちなみにIEでは

function anonymous()
{
  getEventPageX(event);
}

という匿名関数が返ってくる。Firefoxでは、引数のeventonclick関数によってキャプチャーされていることが分かる。じゃ、このonclick関数のeventって何だろう。これは次のようにして調べることが出来る。

 alert(arguments.callee.caller.arguments[0]);

すると次の答えが返ってくる。→デモ2Link

[object MouseEvent]

ほうほう。イベントは、マウスイベントオブジェクトとしてonclick関数に組み込まれているらしい。ならば、これを呼び出して、"e" に渡してやれば、"e" の束縛から逃れられるのではと推察する。なので次のようにして、"e" なしのやつを走らせてみる。→デモ3Link

function getEventPageX(){
 var e = arguments.callee.caller.arguments[0] || window.event;
 if(e.pageX){
  return e.pageX;
 } else if(e.clientX){
  if(d.documentElement && typeof d.documentElement.scrollLeft != "undefined"){
   return d.documentElement.scrollLeft + e.clientX;
  } else if(d.body && typeof d.body.scrollLeft != "undefined"){
   return d.body.scrollLeft + e.clientX;
  }
 }
 return 0;
}

 おおぉー、上手く行った:) 3つ目のデモでは、もはや引数のeは必要なく、getEventPageX()だけで座標を取得していることに着目。

 こりゃいいやと、js/lib.jsjs/editor.jsに出てくる引数"e"をとりあえず、全部なしにしてブロッグを見てみると、意図したように動かない。何でかなと、デバッグダイアログを見てみると、これまでのデモでは、マウスクリックによって直接getEventPageX()を呼び出していたのに対して、実際のスクリプトでは、getEventPageX()などは、別の関数の中で呼び出されている。なので、

arguments.callee.caller.arguments[0]

だと、getEventPageX()を含んだ関数の第一引数を返してしまうのである。初歩的ミス。。それならば、

arguments.callee.caller

を次々に呼び出していけば、そのうち、マウスイベントオブジェクトに到達するはずである。イメージ的には、sourceに向かって遡っていくイベントバブリングですね。これは次のような記述でいい。

var caller = arguments.callee.caller;
while(caller){
 var ob = caller.arguments[0];
 if(ob == '[object MouseEvent]') return ob;
 caller = caller.caller; // 次の呼び出し元にセット
}

ただ、ob == "[object MouseEvent]" というのは何となく「カッコ悪い」。この部分はコンストラクタを用いて次のようにも書ける。

ob.constructor == MouseEvent

 以上をまとめて、IEでも使えるようなクロスな記述にすると以下のような感じ。

function windowEvent(){
 if(window.event) return window.event;
 var caller = arguments.callee.caller;
 while(caller){
  var ob = caller.arguments[0];
  if(ob && ob.constructor == MouseEvent) return ob;
  caller = caller.caller;
 }
 return null;
}

 windowEvent()がそのままIEのwindow.eventに相当する。これを用いればイベント関連の記述に必須であったeからめでたく解放される訳である。最初に出てきたgetEventPageX()関数は、最終的には次のように記述できる。

function getEventPageX(){
 var e = windowEvent();
 if(e.pageX){
  return e.pageX;
 } else if(e.clientX){
  if(d.documentElement && typeof d.documentElement.scrollLeft != "undefined"){
   return d.documentElement.scrollLeft + e.clientX;
  } else if(d.body && typeof d.body.scrollLeft != "undefined"){
   return d.body.scrollLeft + e.clientX;
  }
 }
 return 0;
}

 もはやイベントのキャプチャーのためだけに引数は必要ない。最終的なデモをあげておきます。 →http://p2b.jp/demos/windowEvent.htmlLink  なお、イベント座標取得関数とは別に、イベントが起こった要素の座標を返す、getElementPosition()という関数も新たに定義しています。これは、JavaScriptマスターであるppk氏Link のサイトにある"Find PositionLink " という記事に紹介されている関数をmodifyしたやつです。こんなやつ。

function getElementPosition(){
 var _x = _y = 0;
 var ob = windowEvent().target || windowEvent().srcElement;
 if(ob.offsetParent){
  while (ob.offsetParent){
   _x += ob.offsetLeft; _y += ob.offsetTop;
   ob = ob.offsetParent;
  }
 }
 return [_x, _y];
}

 とりあえず


— posted by martin at 06:10 pm   commentComment [1]  pingTrackBack [0]

ppBlog1.5RC2 再度

category-icon

おはようございます。先週の5月23日にRC2を出して、皆さんからバグフィックスを含め色々なフィードバックを得ることが出来ました。情報を下さった皆さんに感謝します。指摘を受けた部分は、出来る限り修正をしたつもりですが、まだ見落としや、新たなバグは当然あると思います。今回のリリースは、仕様としてまだ流動的な部分もありますが、かなり正式版に近いものになります。前回リリースからの変更点を挙げておきます。

[追記:20:50PM]

 jsスクリプトを lib.js.php にしたんですが、このlib.jsに画像パスを渡す方法を思いついたので、lib.js.phplib.jsにします。コロコロ変えて申し訳ありません。どういう解決法にしたかというと、スクリプトタグ<script>にID属性を与えて、そのIDをテーマIDにすれば、lib.jsを最後に呼び出すとして、ID名は
d.getElementsByTagName("script")[d.getElementsByTagName("script").length-1].id

で取得できますね。うー、何でもっと早く思いつかなかったのか。てな訳で、今日DLされて該当される方は、utils.phpの141行目あたりを

$DIVISION['script'] .= '<script type="text/javascript" id="'.basename($theme_dir).'" src="js/lib.js" charset="'.strtolower(ENCODE).'"></script>';

とされて、admin.phpの89行目も同様に、

<script type="text/javascript" id="'.basename($theme_dir).'" src="js/lib.js" charset="'.ENCODE.'"></script>

として、で、最後に、js/lib.js.phpの中身、9行目を

var ImagePath = d.getElementsByTagName("script")[d.getElementsByTagName("script").length-1].id+'/Images';
としてjs/lib.js.phpjs/lib.jsに改名されて下さい。ほんと申し訳ないです。。

---追記ここまで---

  1. js/script.jsjs/lib.js.php になった。名前と拡張子が変わりました。が、中身は普通のjsファイルです。PHP化しているのはテーマ画像ディレクトリまでのパスを取得するためです。出来れば*.jsのままでいい方法があればと思ったのですが、思い浮かびませんでf(--; 今後、基本的に画像はテーマ指向になり、出来る限り各テーマで画像は用意することになります。
  2. 非公開コメントの機能をとりあえず実装してみた。これは前回からありましたが、まだ仕様も固まっていないようなシロモノでした。現時点で想定していることは、管理者はすべてのコメントが見れるのは当然として、非公開を指定したユーザも、ブラウザのクッキーが有効であれば、自分の非公開コメントは見ることが出来る。また、もし、管理者が非公開コメントにレスすると、そのレスは非公開した者も見ることが出来て、他の人には見えない、というものです。こういう機能は、あればあるで結構使えるなというのが率直な印象です。
  3. 前回のエントリーにも書いていますが、記事作成画面での文字色・背景色のフルカラー化。角丸ボックスのリニューアル。
  4. アマゾンアソシエート関連ファイルの添付。前回、添付し忘れていました。。ついでに、サーチメニューのカテゴリーに「ホーム&キッチン」という項目を追加して、ちょっと弄ってます。

 以上が主要なものでしょうか。あと、細々と至る所、書き換えていますので、基本的には、前回リリース版を使われている方は、ownerディレクトリと投稿・コメント・トラックバックログディレクトリ以外のすべてのPHPファイルは上書きされることを強く推奨します。あと、index.phpと同じレベルにあったImagesディレクトリのいくつかの画像はテーマディレクトリのImagesディレクトリに移ったりしています。

 正式版を100%とすると、完成度は89−93%というところでしょうか。。


— posted by martin at 06:39 am   commentComment [36]  pingTrackBack [2]

HSVマップ組み込みと角丸コーナースクリプト

category-icon

 次のリリースに盛り込む予定のもの。

 記事作成画面では、216色のカラーチャートから文字やマーカー色を選べますが、個人的には216色じゃ足りなくて不満。なので、フルカラー?にしてみました。スクリプト的にも、216個のセルにイベントを設定していた前作に比べ、こちらは画像1枚なのでベターかなと。HSVWは色々勉強になった。

 あと、ボックスの4隅が丸い、いわゆる角丸コーナーですが、それを実現するためのテクニックは、web上にゴマンとあります。ppBlogのjs/script.jsにもそれっぽいやつがありますが、これは画像を使用するし、またその画像に色を揃えるためボックスの背景色も決め打ちになってしまいます。これは宜しくないので、Liquid round cornersLink を読みつつ、じゃ、これをJavaScriptで書いたらどうなるかなと思ってとりあえず書いてみました。画像は使用していません。また、アンチエイリアスを少しだけ意識してみました。ボックスの背景色に合ったボーダーの色とアンチエイリアスを自動的に算出してくれるし、指定することも可能。とりあえず書いただけなのでソースは非常に汚い。一応デモページをあげておきます。

 →http://p2b.jp/demo/HSVmap_Rounded_Corner.htmlLink

HSV2RGB
こんな感じになります

— posted by martin at 02:54 am   commentComment [0]  pingTrackBack [0]

RC2ダウンロード再開

category-icon

 前日リリースしたやつの既知のバグを修正したものをアップしてます。綴りの間違いだったり、パスの設定が変だったり、皆さんのご指摘で助かっています(TT)  個人的には、画像ファイルのキャッシュ生成をどういうタイミングでするかに腐心していましたが、ようやく「これで良いかなぁ」って感じになりました。なので、画像キャッシュが絡んでくるファイル群は、昨日のやつと結構変わっています。utils.phpは当然として、あと、upload.phpとかinsertImage.phpとか、imager.inc.phpとか、gallery.inc.phpとか。これまでは、画像ファイルと、動画ファイルとは、同じキャッシュに含めていましたが、これからは、画像は画像のみ、それ以外のメディアファイルは、データベースとなるキャッシュを別に分けていこうと思います。これは、ポッドキャストなどを見据えてのことです。これからは、動画や音声ファイルのアップロードも増えていくでしょうから。  で、まずは、画像のキャッシュ生成を考えていたので、それ以外のメディアファイルのキャッシュ生成は、正式版までに概要を固めていこうと思います。

 おー、そろそろ寝ないと。


— posted by martin at 03:15 am   commentComment [67]  pingTrackBack [1]

とりあえず小休止

category-icon

 ダウンロードして、設置してくださった皆さん、ほんとに報告ありがとうございます。自分でも新規にインストールして検証したはずだったのに、インストールファイルを入れ違えてアップしていたり、何ともトホホなことしてますねぇ(-o-) とりあえず、ここまでの不具合を修正してから、またDLを再開しようと思います。これは深夜には再開できるはずです。他にも個人的にいくつか気付いた点がありますので、そのあたりも修正して。

 しかしながら、ひとりで検証するのとはスピードが全然違いますねぇ。報告して下さる方々には頭が上がりません。励みになります。というわけでダウンロードはしばしお待ちを。


— posted by martin at 11:06 pm   commentComment [10]  pingTrackBack [0]

T: Y: ALL: Online:
Created in 0.0051 sec.
prev
2006.5
next
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31