javascript

IE"インターネットサイトxxxを開けません。"のバグ  [javascript]  [bug_or_spec]  [IE]

またでたよ。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 javascriptではRadioのchecked属性はドキュメントにappend後じゃないと変更できない  [javascript]  [bug_or_spec]  [IE]

またしてもIE。

ラジオボタンを動的に生成する場合、デフォルトとか以前の結果とかをチェックした状態で表示するために


var myRadio = document.createElement('input'); 
myRadio.type = 'radio';
myRadio.value = 'hoge';
myRadio.checked = true;

とかやるじゃないですか。
IEの場合、これではチェックが付かない。
ドキュメントにappendした後に変更する必要があるんだって。
いい加減にしてくれよIE

IE javascriptではformのname属性を変更できない  [javascript]  [bug_or_spec]  [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’のネーミングセンスの良さに自画自賛

CGIでリファラ(HTTP_REFERER)を取る方法  [perl]  [javascript]  [tips]

あいかわらず、初歩的なところにいます。。。(-_-;)
perlのCGIでアクセス解析のためにリファラ(訪れた人が前に見ていたページ)を取ろうとしてたのですが、検索サイトによって文字が化けたりしてたので、utf8に統一してみようということで、以下のようにしました。

  • ページに埋め込むjavascript

<script language="JavaScript">
  <!--
    document.write('<img src="http://hoge.fuga.funya/access.cgi?rr=' + escape(document.referrer) + '" />');
  // -->
</script>

imgタグ内でアクセス解析用のcgiを呼んでいます。cgi側でHTTP_REFERERを取ると、このスクリプトを入れたページ自身になるので、パラメータとしてrrにリファラを入れています。

  • cgi側(perl)

#!/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に飛ぶブックマークレット  [bookmarklet]  [javascript]

マウスで選択した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にジャンプ

prototype.jsでのradioの扱い方  [javascript]


$A(document.getElementsByName(element_name)).each(function(elm){
  if(elm.checked){
    ほげほげ;
  }
});

でおけ。

IE DOM table tips  [javascript]  [bug_or_spec]  [IE]

  • DOM作成時にtbody書かないとIEはtableを表示しない
  • colspan は colSpanとして設定する必要がある

rails_calenderの表示まで  [javascript]  [mylib]

  • Done: CSSによるスタイル定義
  • Done: DOMによる生成
  • Done: 日クリックevent
  • Done: Closeクリックevent
  • Done: 本日クリックevent
  • Done: 月クリックevent

javascript event tips  [javascript]  [tips]

eventの標準機能を止めないと思わぬことがおこる。


   _disable_default_event: function(evt){
     if (evt.preventDefault) {
       evt.preventDefault();
     } else {
       evt.returnValue = false;
     }
   };

この関数をイベント処理後に呼び出す。

DOM builder作成  [javascript]  [mylib]

DOMの効率的な生成方法案  [javascript]  [idea]

  • 階層の深い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);};

applyの引数展開  [javascript]  [tips]

func.apply(null, array)とするとarrayが展開される。