Empêcher toute forme d'actualisation de page à l'aide de jQuery / Javascript

92

Une fois que l'utilisateur est sur ma page, je ne veux pas qu'il rafraîchisse la page.

  1. À tout moment, l'utilisateur F5appuie sur le bouton d'actualisation ou d'actualisation en haut. Il devrait recevoir une alerte disant

    Vous ne pouvez pas actualiser la page.

  2. De plus, si l'utilisateur ouvre un nouvel onglet et essaie d'accéder à la même URL dans l'onglet précédent, il devrait recevoir une alerte

    Vous ne pouvez pas ouvrir la même page dans 2 onglets

Quoi qu'il en soit, je peux le faire en utilisant JavaScript ou jQuery? Le premier point est vraiment important.

Pankaj
la source
Vous pouvez détecter en utilisant l'API Broadcast Channel ( developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API ) et envoyer des msg pour communiquer entre les onglets. AINSI, en utilisant cela, vous pouvez détecter plusieurs onglets avec la même URL et bloquer les autres onglets.
aXuser264 le

Réponses:

191

# 1 peut être implémenté via window.onbeforeunload.

Par exemple:

<script type="text/javascript">
    window.onbeforeunload = function() {
        return "Dude, are you sure you want to leave? Think of the kittens!";
    }
</script>

L'utilisateur sera invité avec le message et aura la possibilité de rester sur la page ou de continuer son chemin. Cela devient de plus en plus courant. Stack Overflow le fait si vous essayez de vous éloigner d'une page pendant que vous tapez un message. Vous ne pouvez pas complètement empêcher l'utilisateur de recharger, mais vous pouvez le rendre vraiment effrayant s'ils le font.

Le n ° 2 est plus ou moins impossible. Même si vous suiviez les sessions et les connexions des utilisateurs, vous ne pourrez toujours pas garantir que vous détectiez correctement un deuxième onglet. Par exemple, j'ai peut-être une fenêtre ouverte, puis fermez-la. J'ouvre maintenant une nouvelle fenêtre. Vous détecterez probablement cela comme un deuxième onglet, même si j'ai déjà fermé le premier. Désormais, votre utilisateur ne peut pas accéder à la première fenêtre car il l'a fermée, et il ne peut pas accéder à la deuxième fenêtre car vous le refusez.

En fait, le système en ligne de ma banque fait de son mieux pour faire # 2, et la situation décrite ci-dessus se produit tout le temps. Je dois généralement attendre que la session côté serveur expire avant de pouvoir utiliser à nouveau le système bancaire.

Seth
la source
1
Notez simplement que l'événement onbeforeunload n'est pas disponible dans les versions du navigateur Opera.
WillyCornbread
1
Existe-t-il un moyen de faire quelque chose si l'utilisateur choisit de rester sur la page.
riship89
5
J'ai fait l'affaire pour moi, même si vous devriez utiliser window.addEventListener (voir developer.mozilla.org/en-US/docs/Web/Events/beforeunload ) à la place, pour la compatibilité entre navigateurs et pour éviter les problèmes de bibliothèque.
Julien Bérubé
Je sais que cette question est ancienne mais, s'ils voulaient vraiment empêcher plusieurs sessions, pourraient-ils utiliser WebSockets?
Meghan
1
@Sean - Ouais ... si vous vouliez vraiment empêcher plusieurs sessions. Un WebSocket peut effectuer une communication bidirectionnelle avec état. Le client ne va probablement pas devenir soudainement quelqu'un d'autre pendant que le WebSocket est connecté, vous devriez donc être en mesure d'attribuer un jeton à cet utilisateur et de l'effacer une fois le socket fermé. Mais, c'est un piratage autour du comportement attendu de l'agent utilisateur, donc c'est probablement une mauvaise UX. Je peux penser à très peu de cas où quelque chose comme ça serait approprié (peut-être un jeu en ligne - pour empêcher quelqu'un de se connecter en tant que deux griffes de la mort de niveau 37 ...).
Seth
35

Vous ne pouvez pas empêcher l'utilisateur d'actualiser, et vous ne devriez pas vraiment essayer. Vous devriez revenir sur les raisons pour lesquelles vous avez besoin de cette solution, quel est le problème principal ici ?. Commencez par là et trouvez une autre façon de résoudre le problème. Peut-être avez-vous expliqué pourquoi vous pensez que vous devez le faire, cela aiderait à trouver une telle solution.

Briser les fonctionnalités fondamentales du navigateur n'est jamais une bonne idée, plus de 99,999999999% de l'Internet fonctionne et se rafraîchit avec F5, c'est une attente de l'utilisateur, une que vous ne devriez pas casser.

Nick Craver
la source
Le problème est que la page est une application siebel. et lorsqu'un utilisateur se trouve dans une session et frappe l'actualisation, une nouvelle session est créée et l'application se bloque. j'ai donc besoin que l'utilisateur ne puisse pas actualiser.
pankaj
20
@pankaj - Cela devrait être corrigé sur le site de l'application, et les cookies par exemple pour que l'utilisateur partage la session entre les onglets.
Nick Craver
9
Je ne sais pas d'où vous venez d'ici. D'innombrables sites sur Internet empêchent l'actualisation du navigateur si vous avez un formulaire sale, vous alertant sur le fait que vous risquez de perdre vos modifications. Je ne sais pas pourquoi cela «brise les fonctionnalités fondamentales du navigateur».
Siraris
1
@Siraris: Exactement. De plus, je crée une application privée que l'utilisateur est censé pouvoir utiliser même s'il n'est pas dans son réseau privé. Je stocke donc tout dans le stockage du navigateur pour une utilisation hors ligne, mais s'il recharge la page, toute l'application est partie. Ce n'est peut-être pas très «habituel», mais dans ce monde informatique moderne, cela le deviendra de plus en plus.
cslotty
16

Bien que ce ne soit pas une bonne idée de désactiver la clé F5, vous pouvez le faire dans JQuery comme ci-dessous.

<script type="text/javascript">
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };

$(document).ready(function(){
     $(document).on("keydown", disableF5);
});
</script>

J'espère que cela aidera!

Nilesh
la source
27
Qu'en est-il d'OSX, où est CMD + R? Ou mobile où il y a un bouton sur lequel appuyer? Je ne vois pas cela comme une solution
ItalyPaleAle
14

À l'époque de CGI, nous avions de nombreuses formes qui déclenchaient diverses actions backend. Tels que les notifications de texte aux groupes, les travaux d'impression, l'agriculture de données, etc.

Si l'utilisateur était sur une page qui disait "Veuillez patienter ... Exécution d'un travail ÉNORME qui pourrait prendre un certain temps.". Ils étaient plus susceptibles de frapper REFRESH et ce serait MAUVAIS!

POURQUOI? Parce que cela déclencherait des travaux plus lents et finirait par enliser le tout.

La solution? Permettez-leur de faire leur forme. Lorsqu'ils soumettent leur formulaire ... Commencez votre travail et dirigez-les vers une autre page qui leur dit d'attendre.

Où la page au milieu contenait en fait les données de formulaire nécessaires pour démarrer le travail. La page WAIT contient cependant une destruction de l'historique javascript. Ainsi, ils peuvent RELOAD cette page d'attente tout ce qu'ils veulent et cela ne déclenchera jamais le démarrage du travail d'origine en arrière-plan car cette page WAIT ne contient que les données de formulaire nécessaires pour WAIT lui-même.

J'espère que cela a du sens.

La fonction de destruction de l'historique les a également empêchés de cliquer sur RETOUR, puis de se rafraîchir.

Il était très transparent et fonctionnait très bien pendant BEAUCOUP D'ANNÉES jusqu'à ce que l'organisation à but non lucratif soit dissoute.

Exemple: ENTRÉE DE FORMULAIRE - Collectez toutes leurs informations et une fois soumises, cela déclenche votre travail de backend.

RÉPONSE à partir de l'entrée de formulaire - Renvoie du code HTML qui effectue une redirection vers votre page d'attente statique et / ou POST / GET vers un autre formulaire (la page WAIT).

WAIT PAGE - Ne contient que les données FORM liées à la page d'attente ainsi que du javascript pour détruire l'historique le plus récent. Comme (-1 OU -2) pour détruire uniquement les pages les plus récentes, mais leur permet toujours de revenir à leur page d'entrée FORM originale.

Une fois qu'ils sont sur votre page WAIT, ils peuvent cliquer sur REFRESH autant qu'ils le souhaitent et cela ne créera jamais le travail FORM d'origine sur le backend. Au lieu de cela, votre page WAIT devrait inclure une actualisation chronométrée META elle-même afin qu'elle puisse toujours vérifier l'état de leur travail. Lorsque leur travail est terminé, ils sont redirigés de la page d'attente vers l'endroit où vous le souhaitez.

S'ils le font manuellement REFRESH ... Ils ajoutent simplement une vérification supplémentaire de leur statut de travail là-dedans.

J'espère que cela pourra aider. Bonne chance.

Todd
la source
2
Vous n'avez pas obtenu suffisamment de crédit pour cette réponse étonnante et informative. Je vous remercie!!
ShiningLight
2

Le nombre (2) est possible en utilisant une implémentation de socket (comme websocket, socket.io, etc.) avec un battement de cœur personnalisé pour chaque session dans laquelle l'utilisateur est engagé. Si un utilisateur tente d'ouvrir une autre fenêtre, vous avez une vérification du gestionnaire javascript avec le serveur si tout va bien, puis répondez avec un message d'erreur.

Cependant, une meilleure solution est de synchroniser les deux sessions si possible comme dans Google Docs.

seo
la source
2

Le problème n ° 2 peut maintenant être résolu à l'aide de BroadcastAPI .

Pour le moment, il n'est disponible que dans Chrome, Firefox et Opera.

var bc = new BroadcastChannel('test_channel');

bc.onmessage = function (ev) { 
    if(ev.data && ev.data.url===window.location.href){
       alert('You cannot open the same page in 2 tabs');
    }
}

bc.postMessage(window.location.href);
RockLegend
la source