2014-10-10 4 views
2

Jira Tempo 플러그인의 계획 작업 양식을 수정하려고합니다. 따라서 템포 시간표 페이지 에는 2 개의 동작이 바인드되어있는 버튼이 있습니다. 하나는 클릭 동작이고 다른 하나는 포커스입니다. 클릭 동작으로 팝업이 열립니다. 포커스 아웃은 팝업의 양식을 검증합니다. clik 액션을 먼저 실행하고 포커스를 내 보내야합니다.event.stopPropagation(), preventDefault(). stopImmediatePropagation()을 재정의하는 방법

문제는 팝업이 열리면 세 가지 기능을 모두 호출하는 것입니다. event.stopPropagation().preventDefault().stopImmediatePropagation(); 크롬에서 초점이 맞지 않습니다.

IE10 및 Firefox에서 잘 작동합니다.

해당 버튼에 적용하지 않으려면 event.stopPropagation().preventDefault().stopImmediatePropagation()의 jQuery 기본 기능을 무시할 수 있습니까? 3 명 모두 가능합니까?

(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; 
} 
})(); 

UPDATE :

내가 클릭 기능이 무엇에 제어 할 수 없습니다,하지만 난 초점 밖으로 제어 할 수 있습니다, 내가 만든 몇 가지 테스트와 나는

나는이 시도 포커스 아웃이 발생하기 전에 요소가 숨겨져 있기 때문에 Chrome에 포커스 이탈 이벤트가 표시되지 않는 것처럼 보입니다 (팝업 버튼). 나는 mouse out 이벤트로 내 함수를 호출했지만 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); 
} 

감사합니다.

+2

나는 이것이 나쁜 습관이라고 생각하며, 당신의'returnTrue' /'false'는 전혀 이해가 안된다. –

+0

@Andreas Furster 나는 jQuery 라이브러리에서 그것들을 추가했다. 그래서이 세 가지 메서드는 on click 이벤트에서 이미 호출되었지만 수정할 수는 없습니다. 대신 내 # 템포 계획 단추 요소에 적용하지 않으려면 무시하려고합니다. 감사합니다. –

답변

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' />
질문에서

+0

예 @aleha, 그런 식으로하지만 그 요소에 대해 실행되고 싶지 않습니다. 클릭 이벤트 스크립트에 대한 액세스 권한이 없습니다. 그래서 나는 그것을 수정할 수 없다. 또한 세 가지 메소드가 모두 click 이벤트에서 호출됩니다. 그래서 나는 그 버튼에 대해 세 가지를 모두 건너 뛰어야한다. –

+0

Event.prototype 객체를 사용하여 이러한 메서드를 재정의하면 함수를 비우지 않아도됩니까? 'Event.prototype.stopPropagation = function() {}' – aleha

+0

아니, 아무것도 변경되지 않았습니다. –

1

, 그것은 명확하지 않다. 단추 사이의 클릭 이벤트에 바인딩 된 함수를 제어하는 ​​선 사이를 읽고 있지만 focusout 이벤트에 바인딩 된 함수를 제어하지 않기 때문에 이러한 호출을 해결해야합니다.

이벤트 실행을 제어하고 이벤트가 먼저 발생하는지 확인하려면 이벤트가 동일한 유형 인 한 jQuery.bindUp과 같은 값으로이를 수행 할 수 있습니다. 그런 식으로 처리기가 먼저 어쨌든 실행되기 때문에 다른 핸들러가 stopPropagation 등을 호출하려고하는지 신경 쓰지 않아도됩니다.

당신이 제어하는 ​​로직 (먼저 일어날 필요가있는 부분)이 기존 이벤트 핸들러와 같은 이벤트 유형이되도록 코드를 재구성 할 수 있습니까? 그렇다면 jQuery.bindUp을 사용하여 당신이 제어하지 않는 이벤트 처리기보다 먼저 실행 되는가? 종속 비즈니스 로직이 focusout 이벤트로 이동되는 한, 필요한 경우 click 이벤트에 계속 바인드 할 수 있습니다.

(제 가정이 정확하지 않은 경우 문제를보다 자세히 설명하기 위해 질문을 업데이트 할 수 있다면 도움이됩니다.)

+0

감사합니다, 대답은,하지만 정말로 내 문제는 크롬에 초점이 맞지 않아 모든 브라우저마다 다른 이벤트 수신기를 바인딩해야한다는 것입니다. 당신은 브라우저를 감지하는 방법과 다른 이벤트 리스너를 바인드하는 몇 가지 예가 있습니까? –

+0

@AlexRobert, 문제를 격리하고 정확한 문제를 설명하는 jsfiddle을 조합하면 사람들이 당신을 도울 수 있습니다. 이 과정을 통해 문제를 직접 발견 할 수도 있습니다! –

+0

나는이 질문에 삽입 된 코드를 넣을 수 있습니다. 다른 코드는 Atlassian Jira 플랫폼에 있습니다. 액세스 할 수 없습니다. 다른 이벤트 수신기를 사용하여 문제가 해결되었습니다. –