2008年05月22日

JavaScriptがIEとOperaで動かない……原因はAjax.Requestのカンマ。

MOJI-Q 2.0、やっと完成して公開した〜と思ってたらIEとOpera(9.25)で動いていないことが判明。そういえばFirebugを見ながらFirefoxで作っていて、たまにOpera9.5でチェックしただけで他のブラウザは一切チェックしてませんでした。

まず、Firefoxでは大丈夫だけどIEとOperaではダメなものとして、JavaScriptのconstがありました。定数は使えないのか、残念、と思いながらすべてvarに変換。

それでもぜんぜん動かない……orz
IEはエラー行を教えてくれますが、行番号が合ってたり合ってなかったりでよくわかりません。Operaにいたっては完全にだんまり。仕方ないので、いったんすべてのJavaScriptをコメントアウトし、少しずつ表に出すことにしました。面倒で手間のかかる方法ですが確実です。

結局、こういうことでした。

new Ajax.Request('test.cgi',
{
    method: 'post',
    postBody: Form.serialize('form'),

    onSuccess: function(request)
    {
        // Do something
    },
    onComplete: function(request) {}, // ←これが原因
});

赤く書いた、Prototype.jsを使ったAjax.Requestの最後のカンマが原因です。以前はonCompleteの後にonFailureとか書いてあったものを消したので、区切りのカンマが残っていたわけです。そしてFirefoxではエラーにならないので、たった一文字のカンマに気がつくはずもなく。このカンマがあるとOpera9.25やIE7では動きません。

まとめ

  • JavaScriptのconstはFirefox(2.0)、Opera(9.5)では可、IE7、Opera(9.25)では不可。
  • Ajax.Request時のパラメータの最後に不要なカンマがあるとIE7、Opera(9.25)ではエラーになって動かない。Firefox(2.0)、Opera(9.5)、Safariでは問題ない。
  • JavaScriptマジめんどくさい。

2008年04月16日

Prototype.js、Element.setStyleのプロパティ名

Prototype.jsでElement.setStyleメソッドを使ってCSSを使って背景色を設定しようとしたんだけど、うまく行きませんでした。結局、下記のような結果に。

×NG
Element.setStyle($('id'), {'background-color': 'red'});

○OK
Element.setStyle($('id'), {'backgroundColor': 'red'});

なるほど、ハイフンはダメなのかー。代わりにキャメル形式を使うと。
でも、ネットで調べる限りはどこのリファレンスを見ても上記のようなことは書いてないし、NGの方で問題なく動いてました。

Element.setStyle - エレメントに指定CSSプロパティを設定
http://javascriptist.net/ref_prototype/Element.setStyle.html

上記のページのサンプルは問題なく動くし……違いといえばPrototype.jsのバージョンで、上のページは1.5、当方で動かなかったものは1.6でした。1.6からなんか変わったんですかね。まあいいや、キャメル形式で動くし。

2008年04月02日

Operaで、Ajax.Requestがうまく動かない?

マチウケメール便で画像を読み込む処理にPrototype.jsのAjax.Requestメソッドを使っているのですが、なぜか現行のOpera(9.25)ではエラーになってしまいました。request.responseTextも空っぽ。URLが間違っている風。
でもOperaベータ版の9.5は大丈夫だし、Firefox、古いIE6なども問題なし。

調べてみたらちゃんと原因がありました。CGIからHTML::Templateで出力しているページなので、<base>タグを使っていたんですが、Operaの9.5より前のバージョンではJavaScript内(詳しい範囲はちょっと不明)で<base>タグによる指定が無効になってしまうようです。
http://dev.rubyonrails.org/ticket/9373

つまり、HTMLで<base href="http://example.com/cgi/">と指定してあり、JavaScriptでAjax.Request('./test.cgi'...などとやっていたので、「http://example.com/cgi/test.cgi」へリクエストを送るのが正しいんですが、これが9.5より前のOperaでは<base>タグが無視され「./test.cgi」へ送信してしまうようです。結果、そもそもURLが間違っているのでレスポンスも空っぽみたいな。
自分はOperaユーザーなんですが、9.5をメインで使っているため気がつきませんでした。もっとも、そもそも<base>タグを使っていなければ発生しない問題なので、普通はほとんど問題にならないのかも。

9.5が正式版としてリリースされるまでの対策として、下記のようなコードを書きました。Prototype.jsのブラウザ判定を使っているので、Prototype.js 1.5.1以上が必要です。

url = './test.cgi';

// Opera 9.5 より前のバージョンではbaseタグが無効になるのでその対策 
if (Prototype.Browser.Opera && opera.version && (opera.version() < 9.5))
  url = $$('base')[0].readAttribute('href') + url;

new Ajax.Request(url, ...以下略

ウザイですが、これでOpera9.25でも動きます。シェアの少ないOperaなんて無視したいところですが、なにしろ自分が使ってますしね(^^;

関係ないですが、最近はOpera9.5より、SafariやFirefoxの方が体感速度はぜんぜん早いし、OperaはCSSやJavaScriptの挙動も正しいみたいなイメージも崩れてきて、Operaユーザーとしてはさびしい限りです。9.5の正式版で巻き返して欲しいですね。

2008年03月31日

JavaScriptで、コンボボックス/リストボックスに項目を追加する

new Option("ラベル", "値")で<option>タグのオブジェクトが作成できるので、<select>に対応するオブジェクトに対して、listbox.appendChild(new Option("label", "value"))などとすれば追加できます。
http://oshiete1.goo.ne.jp/qa231484.html

ちなみに第一引数のラベルは項目のラベル、<option></option>の中身で、第二引数はvalueの値になります。

ただし、上記の方法はIE6では使えませんでした。項目は追加されて動作もするのですが、ラベルが表示されません(ラベルが空文字列の状態になる)。なのでnew Option()を使わず、document.createElement('option')で生成すればIE6でも正しく追加されました。

var o = document.createElement('option');
o.value = "値";
o.innerHTML = "ラベル";
listbox.appendChild(o);

IE6でスタイルシートが反映されない

FirefoxやIE7、Operaなど現行のブラウザでは問題なく表示されるのに、Internet Explorer 6ではなぜかレイアウトが崩れる。CSSが反映されてない感じだけども、同じスタイルシートを使っている他のページは問題ない。

HTMLファイルの一番最初の行、<!DOCTYPE html ... よりも先に<!--でコメント行を入れていました。HTML::Template用のテンプレートファイルだったもので、プログラムなどを書く時の癖で最初の行にファイルの説明などのコメントを入れていたんですよね。最初の行にDOCTYPE宣言を書かなかった自分のせいで、IE6は全然悪くない...
でも他のブラウザでは問題ないし、気がつくまではかなり悩みました。

2008年03月30日

formタグで、エンターキーを押したときに送信しないようにする

formタグ内の、特にテキストフィールド(type="text")などでエンターキーを押すと、送信ボタンをクリックしたのと同じ動作になってしまいます。そのまま送信すればいい場合は便利ですが、input type="submit"ではなく、buttonタグとJavaScriptを組み合わせて事前チェックなどを行っていた場合は送信されては困る場合があります。

マチウケメール便もボタンをクリックした時はAjax処理がメインで送信はほとんど使っていません。

基本的には、formタグ内にsubmitが無ければエンターキーを押しても送信はされません。submitというのは<input type="submit">、あるいは<button type="submit"></button>です。後者のbuttonタグの場合、typeを指定しない場合のディフォルトがsubmitですので注意が必要です。自分はtypeのディフォルトはbuttonだと思ってました... submitではないbuttonタグには必ずtype="button"を書いておかないとです。

submitが無い場合でも、例えばformタグ内に<input type="text">が一つしか無い場合などはエンターキーで送信となってしまうようです。このことは下記のページに詳しいです。

Enterキーを打ってもsubmit(送信)しないようにするには
http://www.nslabs.jp/enter-submit.rhtml

従ってテキストボックスが一つしかない場合、上記ページのようにform内にダミーの<input type="text" style="position:absolute;visibility:hidden">を置いておく必要があります。

以上のようにsubmitを無くす以外に、JavaScriptでonkeydownイベントを処理してエンターキーを無効にする方法もあります。この方法だとエンターキーを押した時に送信しないようにするだけでなく、何かJavaScriptでの処理を行えるので便利です。マチウケメール便でもエンターキーでフォーカスを移動したり、送信以外のボタンをクリックした時と同じ処理を入れたりしてます。
onkeydownイベントを処理する方法はこちらのページが詳しいです。実際にはonkeydownではなく、onkeypressイベントを使うといいようです。これはonkeydownがsafariなどでうまく動作しないためだそうです。

エンターキーの押下でフォームの送信を行わないようにする
http://blog.nomadscafe.jp/archives/000484.html

ちなみに、onkeypressイベントを使うのは便利ですが、試したところFirefoxの入力補完と衝突してしまいます。途中まで入力し、候補を選んでエンターキーを押した時にその候補が入力されずにonkeypressが処理されてしまうわけです。残念ながら入力補完とonkeypressイベントを共存させる方法がわからなかったので、メールアドレスの入力など、入力補完機能があった方が便利な場所では最初の方法、submitを無くしてダミーのテキストフィールドを置く方法をとりました。

さくらインターネットで、ファイル一覧を表示しないようにする

さくらインターネットでは標準ではディレクトリのファイル一覧が表示されてしまいます。レンタルサーバー等でファイル一覧を見られないようにするには、.htaccessを用意して「Options -Indexes」を書いておくのが一般的ですが、さくらインターネットではOptionsが使えず、「Options」指定があるとエラーになってしまいます。

詳しくはこちらに書かれています。
http://support.sakura.ad.jp/support/manual/rs/tech_htaccess.shtml

上記ページにはファイル一覧を表示しないようにする方法も書かれていますが、エラーメッセージ用のHTMLファイルを用意するとか面倒です。

で、もっと手軽に実現する方法として、.htaccessに「IndexIgnore *」と書いておくと便利です。これをwwwディレクトリにおいておけば、どのディレクトリでもファイル一覧が表示されません。楽ちん。

2008年03月16日

ImageMagick(PerlMagick)で、画像を複製する

同じ画像を使い回したい時、コピーする方法がわからなくて別のオブジェクトを生成して同じ画像を読み込むというバカなことをやってたんですが、あんまりと言えばあんまりだし、時間もかかるしということで、ちゃんと探したらありました。

下記のコードで、minify.jpg、magnify.jpgがそれぞれちゃんと縮小、拡大されていて、$imageにも影響がないことがわかります。

#!/usr/bin/perl

use strict;
use warnings;
use Image::Magick;

# 画像を読み込む
my $image = Image::Magick->new;
$image->Read('source.jpg');

# オブジェクトを複製
my $imageA = $image->Clone();
my $imageB = $image->Clone();

# それぞれ縮小、拡大
$imageA->Minify();
$imageB->Magnify();

# ファイルに書き出す
$imageA->Write('jpg:minify.jpg');
$imageB->Write('jpg:magnify.jpg');
$image->Write('jpg:original.jpg');

print "content-type:text/plain\n\n";
print 'ok';
exit;

2008年03月12日

Windowsで、PerlのCGIをEclipseを使って作る

Windows上でPerlによるCGIをEclipse環境で作りたいときの最初の準備をメモ程度に。

まずActivePerlをインストールします。Windows用のPerlで、これがないとPerl自体が実行ません。こちらのページのDownload ActivePerlというリンクから、いくつかのページを経てダウンロードできます。5.10と少し古い5.8が選べます。
http://aspn.activestate.com/ASPN/Downloads/ActivePerl/

次にEclipseにEPICプラグインをインストールします。EPICはEclipseのPerl開発用プラグインです。Eclipse上でPerlスクリプトが編集出来るようになり、Javaのエディタにはとても及びませんが、色分けや一部のコードアシストも効くようになるので便利。Eclipse上で実行も出来るのでデバッグも楽ちんです。

Eclipseの自動インストール機能を使って、Help → Software Updates → Find and Install で、EPICのリモートサイトのURLは「http://e-p-i-c.sf.net/updates」です。

EPICがインストールできたら、Perl.exeの位置を設定しておく必要があります。これをやらないと文法のチェック機能などが使えません。Window → Preferences → Perl EPIC で、Perl executableというところに、Perl.exeのパスを指定します。右の「...」ボタンで参照できますが、ActivePerlを標準通りインストールした環境なら"C:\Perl\bin\perl.exe"になると思います。

かなりはしょりましたが上記の手順はエクリプスWikiのEpicの項、「http://eclipsewiki.net/eclipse/?epic」に詳しいです。

ちなみに、EPICはソースコードに括弧や引用符を入力した時に自動で閉じ側を入力してくれるんですが、ディフォルトの設定ではしつこく入力されてしまい不便です。設定のPerl EPIC → Editor、Smart typingのタブで設定変更できるので、オフにしておくといいかもしれません。

以上で簡単なCGIはeclipseを使って便利に作ることができます。

2008年02月24日

Androidで2chブラウザ、作ってみたけど……

画質が悪くてすいません。

こちらのエントリでも書いたんですが、Androidで2chブラウザを作ってみました。せっかく作ったので動いているところを動画で。

2chブラウザといってもスレッドを選んで表示する位しかできません。何しろ実機がなく、作ったところでどうなるわけでもないので全然やる気が出ないわけです。実機がないんじゃ需要もないですしね。

ドコモあたりから実機が出たらまた作ろっと。


広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は90日以上新しい記事の投稿がないブログに表示されております。