またでたよ。IE。
jasonpとかでスクリプトを読み込んで実行するときに、最初のkicker(loader?)的なスクリプトを書く場所によってエラーが発生する。
「インターネットサイトxxxを開けません。操作は中断されました」というエラーウィンドウがでて、サイトは表示されない状態となる。
例:
kicker.js
function kicker(){
var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.setAttribute("src","./callee.js");
document.body.appendChild(script);
return true;
}
scriptタグを作ってcallee.jsを読み込むだけ。
callee.js
function callee(){
document.getElementById("hogefuga").appendChild(document.createTextNode("hogefuga"));
return true;
}
callee();
テキストノードを埋め込むだけ。最後に自分を呼んでいる。
buggy.html(動かないケース)
<html>
<head>
<script type="text/javascript" src="./kicker.js" charset="utf-8" ></script>
</head>
<body>
<div>
<div id="hogefuga"></div><!-- ここにテキストノードが書き加わる -->
<script>
<!--
kicker();
//-->
</script>
</div>
</body>
</html>
問題は、scriptタグがdivに囲まれていることらしい。
下記のように変更すると動く
:
<div>
<div id="hogefuga"></div>
</div>
<script>
<!--
kicker();
//-->
</script>
:
でも、いつもいつも外側に書けるわけでもないよね?
そういう時はeventListenerだそうだ。
if(window.addEventListener){
window.addEventListener("load",kicker, false);
}else{
window.attachEvent("onload",kicker);
}
もう、いい加減面倒くさいよ。
参考: http://yusuke.homeip.net/diary/2006/03/12/1142155862799.html
ちなみに、何を作っていて気付いたかというと、このブログの「コメント」欄。
といっても、「はてなブックマーク」をコメント欄代わりに表示しているだけ。
またしてもIE。
ラジオボタンを動的に生成する場合、デフォルトとか以前の結果とかをチェックした状態で表示するために
var myRadio = document.createElement('input');
myRadio.type = 'radio';
myRadio.value = 'hoge';
myRadio.checked = true;
とかやるじゃないですか。
IEの場合、これではチェックが付かない。
ドキュメントにappendした後に変更する必要があるんだって。
いい加減にしてくれよIE
javascriptでformをname属性でアクセスする手法は良く使う。
var abc = document.formname.hoge.value;
これを、動的に生成させたformで行おうと思った場合、IEで問題が起こる。
var myNode = document.getElementById('fuga');
var myForm = document.createElement('form');
myForm.name = 'formname';
var myInput = document.createElement('input');
myInput.name = 'hoge';
myInput.type = 'text';
myInput.size = "40";
myForm.appendChild(myInput);
myNode.appendChild(myForm);
dom生成時に.nameでname属性を変更しているにもかかわらず、IEでは独自のIDがつけられてしまい、上記のname属性を利用したアクセス方法ではアクセスできないのだ!
有り得ないよ。
そこで、こんなユーティリティ関数が必要になる。
function createNamedElement(tag,name){
var isIE =/*@cc_on!@*/false;
var element;
if (name) {
element = (isIE)? document.createElement('<' + tag + ' name="' + name + '">'): document.createElement(tag);
element.name = name;
} else {
element = document.createElement(tag);
}
return element;
}
IE恐るべし。
ちなみに’cc_on’の所は、IEの判定で良く使われる方法(らしい)。
この記事のタグ名’bug_or_spec’のネーミングセンスの良さに自画自賛
あいかわらず、初歩的なところにいます。。。(-_-;)
perlのCGIでアクセス解析のためにリファラ(訪れた人が前に見ていたページ)を取ろうとしてたのですが、検索サイトによって文字が化けたりしてたので、utf8に統一してみようということで、以下のようにしました。
<script language="JavaScript">
<!--
document.write('<img src="http://hoge.fuga.funya/access.cgi?rr=' + escape(document.referrer) + '" />');
// -->
</script>
imgタグ内でアクセス解析用のcgiを呼んでいます。cgi側でHTTP_REFERERを取ると、このスクリプトを入れたページ自身になるので、パラメータとしてrrにリファラを入れています。
#!/usr/bin/perl -w
use strict;
use CGI;
use Encode;
use Encode::Guess qw/euc-jp shiftjis 7bit-jis/;
use utf8;
my $file="access.log";
my $q=new CGI;
my $ref = url_decode($q->param('rr')); #前のページ
my $referer = url_decode($q->referer()); #見られてるページ
my $result="\"$ref\",\"$referer\"\n";
open(FILE,">>:encoding(utf8)", $file) or error($q, "can't open");
print(FILE $result);
close(FILE);
&printimg;
exit;
sub url_decode{
my $str = shift;
return 'hoge' unless $str;
$str =~ tr/+/ /;
$str =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
my $decoder = Encode::Guess->guess($str);
return $decoder->decode($str) if(ref($decoder));
return decode("utf8",$str);
}
sub printimg{
open(COUNTERIMG, "./counter.gif") or error($q, "can't open");
binmode(COUNTERIMG);
print "Content-type: image/gif\n\n";
print <COUNTERIMG>;
close(COUNTERIMG);
}
urlエンコードされた文字を一旦もどしてからEncode::Guessでデコードしてファイルに書き込んでいます。
これにより、文字コードが統一されます。
urlエンコードをデコードするときにpackを利用しているのでutf8フラグ関係が心配なので、utf8フラグをつける前にurlデコードしています。
最後にimgを転送して終了。
なんか美しくないけど、動く。
マウスで選択したURLに飛ぶブックマークレット。
ttpで始まるものにも飛べるように改造してもいいかもしれない。
javascript:(function()%20%7Bvar%20w='';if(window.getSelection)%7Bw=window.getSelection();w=''+w;%7Delse%20if(document.selection)%7Bw=document.selection.createRange().text;%7Dif(w.length%3E0)%7Bwindow.open(w);%7Delse%7Balert(%22nothing%20selected%22);%7D%7D)()
選択したURLにジャンプ
$A(document.getElementsByName(element_name)).each(function(elm){
if(elm.checked){
ほげほげ;
}
});
でおけ。
- DOM作成時にtbody書かないとIEはtableを表示しない
- colspan は colSpanとして設定する必要がある
- Done: CSSによるスタイル定義
- Done: DOMによる生成
- Done: 日クリックevent
- Done: Closeクリックevent
- Done: 本日クリックevent
- Done: 月クリックevent
eventの標準機能を止めないと思わぬことがおこる。
_disable_default_event: function(evt){
if (evt.preventDefault) {
evt.preventDefault();
} else {
evt.returnValue = false;
}
};
この関数をイベント処理後に呼び出す。
- 階層の深いDOMツリーをどうやって効果的に作成するか
- いい案がないようなので、Builderパターンのライブラリを作る。
idea: Directorは、以下の基本creatorを組み合わせる
build_element(type, attr={});
build_elements(function, params = []);
where function(v,i) -> [type, attr[]]
params.map.function.map.function(v,i){bild_element.apply(null.v);};
func.apply(null, array)とするとarrayが展開される。