2

addEventListener と attachEvent を使用してクリックとマウスの機能を処理する、基本的な JavaScript ドロップダウン メニューに取り組んできました。クリック イベントによって呼び出される関数 subOpen は、JavaScript の「this」キーワードを使用して、クリックされた要素の ID を取得します。

イベント追加のサンプル:

//add event listeners to menuitems
for (var i=0; i < menuitems.length; i++) {
    if (menuitems[i].addEventListener) {
        menuitems[i].addEventListener('click', subOpen, false);    
        menuitems[i].addEventListener('mouseout', closeTimer, false);
        menuitems[i].addEventListener('mouseover', cancelTimer, false);
        menuitems[i].addEventListener('selectstart', menucursorselect, false);
    } else if (menuitems[i].attachEvent) {
        menuitems[i].attachEvent('onclick', subOpen);    
        menuitems[i].attachEvent('onmouseout', closeTimer);
        menuitems[i].attachEvent('onmouseover', cancelTimer);
        menuitems[i].attachEvent('onselectstart', menucursorselect);    
    }
}

「this」キーワードを使用した subOpen 関数のサンプル:

function subOpen() {
cancelTimer(); //stops the close timer  

if (submenudisplay) {
    document.getElementById(submenudisplay).style.display = "none";
    activeSubMenu = false;
}
var curMenuId = this.id;
var curSubMenuId = this.id + "submenu";

if (curSubMenuId) {
    document.getElementById(curSubMenuId).style.display = "block";
    activeSubMenu = true;   
}

submenudisplay = curSubMenuId;

現在、以前のバージョンの Internet Explorer を除いて、私がテストしたすべてのブラウザーですべてが機能しています。古いバージョンの IE では、デバッガーは「this.id」に未定義のフラグを立てているため、どのサブメニューを開くべきかわかりません。いくつかの調査を行ったところ、古い IE はイベントをアタッチするときに関数をコピーせずに参照することがわかったので、「this」キーワードで有用なデータを取得する方法はありません。

古いバージョンの IE で動作する同じことを達成するために使用できる別のキーワードまたは関数があるかどうか疑問に思っていました。

私のテストコードの完全版はここにあります:

4

4 に答える 4

4

ハンドラーを呼び出してthis値を手動で設定する関数を使用できます。

ここbindHandlerでは、要素とハンドラーを受け取り、要素をthis値として元のハンドラーを呼び出す新しいハンドラーを返す関数を作成しました。

また、window.eventオブジェクトを元のハンドラーに渡して、その一貫性も確保します。

for (var i=0; i < menuitems.length; i++) {
    if (menuitems[i].addEventListener) {
        menuitems[i].addEventListener('click', subOpen, false); 
        menuitems[i].addEventListener('mouseout', closeTimer, false);
        menuitems[i].addEventListener('mouseover', cancelTimer, false);
        menuitems[i].addEventListener('selectstart', menucursorselect, false);
    } else if (menuitems[i].attachEvent) {
        menuitems[i].attachEvent('onclick', bindHandler(menuitems[i], subOpen));   
        menuitems[i].attachEvent('onmouseout', bindHandler(menuitems[i], closeTimer));
        menuitems[i].attachEvent('onmouseover', bindHandler(menuitems[i], cancelTimer));
        menuitems[i].attachEvent('onselectstart', bindHandler(menuitems[i], menucursorselect));  
    }
}

function bindHandler(elem, handler) {
    return function() {
        return handler.call(elem, window.event);
    };
}

FWIW、反復的なコードの一部を減らすために、これを処理する単一のバインド関数を作成します。

for (var i=0; i < menuitems.length; i++) {
    bindHandler(menuitems[i], 'click', subOpen);
    bindHandler(menuitems[i], 'mouseout', closeTimer);
    bindHandler(menuitems[i], 'mouseover', cancelTimer);
    bindHandler(menuitems[i], 'selectstart', menucursorselect);
}

function bindHandler(elem, type, handler) {
    if (elem.addEventListener)
        elem.addEventListener(type, handler, false);
    else if (elem.attachEvent)
        elem.attachEvent("on" + type,  function() {
            return handler.call(elem, window.event);
        };
}
于 2012-10-25T17:22:40.537 に答える
1
function addHandler(elem, type, handler) {
    elem.addEventListener(type, handler, false);
}
if (!document.addEventListener)
    addHandler = function(elem, type, handler) {
        elem.attachEvent('on'+type, function() {
            handler.call(elem, window.event);
        });
    };

次に、

for (var i=0; i<menuitems.length; i++) {
    addHandler(menuitems[i], 'click', subOpen);
    addHandler(menuitems[i], 'mouseout', closeTimer);
    addHandler(menuitems[i], 'mouseover', cancelTimer);
    addHandler(menuitems[i], 'selectstart', menucursorselect);
}
于 2012-10-25T17:31:46.297 に答える
1

addEventListenerおよびattachEvents関数を直接呼び出すのではなく、jQuery を使用してイベントをバインドする必要があります。jQuery は、これらのブラウザー間の互換性の問題を回避します。

したがって、ここでの私の答えは、それをしないことです。thisただし、実行する場合は、Internet Explorer によって呼び出される関数にはデフォルトでキーワードがないことに注意してください。要素にアクセスするには、 で要素を探す必要がありますwindow.event.srcElement。W3C 互換ブラウザでは、thisまたはを使用できますevent.target_addEventListenerW3C関数のクロスブラウザ版として以下の関数を利用できます。

var _addEventListener = function (obj, evt, ofnc, bubble) {
    var fnc = function (event) {
        if (!event || !event.target) {
            event = window.event;
            event.target = event.srcElement;
        }
        return ofnc.call(obj, event);
    };
    // W3C model
    if (obj.addEventListener) {
        obj.addEventListener(evt, ofnc, !!bubble);
        return true;
    }
    // M$ft model
    else {
        return obj.attachEvent('on' + evt, fnc);
    }
};

//add event listeners to menuitems
for (var i = 0; i < menuitems.length; i++) {
    _addEventListener(menuitems[i], 'click', subOpen, false);
    _addEventListener(menuitems[i], 'mouseout', closeTimer, false);
    _addEventListener(menuitems[i], 'mouseover', cancelTimer, false);
    _addEventListener(menuitems[i], 'selectstart', menucursorselect, false);
}​
于 2012-10-25T17:33:01.787 に答える
-1

実際の「イベント」は処理関数に渡され、イベントから要素を取得できます。

http://www.javascripter.net/faq/eventtargetsrcelement.htm

于 2012-10-25T17:25:21.650 に答える