Is er een manier om te detecteren of een browservenster momenteel niet actief is?

Ik heb JavaScript dat regelmatig activiteiten uitvoert. Wanneer de gebruiker niet naar de site kijkt (d.w.z. het venster of tabblad heeft geen focus), zou het leuk zijn om niet te starten.

Is er een manier om dit te doen met JavaScript?

Mijn referentiepunt: Gmail Chat speelt een geluid af als het venster dat je gebruikt niet actief is.


Antwoord 1, autoriteit 100%

Sinds het schrijven van dit antwoord heeft een nieuwe specificatie de status aanbevelingbereikt dankzij de W3C. De Page Visibility API(op MDN) stelt ons nu in staat om nauwkeuriger te detecteren wanneer een pagina voor de gebruiker verborgen is.

document.addEventListener("visibilitychange", onchange);

Huidige browserondersteuning:

  • Chrome 13+
  • Internet Explorer 10+
  • Firefox 10+
  • Opera 12.10+ [notities lezen]

De volgende code valt terug op de minder betrouwbare vervaging/focus-methode in incompatibele browsers:

(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"});
})();

onfocusinen onfocusoutzijn vereist voor IE 9 en lager, terwijl alle andere gebruik maken van onfocusen onblur, behalve voor iOS, dat onpageshowen onpagehide.


Antwoord 2, autoriteit 18%

Ik zou jQuery gebruiken, want dan hoef je alleen maar dit te doen:

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

Of in ieder geval werkte het voor mij.


Antwoord 3, autoriteit 8%

Er zijn 3 typische methoden die worden gebruikt om te bepalen of de gebruiker de HTML-pagina kan zien, maar geen van hen werkt perfect:

  • De W3C Page Visibility APIzou dit moeten doen (ondersteund sinds : Firefox 10, MSIE 10, Chrome 13). Deze API roept echter alleen gebeurtenissen op wanneer het browsertabblad volledig wordt overschreven (bijvoorbeeld wanneer de gebruiker van het ene naar het andere tabblad gaat). De API roept geen gebeurtenissen op wanneer de zichtbaarheid niet met 100% nauwkeurigheid kan worden bepaald (bijv. Alt+Tab om naar een andere applicatie te schakelen).

  • Het gebruik van op focus/blur gebaseerde methodengeeft je veel valse positieven. Als de gebruiker bijvoorbeeld een kleiner venster boven op het browservenster weergeeft, verliest het browservenster de focus (onblurverhoogd), maar kan de gebruiker het nog steeds zien (het moet dus nog opfrissen). Zie ook http://javascript.info/tutorial/focus

  • Vertrouwen op gebruikersactiviteit(muisbeweging, klikken, getypte toets) levert ook veel valse positieven op. Denk aan hetzelfde geval als hierboven, of aan een gebruiker die een video bekijkt.

Om het hierboven beschreven onvolmaakte gedrag te verbeteren, gebruik ik een combinatie van de 3 methoden: W3C Visibility API, vervolgens focus/blur en gebruikersactiviteitsmethoden om het aantal fout-positieven te verminderen. Hiermee kunnen de volgende gebeurtenissen worden beheerd:

  • Browsertabblad wijzigen in een ander (100% nauwkeurigheid, dankzij de W3C Page Visibility API)
  • Pagina mogelijk verborgen door een ander venster, bijv. vanwege Alt+Tab (waarschijnlijk = niet 100% nauwkeurig)
  • Aandacht van de gebruiker mogelijk niet gericht op de HTML-pagina (waarschijnlijk = niet 100% nauwkeurig)

Dit is hoe het werkt: wanneer het document de focus verliest, wordt de gebruikersactiviteit (zoals muisbewegingen) op het document gecontroleerd om te bepalen of het venster zichtbaar is of niet. De kans op paginazichtbaarheid is omgekeerd evenredig met het tijdstip van de laatste gebruikersactiviteit op de pagina: als de gebruiker gedurende lange tijd geen activiteit op het document verricht, is de pagina hoogstwaarschijnlijk niet zichtbaar. De onderstaande code bootst de W3C Page Visibility API na: deze gedraagt ​​zich op dezelfde manier, maar heeft een klein percentage valse positieven. Het heeft het voordeel dat het multibrowser is (getest op Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9).

  <div id="x"></div>
  <script>
  /**
  Registreert de handler bij de gebeurtenis voor het gegeven object.
  @param obj het object dat de gebeurtenis zal verhogen
  @param evTyp het gebeurtenistype: klik, toetsaanslag, mouseover, ...
  @param fn de event handler-functie
  @param isCapturing stelt de gebeurtenismodus in (true = capture-gebeurtenis, false = borrelende gebeurtenis)
  @return waar als de gebeurtenishandler correct is gekoppeld
  */
  functie addEvent(obj, evType, fn, isCapturing){
   if (isCapturing==null) isCapturing=false;
   if (obj.addEventListener){
    // Firefox
    obj.addEventListener(evType, fn, isCapturing);
    retourneer waar;
   } else if (obj.attachEvent){
    // MSI
    var r = obj.attachEvent('on'+evType, fn);
    retour r;
   } anders {
    onwaar retourneren;
   }
  }
  // registreer voor de mogelijke verandering van de zichtbaarheid van de pagina
  addEvent(document, "potentialvisilitychange", function(event) {
   document.getElementById("x").innerHTML+="potentialVisilityChange: potentialHidden="+document.potentialHidden+", document.potentiallyHiddenSince="+document.potentiallyHiddenSince+" s<br>";
  });
  // registreer bij de W3C Page Visibility API
  var verborgen=null;
  var zichtbaarheidChange=null;
  if (typedocument.mozHidden !== "undefined") {
   hidden="mozHidden";
   zichtbaarheidChange="mozvisibilitychange";
  } else if (typeof document.msHidden !== "undefined") {
   hidden="msHidden";
   zichtbaarheidChange="msvisibilitychange";
  } else if (typeof document.webkitHidden!=="undefined") {
   verborgen="webkitVerborgen";
   zichtbaarheidChange="webkitzichtbaarheidswijziging";
  } else if (typeof document.hidden !=="hidden") {
   verborgen = "verborgen";
   zichtbaarheidChange="zichtbaarheidsverandering";
  }
  if (verborgen!=null && zichtbaarheidChange!=null) {
   addEvent(document, visibilityChange, function(event) {
    document.getElementById("x").innerHTML+=visibilityChange+": "+hidden+"="+document[hidden]+"<br>";
   });
  }
  var potentialPageVisibility = {
   pageVisibilityChangeThreshold:3*3600, // in seconden
   init:functie() {
    functie setAsNotHidden() {
     var dispatchEventRequired=document.potentialHidden;
     document.potentialHidden=false;
     document.potentiallyHiddenSince=0; 
if (dispatcheventrequired) dispatchpagevisibilityChangeEvent ();
    }
    functie initpotentiaallyhyddendetection () {
     if (! hasfocuslocal) {
      // Het venster heeft niet de focus = & GT; Controleer op gebruikersactiviteit in het venster
      LastactionDate = Nieuwe datum ();
      if (timeouthandler! = null) {
       ClearTimeout (timeouthandler);
      }
      timeouthandler = settimeout (checkpagevisibiliteit, potentialpagevisbaarheid.pagevisibilityChangethReshold * 1000 + 100); // +100 MS om afrondingsproblemen onder Firefox te voorkomen
     }
    }
    Functie DispatchPageVisniftChangeEvent () {
     UnifiedvisilityChangeVentDispatchaldo = FALSE;
     Var EVT = document.createeEvent ("evenement");
     evt.initevent ("PotentialvisionChange", waar, waar);
     Document.DispatchEvent (EVT);
    }
    functie checkpagevisibility () {
     VAR-potentialhiddelijkheid = (Hasfocuslocal || Lastactiondate == NULL? 0: MATH.VLOOR ((nieuwe datum (). Get Time () - LastactionDate.Get Time ()) / 1000));
                    document.PotentialHiddensince = potentialhiddelijkheid;
     if (Potentialhiddeduration & GT; = PotentialPageVisbaarheid.PagevisniftChangethReshold & AMP; & AMP;! Document.Potentalhidden) {
      // Pagina Zichtbaarheid Verander Drempel Raiched = & GT; verhoog de even
      document.Potentalhidden = waar;
      DispatchPageVisNibilChangeEvent ();
     }
    }
    Var LastactionDate = NULL;
    var hasfocuslocal = true;
    var HASMOUSEOVER = TRUE;
    document.Potentalhidden = false;
    document.PotentialHiddensince = 0;
    var timeouthandler = null;
    AddEvent (document, "pagina's, functie (evenement) {
     document.getelementByID ("x"). Innerhtml + = "Pageshow / doc: & lt; br & gt;";
    });
    AddEvent (document, "Pagehide", functie (evenement) {
     document.getelementByID ("x"). Innerhtml + = "Pagehide / DOC: & LT; BR & GT;";
    });
    AddEvent (venster, "Pagina's hoeft", functie (evenement) {
     Document.getelementByID ("x"). Innerhtml + = "Pageshow / Win: & LT; BR & GT;"; // verhoogd wanneer de pagina eerst wordt weergegeven
    });
    AddEvent (venster, "Pagehide", functie (evenement) {
     document.getelementByID ("x"). Innerhtml + = "Pagehide / Win: & LT; BR & GT;"; // niet verhoogd
    });
    AddEvent (document, "Mousemove", functie (evenement) {
     LastactionDate = Nieuwe datum ();
    });
    AddEvent (document, "mouseover", functie (evenement) {
     HASMOUSEOVER = TRUE;
     setasnothidden ();
    });
    AddEvent (document, "muisout", functie (evenement) {
     HASMOUSEOVER = FALSE;
     initpotentialhiddendetection ();
    });
    AddEvent (venster, "Blur", functie (evenement) {
     hasfocuslocal = false;
     initpotentialhiddendetection ();
    });
    AddEvent (venster, "Focus", functie (evenement) {
     hasfocuslocal = true;
     setasnothidden ();
    });
    setasnothidden ();
   }
  }
  Potentialpagevisibiliteit.pagevisibilityChangethReshold = 4; // 4 seconden voor testen
  potentialpagevisibility.init ();
  & LT; / script & GT;

Aangezien er momenteel geen werkende cross-browseroplossing zonder vals-positief is, moet u beter nadenken over het uitschakelen van periodieke activiteit op uw website.


Antwoord 4, Autoriteit 4%

gebruiken: Pagina Zichtbaarheid API

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

Kan ik gebruiken? http://caniuse.com/#Feat=pagevisibility


Antwoord 5, Autoriteit 4%

Er is een nette bibliotheek beschikbaar op GitHub:

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

Voorbeeld:

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

Ik heb versie 1.0.1 getest in alle browsers die ik heb en kan bevestigen dat het werkt met:

  • IE9, IE10
  • FF 26,0
  • Chrome 34.0

… en waarschijnlijk alle nieuwere versies.

Werkt niet volledig met:

  • IE8 – geef altijd aan dat tabblad/venster momenteel actief is (.now()retourneert altijd truevoor mij)

Antwoord 6, autoriteit 3%

Ik begon het antwoord op de communitywiki te gebruiken, maar realiseerde me dat het geen alt-tab-gebeurtenissen in Chrome detecteerde. Dit komt omdat het de eerste beschikbare gebeurtenisbron gebruikt, en in dit geval is het de paginazichtbaarheids-API, die in Chrome alt-tabbing niet lijkt te volgen.

Ik besloot het script een beetje aan te passen om allemogelijke gebeurtenissen voor paginafocuswijzigingen bij te houden. Hier is een functie die je kunt gebruiken:

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) {
        visible = !document.hidden;
        document.addEventListener('visibilitychange',
            function() {(document.hidden ? unfocused : focused)()});
    }
    if ('mozHidden' in document) {
        visible = !document.mozHidden;
        document.addEventListener('mozvisibilitychange',
            function() {(document.mozHidden ? unfocused : focused)()});
    }
    if ('webkitHidden' in document) {
        visible = !document.webkitHidden;
        document.addEventListener('webkitvisibilitychange',
            function() {(document.webkitHidden ? unfocused : focused)()});
    }
    if ('msHidden' in document) {
        visible = !document.msHidden;
        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;
};

Gebruik het als volgt:

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

Deze versie luistert naar allede verschillende zichtbaarheidsgebeurtenissen en activeert een callback als een van deze een wijziging veroorzaakt. De focuseden unfocusedhandlers zorgen ervoor dat de callback niet meerdere keren wordt aangeroepen als meerdere API’s dezelfde zichtbaarheidsverandering opvangen.


Antwoord 7, autoriteit 3%

Ik maak een Comet Chat voor mijn app en wanneer ik een bericht ontvang van een andere gebruiker, gebruik ik:

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

Antwoord 8

Dit is echt lastig. Er lijkt geen oplossing te zijn gezien de volgende vereisten.

  • De pagina bevat iframes waar je geen controle over hebt
  • U wilt de wijziging van de zichtbaarheidsstatus volgen, ongeacht de wijziging die wordt geactiveerd door een TAB-wijziging (ctrl+tab) of een vensterwijziging (alt+tab)

Dit gebeurt omdat:

  • De Zichtbaarheids-API van de pagina kan u op betrouwbare wijze informeren over een tabwijziging (zelfs met iframes), maar kan u niet vertellen wanneer de gebruiker van venster verandert.
  • Luisteren naar venstervervaging/focusgebeurtenissen kunnen alt+tabs en ctrl+tabs detecteren, zolang het iframe geen focus heeft.

Gezien deze beperkingen is het mogelijk om een ​​oplossing te implementeren die combineert
– De pagina Zichtbaarheid API
– venster vervagen/focus
– document.activeElement

Dat kan:

  • 1) ctrl+tab als bovenliggende pagina focus heeft: JA
  • 2) ctrl+tab als iframe focus heeft: JA
  • 3) alt+tab als bovenliggende pagina focus heeft: JA
  • 4) alt+tab als iframe focus heeft: NEE<– jammer

Als het iframe focus heeft, worden je vervagings-/focusgebeurtenissen helemaal niet aangeroepen en wordt de pagina Zichtbaarheids-API niet geactiveerd op alt+tab.

Ik bouwde voort op de oplossing van @AndyE en implementeerde deze (bijna goede) oplossing hier:
https://dl.dropboxusercontent.com/u/2683925/estante-components /visibility_test1.html
(sorry, ik had wat problemen met JSFiddle).

Dit is ook beschikbaar op Github: https://github.com/qmagico/estante-components

Dit werkt op chroom/chroom.
Het werkt op firefox, behalve dat het de iframe-inhoud niet laadt (enig idee waarom?)

Hoe dan ook, om het laatste probleem (4) op te lossen, kun je dat alleen doen door te luisteren naar onscherpte/focusgebeurtenissen op het iframe.
Als je enige controle hebt over de iframes, kun je de postMessage API gebruiken om dat te doen.

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

Ik heb dit nog niet met genoeg browsers getest.
Als je meer informatie kunt vinden over waar dit niet werkt, laat het me dan weten in de reacties hieronder.


Antwoord 9

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/


Antwoord 10

dit werkt voor mij op chrome 67, firefox 67,

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

Antwoord 11

dit werkte voor mij

document.addEventListener("visibilitychange", function() {
      document.title = document.hidden ? "I'm away" : "I'm here";
});

demo: https://iamsahilralkar.github.io/document-hidden-demo/


Antwoord 12

In HTML 5 zou je ook kunnen gebruiken:

  • onpageshow: Script dat moet worden uitgevoerd wanneer het venster zichtbaar wordt
  • onpagehide: Script dat moet worden uitgevoerd wanneer het venster is verborgen

Zie:


Antwoord 13

u kunt gebruiken:

(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);
})();

Antwoord 14

Een iets gecompliceerdere manier zou zijn om setInterval()te gebruiken om de muispositie te controleren en te vergelijken met de laatste controle. Als de muis binnen een bepaalde tijd niet is bewogen, is de gebruiker waarschijnlijk inactief.

Dit heeft als bijkomend voordeel dat het aangeeft of de gebruiker inactief is, in plaats van alleente controleren of het venster niet actief is.

Zoals veel mensen hebben opgemerkt, is dit niet altijd een goede manier om te controleren of de gebruiker of het browservenster inactief is, omdat de gebruiker misschien niet eens de muis gebruikt of een video bekijkt, of iets dergelijks. Ik suggereer slechts één mogelijke manier om te controleren op inactiviteit.


Antwoord 15

Dit is een bewerking van het antwoord van Andy E.

Dit zal een taak uitvoeren, b.v. ververs de pagina elke 30 seconden,
maar alleen als de pagina zichtbaar en gefocust is.

Als zichtbaarheid niet kan worden gedetecteerd, wordt alleen focus gebruikt.

Als de gebruiker de pagina focust, wordt deze onmiddellijk bijgewerkt

De pagina wordt pas 30 seconden na een ajax-oproep opnieuw bijgewerkt

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);
}

Antwoord 16

Voor een oplossing zonder jQuery, ga naar Visibility.jsdie informatie geeft over drie paginastatussen

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

en ook gemaksverpakkingen voor 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();
});

Er is ook een fallback voor oudere browsers (IE < 10; iOS < 7) beschikbaar


Antwoord 17

Dit werkt bij het wijzigen van tabbladen, vensters (Alt+Tab) of het maximaliseren van een ander programma vanaf de taakbalk:

var eventName;
var visible = true;
var propName = "hidden";
if (propName in document) eventName = "visibilitychange";
else if ((propName = "msHidden") in document) eventName = "msvisibilitychange";
else if ((propName = "mozHidden") in document) eventName = "mozvisibilitychange";
else if ((propName = "webkitHidden") in document) eventName = "webkitvisibilitychange";
if (eventName) document.addEventListener(eventName, handleChange);
if ("onfocusin" in document) document.onfocusin = document.onfocusout = handleChange; //IE 9
window.onpageshow = window.onpagehide = window.onfocus = window.onblur = handleChange;// Changing tab with alt+tab
// Initialize state if Page Visibility API is supported
if (document[propName] !== undefined) handleChange({ type: document[propName] ? "blur" : "focus" });
function handleChange(evt) {
  evt = evt || window.event;
  if (visible && (["blur", "focusout", "pagehide"].includes(evt.type) || (this && this[propName]))){
    visible = false;
    console.log("Out...")
  }
  else if (!visible && (["focus", "focusin", "pageshow"].includes(evt.type) || (this && !this[propName]))){
    visible = true;
    console.log("In...")
  }
}

Antwoord 18

Voor angular.js is hier een richtlijn (gebaseerd op het geaccepteerde antwoord) waarmee uw controller kan reageren op een verandering in zichtbaarheid:

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);
                    });
                }
            }
        }
    };
});

U kunt het gebruiken zoals dit voorbeeld: <div react-on-window-focus="refresh()">, waarbij refresh()is a Scope-functie in de reikwijdte van welke controller in het kader is.


Antwoord 19

Als u op vol bent browser blur :
Zoals ik merkte, als browser focus verliest Geen van de voorgestelde evenementen. Mijn idee is om op te tellen in een lus en reset de teller als een evenementbrand. Als de teller een limiet bereikt, doe ik een locatie. Href naar een andere pagina. Dit brandt ook als je werkt aan 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();

Dit is een concept die succesvol is getest op FF.


Antwoord 20

Het Chromium-team ontwikkelt momenteel de idle detectie api . Het is beschikbaar als een oorsprongsleiding sinds Chrome 88 , die hiervoor al de 2e oorsprongsproef is voorzien zijn van. Een eerdere oorsprongsrechting ging van Chrome 84 via Chrome 86.

Het kan ook worden ingeschakeld via een vlag:

Inschakelen via Chrome: // vlaggen

Experimenteer met de inactieve detectie-api lokaal, zonder een
Oorsprong Trieken, schakel de
#enable-experimental-web-platform-featuresvlag in
chroom: // vlaggen .

Een demo is hier te vinden:

https://idle-detection.glitch.mexme/

Er moet echter worden opgemerkt dat deze API Toestemming is gebaseerd (zoals het zou moeten zijn, anders zou dit kunnen worden misbruikt om het gedrag van een gebruiker te volgen!).


Antwoord 21

Hier is een solide, moderne oplossing. (Kort een zoet 👌🏽)

document.addEventListener("visibilitychange", () => {
  console.log( document.hasFocus() )
})

Hiermee wordt een luisteraar ingesteld om te trigger wanneer een zichtgelegenheidsgebeurtenis wordt afgevuurd die een focus of vervaging kan zijn.


Antwoord 22

I REREAD DE @ DANIEL-BUCKMASTER-versie
Ik heb de multiple poging niet gemaakt, maar de code lijkt me meer elegant …

// on-visibility-change.js v1.0.1, based on https://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active#38710376
function onVisibilityChange(callback) {
    let d = document;
    let visible = true;
    let prefix;
    if ('hidden' in d) {
        prefix = 'h';
    } else if ('webkitHidden' in d) {
        prefix = 'webkitH';
    } else if ('mozHidden' in d) {
        prefix = 'mozH';
    } else if ('msHidden' in d) {
        prefix = 'msH';
    } else if ('onfocusin' in d) { // ie 9 and lower
        d.onfocusin = focused;
        d.onfocusout = unfocused;
    } else { // others
        window.onpageshow = window.onfocus = focused;
        window.onpagehide = window.onblur = unfocused;
    };
    if (prefix) {
        visible = !d[prefix + 'idden'];
        d.addEventListener(prefix.substring(0, prefix.length - 1) + 'visibilitychange', function() {
            (d[prefix + 'idden'] ? unfocused : focused)();
        });
    };
    function focused() {
        if (!visible) {
            callback(visible = true);
        };
    };
    function unfocused() {
        if (visible) {
            callback(visible = false);
        };
    };
};

Other episodes