JS事件禁用程序:无法阻止本机事件执行程序执行

时间:2015-07-23 09:02:07

标签: javascript jquery javascript-events event-handling disabled-input

所以我正在实现一个JS Event-Disabler类,禁用某个dom元素及其所有子元素的所有Native和Programmable事件隐藏者。

到目前为止,我已经能够禁用所有JQuery事件和默认浏览器事件,但不能像

那样设置事件隐藏者
document.getElementById('cin').addEventListener("click", function(){
        alert('I should not alert when disabled');
});

因此,点击元素('原生元素')不应该提醒,但确实如此。 如何在我的无效功能中阻止这种情况发生。 如果有甚至不需要调用另一个函数但只是禁用所有事件那么这也没关系,但需要能够重新启用所有事件。

另外,我可以向您保证,nothing()函数首先执行。



var tellme = function(who) {
  //console.info('Event by: '+who+' @'+Date.now());   
  alert('Event by: ' + who + ' @' + Date.now());
}
$(window).load(function() {
  /* SOME FUNCTION TO ENSURE OUR FUNCTIONS ARE THE FIRST TO BE CALLED */
  $.fn.bindFirst = function(name, fn) {
    this.on(name, fn);
    this.each(function() {
      var handlers = $._data(this, 'events');
      for (var key in handlers) {
        if (handlers.hasOwnProperty(key)) {
          var listeners = handlers[key];
          if (listeners.length > 1) {
            var lastEvent = listeners.pop();
            listeners.splice(0, 0, lastEvent);
            if (listeners[1].handler.name === lastEvent.handler.name)
              listeners.splice(1, 1);
          }
        }
      }
    });
  };

  function shouldbenothing() {
      tellme('native catcher');
      nothing();
    }
    /* THE DO NOTHING FUNCTION, NEEDS SOMETHING MORE, DOESN'T CANCEL ALL*/

  function nothing() {
    event.cancel = true;
    event.preventDefault();
    event.stopPropagation();
    event.stopImmediatePropagation();
    //Needed for Jquery
    throw new Error("NOT AN ERROR: Just forcefully stopping further events @" /*+Date.now()*/ ); //Add the Date.now to see that this code does run before the native function.
    return false;
  }

  /* THIS WILL ONLY RETURN NON-NATIVE EVENTS, ONLY PROGRAMMED EVENTS*/
  function getAllActiveEvents(element) {
    var result = [];
    var handlers = $._data(element, 'events');
    for (var key in handlers) {
      if (handlers.hasOwnProperty(key)) {
        result.push(key);
      }
    }
    return result.join(' ');
  }

  function getAllEvents(element) {
    var result = [];
    for (var key in element) {
      if (key.indexOf('on') === 0) {
        result.push(key.slice(2));
      }
    }
    return result.join(' ');
  }

  /*SOME PROGRAMMED EVENTS, BESIDES THE NATIVE ONES*/

  $('input').on('keyup', function() {
    $('#text').html(this.value);
  });
  $('p').on('click', function() {
    $('#text').html(this.innerHTML);
    tellme('jquery');
  });
  document.getElementById('jsE').addEventListener("click", function() {
    tellme('p:js');
  });
  document.getElementById('cin').addEventListener("click", function() {
    tellme('input:js');
  });

  /* THE ACTUAL DISABLER CODE */
  /*TOGGLE TO ACTIVE OR DISABLE EVENTS FROM TAKING PLACE NATIVE AND EXTRA*/
  var isOn = false;
  $('button').on('click', function() {
    if (isOn)
      $("#obj *").each(function() {
        $(this).off(getAllEvents($(this)[0]), "", nothing);
        $("#obj").css('pointerEvents','');
      });
    else {
      $("#obj *").each(function() {
        var elem = $(this)[0];
        var events1 = getAllActiveEvents(elem); //Only programmed listeners
        var events2 = getAllEvents(elem); //Native + other listeners
        $(this).bindFirst(events2, nothing);
      });
      $("#obj").css('pointerEvents','none');
    }
    isOn = !isOn;
    this.innerHTML = isOn;
  });
});

p {
  cursor: pointer;  
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<style>p {pointer:hand;}</style>
<div id="obj">
  <p>jquery event</p>
  <p id="jsE">js event</p>
  <p onclick="tellme('native');">native event</p>
  <input id='cin' type="text" />
  <p id="text">3</p>
</div>
<p>not catched</p>
<input type="text">

<button>toggle</button>
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分:0)

可能有一个非常简单的非js纯css解决方案......就像这样:

.whatever {
    -webkit-user-select:none;
    -moz-user-select:none;
    -ms-user-select:none;
    user-select:none;
    pointer-events:none;
}

...只需将whatever - 类添加到您要完全禁用用户互动的任何元素。

答案 1 :(得分:0)

所以我很快就找到了解决方案。 通过使用css代码,我可以禁用所有相关的鼠标事件。然而,这并不能阻止本机事件,比如你是通过JS触发事件,但至少它会从用户的角度停止它。

我实际上也更喜欢css方法,因为它允许我仍然交互并触发事件,例如当我想向用户显示某些内容而不会让用户干扰时。

css代码:

//To Disable    
$("#obj").css('pointerEvents','none');
//To Enable
$("#obj").css('pointerEvents','');

答案 2 :(得分:0)

对于任何寻找完整工作代码的人:在这里。 确保添加css。

/* Event Disabler, disables all events */
/* How to use:
*    Toggle Events: toggleEvents(selector);
*    Disable all Events: toggleEvents('body',true);
*    Enable all Events: toggleEvents('body',false);
*/
var toggleEvents = null;
$(window).load(function(){
    /* SOME FUNCTION TO ENSURE OUR FUNCTIONS ARE THE FIRST TO BE CALLED */
    $.fn.bindFirst = function(name, fn) {
        this.on(name, fn);
        this.each(function() {
        var handlers = $._data(this, 'events');
        for (var key in handlers) {
            if (handlers.hasOwnProperty(key)) {
                var listners = handlers[key];
                if (listners.length > 1) {				
                    var lastEvent = listners.pop();
                    listners.splice(0, 0, lastEvent);          
                    //Removes duplicate eventListners
                    if (listners[1].handler.name === lastEvent.handler.name)
                        listners.splice(1, 1);
                }
            }
        }
        });
    };
    /* THE DO NOTHING FUNTION CANCELS ALL EVENTS, EVEN BY TRIGGERED*/
    function nothing() {
        event.cancel = true;
        event.preventDefault();         
        event.stopPropagation();
        event.stopImmediatePropagation();
        event.bubbles = false;    
        if(window.event){
           window.event.cancelBubble=true;
        }
        //throw new Error("NOT AN ERROR: Forcefully stopping further events");
        return false;
    }
    function getAllActiveEvents(element) {
        var result = [];
        var handlers = $._data(element, 'events');
        for (var key in handlers) {
            if (handlers.hasOwnProperty(key)) {
                result.push(key);
            }
        }
        return result.join(' ');
    }
    function getAllEvents(element) {
        var result = [];
        for (var key in element) {
            if (key.indexOf('on') === 0) {
                result.push(key.slice(2));
            }
        }
        return result.join(' ');
    }
    
    var enabled = false;
    toggleEvents = function(selector,flag) {
        enabled = flag === undefined ? !enabled : flag;
        if (enabled) {
            $(selector+" *").each(function(){	
                //Only programmed and attached listners
                var events1 = getAllActiveEvents($(this)[0]); 
                //All Native events attached or not
                var events2 = getAllEvents($(this)[0]); 
                $(this).bindFirst(events2, nothing );                
            });  
            //Disabled most user pointer events
            $(selector).addClass('eventsDisabled');    
        } else {
            $(selector+" *").each(function() {
                $(this).off(getAllEvents($(this)[0]), "", nothing );
            });
            $(selector).removeClass('eventsDisabled');
        }
    };
});
.eventsDisabled {
    -webkit-user-select:none !important;
    -moz-user-select:none !important;
    -ms-user-select:none !important;
    user-select:none !important;
    pointer-events:none !important;    
}