validar validacion formularios formulario enviar ejemplos con caracteristicas attribute antes javascript browser focus window

validacion - validar formulario javascript html5



¿Hay alguna forma de detectar si una ventana del navegador no está activa actualmente? (18)

Tengo JavaScript que está haciendo actividad periódicamente. Cuando el usuario no está mirando el sitio (es decir, la ventana o pestaña no tiene el foco), sería bueno no ejecutarlo.

¿Hay alguna manera de hacer esto usando JavaScript?

Mi punto de referencia: Gmail Chat reproduce un sonido si la ventana que está utilizando no está activa.


Comencé a usar la respuesta de la wiki de la comunidad, pero me di cuenta de que no estaba detectando eventos alt-tab en Chrome. Esto se debe a que utiliza el primer origen de eventos disponible y, en este caso, es la API de visibilidad de la página, que en Chrome parece no hacer un seguimiento de las tabulaciones alt.

Decidí modificar el script un poco para realizar un seguimiento de todos los eventos posibles para los cambios de enfoque de la página. Aquí hay una función que puedes dejar:

function onVisibilityChange(callback) { var visible = true; if (!callback) { throw new Error(''no callback given''); } function focused() { if (!visible) { callback(visible = true); } } function unfocused() { if (visible) { callback(visible = false); } } // Standards: if (''hidden'' in document) { document.addEventListener(''visibilitychange'', function() {(document.hidden ? unfocused : focused)()}); } if (''mozHidden'' in document) { document.addEventListener(''mozvisibilitychange'', function() {(document.mozHidden ? unfocused : focused)()}); } if (''webkitHidden'' in document) { document.addEventListener(''webkitvisibilitychange'', function() {(document.webkitHidden ? unfocused : focused)()}); } if (''msHidden'' in document) { document.addEventListener(''msvisibilitychange'', function() {(document.msHidden ? unfocused : focused)()}); } // IE 9 and lower: if (''onfocusin'' in document) { document.onfocusin = focused; document.onfocusout = unfocused; } // All others: window.onpageshow = window.onfocus = focused; window.onpagehide = window.onblur = unfocused; };

Úsalo así:

onVisibilityChange(function(visible) { console.log(''the page is now'', visible ? ''focused'' : ''unfocused''); });


Creo un Comet Chat para mi aplicación y cuando recibo un mensaje de otro usuario, uso:

if(new_message){ if(!document.hasFocus()){ audio.play(); document.title="Have new messages"; } else{ audio.stop(); document.title="Application Name"; } }


Desde que escribí originalmente esta respuesta, una nueva especificación ha alcanzado el estado de recomendación gracias al W3C. La API de visibilidad de la página (en MDN ) ahora nos permite detectar con mayor precisión cuándo una página está oculta para el usuario.

Soporte de navegador actual:

  • Chrome 13+
  • Internet Explorer 10+
  • Firefox 10+
  • Opera 12.10+ [ leer notas ]

El siguiente código hace uso de la API, recurriendo al método menos confiable de desenfoque / enfoque en navegadores incompatibles.

(function() { var hidden = "hidden"; // Standards: if (hidden in document) document.addEventListener("visibilitychange", onchange); else if ((hidden = "mozHidden") in document) document.addEventListener("mozvisibilitychange", onchange); else if ((hidden = "webkitHidden") in document) document.addEventListener("webkitvisibilitychange", onchange); else if ((hidden = "msHidden") in document) document.addEventListener("msvisibilitychange", onchange); // IE 9 and lower: else if ("onfocusin" in document) document.onfocusin = document.onfocusout = onchange; // All others: else window.onpageshow = window.onpagehide = window.onfocus = window.onblur = onchange; function onchange (evt) { var v = "visible", h = "hidden", evtMap = { focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h }; evt = evt || window.event; if (evt.type in evtMap) document.body.className = evtMap[evt.type]; else document.body.className = this[hidden] ? "hidden" : "visible"; } // set the initial state (but only if browser supports the Page Visibility API) if( document[hidden] !== undefined ) onchange({type: document[hidden] ? "blur" : "focus"}); })();

onfocusin y onfocusout son necesarios para IE 9 y onfocusout inferiores , mientras que todos los demás utilizan onfocus y onblur , excepto iOS, que usa onpageshow y onpagehide .



Esta es una adaptación de la respuesta de Andy E.

Esto hará una tarea, por ejemplo, actualizar la página cada 30 segundos, pero solo si la página está visible y enfocada.

Si no se puede detectar la visibilidad, solo se utilizará el enfoque.

Si el usuario enfoca la página, se actualizará inmediatamente.

La página no se actualizará de nuevo hasta 30 segundos después de cualquier llamada ajax

var windowFocused = true; var timeOut2 = null; $(function(){ $.ajaxSetup ({ cache: false }); $("#content").ajaxComplete(function(event,request, settings){ set_refresh_page(); // ajax call has just been made, so page doesn''t need updating again for 30 seconds }); // check visibility and focus of window, so as not to keep updating unnecessarily (function() { var hidden, change, vis = { hidden: "visibilitychange", mozHidden: "mozvisibilitychange", webkitHidden: "webkitvisibilitychange", msHidden: "msvisibilitychange", oHidden: "ovisibilitychange" /* not currently supported */ }; for (hidden in vis) { if (vis.hasOwnProperty(hidden) && hidden in document) { change = vis[hidden]; break; } } document.body.className="visible"; if (change){ // this will check the tab visibility instead of window focus document.addEventListener(change, onchange,false); } if(navigator.appName == "Microsoft Internet Explorer") window.onfocus = document.onfocusin = document.onfocusout = onchangeFocus else window.onfocus = window.onblur = onchangeFocus; function onchangeFocus(evt){ evt = evt || window.event; if (evt.type == "focus" || evt.type == "focusin"){ windowFocused=true; } else if (evt.type == "blur" || evt.type == "focusout"){ windowFocused=false; } if (evt.type == "focus"){ update_page(); // only update using window.onfocus, because document.onfocusin can trigger on every click } } function onchange () { document.body.className = this[hidden] ? "hidden" : "visible"; update_page(); } function update_page(){ if(windowFocused&&(document.body.className=="visible")){ set_refresh_page(1000); } } })(); set_refresh_page(); }) function get_date_time_string(){ var d = new Date(); var dT = []; dT.push(d.getDate()); dT.push(d.getMonth()) dT.push(d.getFullYear()); dT.push(d.getHours()); dT.push(d.getMinutes()); dT.push(d.getSeconds()); dT.push(d.getMilliseconds()); return dT.join(''_''); } function do_refresh_page(){ // do tasks here // e.g. some ajax call to update part of the page. // (date time parameter will probably force the server not to cache) // $.ajax({ // type: "POST", // url: "someUrl.php", // data: "t=" + get_date_time_string()+"&task=update", // success: function(html){ // $(''#content'').html(html); // } // }); } function set_refresh_page(interval){ interval = typeof interval !== ''undefined'' ? interval : 30000; // default time = 30 seconds if(timeOut2 != null) clearTimeout(timeOut2); timeOut2 = setTimeout(function(){ if((document.body.className=="visible")&&windowFocused){ do_refresh_page(); } set_refresh_page(); }, interval); }


Esto es realmente complicado. Parece que no hay solución teniendo en cuenta los siguientes requisitos.

  • La página incluye iframes sobre los que no tienes control.
  • Desea realizar un seguimiento del cambio del estado de visibilidad independientemente del cambio que se active mediante un cambio de TAB (ctrl + tab) o un cambio de ventana (alt + tab)

Esto sucede porque:

  • La API de Visibilidad de la página puede informarle de manera confiable sobre un cambio de pestaña (incluso con iframes), pero no puede decirle cuándo el usuario cambia de ventana.
  • La escucha de los eventos de desenfoque / enfoque de la ventana puede detectar alt + tabs y ctrl + tabs, siempre que el iframe no tenga foco.

Dadas estas restricciones, es posible implementar una solución que combine: la API de Visibilidad de la página - desenfoque / enfoque de la ventana - document.activeElement

Eso es capaz de:

  • 1) ctrl + tab cuando la página principal tiene el foco: SÍ
  • 2) ctrl + tab cuando iframe tiene el foco: SI
  • 3) alt + tab cuando la página principal tiene el foco: SÍ
  • 4) alt + tab cuando iframe tiene el foco: NO <- bummer

Cuando el iframe tiene el foco, los eventos de desenfoque / enfoque no se invocan en absoluto, y la API de Visibilidad de la página no se activa en alt + tab.

Construí sobre la solución de @ AndyE e implementé esta (casi buena) solución aquí: https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test1.html (lo siento, tuve algunos problemas con JSFiddle).

Esto también está disponible en Github: https://github.com/qmagico/estante-components

Esto funciona en cromo / cromo. Funciona en Firefox, excepto que no carga los contenidos de iframe (¿alguna idea de por qué?)

De todos modos, para resolver el último problema (4), la única manera de hacerlo es escuchar los eventos de desenfoque / enfoque en el iframe. Si tiene algún control sobre los iframes, puede usar la API postMessage para hacerlo.

https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test2.html

Todavía no he probado esto con suficientes navegadores. Si puede encontrar más información sobre dónde esto no funciona, hágamelo saber en los comentarios a continuación.


Hay 3 métodos típicos utilizados para determinar si el usuario puede ver la página HTML, sin embargo, ninguno de ellos funciona perfectamente:

  • Se supone que la API de visibilidad de la página W3C debe hacer esto (compatible desde: Firefox 10, MSIE 10, Chrome 13). Sin embargo, esta API solo genera eventos cuando la pestaña del navegador está anulada completamente (por ejemplo, cuando el usuario cambia de una pestaña a otra). La API no genera eventos cuando la visibilidad no se puede determinar con el 100% de precisión (por ejemplo, Alt + Tab para cambiar a otra aplicación).

  • El uso de métodos basados ​​en enfoque / desenfoque le da muchos falsos positivos. Por ejemplo, si el usuario muestra una ventana más pequeña en la parte superior de la ventana del navegador, la ventana del navegador perderá el enfoque (se onblur ), pero el usuario aún podrá verlo (por lo tanto, todavía debe actualizarse). Véase también http://javascript.info/tutorial/focus

  • Confiar en la actividad del usuario (movimiento del mouse, clics, teclas tecleadas) también le da una gran cantidad de falsos positivos. Piense en el mismo caso que el anterior, o un usuario que mira un video.

Con el fin de mejorar los comportamientos imperfectos descritos anteriormente, utilizo una combinación de los 3 métodos: API de Visibilidad W3C, luego enfoque / desenfoque y métodos de actividad del usuario para reducir la tasa de falsos positivos. Esto permite gestionar los siguientes eventos:

  • Cambiar la pestaña del navegador a otra (100% de precisión, gracias a la API de Visibilidad de la página W3C)
  • Página potencialmente oculta por otra ventana, por ejemplo, debido a Alt + Tab (probabilístico = no es 100% exacto)
  • La atención del usuario potencialmente no está enfocada en la página HTML (probabilística = no es 100% precisa)

Así es como funciona: cuando el documento pierde el foco, se supervisa la actividad del usuario (como el movimiento del mouse) en el documento para determinar si la ventana es visible o no. La probabilidad de visibilidad de la página es inversamente proporcional al tiempo de la última actividad del usuario en la página: si el usuario no realiza ninguna actividad en el documento durante mucho tiempo, lo más probable es que la página no sea visible. El siguiente código imita la API de visibilidad de la página W3C: se comporta de la misma manera pero tiene una pequeña tasa de falsos positivos. Tiene la ventaja de ser multibrowser (probado en Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9).

<div id="x"></div> <script> /** Registers the handler to the event for the given object. @param obj the object which will raise the event @param evType the event type: click, keypress, mouseover, ... @param fn the event handler function @param isCapturing set the event mode (true = capturing event, false = bubbling event) @return true if the event handler has been attached correctly */ function addEvent(obj, evType, fn, isCapturing){ if (isCapturing==null) isCapturing=false; if (obj.addEventListener){ // Firefox obj.addEventListener(evType, fn, isCapturing); return true; } else if (obj.attachEvent){ // MSIE var r = obj.attachEvent(''on''+evType, fn); return r; } else { return false; } } // register to the potential page visibility change addEvent(document, "potentialvisilitychange", function(event) { document.getElementById("x").innerHTML+="potentialVisilityChange: potentialHidden="+document.potentialHidden+", document.potentiallyHiddenSince="+document.potentiallyHiddenSince+" s<br>"; }); // register to the W3C Page Visibility API var hidden=null; var visibilityChange=null; if (typeof document.mozHidden !== "undefined") { hidden="mozHidden"; visibilityChange="mozvisibilitychange"; } else if (typeof document.msHidden !== "undefined") { hidden="msHidden"; visibilityChange="msvisibilitychange"; } else if (typeof document.webkitHidden!=="undefined") { hidden="webkitHidden"; visibilityChange="webkitvisibilitychange"; } else if (typeof document.hidden !=="hidden") { hidden="hidden"; visibilityChange="visibilitychange"; } if (hidden!=null && visibilityChange!=null) { addEvent(document, visibilityChange, function(event) { document.getElementById("x").innerHTML+=visibilityChange+": "+hidden+"="+document[hidden]+"<br>"; }); } var potentialPageVisibility = { pageVisibilityChangeThreshold:3*3600, // in seconds init:function() { function setAsNotHidden() { var dispatchEventRequired=document.potentialHidden; document.potentialHidden=false; document.potentiallyHiddenSince=0; if (dispatchEventRequired) dispatchPageVisibilityChangeEvent(); } function initPotentiallyHiddenDetection() { if (!hasFocusLocal) { // the window does not has the focus => check for user activity in the window lastActionDate=new Date(); if (timeoutHandler!=null) { clearTimeout(timeoutHandler); } timeoutHandler = setTimeout(checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold*1000+100); // +100 ms to avoid rounding issues under Firefox } } function dispatchPageVisibilityChangeEvent() { unifiedVisilityChangeEventDispatchAllowed=false; var evt = document.createEvent("Event"); evt.initEvent("potentialvisilitychange", true, true); document.dispatchEvent(evt); } function checkPageVisibility() { var potentialHiddenDuration=(hasFocusLocal || lastActionDate==null?0:Math.floor((new Date().getTime()-lastActionDate.getTime())/1000)); document.potentiallyHiddenSince=potentialHiddenDuration; if (potentialHiddenDuration>=potentialPageVisibility.pageVisibilityChangeThreshold && !document.potentialHidden) { // page visibility change threshold raiched => raise the even document.potentialHidden=true; dispatchPageVisibilityChangeEvent(); } } var lastActionDate=null; var hasFocusLocal=true; var hasMouseOver=true; document.potentialHidden=false; document.potentiallyHiddenSince=0; var timeoutHandler = null; addEvent(document, "pageshow", function(event) { document.getElementById("x").innerHTML+="pageshow/doc:<br>"; }); addEvent(document, "pagehide", function(event) { document.getElementById("x").innerHTML+="pagehide/doc:<br>"; }); addEvent(window, "pageshow", function(event) { document.getElementById("x").innerHTML+="pageshow/win:<br>"; // raised when the page first shows }); addEvent(window, "pagehide", function(event) { document.getElementById("x").innerHTML+="pagehide/win:<br>"; // not raised }); addEvent(document, "mousemove", function(event) { lastActionDate=new Date(); }); addEvent(document, "mouseover", function(event) { hasMouseOver=true; setAsNotHidden(); }); addEvent(document, "mouseout", function(event) { hasMouseOver=false; initPotentiallyHiddenDetection(); }); addEvent(window, "blur", function(event) { hasFocusLocal=false; initPotentiallyHiddenDetection(); }); addEvent(window, "focus", function(event) { hasFocusLocal=true; setAsNotHidden(); }); setAsNotHidden(); } } potentialPageVisibility.pageVisibilityChangeThreshold=4; // 4 seconds for testing potentialPageVisibility.init(); </script>

Debido a que actualmente no existe una solución de navegador cruzado que funcione sin un falso positivo, debe pensar dos veces antes de desactivar la actividad periódica en su sitio web.


Hay una biblioteca ordenada disponible en GitHub:

https://github.com/serkanyersen/ifvisible.js

Ejemplo:

// If page is visible right now if( ifvisible.now() ){ // Display pop-up openPopUp(); }

He probado la versión 1.0.1 en todos los navegadores que tengo y puedo confirmar que funciona con:

  • IE9, IE10
  • FF 26.0
  • Cromo 34.0

... y probablemente todas las nuevas versiones.

No funciona completamente con:

  • IE8: siempre indica que la pestaña / ventana está activa actualmente ( .now() siempre devuelve true para mí)

Para angular.js, aquí hay una directiva (basada en la respuesta aceptada) que le permitirá a su controlador reaccionar ante un cambio en la visibilidad:

myApp.directive(''reactOnWindowFocus'', function($parse) { return { restrict: "A", link: function(scope, element, attrs) { var hidden = "hidden"; var currentlyVisible = true; var functionOrExpression = $parse(attrs.reactOnWindowFocus); // Standards: if (hidden in document) document.addEventListener("visibilitychange", onchange); else if ((hidden = "mozHidden") in document) document.addEventListener("mozvisibilitychange", onchange); else if ((hidden = "webkitHidden") in document) document.addEventListener("webkitvisibilitychange", onchange); else if ((hidden = "msHidden") in document) document.addEventListener("msvisibilitychange", onchange); else if ("onfocusin" in document) { // IE 9 and lower: document.onfocusin = onshow; document.onfocusout = onhide; } else { // All others: window.onpageshow = window.onfocus = onshow; window.onpagehide = window.onblur = onhide; } function onchange (evt) { //occurs both on leaving and on returning currentlyVisible = !currentlyVisible; doSomethingIfAppropriate(); } function onshow(evt) { //for older browsers currentlyVisible = true; doSomethingIfAppropriate(); } function onhide(evt) { //for older browsers currentlyVisible = false; doSomethingIfAppropriate(); } function doSomethingIfAppropriate() { if (currentlyVisible) { //trigger angular digest cycle in this scope scope.$apply(function() { functionOrExpression(scope); }); } } } }; });

Puede usarlo como este ejemplo: <div react-on-window-focus="refresh()"> , donde refresh() es una función de alcance en el alcance de cualquier controlador que esté dentro del alcance.


Para una solución sin jQuery, visite Visibility.js que proporciona información sobre tres estados de página

visible ... page is visible hidden ... page is not visible prerender ... page is being prerendered by the browser

y también envoltorios de conveniencia para setInterval

/* Perform action every second if visible */ Visibility.every(1000, function () { action(); }); /* Perform action every second if visible, every 60 sec if not visible */ Visibility.every(1000, 60*1000, function () { action(); });

También está disponible un respaldo para navegadores antiguos (IE <10; iOS <7)


Puedes usar:

(function () { var requiredResolution = 10; // ms var checkInterval = 1000; // ms var tolerance = 20; // percent var counter = 0; var expected = checkInterval / requiredResolution; //console.log(''expected:'', expected); window.setInterval(function () { counter++; }, requiredResolution); window.setInterval(function () { var deviation = 100 * Math.abs(1 - counter / expected); // console.log(''is:'', counter, ''(off by'', deviation , ''%)''); if (deviation > tolerance) { console.warn(''Timer resolution not sufficient!''); } counter = 0; }, checkInterval); })();


Sólo quería añadir: La pregunta no está clara por escrito. "Cuando el usuario no está mirando el sitio (es decir, la ventana o pestaña no tiene el foco) ..."

Puedo mirar un sitio cuando no está enfocado. La mayoría de los sistemas de escritorio pueden mostrar ventanas en paralelo :)

Es por eso que la API de visibilidad de la página es probablemente la respuesta correcta, ya que impide la actualización del sitio cuando el "usuario no puede ver las actualizaciones", que puede ser muy diferente de "la pestaña no tiene el foco".


Si desea actuar sobre todo el desenfoque del navegador : como comenté, si el navegador pierde el foco, no se activará ninguno de los eventos sugeridos. Mi idea es contar en un bucle y reiniciar el contador si se dispara un evento. Si el contador alcanza un límite, hago un location.href a otra página. Esto también se dispara si trabajas en dev-tools.

var iput=document.getElementById("hiddenInput"); ,count=1 ; function check(){ count++; if(count%2===0){ iput.focus(); } else{ iput.blur(); } iput.value=count; if(count>3){ location.href="http://Nirwana.com"; } setTimeout(function(){check()},1000); } iput.onblur=function(){count=1} iput.onfocus=function(){count=1} check();

Este es un borrador probado con éxito en FF.


Una forma un poco más complicada sería usar setInterval() para verificar la posición del mouse y comparar con la última revisión. Si el mouse no se ha movido en un tiempo determinado, el usuario probablemente esté inactivo.

Esto tiene la ventaja adicional de saber si el usuario está inactivo, en lugar de solo verificar si la ventana no está activa.

Como muchas personas han señalado, esta no siempre es una buena manera de verificar si el usuario o la ventana del navegador están inactivos, ya que el usuario puede que ni siquiera esté usando el mouse o esté viendo un video o algo similar. Solo estoy sugiriendo una forma posible de verificar la inactividad.


Yo usaría jQuery porque entonces todo lo que tienes que hacer es esto:

$(window).blur(function(){ //your code here }); $(window).focus(function(){ //your code });

O al menos funcionó para mí.


esto funciona para mí en Chrome 67, Firefox 67,

if(!document.hasFocus()) { // do stuff }


Usando: MDN

document.addEventListener( ''visibilitychange'' , function() { if (document.hidden) { console.log(''bye''); } else { console.log(''well back''); } }, false );

Puedo usar ? http://caniuse.com/#feat=pagevisibility


var visibilityChange = (function (window) { var inView = false; return function (fn) { window.onfocus = window.onblur = window.onpageshow = window.onpagehide = function (e) { if ({focus:1, pageshow:1}[e.type]) { if (inView) return; fn("visible"); inView = true; } else if (inView) { fn("hidden"); inView = false; } }; }; }(this)); visibilityChange(function (state) { console.log(state); });

http://jsfiddle.net/ARTsinn/JTxQY/