jquery-blockuijquery-dirtyforms

DirtyForms does not work properly with $.blockUI


I'm using DirtyForms and $.blockUI plugin, the latter to change pages when clicking on links (in my app, some pages take a couple of seconds more to load and a visual feedback is fine).

When I change field content and then click any link, DirtyForms is triggered: but when I cancel the process to stay on the page, $.blockUI starts its game, resulting in a stuck page

$('form[method="post"]').dirtyForms();
$('a').on('click', function(){
	$.blockUI();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.dirtyforms/2.0.0/jquery.dirtyforms.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js"></script>

<p>Change the field content to activate DirtyForms, then click on the link.<br>
When the popup appears, click on "cancel" to stay on the page.<br>
Watch blockUI getting fired as the link is going to be followed</p>
<form action="#" method="post">
  <input type="text" name="username" required>
  <button type="submit">send</button>
</form>
<a href="https://google.com">click me after changing field content</a>

Please, any solution?

EDIT: I also tried with stay.dirtyforms and afterstay.dirtyforms events, but they have no effect. defer.dirtyforms seems to work but the event is triggered twice (I put a console.log() to check) and I am not sure this is the way to go...


Solution

  • I've edit my answer: I've added some line of code to disable first the onbeforeunload dialog alert, taken from here. And at the end a link to an answer with another idea you can try.

    My idea: you have to prevent the default link action and use the $.blockUI Modal Dialogs methods to open a custom dialog, then catch the link attribute href from the link put it inside a variable and use the variable value for the #yes button of the dialog.

    See if this solution can meet your needs

    /* beforeunload bind and unbind taken from https://gist.github.com/woss/3c2296d9e67e9b91292d */
    
    // call this to restore 'onbeforeunload'
    var windowReloadBind = function(message) {
      window.onbeforeunload = function(event) {
        if (message.length === 0) {
           message = '';
        };
      
        if (typeof event == 'undefined') {
           event = window.event;
        };
        if (event) {
           event.returnValue = message;
        };
        return message;
      }
    };
    
    // call this to prevent 'onbeforeunload' dialog
    var windowReloadUnBind = function() {
        window.onbeforeunload = function() {
          return null;
       };
    };
    
    var linkToFollow; // href to follow
    
    $('form[method="post"]').dirtyForms();
    
    $('a').on('click', function(e){
            e.preventDefault();
            windowReloadUnBind(); // prevent dialog
    	$.blockUI({ message: $('#question'), css: { width: '275px' } });
            linkToFollow = $(this).attr('href');
    });
    
    $('#no').click(function() { 
            $.unblockUI();
            return false; 
    });
    
    $('#yes').click(function() { 
            $(window.location).attr('href', linkToFollow); 
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.dirtyforms/2.0.0/jquery.dirtyforms.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js"></script>
    
    <p>Change the field content to activate DirtyForms, then click on the link.<br>
    When the popup appears, click on "cancel" to stay on the page.<br>
    Watch blockUI getting fired as the link is going to be followed</p>
    <form action="#" method="post">
      <input type="text" name="username" required>
      <button type="submit">send</button>
    </form>
    <a href="https://google.com" class="link">click me after changing field content</a>
    <div id="question" style="display:none; cursor: default"> 
        <h6>Would you like to contine?.</h6> 
        <input type="button" id="yes" value="Yes" /> 
        <input type="button" id="no" value="No" /> 
    </div>

    Other idea taken from another answer: Other idea would be to make a simple jQuery.ajax({}) call before return value in beforeunload as seen in this answer