如何从文档和窗口中删除JavaScript触摸事件处理程序?

时间:2018-12-14 20:05:48

标签: javascript fullcalendar touch event-listener removeeventlistener

我有一个网页,其中显示了FullCalendar的日历

日历被托管在公共Salesforce社区页面中。

我希望能够使用touchdrag通过移动设备在日历中创建事件。

Salesforce社区和FullCalendar均支持移动设备。

还有FullCalendar has touch support

但是当我使用移动设备访问社区页面时,无法使用touchdrag创建日历条目。

Salesforce社区页面/框架创建了touch个事件处理程序:

  • document代表touchstarttouchendtouchcancel
  • window for touchmove

似乎覆盖了FullCalendar touch事件。

这是调试示例日历:

如何删除touchdocument上的window事件处理程序?

我尝试添加:

    document.addEventListener("touchstart", function (event) {
        event.preventDefault();
        console.log("touchstart: event.preventDefault()");
    }, false);

    document.addEventListener("touchend", function (event) {
        event.preventDefault();
        console.log("touchend: event.preventDefault()");
    }, false);

    document.addEventListener("touchcancel", function (event) {
        event.preventDefault();
        console.log("touchcancel: event.preventDefault()");
    }, false);

    window.addEventListener("touchmove", function (event) {
        event.preventDefault();
        console.log("touchmove: event.preventDefault()");
    }, false);

但是我只是在控制台中收到此错误:

  

[干预]由于目标被视为被动,因此无法阻止被动事件侦听器中的Default。

并且所有日历按钮都不再起作用。

4 个答案:

答案 0 :(得分:8)

如果添加新的侦听器,则无法删除该侦听器。所有侦听器将添加到队列中。例如,您可以在这里看到它:

var listenerLoad = function(e){console.log(1)};
window.addEventListener('load', listenerLoad, false);
window.addEventListener('load', listenerLoad, true);
window.addEventListener('load', function(e){console.log(3)}, false);
window.onload = function(e){console.log(4)};

但是,如果为此使用适当的功能,则可以删除侦听器。您必须使用功能 EventTarget.removeEventListener() 之前请仔细阅读本文档。通过此事件的初始化,参数必须与addEventListener()中的相同。指向侦听人员的指针应该与addEventListener()中的相同。例如,如果 他们具有指向侦听者的指针,例如:

var listenerTouchStart = function(e){/**/},
    listenerTouchEnd = function(e){/**/},
    listenerTouchCancel = function(e){/**/},
    listenerTouchMove = function(e){/**/};

然后您可以按以下方式删除侦听器:

document.removeEventListener('touchstart', listenerTouchStart, false);
document.removeEventListener('touchend', listenerTouchEnd, false);
document.removeEventListener('touchcancel', listenerTouchCancel, false);
window.removeEventListener('touchmove', listenerTouchMove, false);

但是请不要忘记window.removeEventListener('touchmove', listenerTouchMove, false);window.removeEventListener('touchmove', listenerTouchMove, true);是不同的。如果他们用false添加监听器,而您尝试用true删除监听器,则它将不起作用。小心!

如果要查找侦听器函数名称,则有3种方法:

  1. 您可以在代码中手动搜索。
  2. 在Chrome开发者工具(包括Opera),Safari Inspector和Firebug中的开发者控制台中,您可以输入控制台 getEventListeners(Object); 。例如,在第一个示例中,对于我们的窗口,您将具有以下输出:

enter image description here

如果侦听器添加了匿名功能,则它没有名称。

  1. 您可以使用ListenerTracker脚本。这是它的源代码(请勿尝试执行此代码段–只是隐藏此长代码):

// THIS SNIPPET SHOULD NOTHING DO.
// IT IS ONLY TO HIDE THIS LONG CODE

function DO_NOT_COPY_THIS_LINE() //<-DO NOT COPY THIS LINE
{
    //////////////////////////////
    //ListenerTracker Script START
    //////////////////////////////

    var ListenerTracker = new function()
    {
        var is_active=false;
        // listener tracking datas
        var _elements_  =[];
        var _listeners_ =[];
        this.init=function(){
            if(!is_active){//avoid duplicate call
                intercep_events_listeners();
            }
            is_active=true;
        };
        // register individual element an returns its corresponding listeners
        var register_element = function(element){
            if(_elements_.indexOf(element)==-1){
                // NB : split by useCapture to make listener easier to find when removing
                var elt_listeners=[{/*useCapture=false*/},{/*useCapture=true*/}];
                _elements_.push(element);
                _listeners_.push(elt_listeners);
            }
            return _listeners_[_elements_.indexOf(element)];
        };
        var intercep_events_listeners = function(){
            // backup overrided methods
            var _super_={
                "addEventListener"      : HTMLElement.prototype.addEventListener,
                "removeEventListener"   : HTMLElement.prototype.removeEventListener
            };

            Element.prototype["addEventListener"] = function(type, listener, useCapture){
                var listeners=register_element(this);
                // add event before to avoid registering if an error is thrown
                _super_["addEventListener"].apply(this,arguments);
                // adapt to 'elt_listeners' index
                useCapture=useCapture?1:0;

                if(!listeners[useCapture][type])listeners[useCapture][type]=[];
                listeners[useCapture][type].push(listener);
            };

            Element.prototype["removeEventListener"] = function(type, listener, useCapture){
                var listeners=register_element(this);
                // add event before to avoid registering if an error is thrown
                _super_["removeEventListener"].apply(this,arguments);
                // adapt to 'elt_listeners' index
                useCapture=useCapture?1:0;
                if(!listeners[useCapture][type])return;
                var lid = listeners[useCapture][type].indexOf(listener);
                if(lid>-1)listeners[useCapture][type].splice(lid,1);
            };

            Element.prototype["getEventListeners"] = function(type){
                var listeners=register_element(this);
                // convert to listener datas list
                var result=[];
                for(var useCapture=0,list;list=listeners[useCapture];useCapture++){
                    if(typeof(type)=="string"){// filtered by type
                        if(list[type]){
                            for(var id in list[type]){
                                result.push({"type":type,"listener":list[type][id],"useCapture":!!useCapture});
                            }
                        }
                    }else{// all
                        for(var _type in list){
                            for(var id in list[_type]){
                                result.push({"type":_type,"listener":list[_type][id],"useCapture":!!useCapture});
                            }
                        }
                    }
                }
                return result;
            };
        };
    }();
    ListenerTracker.init();

    //////////////////////////////
    //ListenerTracker Script END
    //////////////////////////////
}

我已找到此ListenerTracker脚本 here 。使用此脚本,您甚至可以得到匿名侦听器,但是您必须先添加它,然后才能在代码中添加一些侦听器。

祝你好运!

答案 1 :(得分:1)

不确定您(OP)遇到什么问题。在运行Safari的iPad上查看时,https://sfse-developer-edition.eu16.force.com/FullCalendar/s/最适合我。我发现了一些错误(请参阅下文),但是也许您接触的时间不够长。

根据FullCalendar documentation:“在触摸设备上,为了使用户开始拖放事件,他们必须先按住该事件才能“选择” ”((强调原始内容))。您可以使用longPressDelay配置延迟。

无论您遇到什么问题,我都会说最好的解决办法不太可能涉及删除事件处理程序。您更有可能在SalesForce社区的文档中找到有关如何将其他JavaScript软件包集成到页面中的答案。

例如,我在这段代码中发现了一个错误,Chrome指出该错误来自https://sfse-developer-edition.eu16.force.com/FullCalendar/s/components/c/FullCalendar.js 但实际上似乎并非来自该URL。无论如何,给定console.log('loadCalendar')行,我猜你是OP写的。

 "helper":{
    "loadCalendar":function(component) {
        console.log('loadCalendar');
        var params;
        var self = this;
        var calendar = component.find('calendar').getElement();
        $(calendar).fullCalendar('destroy');
        $(calendar).fullCalendar({
            header: {
                left: 'prev,next',
                center: 'title',
                right: 'month,agendaWeek,agendaDay'
            },
            schedulerLicenseKey: '0537034756-fcs-1530699190',
            defaultView: 'agendaWeek',
            // <snip> bunch of stuff omitted for brevity
            select: function (starts, ends) {
                params.starts = starts.format('x');
                params.ends = ends.format('x');

            },
            // <snip> lots more stuff omitted

这里的问题是params从未被初始化,因此params.starts是无效的引用,它抛出未捕获的TypeError。可以通过将var params;替换为var params = {};来解决此问题,但我不确定。

答案 2 :(得分:0)

也许尝试将“ SFDC” touch事件转发到FullCalendar事件

document.addEventListener("touchstart", function (event) {
    myFullCalendarEvent.OnTouch(event);
}, false);

尽管一般来说,当我仍然希望它在较低级别运行时,我从未尝试过删除此类事件……鉴于您当前的方法存在问题,这就是我接下来要去的地方。 >

答案 3 :(得分:0)

EventTarget.removeEventListener()方法从EventTarget中删除先前已向EventTarget.addEventListener()注册的事件侦听器。使用事件类型,事件侦听器功能本身以及可能影响匹配过程的各种可选选项的组合来标识要删除的事件侦听器;请参阅匹配事件侦听器以进行删除。

有关https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener的更多信息