JavaScript



2011 8月24日

とあるスクリプトで最初の実行時には正常に動作するのだけれど、同一ページを再訪問(リロードではなく)した時に不具合が出た。

webkit系のブラウザで不具合が確認できたのだけれど、どうやらgetElementById()でnullが帰っている様子。

ググってみると同じような現象で悩んでいる人もいるみたい。DOM構築前だとnullが帰る事もあるのが原因のようだ。

onLoadイベントとかはjQuery使っているのなら簡単に実装できるのだけれど、純粋JSで書いているスクリプトだし、他所様に配信するスクリプトなので解決方法を探る。

jQuery使っているのなら、$.ready(function(){…}) でいいのだろうけど、そうはいかない。じゃあ、onLoadイベントに登録すればいい。いいのだけど、onLoadイベントは1つしか実行できないので工夫が必要になる。

  • Javascript onloadが複数ある場合の対処法 ~FancyZoomとCubeブログシールを共存させる : ブログ・カスタマイズ徒然記
  • ここら辺の記事を参考に How to use multiple window.onload events with external scripts – Javascript FAQ – Tek-Tips にある addOnloadEvent を組み込んで対処する。

    処理的には document.write() でかいたHTML中にあるIDが付いたタグの中に別処理で作成したHTMLを放り込むもの。

    実行したい関数には引数を指定しているので、
    addOnloadEvent(function(){ print_image(hoge,fuga) });
    みたいな感じにすればonLoadイベントとして実行してくれる。

    そうすることで、getElementById()でnullが帰らなくなる。







    2011 6月12日

    とあるスクリプトで javascriptでiframeを書き、そのフレームをさらに書き換える・・・というものがあるのですが、スクリプトをページ内に複数設置すると、chromeでエラーになってしまうので回避策。

    今までは

    document.write('<IFRAME id="フレーム名" name="フレーム名" ....></IFRAME>');

    で描写して、ターゲットとなるiframeを

    var target_iframe = frames[フレーム名];

    で取得していたのですが、これが2度目以降の実行時にundefinedとなってしまう。

    var target_iframe = document.getElementById(ifrname).contentWindow;

    でもやはり取得できず。
    他のブラウザでは問題ないので気が付かなかったのだけれど、chromeのみ症状が出た。

    DOMでiframeを追加

    解決策としてはDOMでiframeを追加する事で望んだ結果が得られた。

    var iframe = document.createElement('IFRAME');
    iframe.setAttribute('id', 'フレーム名');
    iframe.setAttribute('name', 'フレーム名');
    ...
    document.body.appendChild(iframe);

    …つづきを読む







    2010 7月1日

    IEの6,7,8を判別するJavascript
    JavaScriptでIEかどうかをたったの1行で判別する方法

    この両者のスクリプトを合わせてみた。
    ライブラリを使いたくない(or使えない)状況で役に立つかも。
    ちなみに「IEの6,7,8を判別するJavascript」のコードは間違っていたので少々修正。

    if (typeof document.body.style.maxHeight != "undefined") {
        if (!/*@cc_on!@*/false){
            // Not IE.
            alert('Not IE.');
        }else if (document.documentMode >=8) {
            // IE8
            alert('IE8');
        }else {
            //IE7, IE8(IE7 mode)
            alert('IE7, IE8(IE7 mode)');
        }
    } else {
        // IE6, older browsers
        alert(' IE6, older browsers');
    }

    Windows XP の IE8、IE7、FireFox、Chromeで確認OK.
    Mac の Safari、FireFox、Opera、Chrome でもOK.







    2010 7月1日

    相変わらずクソな実装のIE。
    他のブラウザで全部動くのにIE 7.0 以下の挙動はホントにクソ。
    先人の方々に感謝感激雨あられですわ。

    IEでのgetAttribute,setAttributeのバグ

    // NG
    element.getAttribute("class");
    element.setAttribute("style", "background-color: #fff; color: #000;");
    element.setAttribute("onclick", "clickHandler(event);");
    
    // OK
    element.getAttribute("className");
    element.style.cssText = "background-color: #fff; color: #000;";
    element.setAttribute("onclick", new Function("clickHandler(event);"));

    IEでsetAttribute()とremoveAttribute()がうまく動かない問題 (ウップス!!なかわけ)

    しかも、かなり重要なことを発見しました。
    
    属性名を小文字で書かないとうまく動かない!!(IE7で確認)
    
    setAttribute("onClick", new Function(""));
    
    ではダメなのです。うまく処理されません。
    
    setAttribute("onclick", new Function(""));

    あー、これも引っかかってたわ。

    ただし、上記の対応をすると他のブラウザで動かない。IE8 でもエラーが出る。IE 7以下用に振り分けないとダメなのか。。。

    まぁ、そろそろIE7以下は捨ててもいいよ・・・ね?

    結局

    ベタにHTMLを document.write() で書けばいい訳で・・。
    クロスブラウザにするには手間ががかかる・・。







    2010 5月20日

    自動でSSLページへ移動させるJavaScript

    ログインページ等でSSLのみのアクセスにしたいページがある場合、リンクをhttpsから始まるURL にしなくてはならないのでちょっと面倒。

    仮想パス(../aaa/bbb/ccc.html)やフルパス(/aaa/bbb.html)で既にサイトを公開している場合には、どこかしらで修正を見逃す場合もある。

    それならhttp でアクセスされた場合はhttps へ移動させればよさそう。
    head内とかに以下のJavascript を設置するだけでOK.

    <script><!-- change ssl protocol
      if (document.location.protocol==="http:")
      {location.replace('https://'+window.location.host+window.location.pathname);}
    //--></script>

    今までのパスを変更しないで済むので多少楽・・・かな。