Как переопределить event.stopPropagation(),preventDefault().stopImmediatePropagation()

Я пытаюсь изменить рабочую форму плана плагина Jira Tempo. Итак, на странице расписания темпа у меня есть кнопка, у которой есть 2 привязанных действия, одно действие щелчка, а другое - фокус. действие щелчка открывает всплывающее окно. и фокус проверяет форму во всплывающем окне. Мне нужно, чтобы сначала было выполнено действие клика, а затем фокус.

Проблема в том, что когда открывается всплывающее окно, происходит вызов всех трех функций. event.stopPropagation().preventDefault().stopImmediatePropagation(); поэтому фокус не срабатывает в хроме.

В IE10 и Firefox отлично работает.

Могу ли я переопределить базовую функцию jQuery ofevent.stopPropagation().preventDefault().stopImmediatePropagation(), чтобы она не применялась к этой кнопке? может все три?

Я пробовал это:

(function () {
jQuery.Event.prototype = {
    isDefaultPrevented: returnFalse,
isPropagationStopped: returnFalse,
isImmediatePropagationStopped: returnFalse,
    stopPropagation: function () {
        if (jQuery('#tempo-plan-button').hasClass(this.currentTarget.className)) {

        } else {
            var e = this.originalEvent;

            this.isPropagationStopped = returnTrue;

            if (e && e.stopPropagation) {
                e.stopPropagation();
            }
        }
    },
    preventDefault: function () {
        if (jQuery('#tempo-plan-button').hasClass(this.currentTarget.className)) {

        } else {
            var e = this.originalEvent;

            this.isDefaultPrevented = returnTrue;

            if (e && e.preventDefault) {
                e.preventDefault();
            }
        }
    },
    stopImmediatePropagation: function () {
        if (jQuery('#tempo-plan-button').hasClass(this.currentTarget.className)) {

        } else {
            var e = this.originalEvent;

            this.isImmediatePropagationStopped = returnTrue;

            if (e && e.stopImmediatePropagation) {
                e.stopImmediatePropagation();
            }

            this.stopPropagation();
        }
    }

};
function returnFalse() {
    return false;
}
function returnTrue() {
    return true;
}
})();

ОБНОВИТЬ:

У меня нет контроля над тем, что делает функция щелчка, но у меня есть контроль над фокусом, я провел некоторый тест, и мне кажется, что Chrome не видит событие фокуса, потому что элемент скрыт до того, как произойдет фокус (это всплывающая кнопка). Мне удалось вызвать свои функции с помощью события мыши, но это не работает в IE, поэтому мне нужно привязать отдельный прослушиватель событий для IE и Chrome, Firefox, Safari. Можете ли вы помочь с некоторыми примерами обнаружения браузера.

ОБНОВЛЕНИЕ 2:

Моя проблема решена с другим слушателем всплывающего элемента. бывший:

jQuery(document).ready(function ($) {
var currentUser = null;
var selected = null;
var opened = null;
var formOpened = null;
var activityField = null;
var activitySelected = null;
var popupBody = null;
var formOpened = null;
var periodCheckbox = null;
var dateField = null;
var endDateField = null;
var plannedHours = null;
var periodselected = null;
var days = 1;
var startdate = 0;
var enddate = 0;
var planButton = $('#tempo-plan-button');
//this is the default LM-Holiday activity ID set this
value to corespond with the value on jira tempo form.
var holidayid = "10100";
var holidaysLeft = 21; /*
 $('#tempo-plan-button').click(function () {
 alert("click event");
 });
 $('#tempo-plan-button').focusin(function () {
 alert("focus event");
 });
 $('#tempo-plan-button').hover(function () {
 alert("hover event");

 });
 $('#tempo-plan-button').mouseleave(function () {
 alert("mouse leave event");

 });
 $('#tempo-plan-button').mouseout(function () {
 alert("mouse out event");

 }); */
$('body').one('focus', 'div[class="aui-popup aui-dialog"]', function (event) {
    $('div[class="aui-popup aui-dialog"]').each(function () {
        popupBody = $(this).find(".dialog-components");
        if ($(this).find(".dialog-title").hasClass("tempo-add-button") === false) {
            i = 0;
            j = 0;
            $(popupBody).find(".dialog-page-menu li").each(function () {
                if ($(this).attr("class") === "page-menu-item selected") {
                    button = $(this).find('.item-button');
                    if ((button).text() === "Internal") {
                        selected = i;
                    }
                }
                i++;
            });
            $(popupBody).find(".dialog-panel-body").each(function () {
                if ($(this).is(":visible")) {
                    opened = j;
                    formOpened = $(this).find('form');
                }
                j++;
            });
            if (selected === null) {
                i = 0;
                j = 0;
                $(popupBody).find(".dialog-page-menu li").click(function () {
                    $(popupBody).find(".dialog-page-menu li").each(function () {
                        if ($(this).attr("class") === "page-menu-item selected") {
                            button = $(this).find('.item-button');
                            if ((button).text() === "Internal") {
                                selected = i;
                            }
                        }
                        i++;
                    });
                    $(popupBody).find(".dialog-panel-body").each(function () {
                        if ($(this).is(":visible")) {
                            opened = j;
                            formOpened = $(this).find('form');
                        }
                        j++;
                    });
                    if (selected === opened) {
                        activityField = $(formOpened).find('.tempo-activity-picker.select');
                        periodCheckbox = $(formOpened).find('.showperiod.tempo-show-period');
                        dateField = $(formOpened).find(' input[name="date"]');
                        endDateField = $(formOpened).find('input[name="enddate"]');
                        plannedHours = $(formOpened).find('input[name="time"]');
                        days = 1;
                        $(activityField).change(function () {
                            activitySelected = $(this).val();
                        });

                        $(periodCheckbox).change(function () {
                            if ($(this).prop("checked")) {
                                periodselected = true;
                            }
                            else
                            {
                                periodselected = false;

                            }
                        });
                        $(dateField).change(function () {
                            if (periodselected) {
                                startdate = parseDate($(this).val());
                                enddate = parseDate($(endDateField).val());
                            } else {
                                days = 1;
                            }
                            ;
                        });
                        $(endDateField).change(function () {
                            startdatestring = $(dateField).val();
                            enddatestring = $(this).val();
                            startdate = parseDate(startdatestring);
                            enddate = parseDate(enddatestring);
                        });
                        $(plannedHours).off("focusin");
                        $(plannedHours).focusin(function () {
                            if (activitySelected === holidayid) {
                                if (periodselected) {
                                    days = calcBusinessDays(startdate, enddate);

                                    if (holidaysLeft >= days) {
                                        holidaysLeft = holidaysLeft - days;
                       alert("Mai ai " + holidaysLeft + " zile de concediu ramase!");
                      $(popupBody).find('button[accesskey="s"]').removeAttr('disabled');
                                    }
                                    else {
         $(popupBody).find('button[accesskey="s"]').attr('disabled', 'disabled');
         alert('trebuie sa selectezi o perioada mai mica de' + holidaysLeft + 'de zile');
                                    }
                                } else
                                {
                                    if (holidaysLeft >= days) {
                                        holidaysLeft = holidaysLeft - days;
                                 alert("Mai ai " + holidaysLeft + " zile de concediu ramase!");
                        $(popupBody).find('button[accesskey="s"]').removeAttr('disabled');
                                    }
                                    else {
                 $(popupBody).find('button[accesskey="s"]').attr('disabled', 'disabled');
               alert('trebuie sa selectezi o perioada mai mica de' + holidaysLeft + 'de zile');
                                    }
                                }
                            }
                        });
                    }
                });
            } else {
                j = 0;
                $(popupBody).find(".dialog-panel-body").each(function () {
                    if ($(this).is(":visible")) {
                        opened = j;
                        formOpened = $(this).find('form');
                    }
                    j++;
                });
                if (selected === opened) {
                    activityField = $(formOpened).find('.tempo-activity-picker.select');
                    periodCheckbox = $(formOpened).find('.showperiod.tempo-show-period');
                    dateField = $(formOpened).find(' input[name="date"]');
                    endDateField = $(formOpened).find('input[name="enddate"]');
                    plannedHours = $(formOpened).find('input[name="time"]');
                    days = 1;
                    $(activityField).change(function () {
                        activitySelected = $(this).val();
                    });

                    $(periodCheckbox).change(function () {
                        if ($(this).prop("checked")) {
                            periodselected = true;
                        }
                        else
                        {
                            periodselected = false;

                        }
                    });
                    $(dateField).change(function () {
                        if (periodselected) {
                            startdate = parseDate($(this).val());
                            enddate = parseDate($(endDateField).val());
                        } else {
                            days = 1;
                        }
                        ;
                    });
                    $(endDateField).change(function () {
                        startdatestring = $(dateField).val();
                        enddatestring = $(this).val();
                        startdate = parseDate(startdatestring);
                        enddate = parseDate(enddatestring);
                    });
                    $(plannedHours).off("focusin");
                    $(plannedHours).focusin(function () {
                        if (activitySelected === holidayid) {
                            if (periodselected) {
                                days = calcBusinessDays(startdate, enddate);

                                if (holidaysLeft >= days) {
                                    holidaysLeft = holidaysLeft - days;
               alert("Mai ai " + holidaysLeft + " zile de concediu ramase!");
               $(popupBody).find('button[accesskey="s"]').removeAttr('disabled');
                                }
                                else {
                       $(popupBody).find('button[accesskey="s"]').attr('disabled', 'disabled');
                alert('trebuie sa selectezi o perioada mai mica de' + holidaysLeft + 'de zile');
                                }
                            } else
                            {
                                if (holidaysLeft >= days) {
                                    holidaysLeft = holidaysLeft - days;
                              alert("Mai ai " + holidaysLeft + " zile de concediu ramase!");
                         $(popupBody).find('button[accesskey="s"]').removeAttr('disabled');
                                }
                                else {
                    $(popupBody).find('button[accesskey="s"]').attr('disabled', 'disabled');
          alert('trebuie sa selectezi o perioada mai mica de' + holidaysLeft + 'de zile');
                                }
                            }
                        }
                    });
                }
            }
            ;
        }
        ;
        return false;
    });

    $.ajax({
        type: "GET",
        url: location.protocol + '//' + location.host + "/rest/api/2/myself",
        success: function (response) {
            currentUser = $.parseJSON(response);
        },
        error: function (response) {
            alert("Eroare" + response.result);
        }
    });
    return false;
});
});
 function calcBusinessDays(dDate1, dDate2) { // input given as Date objects
var iWeeks, iDateDiff, iAdjust = 0;
if (dDate2 < dDate1)
    return -1; // error code if dates transposed
var iWeekday1 = dDate1.getDay(); // day of week
var iWeekday2 = dDate2.getDay();
iWeekday1 = (iWeekday1 === 0) ? 7 : iWeekday1; // change Sunday from 0 to 7
iWeekday2 = (iWeekday2 === 0) ? 7 : iWeekday2;
if ((iWeekday1 > 5) && (iWeekday2 > 5))
    iAdjust = 1; // adjustment if both days on weekend
iWeekday1 = (iWeekday1 > 5) ? 5 : iWeekday1; // only count weekdays
iWeekday2 = (iWeekday2 > 5) ? 5 : iWeekday2;

// calculate differnece in weeks (1000mS * 60sec * 60min * 24hrs * 7 days = 604800000)
iWeeks = Math.floor((dDate2.getTime() - dDate1.getTime()) / 604800000);

if (iWeekday1 <= iWeekday2) {
    iDateDiff = (iWeeks * 5) + (iWeekday2 - iWeekday1);
} else {
    iDateDiff = ((iWeeks + 1) * 5) - (iWeekday1 - iWeekday2);
}

iDateDiff -= iAdjust // take into account both days on weekend

return (iDateDiff + 1); // add 1 because dates are inclusive
}
function parseDate(s) {
var lastSlash = s.lastIndexOf("/");
var years = s.substring(lastSlash + 1);
years = "20" + years;
s = s.replaceAt(lastSlash + 1, years);
var pattern = /(.*?)\/(.*?)\/(.*?)$/;
var result = s.replace(pattern, function (match, p1, p2, p3) {
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    return (months.indexOf(p2) + 1) + "/" + (p1) + "/" + p3;
});
return new Date(result);
}
String.prototype.replaceAt = function (index, character) {
 return this.substr(0, index) + character + this.substr(index + character.length);
};
function propStopped(event) {
var msg = "";
if (event.isPropagationStopped()) {
    msg = "called";
} else {
    msg = "not called";
}
alert(msg);
}

Спасибо.


person Alex Robert    schedule 10.10.2014    source источник
comment
Я думаю, что это плохая практика, и ваши returnTrue/false полны, не имеют никакого смысла.   -  person Andreas Furster    schedule 10.10.2014
comment
@Andreas Furster Я добавил их из библиотеки jQuery. Итак, эти три метода уже вызываются в событии по клику, но я не могу это изменить. вместо этого я хочу переопределить их, чтобы они не применялись к моему элементу #tempo-plan-button. Спасибо.   -  person Alex Robert    schedule 10.10.2014


Ответы (2)


Вы имели в виду это?

Event.prototype.stopPropagation = function(){ alert('123') }
$('input').on('click',function(e){
  e.stopPropagation();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type='button' value='click' />

person aleha    schedule 10.10.2014
comment
Да, @aleha, что-то в этом роде, но я не хочу, чтобы меня казнили за этот элемент. и у меня нет доступа к сценарию события клика. поэтому я не могу это изменить. а также все три метода вызываются в событии клика. поэтому я должен пропустить все три для этой кнопки. - person Alex Robert; 10.10.2014
comment
простое переопределение этих методов с использованием объекта Event.prototype для пустой функции не поможет? Event.prototype.stopPropagation = function(){ } - person aleha; 10.10.2014
comment
Нет, ничего не изменилось. - person Alex Robert; 10.10.2014
comment
так что это была проблема с самим событием, фокус вообще не срабатывал в chrome, но срабатывал mouseout, но теперь, если я использую второй IE, я не вижу событие ... так что мне нужен обходной путь? какие-либо предложения? - person Alex Robert; 10.10.2014

Из вопроса неясно, какой код вы контролируете. Я читаю между строк, что, возможно, вы управляете функцией, связанной с событием нажатия кнопки, но вы не управляете функцией, связанной с событием focusout, поэтому вам нужно обойти эти вызовы.

Если вы хотите контролировать выполнение событий и убедиться, что ваше происходит первым, это можно сделать с помощью чего-то вроде jQuery.bindUp, только если события одного типа. Таким образом, вам все равно, попытается ли другой обработчик вызвать stopPropagation и т. д., потому что ваш обработчик все равно будет выполняться первым.

Учитывая это, возможно ли реструктурировать ваш код так, чтобы логика, которой вы управляете (часть, которая должна произойти в первую очередь!) имела тот же тип события, что и существующий обработчик событий, а затем использовать jQuery.bindUp, чтобы убедиться, что он выполняется перед обработчиком событий, который вы не контролируете? Вы по-прежнему можете привязываться к событию click, если вам это нужно, пока зависимая бизнес-логика перемещается в событие focusout.

(Если мои предположения неверны, было бы полезно, если бы вы могли обновить вопрос, чтобы более подробно описать ограничения проблемы.)

person Scott Dudley    schedule 10.10.2014
comment
спасибо за ответ, но на самом деле моя проблема заключалась в том, что хром не видел фокуса, и теперь мне нужно привязать разные прослушиватели событий для каждого браузера. у вас есть пример, как определить браузер и в соответствии с ним связать разные прослушиватели событий? - person Alex Robert; 13.10.2014
comment
@AlexRobert, людям будет легче помочь вам, если вы изолируете проблему и (скажем) соберете jsfiddle, который демонстрирует точную проблему. Этот процесс также может привести к тому, что вы сами обнаружите проблему! - person Scott Dudley; 13.10.2014
comment
я могу поместить только свой код, который вставлен в этот вопрос, другой код находится на платформе Atlassian Jira. и не могу получить к нему доступ. Я решил проблему, используя другой прослушиватель событий. - person Alex Robert; 16.10.2014