Отключение кнопки в ванильном JavaScript и в jQuery

Ванильный JavaScript

В ванильном JavaScript можно легко включить и отключить кнопку, используя следующую инструкцию:

button.disabled = state;

Это работает, когда люди пытаются щелкнуть по кнопке, а при нажатии кнопки программно:

var button = document.getElementById('myButton');

button.addEventListener('click', function() {
    alert('world');
});

button.disabled = true;
button.click(); // No output
button.disabled = false;
button.click(); // Output : "Hello" and "world
button.disabled = true;
button.click(); // No output
<input type="button" id="myButton" value="button" onClick="alert('Hello')"/>

Ответы

Ответ 1

Чтобы достичь ожидаемого результата, вы можете использовать .isTrigger в обработчике jQuery click, чтобы определить, запускается ли событие javascript, а не действие пользователя.

Определить прослушиватель событий атрибута как именованную функцию, где this можно передать, чтобы проверить свойство disabled в if, если alert() вызывается или не вызывается.

Используйте .attr("disabled", "disabled") для установки disabled в элементе, .removeAttr("disabled") для удаления атрибута; .attr("onclick", null) удалить атрибут атрибута события onclick; .attr("onclick", "handleClick(true)") в reset атрибут события.

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

<input type="button" id="myButton" value="button" onclick="handleClick(this)" />
<script>
  function handleClick(el) {
    if (el.disabled !== "disabled")
      alert("Hello")
  }
  var button = $("#myButton");

  button.on("click", function(e) {
    console.log(e);
    if (e.isTrigger !== 3 && !e.target.disabled)
      alert("world");
  });

  button.attr("disabled", "disabled");
  button.attr("onclick", null);
  button.click(); // no output
  
  setTimeout(function() {
    button.removeAttr("disabled");
    button.attr("onclick", "handleClick(button[0])");
    button.click(); // Output : "world" and "Hello"
    // click button during 9000 between `setTimeout` calls
    // to call both jQuery event and event attribute
  }, 1000);

  setTimeout(function() {
    button.attr("disabled", "disabled");
    button.attr("onclick", null);
    button.click(); // no output
  }, 10000);
  
</script>

Ответ 2

Если вы посмотрите на jquery-1.12.4.js в этих строках:

handlers: function( event, handlers ) {
    var i, matches, sel, handleObj,
        handlerQueue = [],
        delegateCount = handlers.delegateCount,
        cur = event.target;

    // Support (at least): Chrome, IE9
    // Find delegate handlers
    // Black-hole SVG <use> instance trees (#13180)
    //
    // Support: Firefox<=42+
    // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
    if ( delegateCount && cur.nodeType &&
        ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {

        /* jshint eqeqeq: false */
        for ( ; cur != this; cur = cur.parentNode || this ) {
            /* jshint eqeqeq: true */

            // Don't check non-elements (#13208)
            // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
            if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {

Вы увидите различную обработку событий в соответствии с типом делегирования:

$(document).on("click", '#btn', function() {
  console.log("world");
});


$(function () {
  $('#btnToggle').on('click', function(e) {
    $('#btn').prop('disabled', !$('#btn').prop('disabled'));
  });
  
  
  $('#btnTestClick').on('click', function(e) {
    $('#btn').click();
  });
});
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>

<button id="btn">Click  Me</button>
<button id="btnToggle">Enable/Disable button</button>
<button id="btnTestClick">Test Click</button>

Ответ 3

Использование .prop() - правильный способ сделать это. Я думаю, что проблема в том, что вы "тестируете" ее. См. Этот пример, где кнопки отключены/включены с помощью кнопки переключения независимо от того, прикреплен ли обработчик с помощью onclick или с помощью jquery.

window.testFunc = function(event) {
  if (!$('#myButton2').prop('disabled')) {
     alert("hello");
     console.log("hello");
  }
}

$(document).ready(function() {
  var button = $("#myButton2");

  button.on("click", function(event) {
    if (!$(this).prop('disabled')) {
        alert("world");    
        console.log("world");
    }
  });

  $('#toggleButton').click(function() {
	  $('#myButton1').prop('disabled', !$('#myButton1').prop('disabled'));
      $('#myButton2').prop('disabled', !$('#myButton2').prop('disabled'));
  });
  
  $('#tester').click(function() {
  	$('#myButton1').click();
    $('#myButton2').click();
    
  });

})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" id="myButton1" value="vanilla button (hello)" onclick="window.testFunc(event)"/>
<input type="button" id="myButton2" value="jquery button (world)"/>
<input type="button" id="toggleButton" value="toggle disabled"/>
<input type="button" id="tester" value="test the buttons"/>

Ответ 4

Вы вызываете функцию click напрямую 3 раза (button.click()), которая срабатывает независимо от отключенного атрибута.

Отключенное свойство реагирует только на события кликов.

См. обновленный пример:

    var button = $("#myButton");
var button2 = $("#myButton2");

button.prop("disabled", false);

button.on("click", function() {
    alert("world");
   button2.prop("disabled", false);
});

button2.prop("disabled", true); 

button2.on("click", function() {
    alert("world");
   button.prop("disabled", true);
});
<script src="https://code.jquery.com/jquery-1.12.2.min.js"></script>
<input type="button" id="myButton" value="button" onClick="alert('Hello')"/>
<input type="button" id="myButton2" value="button2" />