Спыніць распаўсюд для канкрэтнага апрацоўшчыка

Скажам, у мяне ёсць карыстацкі выпадальны спіс (). Пры націску кнопкі я хачу, каб выклікаць меню, і калі карыстальнік пстрыкае за межамі меню, я хачу, каб закрыць. Так што я зрабіць нешта накшталт гэтага:

$(myDropDown).mousedown(dropDownMouseDown);
$("html").mousedown(htmlMouseDown,myDropDown);
function dropDownMouseDown(event) {
    event.target.open();
    event.stopPropagation();//I need this line or else htmlMouseDown will be called immediately causing the dropDown-menu to close right before its opened
}
function htmlMouseDown() {
    this.close();
}

Ну, гэта працуе. Але што, калі я дадам два з іх? Калі я націскаю, каб адкрыць першы, тое ж самае на другім, то абодва будуць адкрыты, паколькі dropDownMouseDown спыняе распаўсюджванне так, што htmlMouseDown ніколі не выклікаецца для першага. Як гэта абысці? Калі б я быў толькі гэтыя два затым дадаць некаторую логіку, якая, вядома, будзе лёгка, але калі колькасць дынамічна? Акрамя таго, я не мог бы хацець назваць event.stopPropagation (), таму што ён будзе рабіць дзіўныя рэчы ў іншыя бібліятэкі, якія я выкарыстоўваю, якія слухаюць для гэтай падзеі таксама? Я таксама паспрабаваў паставіць гэты радок: $ ( "HTML"). MouseDown (htmlMouseDown, myDropDown) ўнутры dropDownMouseDown-апрацоўшчыка, але яна будзе называцца адразу ў любым выпадку, як толькі вылучэнне бурбалак дасягае HTML-элемента.

4
Вы карыстаецеся дэлегаванне падзей тут, захапіўшы кожнае падзея на HTML элемента. Вы маглі б быць альбо «больш канкрэтна» у тым, дзе вы ловіце падзея (толькі на самым выпадальным спіс), або - калі вы хочаце захаваць падзея дэлегацыі - вы можаце паглядзець на target_of падзея, каб убачыць, які элемент ён быў выкліканы на.
дададзена аўтар CBroe, крыніца
Вы карыстаецеся дэлегаванне падзей тут, захапіўшы кожнае падзея на HTML элемента. Вы маглі б быць альбо «больш канкрэтна» у тым, дзе вы ловіце падзея (толькі на самым выпадальным спіс), або - калі вы хочаце захаваць падзея дэлегацыі - вы можаце паглядзець на target_of падзея, каб убачыць, які элемент ён быў выкліканы на.
дададзена аўтар CBroe, крыніца

9 адказы

Калі ў вас ёсць селектар для dropdows, (скажам, « .dropdown »), я хацеў бы паспрабаваць выкарыстоўваць « .not() »

$('.dropdown').mousedown(dropDownMouseDown);

$("html").on('mousedown', htmlMouseDown);

function dropDownMouseDown(event) {
    event.target.open();
}

function htmlMouseDown(event) {
  $('.dropdown').not($(event.target)).close();
}

Here is a fiddle in the same idea with CSS classes : http://jsfiddle.net/eFEL6/4/

2
дададзена
у выпадку reactjs я выкарыстоўваю (this.refs.el! = e.target)
дададзена аўтар bazi, крыніца

Калі ў вас ёсць селектар для dropdows, (скажам, « .dropdown »), я хацеў бы паспрабаваць выкарыстоўваць « .not() »

$('.dropdown').mousedown(dropDownMouseDown);

$("html").on('mousedown', htmlMouseDown);

function dropDownMouseDown(event) {
    event.target.open();
}

function htmlMouseDown(event) {
  $('.dropdown').not($(event.target)).close();
}

Here is a fiddle in the same idea with CSS classes : http://jsfiddle.net/eFEL6/4/

2
дададзена
у выпадку reactjs я выкарыстоўваю (this.refs.el! = e.target)
дададзена аўтар bazi, крыніца

Калі ў вас ёсць селектар для dropdows, (скажам, « .dropdown »), я хацеў бы паспрабаваць выкарыстоўваць « .not() »

$('.dropdown').mousedown(dropDownMouseDown);

$("html").on('mousedown', htmlMouseDown);

function dropDownMouseDown(event) {
    event.target.open();
}

function htmlMouseDown(event) {
  $('.dropdown').not($(event.target)).close();
}

Here is a fiddle in the same idea with CSS classes : http://jsfiddle.net/eFEL6/4/

2
дададзена
у выпадку reactjs я выкарыстоўваю (this.refs.el! = e.target)
дададзена аўтар bazi, крыніца

Што аб выкарыстанні зменнай, якая ўтрымлівае апошнюю openened адзін? Ёсць, верагодна, шмат іншых спосабаў зрабіць гэта, але вось так, як я мог думаць:

var lastOpened = null;//initially nothing is open (unless something is)

тады:

function dropDownMouseDown(event) {
    if (lastOpened != null) {//if one is still open
        lastOpened.close();//close it
        lastOpened = null;//nothing is open anymore
    }

    event.target.open();
    lastOpened = event.target;//now this one is open
    event.stopPropagation();
}

function htmlMouseDown() {
    this.close();
    lastOpened = null;//nothing is open
}

Гэта павінна працаваць так, каб апошні адкрыў адзін заўсёды замыкацца перад адкрыццём новага.

1
дададзена

Што аб выкарыстанні зменнай, якая ўтрымлівае апошнюю openened адзін? Ёсць, верагодна, шмат іншых спосабаў зрабіць гэта, але вось так, як я мог думаць:

var lastOpened = null;//initially nothing is open (unless something is)

тады:

function dropDownMouseDown(event) {
    if (lastOpened != null) {//if one is still open
        lastOpened.close();//close it
        lastOpened = null;//nothing is open anymore
    }

    event.target.open();
    lastOpened = event.target;//now this one is open
    event.stopPropagation();
}

function htmlMouseDown() {
    this.close();
    lastOpened = null;//nothing is open
}

Гэта павінна працаваць так, каб апошні адкрыў адзін заўсёды замыкацца перад адкрыццём новага.

1
дададзена

Што аб выкарыстанні зменнай, якая ўтрымлівае апошнюю openened адзін? Ёсць, верагодна, шмат іншых спосабаў зрабіць гэта, але вось так, як я мог думаць:

var lastOpened = null;//initially nothing is open (unless something is)

тады:

function dropDownMouseDown(event) {
    if (lastOpened != null) {//if one is still open
        lastOpened.close();//close it
        lastOpened = null;//nothing is open anymore
    }

    event.target.open();
    lastOpened = event.target;//now this one is open
    event.stopPropagation();
}

function htmlMouseDown() {
    this.close();
    lastOpened = null;//nothing is open
}

Гэта павінна працаваць так, каб апошні адкрыў адзін заўсёды замыкацца перад адкрыццём новага.

1
дададзена

Дзякуй за адказы. Яны сапраўды ацанілі. Я зрабіў высветліць спосаб зрабіць гэта, што я задаволены. Вось як:

$(myDropDown).mousedown(dropDownMouseDown);
$("html").mousedown(myDropDown,htmlMouseDown);//Pass in the dropDown as the data argument, which can then be accessed by doing event.data in the handler
function dropDownMouseDown(event) {
    event.target.open();
}
function htmlMouseDown(event) {
    if (event.target!=event.data)//event.target is the element that was clicked, event.data is set to the dropdown that this handler was added for. Unless these two elements are the same then we can...
        event.data.close();///close the dropdown this handler was added for
}

Не магу паверыць, што я не думаю пра гэта. У маім выпадку, хоць элемент, які адкрывае/закрывае маюць даччыныя-элементы так event.target можа быць адзін з даччыных элементаў замест элемента, што апрацоўшчык быў далучаны. Так што я змяніў мой HTML-элемент-апрацоўшчык да гэтага:

    function htmlMouseDown(event) {
       var element=event.target;
        while (element) {
            if (element==event.data)
                return;
            element=element.parentElement;
        }
        event.data.hide();
    }
0
дададзена

Дзякуй за адказы. Яны сапраўды ацанілі. Я зрабіў высветліць спосаб зрабіць гэта, што я задаволены. Вось як:

$(myDropDown).mousedown(dropDownMouseDown);
$("html").mousedown(myDropDown,htmlMouseDown);//Pass in the dropDown as the data argument, which can then be accessed by doing event.data in the handler
function dropDownMouseDown(event) {
    event.target.open();
}
function htmlMouseDown(event) {
    if (event.target!=event.data)//event.target is the element that was clicked, event.data is set to the dropdown that this handler was added for. Unless these two elements are the same then we can...
        event.data.close();///close the dropdown this handler was added for
}

Не магу паверыць, што я не думаю пра гэта. У маім выпадку, хоць элемент, які адкрывае/закрывае маюць даччыныя-элементы так event.target можа быць адзін з даччыных элементаў замест элемента, што апрацоўшчык быў далучаны. Так што я змяніў мой HTML-элемент-апрацоўшчык да гэтага:

    function htmlMouseDown(event) {
       var element=event.target;
        while (element) {
            if (element==event.data)
                return;
            element=element.parentElement;
        }
        event.data.hide();
    }
0
дададзена

Дзякуй за адказы. Яны сапраўды ацанілі. Я зрабіў высветліць спосаб зрабіць гэта, што я задаволены. Вось як:

$(myDropDown).mousedown(dropDownMouseDown);
$("html").mousedown(myDropDown,htmlMouseDown);//Pass in the dropDown as the data argument, which can then be accessed by doing event.data in the handler
function dropDownMouseDown(event) {
    event.target.open();
}
function htmlMouseDown(event) {
    if (event.target!=event.data)//event.target is the element that was clicked, event.data is set to the dropdown that this handler was added for. Unless these two elements are the same then we can...
        event.data.close();///close the dropdown this handler was added for
}

Не магу паверыць, што я не думаю пра гэта. У маім выпадку, хоць элемент, які адкрывае/закрывае маюць даччыныя-элементы так event.target можа быць адзін з даччыных элементаў замест элемента, што апрацоўшчык быў далучаны. Так што я змяніў мой HTML-элемент-апрацоўшчык да гэтага:

    function htmlMouseDown(event) {
       var element=event.target;
        while (element) {
            if (element==event.data)
                return;
            element=element.parentElement;
        }
        event.data.hide();
    }
0
дададзена