CSSのみでポップアップメニューが実現出来ない環境への対策。

CSSのみでポップアップメニューが実現出来ない環境への対策・目次。

インターネットエクスプローラ 6.0でポップアップメニューを実現するスクリプトの概要。

CSSで実現するポップアップメニューでは、CSSだけでポップアップメニューが実現出来る事を実例を交えて解説いたしました。

しかし、現在まだユーザ数が多いインターネットエクスプローラ 6.0では、CSSだけでポップアップメニューを実現する事は出来ません。

このため、インターネットエクスプローラ 6.0に対しては、ポップアップしないままにしておくか、JAVAスクリプトなどの別の方法で対応するかのどちらかと言う事になります。

ここでは、JAVAスクリプトを併用する方法について解説いたします。

尚、前提条件として、CSSで実現するポップアップメニューで解説しているHTMLのマークアップ方法とCSSを用いるものとして話を進めていきます。

インターネットエクスプローラ 6.0でポップアップメニューを実現するスクリプトのサンプル。

試しに、PC環境の

などでご覧の方は、以下の実験サイトにアクセスしてみてください。

インターネットエクスプローラ 6.0でポップアップメニューを実現するスクリプトの実際。

それでは、実際にスクリプトを作ってみましょう。

インターネットエクスプローラ 6.0でポップアップメニューを実現するスクリプトのコード。

インターネットエクスプローラ 6.0でポップアップメニューを実現するスクリプトのコードは以下のようになります。

/*
    インターネットエクスプローラ 6.0まででポップアップメニューを実現するためのスクリプト。
*/
menu_ID='MENU_NAVI'; // メニューバーに与えたID。
pm_onload=window.onload;

//    IE 6.0であれば、スタイル調整をするif (document.all && !window.opera &&
    navigator.userAgent.indexOf('Trident/')<0 &&
    navigator.userAgent.indexOf('MSIE 7.')<0) {
    window.onload=style_IE6;
    }

/***************************************************************/
function style_IE6() {

    /* onloadで実行させるべき処理があれば先にやっておく。 */
    if (pm_onload) pm_onload();

    /* メニューバーがなければ何もしない。 */
    if (!(ele=document.all[menu_ID])) return;

    /* メニューバーの幅を100%にする。 */
    var i=document.documentElement.clientWidth || document.body.clientWidth;
    ele.style.width=i+'px';
    ele.style.height='1.7em';

    /* メニューバーからカーソルが消えた場合にポップアップメニューを消すようにする。 */
    ele.style.display='block';
    ele.onmouseout=hide4IEall;

    /********************************************************
       <p>要素(ポップアップメニューへの見出し)に
       1.カーソルが置かれた場合に下位のポップアップメニューを表示する、
       措置を執る。
    ********************************************************/
    var ele2=ele.getElementsByTagName('p');
    i=-1;
    while (++i<ele2.length) {
        ele2[i].onmouseover=show4IE1;
        }

    /*
       <ul>要素(ポップアップメニュー)に
       1.カーソルが置かれた場合に自分自身が消えないようにする、
       2.置かれたカーソルが去った場合に消すようにする
       措置を執る。
    */
    ele2=ele.getElementsByTagName('ul');
    i=-1;
    while (++i<ele2.length) {
        ele2[i].onmouseover=show4IE2;
        ele2[i].onmouseout=hide4IE2;
        }
}

var timeID;
var m_obj='';
/*********************************************************
  ポップアップメニューを全部消す処理。
*********************************************************/
function hide4IEall() {
    clearTimeout(timeID);
    /*
        すぐには消さず、0.5秒経つまで消さない。
        ※こうしないと、他の表示させるべき箇所にカーソルが移動しても消されてしまうため、
    */
    timeID=setTimeout('hide4IEall_2()', 500);
}

/* ポップアップメニュー全消し処理本体。 */
function hide4IEall_2() {
    clearTimeout(timeID);
    var ele=document.all[menu_ID];
    if (!ele) return;
    ele=ele.getElementsByTagName('ul');
    i=ele.length;
    while (--i>=0) {
        ele[i].style.display='none';
        }
}

/*********************************************************
  指定されたポップアップメニューを表示させる処理。
*********************************************************/
function show4IE1() {
    hide4IEall_2();    //事前に全部ポップアップメニューを消す。

    //    <p>要素と兄弟要素となっている<ul>要素を探す。
    var ele=this.parentNode;   //一旦親要素ノードの…
    ele=ele.childNodes;        //子ノード集合を得、その中から探す。
    var i=ele.length;
    while (--i>=0) {
        if (ele[i].nodeType!=1) continue;
        if (ele[i].tagName.toLowerCase()=='ul') break;
        }
    if (i<0) return;    //見付からなかった場合。
    //    見付かったらそれを表示させる。
    ele[i].style.display='block';
}

/*********************************************************
  カーソルが置かれたポップアップメニュー自身のを表示処理。
*********************************************************/
function show4IE2() {
    clearTimeout(timeID);      //ポップアップメニュー消去処理が行われた場合はキャンセルする。
    this.style.display='block';
}

/*********************************************************
  カーソルが置かれたポップアップメニューから
  カーソルが外れた場合に自分自身を消去する処理。
*********************************************************/
function hide4IE2() {
    clearTimeout(timeID);
    m_obj=this;
    /*
        すぐには消さず、0.5秒経つまで消さない。
        ※こうしないと、他の表示させるべき箇所にカーソルが移動しても消されてしまうため、
    */
    timeID=setTimeout('hide4IE2_2()', 500);
}

function hide4IE2_2() {
    clearTimeout(timeID);
    m_obj.style.display='none';
}

ここでは重要と思われる点を中心に解説して行きましょう。

インターネットエクスプローラ 6.0でポップアップメニューを実現するスクリプトの解説。

以下、インターネットエクスプローラ 6.0でポップアップメニューを実現するスクリプトの具体的な処理について簡単に解説いたします。

インターネットエクスプローラ 6.0でポップアップメニューを実現するスクリプトの冒頭部。

スクリプトの冒頭では、

  1. 先ずポップアップメニューに与えているID(ここでは MENU_NAVI)を指定しておき、
  2. その後、インターネットエクスプローラ 6.0以前の場合に限り、ページ読み込み完了後に函数 style_IE6()を呼ぶように

しております。

インターネットエクスプローラ 6.0以前であると判定されるのは、以下の条件を全て満たした場合です。

document.all オブジェクトが存在している事
言うまでもなく、document.all オブジェクトはインターネットエクスプローラの独自実装です。
window.opera オブジェクトが存在していない

オペラでも、インターネットエクスプローラとの互換性を確保するため、document.all オブジェクトを実装しております。

また、オペラでは、オペラである事を識別出来るようにするため、window.opera オブジェクトを独自に実装しております。

従って、window.opera オブジェクトがあればそれはオペラなので対象外と言う事になります。

ユーザエージェント文字列にあるキーワードが入っていない事
ユーザエージェント文字列に、インターネットエクスプローラ 7.0を表す MSIE 7. や 同 8.0以降(8.0での7.0互換モードを含む) Trident/ が入っていない事が条件です。

函数 style_IE6() の処理。

函数 style_IE6()は、インターネットエクスプローラ 6.0 以前で呼び出される函数です。

函数 style_IE6() での事前処理。

函数 style_IE6()では、先ず事前処理として、以下の処理が行われます。

  1. 先ず、onloadで実行させる筈であった処理を先に済ませます。
  2. 続いて、ポップアップメニューのメニューバーとなる要素が存在しているかどうかを確認し、存在していなければ底で処理を終了します。
  3. その上で、メニューバーの幅を画面の横幅一杯に変更します。インターネットエクスプローラ 6.0までのCSSはかなりバギーで、widthプロパティを指定しても正常にレンダリングされないので、このように画面の横幅を取得してそれをwidthプロパティの値としております。
函数 style_IE6() での本処理。

函数 style_IE6()事前処理を済ませたら、いよいよ本処理に入ります。

本処理で行っている事は以下の三つです。

  1. メニューバー部分からカーソルが離れた際に、ポップアップメニューを全て消す函数 hide4IEall()を呼ぶように仕掛ける。
  2. ポップアップメニュー内にある見出し(<p>要素)にマウスでポイントされた場合には、同じ階層にあるメニュー(<ul>要素)を表示する函数 show4IE1()を呼ぶように仕掛ける。
  3. ポップアップメニュー内にあるメニュー(<ul>要素)に於いて、

    1. ポイントされている場合に自分自身が消されないようにする函数 show4IE2()を呼ぶように
    2. ポイントが外れた場合に自分自身を消去する函数 hide4IE2()を呼ぶように

    それぞれします。

ポップアップメニューとなる要素から、<p>要素或いは<ul>要素だけを抽出するのは 要素オブジェクト.getElementsByTagName() メソッドで造作なく行えます。

ポップアップメニューを全て消す函数 hide4IEall() の処理。

函数 hide4IEall()は、全てのポップアップメニューを消す函数です。

実際には本体は別の函数である、hide4IEall_2()であり、函数 hide4IEall()は 0.5秒後にこれを呼び出すように設定しております。

何故すぐに消去処理をしないのかと申しますと、この函数はマウスカーソルがポップアップメニューのメニューバー部分から外れたときに呼び出されるからです。

メニューバーから外れたカーソルは何処に行くか…表示中だったポップアップメニュー部分にカーソルが移動した場合、この函数で既に消されてしまってはポップアップメニューとして使い物になりません。

このため、0.5秒と言う短いタイムラグを発生させてその間にポップアップメニューを表示させるべき箇所にカーソルが移動していたら、この函数で予定した全消去処理をキャンセルさせる、すなわちポップアップメニューの全部消去を行わないようにします。

函数 hide4IEall_2()で行われる全部消去の処理は、指定されたIDからメニュー部分となる<ul>要素を抽出し、それらを全て非表示にすると言うものです。

対応するポップアップメニューを表示させる函数 show4IE1() の処理。

函数 show4IE1()は、見出しをポイントした際に対応するメニューを表示させる函数です。

初めに、

が呼び出されていて、0.5秒以内にこれらの本処理が発動するようになっているのであれば、それをキャンセルしてメニュー消去を防止します。

その上で、当該要素の親要素内にある <ul>要素をスキャンして、見付かればそれをブロック表示にするようにします。

ポイントしているポップアップメニューを消さない函数 show4IE2() の処理。

函数 show4IE1()は、ポップアップメニューがポイントされている際に、それが消えないようにするための函数です。

具体的には函数 show4IE1()同様、

が呼び出されていて、0.5秒以内にこれらの本処理が発動するようになっているのであれば、それをキャンセルしてメニュー消去を防止します。

指定されたポップアップメニューを消去する函数 hide4IE2() の処理。

函数 hideIE2()は、見出しをポイントした際に対応するメニューを表示させる処理です。

具体的には函数 hide4IEall()同様、本処理を函数 hide4IE2_2()に分離し、0.5秒経過してから消すようにします。

このようにした理由も全く同じです。

最後に。

このスクリプトは実は ○○.all[△△] を ○○.getElementById(△△) に書き換えれば、ファイヤーフォックスやサファリなどでも実行可能になります。

ただ、CSSのみでやれればその方が遙かに簡単なので、どうしてもCSSだけでは実現出来ないインターネットエクスプローラ 6.0までのみを対象としております。

勿論、ポップアップの際に動きを持たせたいなどと言うような場合には上記のような書き換えを行うなどして他のブラウザでもこのスクリプトを通す必要が出てきます。

しらぎくのウェブサイト作成入門サイトマップ



marguerite.site@gmail.com