7
votes

JavaScript - fermer la fenêtre contextuelle avec le bouton de retour

J'ai une fonctionnalité contextuelle personnalisée. Ce que je veux, c'est que le bouton de retour du navigateur ferme cette fenêtre contextuelle.

Mon scénario idéal serait de NE PAS afficher de hashtag dans la barre d'URL.

J'ai essayé de mettre window.history. pushState ('forward', null, ''); dans ma fonction showPopup () puis en faisant ce qui suit:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="popup-link">Click</button>

<div class="popup">
    <button class="popup-close">x</button>
    <!-- popup content here -->
</div>

Cela fonctionne mais le problème est que lorsque je ferme manuellement la fenêtre contextuelle, je dois appuyer deux fois sur le bouton retour pour revenir à la page précédente (évidemment parce qu'une entrée d'historique du navigateur a été ajoutée lors de l'ouverture de la fenêtre contextuelle).

Quelle est la meilleure façon de procéder? Cela peut-il être fait sans ajouter une entrée d'historique du navigateur? Ce que j'essaye de faire, c'est de reproduire le comportement d'une application mobile. Appuyez sur le bouton de retour dans une application mobile pour supprimer généralement les modaux ouverts ou les menus contextuels.

.popup {
  background-color: #ccc;
  width: 300px;
  height: 300px;
  display: none;
}

.popup.active {
    display: block;
}
$('.popup-link').click(function() {
    showPopup();
});

$('.popup-close').click(function() {
    hidePopup();
});

function showPopup() {
    $('.popup').addClass('active');
}

function hidePopup() {
    $('.popup').removeClass('active');
}
$(window).on('popstate', function () {
    closePopup();
});


5 commentaires

Changer le comportement standard est une expérience utilisateur terrible. Pourquoi feriez-vous une telle chose?


Eh bien, vous pourriez affirmer que ce "comportement standard" est une mauvaise expérience utilisateur - car beaucoup d'utilisateurs maintenant (en particulier les utilisateurs d'applications mobiles) sont habitués à appuyer pour rejeter les fenêtres contextuelles et les invites.


Eh bien, vous argumenteriez sur un argument incorrect.


Qu'entendez-vous par fermer manuellement la fenêtre contextuelle ? Voulez-vous dire fermer le popup en utilisant le bouton close avec la classe popup-close ?


Même si votre problème n'existe plus ou a été résolu autrement, vous devez suivre les réponses affichées.


7 Réponses :


4
votes

Cependant, je ne recommande pas de remplacer la gestion habituelle de l'historique du navigateur (bouton retour) pour l'utiliser à votre guise ....

Je pense que la seule chose que vous avez manquée dans votre exemple est que le bouton de fermeture ne doit pas fermer le modal tout seul, mais simplement exécuter un événement backbutton (qui finira par fermer le modal).

Cette solution simple fonctionnera comme vous le souhaitez.


1 commentaires

12
votes

Il n'est pas possible de le faire sans ajouter des entrées d'historique du navigateur car vous ne pouvez pas remplacer le comportement du bouton Précédent, voir Intercepter l'appel au bouton de retour de mon application AJAX: je ne veux rien faire

La réponse de Sujumayas est une bonne option, vous devriez cependant introduire une variable supplémentaire pour éviter des problèmes avec l'historique lors de l'ouverture de plusieurs fenêtres contextuelles (par exemple, en cliquant sur le bouton plusieurs fois)

Voici un exemple de code possible: p >

let popupOpen = false;

$(".popup-link").click(function() {
    showPopup();
});

$(".popup-close").click(function() {
    window.history.back();
});

function showPopup() {
    if (popupOpen) {
        window.history.back();
    }
    popupOpen = true;
    window.history.pushState("forward", null, "");
    $(".popup").addClass("active");
}

function hidePopup() {
    popupOpen = false;
    $(".popup").removeClass("active");
}

$(window).on("popstate", function() {
    hidePopup();
});

De plus, veuillez noter que vous pourriez avoir des problèmes avec Opera Mini: https: //caniuse.com/#search=history


1 commentaires

@GSTAR Je pense que c'est ce que vous recherchez.



1
votes

Je fais déjà quelque chose comme ça, et cela fonctionne bien avec le bouton de retour du navigateur et en appuyant sur le bouton de retour d'Android. Je n'affiche pas non plus de hashtag dans la barre d'URL.

Voici le talon (j'ai juste essayé de l'appliquer à votre scénario):

function freezeHistory() {
  window.history.pushState({}, window.document.title, window.location.href);
}

function goBack() {
  /*
    Custom history back actions: close panel, close popup, close drop-down menu
  */
  var popupOpen = $(".popup.active").length > 0;
  if(popupOpen) {
    hidePopup();
    return false;
  }
  window.history.back();
  return true;
}

function showPopup() {
  $('.popup').addClass('active');
  freezeHistory();
}

function hidePopup() {
  $('.popup').removeClass('active');
}

$(window).on("popstate", function(e) {
  /* 
     Browsers tend to handle the popstate event differently on page load. 
     Chrome (prior to v34) and Safari always emit a popstate event on page load, 
     but Firefox doesn’t.
  */
  goBack();
})

Si cela a gagné ' t travailler pour vous hors de la boîte, c'est parce qu'à mon humble avis, vous devrez peut-être clarifier un peu comment vous comptez gérer l'historique de la page. N'hésitez pas à ajouter plus de détails à votre question si cela ne fonctionne pas comme prévu maintenant, mais de toute façon, je crois fermement que vous avez eu l'idée et que vous êtes en mesure de l'appliquer dans le scénario de votre application Web. p>


0 commentaires

0
votes

Ouvrez la fenêtre contextuelle et essayez d'aller et venir avec les boutons d'historique du navigateur

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="popup-link">Click</button>

<div class="popup">
    <button class="popup-close">x</button>
    <!-- popup content here -->
</div>
.popup {
            background-color: #ccc;
            width: 300px;
            height: 300px;
            display: none;
        }

        .popup.active {
            display: block;
        }
$(document).ready(function () {
    // manage popup state
    var poped = false;
    $('.popup-link').click(function () {
        // prevent unwanted state changtes
        if(!poped){
            showPopup();
        }
    });

    $('.popup-close').click(function () {
        // prevent unwanted state changtes
        if(poped){
            hidePopup();
        }
    });

    function showPopup() {
        poped = true;
        $('.popup').addClass('active');
        // push a new state. Also note that this does not trigger onpopstate
        window.history.pushState({'poped': poped}, null, '');
    }

    function hidePopup() {
        poped = false;
        // go back to previous state. Also note that this does not trigger onpopstate
        history.back();
        $('.popup').removeClass('active');
    }
});

// triggers when browser history is changed via browser
window.onpopstate = function(event) {
    // show/hide popup based on poped state
    if(event.state && event.state.poped){
        $('.popup').addClass('active');
    } else {
        $('.popup').removeClass('active');
    }
};


0 commentaires

0
votes

Vous pouvez ajouter window.history.go (-2) à votre popstate. Cela devrait vous ramener deux fois, ce qui serait votre page d'origine avant le modal car pushState a ajouté une entrée à votre objet d'historique.

Inversement, vous pouvez utiliser history.back (2) Utilisez window.location.href pour parcourir 2 pages revenir et recharger


0 commentaires

0
votes

Lancez simplement window.history.back (); lors de la fermeture du popup.

$('.popup-close').click(function() {
    hidePopup();
    window.history.back();
});


0 commentaires

0
votes

Vous auriez deux options pour implémenter ceci:

Option 1: Utilisation de l'événement window.beforeunload . référence

$('.popup-link').click(function() {
  showPopup();
  window.history.pushState('popup-open', null, '');
  $(window).on('popstate', hidePopup);
});

$('.popup-close').click(function() {
  if(history.state == 'popup-open')  {
    window.history.back();
  }
  hidePopup();
});

function hidePopup() {
    $(window).off('popstate', hidePopup);
    $('.popup').removeClass('active');
}


1 commentaires

L'option 1 génère l'erreur "Uncaught RangeError: taille maximale de la pile des appels dépassée" dans la console à cause de cela, "$ (window) .off (" beforeunload ", hidePopup);"