Как удалить обработчик событий JavaScript touch из документа и окна? - PullRequest
0 голосов
/ 14 декабря 2018

У меня есть веб-страница, на которой отображается календарь FullCalendar

Календарь размещается на общедоступной странице сообщества Salesforce.

Я хочу иметь возможностьсоздавать события в календаре через мобильное устройство, используя touch и drag.

. Сообщества Salesforce и FullCalendar поддерживают мобильные устройства.

и FullCalendar имеет сенсорную поддержку

Нокогда я захожу на страницу сообщества с помощью мобильного устройства, я не могу использовать touch и drag для создания записи календаря.

Существуют touch обработчики событий, созданные страницей / структурой сообщества Salesforce:

  • document для touchstart и touchend и touchcancel
  • window для touchmove

, которые кажутсяпереопределить события FullCalendar touch.

Вот примеркалендарь для отладки:

Как удалить обработчики событий touch на document и 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 голосов
/ 18 декабря 2018

Метод EventTarget.removeEventListener () удаляет из EventTarget прослушиватель событий, ранее зарегистрированный в EventTarget.addEventListener ().Прослушиватель событий, подлежащий удалению, идентифицируется с использованием комбинации типа события, самой функции прослушивателя событий и различных необязательных опций, которые могут влиять на процесс сопоставления;см. Соответствующие прослушиватели событий для удаления.

Подробнее о https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener

0 голосов
/ 17 декабря 2018

Вы не можете удалить слушателя, если добавляете нового слушателя.Все слушатели будут добавлены в очередь.Вы можете увидеть это, например, здесь:

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 DevTools (Opera inclusive), Safari Inspector и в Firebug вы можете набрать в консоли getEventListeners(Object);.Например, для нашего окна в первом примере у вас будет такой вывод:

enter image description here

И если слушатель был добавлен с анонимной функциейтогда у него нет имени.

Вы можете использовать скрипт 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 здесь .С помощью этого сценария вы получите даже анонимных слушателей, но вы должны добавить его, прежде чем они добавят несколько слушателей в код.

Удачи!

0 голосов
/ 18 декабря 2018

Не знаю точно, с какой проблемой вы (ОП) сталкиваетесь.https://sfse -developer-edition.eu16.force.com / FullCalendar / s / в основном работает для меня при просмотре на iPad под управлением Safari.Я обнаружил некоторые ошибки (см. Ниже), но, возможно, вы просто недостаточно долго касаетесь.

Согласно документации FullCalendar : «На сенсорном устройстве пользователь может начать перетаскивание.События n-drop, они должны сначала нажать и удерживать событие, чтобы «выбрать» его!" (выделение в оригинале) .Вы можете настроить задержку, используя longPressDelay.

Какую бы проблему вы ни испытывали, я бы сказал, что маловероятно, что лучшее исправление - это удаление обработчиков событий.Скорее всего, вы найдете ответ в документации для SalesForce Community о том, как интегрировать другие пакеты JavaScript в страницу.

Например, я обнаружил ошибку в этом фрагменте кода, который, по словам Chrome, взят из https://sfse -developer-edition.eu16.force.com / FullCalendar / s / components / c / FullCalendar.js , но на самом деле, похоже, не из этого URL.В любом случае, учитывая строку console.log('loadCalendar'), я предполагаю, что вы, ОП, написали это.

 "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 = {};, но я не уверен.

0 голосов
/ 17 декабря 2018

Возможно, попробуйте переслать событие "SFDC" touch в событие FullCalendar

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

Хотя в целом я никогда не пытался удалять подобные события, когда все еще ожидаю, что оно будет работать на более низком уровне.... Учитывая, что у вас проблемы с вашим текущим подходом, я бы пошел дальше ...

...