JavaScript周りのことをば

category-icon

 おはようございます。最新版のリリースに向けて、近頃はそれなりに時間を充てています。ppBlogでは、JavaScriptはかなり重要な位置を占めています。一応、JavaScriptオフでも閲覧には問題ないとは思うのですが、管理モードなどでは必須です。

 で、ppBlogでの主要なJavaScriptライブラリである、js/script.jsの見直しを進めているところです。この中で、windowのonloadイベントには、いくつかの関数を割り当てています。これまでは、

addEvent(window, "load", function (){
 roundedStyle();
 quotedStyle();
 initCSSHover();
 if(moz) hackFirefoxToolTip();
});

でしたが、これだと、HTMLのDOMエレメントのみならず、外部リンクや画像やらも読み込んだ後でないと発動しません。画像など読み終えてなくても、DOMエレメントを読み込んでパースした時点で動く関数などはさっさと動いて欲しいものです。このようなことは誰もが思っているみたいで、JavaScriptマスターのDean Edwardsは、Firefoxに DOMContentLoaded という隠し属性みたいなやつを見つけて、それで、ごにょごにょやっています。→ The window.onload Problem - Solved!Link

 でも、個人的には、あまりスマートな方法には見えないんで(IE向けには外部スクリプトを別に用意しないといけないし)、自分なりにも考えてみました。そもそも、IEにあるdocument.readyStateG みたいなやつが標準で提供されていれば、みんな悩まずに済むのだけれど、ないから仕方なし(IEでも、挙動不審なところがあるようだし)。

 で、原始的な方法ではあるが、DOMエレメントの数を取得する d.documentElement.getElementsByTagName("*").length をミリ秒単位で監視しておき、それがプラトーに達した時点を読み込み完了とするというアプローチでスクリプトを書いてみた。こんな感じ。

DOM = {
 ready : false,
 size : d.documentElement.getElementsByTagName("*").length,
 check : function(){ DOM.ready ?  DOM.onload() : DOM.update.await(100)(DOM.size); },
 update : function(i){
  if(d.documentElement.getElementsByTagName("*").length==i){
   DOM.ready = true;
   DOM.onload();
  } else {
   DOM.size = d.documentElement.getElementsByTagName("*").length;
   DOM.update.await(50)(DOM.size);
  }
 },
 onload : function(){}
}
DOM.check();

 あまり深くは考えていないけど、これで期待通りの動作をしている感じ。このサイトのppBlogでは、先ほどのwindow.onloadのイベントを、こっちに割り当てて、

DOM.onload = function(){
 roundedStyle();
 quotedStyle();
 initCSSHover();
 if(moz) hackFirefoxToolTip();
}

というふうにしています。このやり方だとブラウザを選ばなくてベターではなかろうか。アイコン画像なんかを全部表示していなくても、DOMツリーを読み込んだ時点で発動します。エドワーズのとこにあるデモのスクリプト(http://dean.edwards.name/my/busted.htmlLink )に似せて同じことをDOM.onload で実現したサンプルを載せておきます。→http://p2b.jp/demos/busted.htmlLink

 ちなみに、Functionオブジェクトに、新たにawaitというメソッドを定義してそれを使っています。まぁ普通にsetTimeoutでやれば良いのだけれど、勉強がてら。JavaScriptマスターである最速インターフェース研究会さんのエントリーを参考にしました。→ Function.prototypeを拡張して遅延実行を実現する Link

 まだよく理解していないので違うかもしれないけれど、このawaitメソッドをまねて、loopというのを定義しました。正しいのかな? 狙いとしては、limitで指定した回数だけ、msミリ秒おきに関数を実行するというやつです。

Function.prototype.loop = function(ms, limit){
 var count = 0, self = this;
 return function(a){
  if(limit <= count) return;
  count++;
  self.await(ms)(a);
  arguments.callee.await(ms)(a);
 }
}

 今のところppBlogでは、これは使っていないけど使うかもしれない。簡単な例としては、

var func = function(v){alert(v);}
func.loop(1000,3)("1秒おきにアラートを3回表示");

とか。

 あと、ログインの際にAjaxを使って、少しだけログインの手順を減らすというのを考えています。その際にAjaxのPOSTメソッドでユーザー名とパスワードを送信するのですが、このままだとセキュリティー的に気持ち悪いので、MD5で暗号化してから送信するようにする予定です。大まかな動作は確認出来ています。とりあえず。(あぁ、コメント数がマイナスになるのも直さないと・・・)

— posted by martin at 07:18 am   commentComment [0]  pingTrackBack [0]

アクセス解析の暫定版

category-icon

こんばんは。フォーラムで、アクセス解析にあるYahooエンジンの「検索語」が文字化けしているというご指摘がありました。原因のひとつにログファイル自体の文字コードが統一されていないこともあるので、この際、UTF-8でログも統一するようにした暫定版をアップしておきます。ログの文字コードをUTF-8に決め打ちして、現在のログとの互換は考慮していません。なので、現在のログは手元にダウンロードしておくなりしておいた方が良いかもしれません。この新しいやつを使ってみたいという方は、4月分のログに関しては、適当に保存後、FTPソフト上で削除しておくと、新しいログと古いログとがごっちゃにならずに済みます。

 最終的には、現状、ログはひと月に1ファイルですが、これだとアクセスに応じてログサイズが肥大するので、あるサイズ以上になれば分割するなどの処理も必要だなぁと思っています。
Browser share
相変わらず、スレイプニル強いですね。最近、自分はLunascape使ってます。
 なお、ブラウザのアイコンもいくつか増やしました。マックOS XにはSafari以外にも「シイラ Shiira」なんていうお洒落なブラウザがあるようで、それのアイコンも追加しています。以下にスクリーンショットを載せておきますね。
keyword
「メモリーリーク」でやたらと飛んでくる。
 検索エンジンのプラットフォームに、Wikipediaもあり、これ経由のアクセスがそれなりにあるので、このアイコンも追加してます。自分のサイトの「検索語アクセス」を見てみると、以前の書き込みで、IEのメモリーリーク問題について言及していたんですが、そのせいか、この検索語でのアクセスも目立ちます。あとは、当然ながら「ppBlog」でのアクセスは多いです。
platform
Windows強し。BecomeBot なんていう巡回ロボットもいる。
 生データを見てみると、Mozillaならぬ「Monazilla」というのもちらほらとあり、これは2ちゃんねる専用ログ巡回ソフトのようです。これのアイコンも追加してます。
UTF8
グーグルのサイトのソースをエディタで表示させたところ。正しくはUTF-8です。

 これから先は余談なんですが、グーグルの検索語を表示する際に、たまに文字コードの変換エラーが出るのがあって、生ログを調べてみると、なんと、文字コード指定の「ie=UTF-8」の部分が「ie=UFT-8」になっているじゃないですか。しかも、これはグーグル本家(google.co.jp)が間違っているのです。何故なら、UTF-8をフルスペルで書くと、8-bit UCS Transformation Format ですから。証拠を載せておきます。

このために、スクリプトの中で、
if($enc=='UFT-8') $enc = 'UTF-8';
という何ともトホホな処理を入れています。まぁ、そのうち修正されるのでしょうが。UFTと言えば、医療の現場では、ウラシルとテガフールの合剤である抗がん剤のことで、大腸ガンなど種々のガンの治療に使われています。UFTカプセルという経口の抗がん剤が出来たことで、患者さんの負担も随分 軽減したと思います。

 さらに余談ですが、今日グーグルで調べ物をしていると、グーグルのロゴが変わっているのに気付きました。なんだかミロっぽいなと。そこでピンと来て、ホアン・ミロWについて調べてみると、案の定、4月20日はミロの生誕日なんですね。しかも、最近は「ホアン」じゃなくてより現地語に近い発音の「ジョアン」ということも知り。グーグルの社員にきっとミロ好きがいたんでしょうね。こういう余興大好きです。このロゴは今日(4月20日)だけかもしれないので、記念にこれも載せておきますね。しかし、見事にミロっぽい。

miro-google
ミロ風にGoogleって描いてます。ピカソと同じぐらいミロも好き。シュール。
添付ファイル: stat_EUC.zipattachedIcon 

— posted by martin at 09:06 pm   commentComment [6]  pingTrackBack [0]

RC1アップ

category-icon

とりあえず、EUC-JP版とUTF-8版をアップしました。何だか、久しぶりに取り組んだので自分でも忘れている部分(関数の定義とか)などあり、作業を思い出すのが大変だったり。もうちょっと気合を入れねば。

 てなわけで、インストーラーは、RC2で付けようと思います。1.5ベータと比してそれほど変わってはいないと思うのですが、新機能としては、コメントやトラックバックの際の「NGワード」を付けたことでしょうか。管理画面の「IPコントロール」から設定できます。1.5ベータをお使いの方は、最低限、

  • onwer/ini.inc.php
  • owner/ngwords.inc.php(←今回新しく追加になった)
  • admin.php
  • trackback.php
  • modules/ 以下全部
  • js/ 以下全部
  • css/ 以下全部

を上書きすればいいのではと。なお、ini.inc.phpでは、管理者名とパスワードなども設定しているので、上書きする際には、予め、この部分を書き換えておくと、そのままログイン出来ます。初期設定では、

ID:admin
PWD:pass

になっているので、そのまま上書きした場合は、これでログインして、自分のやつに変更できます。

 上のように、逐次上書きというのは、漏れもありそうなので、確実なのは、

  1. RC1を新規にアップ
  2. 各ディレクトリのパーミッションを変更(これが一番キモです)
  3. ログやコメントログやトラックバックログ、PIXディレクトリの画像をそのまま移す
  4. 何か新規に記事を書き込めばキャッシュファイルが更新されるので、それでOK

という流れでしょうか。  細かいところで言えば、記事の編集時のテキストエリアの高さを広げたり、狭めたりするボタンを付けたり、テーマ切り替えメニューをプルダウン式からリスト形式(UL)に変えて、スタイルシートでお洒落に見えるようにしたりとか ギャラリーのスタイルシートを大幅に変えたりとか、色々変わっている所は変わっています。

 あと、UTF-8の場合、そのままログを移しても、文字コードが違うために確実に動きません。文字コード変換スクリプトをそのうちアップしようとは思いますが、ちなみに自分は、フリーソフトの「KanjiTranslater 1.3Link 」を使いました。素晴らしいツールを提供して下さっているKASHIM.COMさんに感謝です。


— posted by martin at 12:09 am   commentComment [22]  pingTrackBack [2]

今夜RC1リリース

category-icon

おはようございます。このところ多忙につき、ppBlogの開発・サポートはまったく手付かずでしたが、今夜ppBlog1.5RC1を出します。ほんとは、日曜深夜に出そうと思ったのですが、ちょくちょく中断があり進みませんでした。。なかなか都合良くは行かないものです。

 小生のサポートが不十分にもかかわらず、有志の方々の援助もあり、ppBlogを使って下さる方も着々と増えており、このような状況を看過するわけには行きませんで。心を新たに、開発に励みたいと思います。ロードマップをば。

  • 今夜RC1リリース
  • 今週末〜来週RC2
  • 再来週 1.5正式版リリース
てなところです。これは、タイトに進んでいくのでは思っています。RC1における1.5のβ版からの変更としては、コメントやトラックバックでのNGワード対策も盛り込んでます。小生も実際に、トラックバックスパムを受け、これに対処したものです。これで、少なくとも小生が受けた海外からのスパムは完全にブロック出来ています。 あ、あと文字コードですが、従来のEUC-JP版に加え、UTF-8版も一緒にリリースします。

— posted by martin at 06:08 am   commentComment [7]  pingTrackBack [0]

IEのメモリリーク問題

category-icon

IEあるいはIEエンジンのブラウザ(Sleipnirとか)を使っていて、どうもページの描画速度が遅い気がする―もっと正確には最初にページを開いたときより遅くなった―と感じたことはないだろうか? 特にあなたがJavaScriptを多用したページを開いているならば、もしかしたらIE特有のメモリリーク問題(IE memory leaks problemG)が原因かもしれない。

 余談ですが、前回のmoblogエントリーは、自分のブログにモブログしたつもりが間違ってこちらにエントリーしてしまいました。気が向いたら移動しておきます。

 で、本題ですが、この問題はより多くの利用者が(IEエンジンの)タブブラウザーを使うようになればなるほど顕在化してくると思われるのでメモしておこうと思います。ppBlogでもJavaScriptは欠かせませんし。最初に言っておきますが、この問題はIE4-6に特有のもので他のモダンなブラウザは影響を受けません。

 では、早速、IE6単体で(タブブラウザではなく)このテストページLink を開いて下さい。216色のカラーチャートを作成し、その各セルにマウスイベントを設定しているシンプルなデモです。ページを開いたらリロードを何回か繰り返してみましょう。生成時間がどんどん長くなっているのを確認したら、そのページを一度閉じて、新たに次のテストページLink を開いて同様にリロードを繰り返してみましょう。どうでしょうか?今度は生成時間が伸びていくということはありません。

 この2つのページの違いは何でしょうか?最初のテストページでは、まさにメモリーリークが起こっています。リンク先にも書いてありますが、分かる方はControl + Alt + Del キーを押して、タスクマネージャを起動、IEXPLOERE.EXEのメモリを見ながらリロードを繰り返せばメモリが肥大化していくのを見ることができます(尚、ウィンドウを閉じればメモリは開放されます)。この2つのテストページの違いは、ほんのちょっとしたことです。やや専門的になるかもしれませんが、イベントを定義する関数を定義しているのですが、その扱いの違いです。もともとは、Scott AndrewLink (最近は専ら音楽に夢中のようです。。)がW3CとIE特有のイベント定義関数の差を吸収するために作り出したaddEvent/removeEvent関数ですが、オリジナルのままでは、IEのthis参照に問題があったために、様々なバージョンが編み出されました。ppBlog1.5βでも似たようなやつを付けていますが、ここに挙げるのはその改訂版です。まず、メモリリークを起こすやつから。

function addEvent(obj, evType, fn){
 if(!obj["_"+evType]){
  obj["_"+evType] = [];
  if(obj["on" + evType] != null) obj["_"+evType].push(obj["on" + evType]);
  obj["on" + evType] = function(e){
   var e = e || window.event;
   for(var i in this["_"+e.type]) this["_"+e.type][i].apply(this,[e]);
  }
 } else {
  for(var i in obj["_"+evType]) if(obj["_"+evType][i]===fn) return;
 }
 obj["_"+evType].push(fn);
};

function removeEvent(obj, evType, fn){
 if(obj["_"+evType]){
  for(var i in obj["_"+evType]){
   if(obj["_"+evType][i]===fn) delete obj["_"+evType][i];
  }
 }
};

 addEventの中で、匿名関数を使っています(ホナ トピンクの部分)。次にメモリリークを起こさないやつ。

function addEvent(obj, evType, fn){
 if(!obj["_"+evType]){
  obj["_"+evType] = [];
  if(obj["on" + evType] != null) obj["_"+evType].push(obj["on" + evType]);
  obj["on" + evType] = evokeEvent;
 } else {
  for(var i in obj["_"+evType]) if(obj["_"+evType][i]===fn) return;
 }
 obj["_"+evType].push(fn);
};

function removeEvent(obj, evType, fn){
 if(obj["_"+evType]){
  for(var i in obj["_"+evType]){
   if(obj["_"+evType][i]===fn) delete obj["_"+evType][i];
  }
 }
};

function evokeEvent(e) {
 var e = e || window.event;
 for(var i in this["_"+e.type]) this["_"+e.type][i].apply(this,[e]);
};

 具体的に各オブジェクトにイベントを設定していく部分をaddEvent関数の外に出していますね。おかげで関数が3つになっちゃってます。世の中の多くのJavaScriptの書き手は、「スクリプトはシンプルなのがスマートだ」という理念を持っていて、自分もその一人です。その結果として関数内の匿名関数やクロージャーを多用する傾向にあります。悲しいかな、IEにはこれが通用しないのです。もっと詳しくこの問題を理解するキーワードは、「クロージャーclosure」と「循環参照 circular reference」です。ここで詳しく解説しようとは思っていないので悪しからず。以下のサイトを参照してください。Richard CornfordのサイトLink が端的にこの問題を指摘しています。

The Internet Explorer web browser (verified on versions 4 to 6 (6 is current at the time of writing)) has a fault in its garbage collection system that prevents it from garbage collecting ECMAScript and some host objects if those host objects form part of a "circular" reference. The host objects in question are any DOM Nodes (including the document object and its descendants) and ActiveX objects. If a circular reference is formed including one or more of them, then none of the objects involved will be freed until the browser is closed down, and the memory that they consume will be unavailable to the system until that happens.

 この問題は、Microsoftも認識しているのでIE7では解決されると良いのですが。尚、上に挙げたサイトで、最後のMihaiのページもよくまとまっているのですが、Mihaiが例示しているメモリーリークの退避例でも、やはりリークが起こるような気がします。

 あと、メモリーリークを起こすページを検出するツールがあるので、これもリンクしておきます。もっとも、このツールは完璧ではなく、すべてのメモリリークを検出するわけではないですが目安にはなるかと。メモリー負荷テスト(Blow memory)は、メモリーが増大していく様を見れるので有用です(もっともタスクマネージャーでも見れますが)。

Out of Hanwell:IEメモリリーク検出ツールLink

タブブラウザが出てくる以前は、この問題はさほど気にすることもなかったかもしれませんが、タブブラウザでは、常に複数のページを開いているというのが当たり前ですし、AJAXの台頭で、これからもJavaScriptはwebページで多用されるでしょうから、この問題を認識しておくのも悪くはないと思います。自分みたいなプログラム配布者はなおさらです。

 あ、あと、スコット・アンドリューがaddEvent/removeEventについて最初に紹介したページを見付けたのでリンクしておきますね。 →http://www.scottandrew.com/weblog/articles/cbs-eventsLink


— posted by martin at 01:09 pm   commentComment [7]  pingTrackBack [2]

T: Y: ALL: Online:
Created in 0.0114 sec.
prev
2025.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