Переключение обработчиков кликов в Javascript
у меня есть кнопка HTML, к которой я прикрепляю событие, используя jQuery bind()
, например:
$('#mybutton').bind('click', myFirstHandlerFunction);
на myFirstHandlerFunction
, Я бы хотел, чтобы этот обработчик заменил себя новым обработчиком,mySecondHandlerFunction
, например:
function myFirstHandlerFunction(e) {
$(this).unbind('click', myFirstHandlerFunction).bind('click', mySecondHandlerFunction);
}
во втором обработчике щелчка,mySecondHandlerFunction
, Я хотел бы переключить кнопку обратно в исходное состояние: unbind mySecondHandlerFunction
обработчик и подключите исходный обработчик,myFirstHandlerFunction
, например:
function mySecondHandlerFunction(e) {
$(this).unbind('click', mySecondHandlerFunction).bind('click', myFirstHandlerFunction);
}
это отлично работает, за исключением одного маленького подробно: поскольку событие click еще не распространилось через каждый из обработчиков кнопки click, событие click передается в следующий обработчик кнопки click, который является обработчиком, который был только что связан в предыдущем обработчике. Конечный результат mySecondHandlerFunction
выполняется сразу после myFirstHandlerFunction
выполняется.
эта проблема может быть легко решена путем вызова e.stopPropagation()
в каждом обработчике, но это имеет отрицательный побочный эффект отмены любых других обработчиков щелчка, которые возможно, были прикреплены независимо.
есть ли способ безопасно и последовательно переключаться между двумя обработчиками щелчка, не останавливая распространение события щелчка?
6 ответов
обновление: С этой формы
toggle()
был удален в jQuery 1.9, Решение ниже не работает. См.этот вопрос для альтернативы.
похоже toggle () решит вашу проблему:
$("#mybutton").toggle(myFirstHandlerFunction, mySecondHandlerFunction);
код выше будет регистрироваться myFirstHandlerFunction
и mySecondHandlerFunction
называться на альтернативной кликов.
просто используйте логическое значение для переключения функций обработчика, нет необходимости жонглировать, какой обработчик слушает:
$('#mybutton').bind('click', myHandlerFunction);
var first = true;
function myHandlerFunction(e) {
if(first){
// Code from the first handler here;
}else{
// Code from the second handler here;
}
first = !first; // Invert `first`
}
это решение является взломом, но это is короткий и сладкий для вашей грубой работы:
$('#myButton').click(function() {
(this.firstClk = !this.firstClk) ? firstHandler(): secondHandler();
});
это хак, потому что он ставит новое свойство непосредственно на this
который является элементом HTML DOM click-target, и это, возможно, не лучшая практика. Тем не менее, это позволяет избежать создания новых глобалов, и его можно использовать без изменений на разных кнопках одновременно.
обратите внимание, что первая часть троичной операции использует =
, а не ==
или ===
, то есть это задание, а не сравнение. Обратите внимание также, что при первом нажатии кнопки,this.firstClk
не определено, но сразу отрицается, что делает первую часть троичной операции оцениваемой до true
в первый раз.
вот рабочая версия:
$('#a > button').click(function() {(this.firstClk = !this.firstClk) ? a1(): a2();});
$('#b > button').click(function() {(this.firstClk = !this.firstClk) ? b1(): b2();});
function a1() {$('#a > p').text('one');}
function a2() {$('#a > p').text('two');}
function b1() {$('#b > p').text('ONE');}
function b2() {$('#b > p').text('TWO');}
div {display: inline-block;width: 10em;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a"><p>not yet clicked</p><button>click</button></div>
<div id="b"><p>NOT YET CLICKED</p><button>CLICK</button></div>
Я смотрел на это сегодня и понял, что все еще не было способа сделать это без глобальной переменной. Я придумал следующее, Чтобы добавить местоположения в базовую карту ESRI, но это тоже будет работать в целом:
function addLocationClickHandler() {
var addLocationClick = overviewMap.on('click', function (event) {
addLocationClick.remove();
})
$('#locationAddButton').one('click', function (cancelEvent) {
addLocationClick.remove();
$('#locationAddButton').on('click', addLocationClickHandler)
});
}
$('#locationAddButton').on('click', addLocationClickHandler)
Это должно позволить вам поместить что-то еще в раздел, где вы перезаписываете обработчик click и не требуете глобальной переменной.
Это поможет добавить атрибут data-click-state на вашу кнопку
$(document).ready(function(){
$('#mybutton').on('click',function(){
if($(this).attr('data-click-state') == 1) {
$(this).attr('data-click-state', 0)
myFirstHandlerFunction();
} else {
$(this).attr('data-click-state', 1)
mySecondHandlerFunction();
}
});
});
такой:
$(this).bind('click', myMasterHandler);
handler = 0;
function myMasterHandler(e) {
if(handler == 0) {
myFirstHandler(e);
handler = 1;
} else {
mySecondHandler(e);
handler = 0;
}
}