悔しいことにハマったので、メモ。
次のような感じで、javascriptでformをサブミットしようとしたら、エラーになってしまう。
<form name="addForm" action="/add" method="post"> <input type="button" name="submit" onclick="document.forms[0].submit()" value="送信" /> </form>
理由を聞いてみると、
document.forms[0].submit is not a function
関数じゃないって、そんなわけあるかい。javascriptの不審な動きに、仕方なくひとつひとつ探っていって、やっと分かりましたよ。formタグのなかに、「submit」という名前の要素を置くと、そっちを参照しちゃうみたい。ここでは、ボタンの名前に「submit」なんて付けているからダメだと。
言われてみれば、確かにそれはそれで正しい気がする。でも、まあ、もう少し優しい言葉を返してくれても良いんじゃないだろうか。同じ理由で、例えば、action や target という名前も、避けないといけないってことだよね。
回避策もありそうな気はするんだけどなあ。見つけたらエントリしまっす。
Posted by dT by 02:19 | Comments (0) | TrackBacks (0)
JavaScriptで外部CSSで定義した値を参照する場合
var mystyle = element.style
ではなく
var mystyle;
if (document.defaultView && document.defaultView.getComputedStyle) {
// firefox, opera
mystyle = document.defaultView.getComputedStyle(element, '');
} else if (element.currentStyle) {
// ie
mystyle = element.currentStyle;
}
ってしないといけない。
恥ずかしながら今まで全然知らなかったけど、よく困らなかったなあ、自分。prototype.js には、Element.getStyle() というのがあるから、それを使えば良いのだけど、やっぱり基本原理みたいなものを押さえていないと気持ち悪いので。
詳細はこちらが、スゴイ詳しいです。amachang 氏、さすがの内容。
Posted by dT by 23:21 | Comments (0) | TrackBacks (0)
NodeListのノードをremoveChildで順番に消していこうとしたら、半分くらい残る。なぜ。
var tbody = document.getElementsById("hoge");
var nodelist = tbody.getElementsByTagName("tr");
var len = nodelist.length;
for (var i = 0; i < len; i++) {
tbody.removeChild(nodelist[i]);
}
上手く説明できないけど、nodelistの数値インデックスの関係がおかしくなっている。getElementsByTagNameが返すNodeListは参照で、ノードを削除していくごとに、動的にNodeListの長さも変わっていくのかな。だから、削除していくと、「そんな数字インデックスに該当するノードは無いよー」ってなってるっぽい。
ということで、ノードの削除は、常にNodeListの先頭のものを対象に実行するとキレイに行く。
while (nodelist.length > 0) {
tbody.removeChild(nodelist[0]);
}
仕組みが分かれば、そりゃそうだって話なんだよね。リスト操作の基本か。こういうこと考えると、Iteratorがあると便利なのかもしれない。
Posted by dT by 11:42 | Comments (0) | TrackBacks (0)
httpsな環境でGoogle Analytics用コードを埋め込んでいると、IEでアクセスしたときに次のようなアラートウィンドウが開く。

「このページにはセキュリティで保護されている項目と保護されていない項目が含まれています。」と、ちょっと親切なふりをしているが、これってユーザーに何かメリットがあるんだろうか。どちらかと言えば、煩わしくて邪魔だと思うんだけど…。
気になったので調べたら、回避策があった!
Google AnalyticsをHTTPS(SSL)なページで使う
× http://www.google-analytics.com/urchin.js ○ https://ssl.google-analytics.com/urchin.js
SSL対応のUrchinサーバーがちゃんと用意されているとは、さすが。
Posted by dT by 18:09 | Comments (3) | TrackBacks (0)
実験的に書いていたスクロールいじり系のスクリプトが、アプリケーションに組み込んだ途端に動かなくなった。scrollTopの値が常に0になる。むむぅ。
ハマりそうになって調べたら、どうもDOCTYPEによって、scrollTopの参照の仕方を変えないといけないとのこと。DOCTYPEの変更でjavascriptの挙動まで変わるとは思わなかった。理屈を言われれば道理が通るけど、しかしこれは反応できないッス…。
DOCTYPEを指定しない場合は、
document.body.scrollTop
DOCTYPEを指定する場合は、
document.documentElement.scrollTop
これで値を取得しないと、正しく参照できないと。他にもこの手のプロパティは同じような動作するんだろうなあ。覚えておかないと、ハマりそう。
Posted by dT by 23:02 | Comments (0) | TrackBacks (0)
javascript の delete 演算子の使い方を勘違いしていたっぽい。
てっきり不使用オブジェクトを削除することで、メモリを開放できるもんだとばかり思っていた。ところが、実際には undefined で上書きするだけで、メモリはまったく開放されない。結局、javascript におけるメモリ管理は、各クライアントの GC にまかせるしか無いのか。うーん。
Ajax の興隆以来、よく javascript コードを見るようになった。そこで気付くのが、多くの人が富豪的アプローチをしていること。onmouseover イベントを document に対して attachEvent しちゃうのかー、贅沢すぎー、みたいな。
今やクライアント側の性能が十分だから、あんまり気にしなくても良いのかもしれないけど、javascript で out of memory 的なことって起こるんだろうか。どこまで耐えれるのか、落ち着いたら実験してみたいなあ。
Posted by dT by 23:27 | Comments (0) | TrackBacks (1)
Yahoo!Maps のように、FlashとJavascriptを連携させて、URLのhashを書き換えていこうと思ったら、ずっこけた。悪名高きOperaで location.hash を書き換えると、勝手に画面がリロードされてしまう。なぜ。
いろいろ追っていった結果、現在のhash値と代入する値が同一の場合、リロードになるっぽい。どんな仕様ですか。しょうがないので、if文で分岐するがよろし。
function setHash(_value) {
if(location.hash != "#" + _value) {
location.hash = _value;
}
}
「これはバグだ!」と思ったら、なんか Safari でも同じような動きになる。スタンダードって何だろうとか考えさせる、罪なブラウザたち。やめて欲しい。
Posted by dT by 21:28 | Comments (0) | TrackBacks (1)
HTMLからFlashに変数を渡すには、2通りの方法がある。ひとつはFlashVarsを使用する方法、もうひとつはSWFファイルURL指定時に、クエリーとして変数を付加する方法。
// 後者抜粋 <param name="movie" value="deftrash.swf?hoge=foo" /> <embed src="deftrash.swf?hoge=foo" ... />
前者は FlashPlayer6 以上で、後者はもっと前の世代でもOK。そんなわけで、後者の方法を使用している人も多いはず。ところが、ここで落とし穴。変数の文字列に「#」が含まれていると、Operaでは、「#」以降の文字列を渡すことができない!(FlashVarsの方法では大丈夫っぽい)
どうやらURLエンコーディングしてあげる必要があるみたい。
// JavaScript で対応する場合
<script type="text/javascript">
document.write("<param name=\"movie\" value=\"deftrash.swf?hoge=\" + escape("#foo") + "\" />");
document.write("<embed src=\"deftrash.swf?hoge=" + escape("#foo") + "\" ... />");
</script>
location.hashをFlash側に渡そうとして、コレにすごいハマった。Operaとかスゴイ嫌いだよ。ううう。
Posted by dT by 21:00 | Comments (0) | TrackBacks (0)
これまで、javascript で正規表現のマッチング結果を得るときは、バカのひとつ覚えで String.match を使っていた。
var str = "12345";
var reg = new RegExp(/123/);
if(str.match(reg)) {
// マッチしたときの処理
}
でも、match関数の戻り値は「最初にマッチした部分の文字列(マッチしなかった場合は null)」 で、純粋にマッチしたかどうかを知りたい場合では、わずかにリッチすぎる。そのような場合は、RegExp.test (戻り値はtrue / false) を使うのが良い。
var str = "12345";
var reg = new RegExp(/123/);
if(reg.test(str)){
// マッチしたときの処理
}
Posted by dT by 12:50 | Comments (0) | TrackBacks (0)
ちょっと切ない JavaScript の話。
onload で複数の処理を行うために、Observer パターンを使おうと思ったわけです。ファサードになるファンクションを設けるのも良いけど、融通が利きにくいし。
というわけで、document にリスナーオブジェクトを登録&実行したんだけど、これがピクリとも動かない。原因は、document.onload が存在しないこと。何故。じゃあ、body タグに書く onload は何に対応するんだ。色々イジった結果、自作の処理とバインドできる onload は、window オブジェクトのそれだけの模様。
document.writeln(document.onload); // 結果は undefined document.writeln(window.onload); //結果は null (バインド可能)
ちなみに、一番上のスコープで this と書くと、window を指すみたい。ということで、
this.addEventListner("doSomething", lintener1);
this.addEventListner("doSomething", lintener2);
this.onload = this.dispatchEvent(
{type:"doSomething", target:this}
);
こんな形になりました。厄介だ。
Posted by dT by 21:38 | Comments (0) | TrackBacks (1)
webアプリケーションテストツール seleniumがヤバすぎる
JavaScriptベースのWebアプリケーション用テストツールらしい。各種ブラウザ経由で、サクサクっとテストできそうな雰囲気。JUnitも良いけど、あれは仕様変更に弱いっていうか、仕様変更が相次ぐと置き去りにされる傾向にあるからな…って、それはそれでマズイ話だけど。
Ajaxもびっくらこいたけど、このseleniumもスゴそう。一部ではJavaScriptにダメ言語のレッテルを貼り付けているけど、使い方次第なんだろうね。selenium、どっかで使ってみよう。
Posted by dT by 02:05 | Comments (0) | TrackBacks (1)
JavaScriptのEventまわりについて調べていたら、見たことない記法が出てきた。なんか変数の後ろにコロン付けて、それに続けてfunctionとかあるんだわ。型みたいなの。検索してみると、オブジェクト初期化子というものらしい。
var hoge = {
doMoge : function(_argument) {
alert(_argument);
}
}
hoge.doMoge();
オブジェクト初期化子を使うと、Objectのインスタンス生成時に、そのプロパティの初期化ができる模様。上の例は、プロパティを関数で初期化してみたところ。
単純化すると、こういう話。
// 次の2行は同じ意味
var hoge = new Object();
var moge = {};
もちろん new してから代入しても同じだけど、明示的に初期化できるから、こっちの方がコードの可読性は良い。単純化の例だと逆効果になりそうだけど、ちゃんと使えば素敵かもしれない。まあ、最近クラス化が基本になってるから、使い場所ないんじゃないかって、専らの噂だけどね。
Posted by dT by 16:35 | Comments (0) | TrackBacks (0)