event.preventDefault ()를 사용한 후 이벤트를 트리거하는 방법


155

예를 들어 발사 준비가 될 때까지 이벤트를 개최하고 싶습니다.

$('.button').live('click', function(e){

   e.preventDefault(); 

   // do lots of stuff

   e.run() //this proceeds with the normal event    

}

run()위에서 설명한 기능 과 동등한 기능이 있습니까?


기본 동작은 핸들러가 반환 된 후에 만 ​​발생합니다. 나중에 처리기에서 허용하도록 해당 동작을 방지하는 것은 의미가 없습니다.
프레데릭 하 미디

7
@ FrédéricHamidi 불행히도 비동기 항목 ($ .ajax, 콜백 등)을 사용하면 기본 동작이 발생합니다.
vzwick

답변:


164

아니. 이벤트가 취소되면 취소됩니다.

그래도 플래그를 사용하여 사용자 지정 코드가 이미 실행 중인지 여부를 결정하는 이벤트를 나중에 다시 실행할 수 있습니다.

var lots_of_stuff_already_done = false;

$('.button').on('click', function(e) {
    if (lots_of_stuff_already_done) {
        lots_of_stuff_already_done = false; // reset flag
        return; // let the event bubble away
    }

    e.preventDefault();

    // do lots of stuff

    lots_of_stuff_already_done = true; // set flag
    $(this).trigger('click');
});

보다 일반적인 변형 (전역 네임 스페이스 오염을 피할 수있는 추가 이점이 있음)은 다음과 같습니다.

function onWithPrecondition(callback) {
    var isDone = false;

    return function(e) {
        if (isDone === true)
        {
            isDone = false;
            return;
        }

        e.preventDefault();

        callback.apply(this, arguments);

        isDone = true;
        $(this).trigger(e.type);
    }
}

용법:

var someThingsThatNeedToBeDoneFirst = function() { /* ... */ } // do whatever you need
$('.button').on('click', onWithPrecondition(someThingsThatNeedToBeDoneFirst));

다음을 지원하는 보너스 초소형 jQuery 플러그인 Promise:

(function( $ ) {
    $.fn.onButFirst = function(eventName,         /* the name of the event to bind to, e.g. 'click' */
                               workToBeDoneFirst, /* callback that must complete before the event is re-fired */
                               workDoneCallback   /* optional callback to execute before the event is left to bubble away */) {
        var isDone = false;

        this.on(eventName, function(e) {
            if (isDone === true) {
                isDone = false;
                workDoneCallback && workDoneCallback.apply(this, arguments);
                return;
            }

            e.preventDefault();

            // capture target to re-fire event at
            var $target = $(this);

            // set up callback for when workToBeDoneFirst has completed
            var successfullyCompleted = function() {
                isDone = true;
                $target.trigger(e.type);
            };

            // execute workToBeDoneFirst callback
            var workResult = workToBeDoneFirst.apply(this, arguments);

            // check if workToBeDoneFirst returned a promise
            if (workResult && $.isFunction(workResult.then))
            {
                workResult.then(successfullyCompleted);
            }
            else
            {
                successfullyCompleted();
            }
        });

        return this;
    };
}(jQuery));

용법:

$('.button').onButFirst('click',
    function(){
        console.log('doing lots of work!');
    },
    function(){
        console.log('done lots of work!');
    });

4
.live는 지원되지 않습니다. 아래 @Cory Danielson 예제에 사용 된 .on을 사용하십시오.
nwolybug

이것은 다시 .click에 들어가고 마침내 "너무 많은 재귀"를 볼 수 있습니다
Himanshu Pathak

5
@HimanshuPathak- lots_of_stuff_already_done = true;플래그 설정을 잊었을 수 있습니다. 그렇지 않으면 함수가 계속 재귀를 유지할 수있는 방법이 없습니다.
vzwick

73

허용되는 답변의 최신 버전입니다.

간단한 버전 :

$('#form').on('submit', function(e, options) {
    options = options || {};

    if ( !options.lots_of_stuff_done ) {
        e.preventDefault();
        $.ajax({
            /* do lots of stuff */
        }).then(function() {
            // retrigger the submit event with lots_of_stuff_done set to true
            $(e.currentTarget).trigger('submit', { 'lots_of_stuff_done': true });
        });
    } else {
        /* allow default behavior to happen */
    }

});



이와 같은 좋은 유스 케이스는 작동하는 레거시 양식 코드가있을 수 있지만 양식을 제출하기 전에 전자 메일 주소 유효성 검사와 같은 것을 추가하여 양식을 개선하라는 요청을 받았습니다. 백엔드 양식 포스트 코드를 파는 대신 API를 작성한 다음 양식이 기존 POST를 수행하기 전에 먼저 해당 API에 도달하도록 프론트 엔드 코드를 업데이트 할 수 있습니다.

이를 위해 여기에 작성한 것과 비슷한 코드를 구현할 수 있습니다.

$('#signup_form').on('submit', function(e, options) {
    options = options || {};

    if ( !options.email_check_complete ) {

        e.preventDefault(); // Prevent form from submitting.
        $.ajax({
            url: '/api/check_email'
            type: 'get',
            contentType: 'application/json',
            data: { 
                'email_address': $('email').val() 
            }
        })
        .then(function() {
            // e.type === 'submit', if you want this to be more dynamic
            $(e.currentTarget).trigger(e.type, { 'email_check_complete': true });
        })
        .fail(function() {
            alert('Email address is not valid. Please fix and try again.');
        })

    } else {

        /**
             Do traditional <form> post.
             This code will be hit on the second pass through this handler because
             the 'email_check_complete' option was passed in with the event.
         */

        $('#notifications').html('Saving your personal settings...').fadeIn();

    }

});

1
"백엔드 양식 포스트 코드를 파헤치는 대신"... 실제로 어쨌든 클라이언트 측 유효성 검사에만 의존 할 수는 없습니다.
Diego V

18

당신은 같은 것을 할 수 있습니다

$(this).unbind('click').click();

이것은 정말 좋은 해결책이지만 IE10 / 11에서는 작동하지 않는 것 같습니다. (
JonB

47
왜 "고통"이라는 단어를 검열 했습니까?
Sean Kendle

클릭이 발생했지만 다시 클릭 할 수 있습니까?
Tom Anderson

16

다음 isDefaultPrevented과 같이 속성을 재정의하십시오 .

$('a').click(function(evt){
  evt.preventDefault();

  // in async handler (ajax/timer) do these actions:
  setTimeout(function(){
    // override prevented flag to prevent jquery from discarding event
    evt.isDefaultPrevented = function(){ return false; }
    // retrigger with the exactly same event data
    $(this).trigger(evt);
  }, 1000);
}

IMHO, 이것은 정확히 동일한 데이터로 이벤트를 다시 트리거하는 가장 완벽한 방법입니다.


e정의되지 않았습니다. 이어야합니다 evt.preventDefault(). 편집하려고했지만 편집 한 내용은 6 자 이상이어야하며 2 :(
kevnk

3
@kevnk, 나는 일반적으로 라인 주석의 형태로 편집에 대한 간단한 설명을 포함합니다. 제출 된 문자 수를 늘려야합니다.
재귀

왜이 답변이 더 많이지지되지 않았는지 모릅니다. 이것은 정말 유용합니다. 와 함께 전파가 작동하지 않습니다 event.isPropagationStopped = function(){ return false; };. 또한 이벤트에 사용자 정의 특성을 추가하여 조치를 방해 한 점검이 수행되어 다시 작성되지 않은 경우 핸들러에서 감지 할 수 있습니다. 큰!
Kaddath

Bootstrap 4 Tabs에 사용했는데 완벽하게 작동했습니다. 많은 감사합니다. $ ( '# v-pills-tab a'). on ( 'click', function (e) {e.preventDefault (); setTimeout (function () {e.isDefaultPrevented = function () {return false;} $ ( '# v-pills-home-tab'). on ( 'shown.bs.tab', function () {$ ( '. mainDashboard'). show (); $ ( '# changePlans'). hide (); });}, 1000); $ (this) .tab ( 'show');});
Surya R Praveen

8

의 사용이 가능 currentTarget합니다 event. 예는 양식 제출을 진행하는 방법을 보여줍니다. 마찬가지로 onclick속성 등에서 기능을 얻을 수 있습니다 .

$('form').on('submit', function(event) {
  event.preventDefault();

  // code

  event.currentTarget.submit();
});

제출은 유효한 기능이 아닙니다
Devaffair

submit()같은 요소 를 호출 하면``$ ( 'form'). on ( 'submit') 코드를 반환하지 않고 반복해서 다시 실행합니까?
Fanie Void

7

그냥 수행하지 않거나 e.preventDefault();조건부로 수행하십시오.

원래 이벤트 작업이 발생할 확실히 변경할 수 없습니다 .

언젠가 원래 UI 이벤트를 "재 작성"하려면 (예 : AJAX 요청의 콜백에서) vzwick의 답변과 같은 다른 방법으로 위조해야합니다 ... 그러한 접근법의 유용성에 의문을 제기하십시오.



3

"많은 것들"이 비동기 적으로 동작하지 않는 한, 이것은 절대적으로 불필요합니다. 이벤트는 모든 처리기를 순서대로 진행할 것입니다. 따라서 부모 요소에 onklick 이벤트가 발생하면 onclik 후에 발생합니다. 아이의 사건이 완전히 처리되었습니다. 자바 스크립트는 이벤트 처리를 "중지"시키는 일종의 "멀티 스레딩"을 수행하지 않습니다. 결론 : 동일한 핸들러에서 이벤트를 재개하기 위해 "일시 중지"하는 것은 의미가 없습니다.

만약 "많은 것들" 비동기적인 것이면 그것은 또한 비동기적인 것들이해야 할 일 (비동기적인 것들)을 행하지 못하게하고 모든 것들이 순서대로있는 것처럼 행동하게합니다 (우리가 첫 단락으로 돌아 오는 곳) )


중간에 프로세스가 비동기 적입니다, 나는 아약스 콜백에서 결과를 발사하고 싶습니다 ...
Mazatec

1
아약스 요청을 기다려야한다면 (jquery의 경우 async-fag가 있습니다 : api.jquery.com/jQuery.ajax ) ... 동시에 아약스 요청을 만드는 것은 거의 모든 경우에 나쁜 생각입니다. 다른 솔루션을 찾는 것이 좋습니다.
oezi

3

내가 사용하는 접근법은 다음과 같습니다.

$('a').on('click', function(event){
    if (yourCondition === true) { //Put here the condition you want
        event.preventDefault(); // Here triggering stops
        // Here you can put code relevant when event stops;
        return;
    }
    // Here your event works as expected and continue triggering
    // Here you can put code you want before triggering
});

2

앵커 태그로 작업하는 경우 허용되는 솔루션이 작동하지 않습니다. 이 경우을 호출 한 후 링크를 ​​다시 클릭 할 수 없습니다 e.preventDefault(). jQuery에 의해 생성 된 클릭 이벤트는 기본 브라우저 이벤트 위에 계층화되어 있기 때문입니다. 따라서 앵커 태그에서 '클릭'이벤트를 트리거하면 링크를 따라 가지 않습니다. 대신 jquery-simulate 와 같은 라이브러리를 사용하여 기본 브라우저 이벤트를 시작할 수 있습니다.

이에 대한 자세한 내용은이 링크를 참조하십시오.


1

또 다른 해결책은 이벤트 리스너에서 window.setTimeout을 사용 하고 이벤트 프로세스가 완료된 후 코드를 실행하는 것입니다. 뭔가 ...

window.setTimeout(function() {
  // do your thing
}, 0);

대기에 신경 쓰지 않기 때문에 기간에 0 을 사용 합니다.


1

이 주제는 오래되었지만 내가 기여할 수 있다고 생각합니다. 해당 동작을 이미 알고 있으면 핸들러 함수에서 언제든지 특정 요소에서 이벤트의 기본 동작을 트리거 할 수 있습니다. 예를 들어, 재설정 단추에서 클릭 이벤트를 트리거하면 실제로 가장 가까운 양식의 재설정 기능을 기본 동작으로 호출합니다. 핸들러 함수에서 preventDefault 함수를 사용한 후 핸들러 코드에서 가장 가까운 형식으로 재설정 함수를 호출하여 기본 동작을 호출 할 수 있습니다.


0

이 예제가 도움이 될 수 있으면 일부 링크에 "custom confirm popin"을 추가합니다 ( "$ .ui.Modal.confirm"코드를 유지합니다. 원래 작업을 실행하는 콜백의 예일뿐입니다).

//Register "custom confirm popin" on click on specific links
$(document).on(
    "click", 
    "A.confirm", 
    function(event){
        //prevent default click action
        event.preventDefault();
        //show "custom confirm popin"
        $.ui.Modal.confirm(
            //popin text
            "Do you confirm ?", 
            //action on click 'ok'
            function() {
                //Unregister handler (prevent loop)
                $(document).off("click", "A.confirm");
                //Do default click action
                $(event.target)[0].click();
            }
        );
    }
);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.