क्या यह पता लगाने का एक तरीका है कि क्या ब्राउज़र विंडो वर्तमान में सक्रिय नहीं है?


585

मेरे पास जावास्क्रिप्ट है जो समय-समय पर गतिविधि कर रहा है। जब उपयोगकर्ता साइट को नहीं देख रहा है (यानी, विंडो या टैब में फोकस नहीं है), तो इसे न चलाना अच्छा होगा।

क्या जावास्क्रिप्ट का उपयोग करने का एक तरीका है?

मेरा संदर्भ बिंदु: यदि आप जिस विंडो का उपयोग कर रहे हैं वह जीमेल चैट सक्रिय नहीं है।


8
उन लोगों के लिए जो नीचे दिए गए जवाबों से संतुष्ट नहीं हैं, requestAnimationFrameएपीआई की जांच करें या आधुनिक सुविधा का उपयोग करें, जब खिड़की दिखाई न देने पर setTimeout/ आवृत्ति setIntervalकम हो जाती है (उदाहरण के लिए क्रोम में सेकंड)।
रॉब डब्ल्यू

2
document.body.onblur = function (e) {कंसोल.लॉग ('लामा');} गैर केंद्रित तत्वों के लिए काम किया।
WhyMe

2
क्रॉस-ब्राउज़र संगत समाधान के लिए इस उत्तर को देखें जो W3C पृष्ठ दृश्यता API का उपयोग करता है, जो उन ब्राउज़रों में वापस blur/ पर गिरता focusहै जो इसका समर्थन नहीं करते हैं।
मैथियास ब्यनेंस

2
नीचे दिए गए 80% उत्तर इस प्रश्न के उत्तर नहीं हैं । प्रश्न वर्तमान में सक्रिय नहीं होने के बारे में पूछता है, लेकिन नीचे दिए गए उत्तर के बारे में नहीं दिखाई देते हैं जो इस प्रश्न का उत्तर नहीं है। उन्हें यकीनन "एक उत्तर नहीं" के रूप में चिह्नित किया जाना चाहिए
gman

जवाबों:


691

मूल रूप से यह उत्तर लिखने के बाद, एक नया विनिर्देशन पहुंच गया है W3C के लिए सिफारिश की स्थिति । पृष्ठ दृश्यता API (पर MDN ) अब हमें और अधिक सही पता लगाने के लिए जब एक पृष्ठ उपयोगकर्ता के लिए छिपा हुआ है की अनुमति देता है।

document.addEventListener("visibilitychange", onchange);

वर्तमान ब्राउज़र समर्थन:

  • क्रोम 13+
  • इंटरनेट एक्सप्लोरर 10+
  • फ़ायरफ़ॉक्स 10+
  • ओपेरा 12.10+ [ नोट्स पढ़ें ]

निम्न कोड असंगत ब्राउज़रों में कम विश्वसनीय ब्लर / फ़ोकस विधि पर वापस आता है:

(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और आईई 9 और उससे कम के लिए आवश्यकonfocusout हैं , जबकि अन्य सभी उपयोग करते हैं और , आईओएस को छोड़कर, जो उपयोग करता है और ।onfocusonbluronpageshowonpagehide


1
@ घंटी: आईई को प्रचार करना चाहिए focusinऔर focusoutआईफ्रेम से ऊपरी खिड़की तक। नए ब्राउज़रों के लिए, आपको बस प्रत्येक iframe की ऑब्जेक्ट पर focusऔर blurईवेंट को हैंडल करना होगा window। आपको मेरे द्वारा जोड़े गए अद्यतन कोड का उपयोग करना चाहिए जो कम से कम उन मामलों को नए ब्राउज़रों में शामिल करेगा।
एंडी ई

3
@JulienKronegg: यही कारण है कि मेरे जवाब में विशेष रूप से पेज विजिबिलिटी एपीआई का उल्लेख है, जो मूल रूप से मेरा उत्तर लिखने के बाद काम करने की स्थिति में प्रवेश करता है। फ़ोकस / ब्लर विधियाँ पुराने ब्राउज़रों के लिए सीमित कार्यक्षमता प्रदान करती हैं। आपके जवाब के रूप में अन्य घटनाओं के लिए बाध्य, इस से अधिक एक महान सौदा कवर नहीं करता है और व्यवहार संबंधी मतभेदों के जोखिम में अधिक होता है (जैसे कि आईई जब माउस को फायरिंग नहीं करता है तो कर्सर के नीचे पॉप अप होता है)। मेरा सुझाव है कि उपयोगकर्ता को इंगित करने वाले संदेश या आइकन को प्रदर्शित करने के लिए एक अधिक उपयुक्त कार्रवाई होगी कि पृष्ठ निष्क्रियता के कारण अपडेट लगातार कम हो सकते हैं।
एंडी ई।

6
@ एंडी मैं क्रोमियम पर इस समाधान की कोशिश की। यदि मैं टैब बदलता हूं तो यह काम करता है, लेकिन अगर मैं विंडोज़ (ALT + टैब) बदलता हूं तो यह नहीं होता है। इसे होना चाहिए? यहाँ एक पहेली है - jsfiddle.net/8a9N6/17
टोनी लम्पापा

2
@ हेलियोडर: मैं अब उत्तर के लिए कोड को न्यूनतम रखना चाहूंगा। यह कभी भी एक कट-एंड-पेस्ट पूर्ण समाधान होने का इरादा नहीं था, क्योंकि कार्यान्वयनकर्ता शरीर पर एक कक्षा स्थापित करने से बचना चाहते हैं और पूरी तरह से एक अलग कार्रवाई कर सकते हैं (जैसे कि रोकना और टाइमर शुरू करना)।
एंडी ई

8
@AndyE आपका समाधान केवल तभी काम करता है जब उपयोगकर्ता टैब बदलता है, या विंडो को छोटा / अधिकतम करता है। हालाँकि, यदि उपयोगकर्ता टैब को सक्रिय छोड़ता है, तो ऑनकॉन्ग इवेंट चालू नहीं होता है, लेकिन टास्कबार से इस पर एक अन्य प्रोग्राम को अधिकतम करता है। क्या उस परिदृश्य का कोई हल है? धन्यवाद!
user1491636

132

मैं jQuery का उपयोग करेगा क्योंकि तब आपको बस इतना करना है:

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

या कम से कम इसने मेरे लिए काम किया।


1
मेरे लिए इस कॉल को दो बार iframe में
msangel

फ़ायरफ़ॉक्स में, अगर आप फायरबग कंसोल (एक ही पृष्ठ पर) के अंदर क्लिक करते हैं, तो windowढीला फोकस होगा, जो सही है, लेकिन आपके इरादे पर निर्भर करता है कि आपको क्या चाहिए।
माजिद फौलादपुर

21
यह अब आधुनिक ब्राउज़रों के वर्तमान संस्करणों के लिए काम नहीं करता है, स्वीकृत उत्तर (पेज विजिबिलिटी एपीआई) देखें
जॉन z

यह समाधान iPad पर काम नहीं करता है कृपया "Pageshow" घटना का उपयोग करें
ElizaS

पेज लोड होने पर BLUR और FOCUS दोनों बंद हो जाते हैं। जब मैं अपने पृष्ठ से एक नई विंडो खोलता हूं तो कुछ भी नहीं होता है लेकिन एक बार जब नई विंडो बंद हो जाती है तो दोनों घटनाएँ बंद हो जाती हैं: / (IE8 का उपयोग करके)
SearchForKnowledge

49

यह निर्धारित करने के लिए 3 विशिष्ट तरीके उपयोग किए जाते हैं कि क्या उपयोगकर्ता HTML पृष्ठ देख सकता है, हालांकि उनमें से कोई भी पूरी तरह से काम नहीं करता है:

  • W3C पृष्ठ दृश्यता API यह करने के लिए माना जाता है (समर्थित के बाद से: फ़ायरफ़ॉक्स 10, MSIE 10, क्रोम 13)। हालाँकि, यह एपीआई केवल उन घटनाओं को बढ़ाता है जब ब्राउज़र टैब पूरी तरह से ओवरराइड हो जाता है (जैसे जब उपयोगकर्ता एक टैब से दूसरे में बदलता है)। जब दृश्यता 100% सटीकता (जैसे किसी अन्य एप्लिकेशन पर स्विच करने के लिए Alt + Tab) के साथ निर्धारित नहीं की जा सकती, तो API ईवेंट नहीं बढ़ाती है।

  • फ़ोकस / ब्लर आधारित विधियों का उपयोग करने से आपको बहुत सी झूठी सकारात्मक जानकारी मिलती है। उदाहरण के लिए, यदि उपयोगकर्ता ब्राउज़र विंडो के शीर्ष पर एक छोटी विंडो प्रदर्शित करता है, तो ब्राउज़र विंडो फ़ोकस ( onblurबढ़ा हुआ) खो देगी लेकिन उपयोगकर्ता अभी भी इसे देख पा रहा है (इसलिए इसे अभी भी ताज़ा करने की आवश्यकता है)। Http://javascript.info/tutorial/focus को भी देखें

  • उपयोगकर्ता गतिविधि (माउस चाल, क्लिक, कुंजी टाइप) पर भरोसा करने से आपको बहुत सी झूठी सकारात्मक भी मिलती है। ऊपर के रूप में एक ही मामले के बारे में सोचो, या एक वीडियो देखने वाले उपयोगकर्ता।

ऊपर वर्णित अपूर्ण व्यवहार को सुधारने के लिए, मैं 3 विधियों के संयोजन का उपयोग करता हूं: W3C दृश्यता API, फिर झूठी सकारात्मक दर को कम करने के लिए फ़ोकस / ब्लर और उपयोगकर्ता गतिविधि विधियों पर ध्यान दें। यह निम्नलिखित घटनाओं का प्रबंधन करने की अनुमति देता है:

  • ब्राउज़र टैब को एक दूसरे से बदलना (100% सटीकता, W3C पृष्ठ दृश्यता API के लिए धन्यवाद)
  • संभावित रूप से Alt + Tab (संभावित 100% सटीक नहीं) के कारण किसी अन्य विंडो द्वारा छिपाया गया पेज
  • उपयोगकर्ता का ध्यान संभवतः HTML पृष्ठ पर केंद्रित नहीं है (संभाव्य = 100% सटीक नहीं)

यह इस तरह से काम करता है: जब दस्तावेज़ फ़ोकस खो देता है, तो दस्तावेज़ पर उपयोगकर्ता गतिविधि (जैसे माउस चाल) यह निर्धारित करने के लिए निगरानी की जाती है कि खिड़की दिखाई दे रही है या नहीं। पृष्ठ दृश्यता की संभावना पृष्ठ पर अंतिम उपयोगकर्ता गतिविधि के समय के विपरीत आनुपातिक है: यदि उपयोगकर्ता दस्तावेज़ पर लंबे समय तक कोई गतिविधि नहीं करता है, तो पृष्ठ संभवतः सबसे अधिक दिखाई नहीं देता है। W3C पृष्ठ दृश्यता API की नकल करने वाला कोड नीचे व्यवहार करता है: यह उसी तरह व्यवहार करता है, लेकिन एक छोटी झूठी सकारात्मक दर है। इसका मल्टीब्रोसर (फ़ायरफ़ॉक्स 5, फ़ायरफ़ॉक्स 10, एमएसआईई 9, एमएसआईई 7, सफारी 5, क्रोम 5 टेस्ट पर परीक्षण) होने का फायदा है।

    <div id = "x"> </ div>

    <Script>
    / **
    दिए गए ऑब्जेक्ट के लिए ईवेंट के लिए हैंडलर को पंजीकृत करता है।
    @ अपरम ने उस वस्तु को देखा जो घटना को बढ़ाएगी
    @param ईवेंट टाइप करें: क्लिक करें, कीपर्स, माउसओवर, ...
    @ अपरम ने इवेंट हैंडलर फंक्शन किया
    @param ईवेंट मोड सेट कर रहा है (सही = कैप्चरिंग ईवेंट, असत्य = बबलिंग ईवेंट)
    @ ग्रेट सही है अगर इवेंट हैंडलर को सही तरीके से संलग्न किया गया है
    * /
    फ़ंक्शन जोड़ें (obj, evType, fn, isCapturing) {
      if (isCapturing == null) हो रहा है। 
      अगर (obj.addEventListener) {
        // फ़ायरफ़ॉक्स
        obj.addEventListener (evType, fn, isCapturing);
        सच लौटना;
      } और अगर (obj.attachEvent) {
        // MSIE
        var r = obj.attachEvent ('on' + evType, fn);
        वापसी r;
      } अन्य {
        विवरण झूठा है;
      }
    }

    // संभावित पृष्ठ दृश्यता परिवर्तन के लिए रजिस्टर करें
    addEvent (दस्तावेज़, "पोटेंशियलवाइसीचेंज", फंक्शन (ईवेंट) {
      document.getElementById ("x")। भीतर HTML + = "संभाव्य क्षमता: परिवर्तन: संभावितHidden =" + document.potentialHidden + ", document.potentiallyHiddenSince =" + document .potentiallyHiddenSince + "s <br>";
    });

    // W3C पृष्ठ दृश्यता API पर रजिस्टर करें
    var छिपा हुआ = अशक्त;
    var दृश्यता परिवर्तन = अशक्त;
    अगर (टाइप करें document.mozHidden! == "अपरिभाषित") {
      छिपा = "mozHidden";
      visibilityChange = "mozvisibilitychange";
    } और अगर (टाइपो डॉक्यूमेंट .msHidden! == "अनिर्धारित") {
      छिपा = "msHidden";
      visibilityChange "msvisibilitychange" =;
    } और अगर (टाइपऑफ़ दस्तावेज़ ।webkitHidden! == "अपरिभाषित") {
      छिपा = "webkitHidden";
      visibilityChange "webkitvisibilitychange" =;
    } और अगर (टाइपो डॉक्यूमेंट.हेड! == "हिडन") {
      छिपा = "छिपा";
      visibilityChange = "visibilitychange";
    }
    अगर (छिपा हुआ! = अशक्त && दृश्यता परिवर्तन! = अशक्त) {
      addEvent (दस्तावेज़, दृश्यता परिवर्तन, फ़ंक्शन (घटना) {
        document.getElementById ("x")। भीतर HTML + = दृश्यता परिवर्तन + ":" + छिपा + "=" + दस्तावेज़ [छिपा] + "<br>";
      });
    }


    var संभावितPageVisibility = {
      पेजविजिबिलिटी चेंजट्रेशल्ड: 3 * 3600, // सेकंड में
      init: फ़ंक्शन () {
        फंक्शन सेटअनॉटहेड () {
          var dispatchEventRequired = document.potentialHidden;
          document.potentialHidden झूठी =;
          document.potentiallyHiddenSince = 0;
          if (dispatchEventRequired) dispatchPageVisibilityChangeEvent ();
        }

        फ़ंक्शन initPotentiallyHiddenDetection () {
          अगर (है! हैफोकल) {
            // विंडो में फ़ोकस नहीं है => विंडो में उपयोगकर्ता गतिविधि के लिए जाँच करें
            lastActionDate = नई तिथि ();
            अगर (टाइमआउट हैंडलर! = अशक्त) {
              clearTimeout (timeoutHandler);
            }
            timeoutHandler = setTimeout (checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // +100 एमएस फ़ायरफ़ॉक्स के तहत समस्याओं से बचने के लिए
          }
        }

        समारोह प्रेषणपैजिबिलिटी परिवर्तन () {
          unifiedVisilityChangeEventDispatchAllowed झूठी =;
          var evt = document.createEvent ("इवेंट");
          evt.initEvent ("potentialvisilitychange", सत्य, सत्य);
          document.dispatchEvent (evt);
        }

        समारोह checkPageVisibility () {
          var संभावितहेडड्रेडेशन = (hasFocusLocal || lastActionDate == null; 0: Math.floor ((नई तिथि) () getTime () - lastActionDate.getTime () / 1000 /);
                                        document.potentiallyHiddenSince = potentialHiddenDuration;
          अगर (पोटेंशियल हैडिडेशन> = पोस्पेक्ट विजिबिलिटी। पेज विजिबिलिटी चेंजट्रेशोल्ड &&! document.potentialHidden) {
            // पृष्ठ दृश्यता में परिवर्तन की सीमा => समान बढ़ाएँ
            document.potentialHidden सच =;
            dispatchPageVisibilityChangeEvent ();
          }
        }

        var lastActionDate = null;
        var hasFocusLocal = true;
        var hasMouseOver = true;
        document.potentialHidden झूठी =;
        document.potentiallyHiddenSince = 0;
        var timeoutHandler = null;

        addEvent (दस्तावेज़, "पेजशो", फ़ंक्शन (घटना) {
          document.getElementById ( "x") innerHTML + = "pageshow / doc: <br>"।
        });
        addEvent (दस्तावेज़, "पेजहाइड", फ़ंक्शन (घटना) {
          document.getElementById ( "x") innerHTML + = "pagehide / doc: <br>"।
        });
        addEvent (विंडो, "पेजशो", फंक्शन (ईवेंट) {
          document.getElementById ( "x") innerHTML + = "pageshow / जीत: <br>"। // उठाया गया जब पृष्ठ पहले दिखाता है
        });
        addEvent (विंडो, "पेजहाइड", फंक्शन (ईवेंट) {
          document.getElementById ( "x") innerHTML + = "pagehide / जीत: <br>"। // नहीं उठाया गया
        });
        addEvent (दस्तावेज़, "मूसमव", फ़ंक्शन (घटना) {
          lastActionDate = नई तिथि ();
        });
        addEvent (दस्तावेज़, "माउसओवर", फ़ंक्शन (घटना) {
          hasMouseOver सच =;
          setAsNotHidden ();
        });
        addEvent (दस्तावेज़, "माउसआउट", फ़ंक्शन (घटना) {
          hasMouseOver झूठी =;
          initPotentiallyHiddenDetection ();
        });
        addEvent (विंडो, "ब्लर", फंक्शन (ईवेंट) {
          hasFocusLocal झूठी =;
          initPotentiallyHiddenDetection ();
        });
        addEvent (विंडो, "फ़ोकस", फ़ंक्शन (ईवेंट) {
          hasFocusLocal सच =;
          setAsNotHidden ();
        });
        setAsNotHidden ();
      }
    }

    potentialPageVisibility.pageVisibilityChangeThreshold = 4; // परीक्षण के लिए 4 सेकंड
    potentialPageVisibility.init ();
    </ Script>

चूंकि वर्तमान में झूठी सकारात्मक के बिना कोई काम नहीं कर रहा है क्रॉस-ब्राउज़र समाधान, आपको अपनी वेब साइट पर आवधिक गतिविधि को अक्षम करने के बारे में दो बार बेहतर सोचना चाहिए।


उपर्युक्त कोड में गलत पॉज़िटिव के कारण अपरिभाषित कीवर्ड के बजाय स्ट्रिंग 'अपरिभाषित' पर एक सख्त तुलना ऑपरेटर का उपयोग नहीं किया जाएगा?
जोनाथन

@किरण: वास्तव में यह Alt + Tab के साथ काम कर रहा है। जब आप Alt + Tab करते हैं तो आप यह निर्धारित नहीं कर सकते हैं कि पृष्ठ छिपा हुआ है क्योंकि आप छोटी विंडो में स्विच कर सकते हैं ताकि आप यह गारंटी न दे सकें कि आपका पृष्ठ पूरी तरह से छिपा हुआ है। यही कारण है कि मैं "संभावित रूप से छिपे हुए" की धारणा का उपयोग करता हूं (उदाहरण में, दहलीज 4 सेकंड के लिए सेट है, इसलिए आपको कम से कम 4 सेकंड के लिए Alt + Tab का उपयोग करके दूसरी विंडो पर स्विच करने की आवश्यकता है)। हालाँकि आपकी टिप्पणी से पता चलता है कि उत्तर इतना स्पष्ट नहीं था, इसलिए मैंने इसे पुनः प्रकाशित किया।
जुलियन क्रोनग डे

@JulienKronegg मुझे लगता है कि यह अभी तक का सबसे अच्छा समाधान है। हालाँकि, ऊपर दिए गए कोड को कुछ रिफैक्टिंग और अमूर्त की जरूरत है। आप इसे GitHub पर अपलोड क्यों नहीं करते हैं और समुदाय को इसे फिर से बनाने दे रहे हैं?
जैकब

1
@ जेकब मुझे खुशी है कि आपको मेरा समाधान पसंद आया। अपने आप को एक GitHub परियोजना में बढ़ावा देने के लिए स्वतंत्र महसूस करें। मैं लाइसेंस के साथ कोड देता हूं क्रिएटिव कॉमन्स द्वारा Creativecommons.org/licenses/by/4.0
जूलियन क्रोनग

26

GitHub पर एक साफ-सुथरी लाइब्रेरी उपलब्ध है:

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

उदाहरण:

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

मैंने अपने सभी ब्राउज़रों पर संस्करण 1.0.1 का परीक्षण किया है और पुष्टि कर सकता हूं कि यह साथ काम करता है:

  • IE9, IE10
  • एफएफ 26.0
  • क्रोम 34.0

... और शायद सभी नए संस्करण।

के साथ पूरी तरह से काम नहीं करता है:

  • IE8 - हमेशा इंगित करें कि टैब / विंडो वर्तमान में सक्रिय है ( .now()हमेशा trueमेरे लिए रिटर्न )

IE9 में समस्या के कारण स्वीकृत उत्तर। यह लाइब्रेरी बेहतरीन काम करती है।
टॉम तेमन

20

उपयोग करना: पृष्ठ दृश्यता API

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

क्या में उपयोग कर सकता हूँ ? http://caniuse.com/#feat=pagevisibility


सवाल पेज विजिबिलिटी का नहीं है। यह सक्रिय नहीं है / सक्रिय नहीं है
gman

मुझे लगता है कि ओपी ide के कार्य के बारे में बात नहीं कर रहा है
l2aelba

1
मैं विचारधारा के बारे में बात नहीं कर रहा हूँ। मैं दूसरे ऐप में ऑल्ट-टैबिंग / सेमी-टैबिंग के बारे में बात कर रहा हूं। अचानक पृष्ठ सक्रिय नहीं है। पृष्ठ दृश्यता एपीआई मुझे यह जानने में मदद नहीं करता है कि क्या पृष्ठ सक्रिय नहीं है, यह केवल मुझे यह जानने में मदद करता है कि क्या यह संभव नहीं है।
gman

18

मैं अपने ऐप के लिए एक धूमकेतु चैट बनाता हूं, और जब मुझे एक अन्य उपयोगकर्ता से संदेश प्राप्त होता है जिसका मैं उपयोग करता हूं:

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

2
IE6 पर वापस समर्थन के साथ सबसे साफ समाधान
पॉल कूपर

4
document.hasFocus()इसे करने का सबसे साफ तरीका है। दृश्यता एपीआई या घटना के आधार पर या उपयोगकर्ता गतिविधि / गतिविधि की कमी के विभिन्न स्तरों की तलाश में अन्य सभी तरीके अतिव्याप्त और किनारे के मामलों और छिद्रों से भरे हुए हो जाते हैं। इसे एक साधारण अंतराल पर रखें और परिणाम बदलने पर एक कस्टम ईवेंट बढ़ाएँ। उदाहरण: jsfiddle.net/59utucz6/1
danatcofo

1
कुशल, और अन्य समाधानों के विपरीत जब आप किसी अन्य ब्राउज़र टैब या विंडो पर स्विच करते हैं, और यहां तक ​​कि एक अलग एप्लिकेशन भी सही प्रतिक्रिया देता है।
उल्लू

कोई संदेह नहीं है, इसका सबसे साफ तरीका है, लेकिन यह फ़ायरफ़ॉक्स में काम नहीं करता है
हार्ड चुग

1
यदि मैं Chrome देव टूल खोलता हूं तो document.hasFocus () गलत के बराबर है। या यहां तक ​​कि अगर आप ब्राउज़र के शीर्ष पैनल पर क्लिक करते हैं, तो भी ऐसा ही होता है। मुझे यकीन नहीं है कि यह समाधान वीडियो, एनीमेशन, आदि को रोकने के लिए उपयुक्त है
tylik

15

मैंने समुदाय विकी उत्तर का उपयोग करना शुरू कर दिया, लेकिन यह महसूस किया कि यह क्रोम में ऑल-टैब इवेंट्स का पता नहीं लगा रहा था। ऐसा इसलिए है क्योंकि यह पहले उपलब्ध इवेंट स्रोत का उपयोग करता है, और इस मामले में यह पृष्ठ दृश्यता एपीआई है, जो क्रोम में ऑल-टैबिंग को ट्रैक नहीं करता है।

मैंने पृष्ठ फ़ोकस परिवर्तनों के लिए सभी संभावित घटनाओं पर नज़र रखने के लिए स्क्रिप्ट को थोड़ा संशोधित करने का निर्णय लिया । यहाँ एक समारोह है जिसे आप इसमें छोड़ सकते हैं:

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

इसे इस तरह उपयोग करें:

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

यह संस्करण सभी अलग-अलग दृश्यता घटनाओं के लिए सुनता है और यदि उनमें से कोई भी बदलाव का कारण बनता है तो कॉलबैक फायर करता है। focusedऔर unfocusedसंचालकों सुनिश्चित करें कि कॉलबैक कई बार यदि एक से अधिक एपीआई एक ही दृश्यता परिवर्तन को पकड़ने नहीं बुलाया गया है।


उदाहरण के लिए क्रोम दोनों है document.hiddenऔर document.webkitHidden। बिना elseमें ifनिर्माण हम 2 कॉलबैक कॉल सही होगा?
क्रिस्टियान वेस्टरबेक

@ChristiaanWesterbeek यह एक अच्छी बात है, मैंने ऐसा नहीं सोचा था! अगर आप इस पोस्ट को संपादित कर सकते हैं तो आगे बढ़ें और मैं स्वीकार कर लूंगा :)
डैनियल बकमास्टर

उह अरे एक मिनट रुकिए: क्रिस्टियानानवेस्टरबेक द्वारा सुझाए गए "और" को जोड़ने के लिए संपादित करें और वास्तव में @ 1.21Gigawatts द्वारा जोड़ा गया एक अच्छा विचार नहीं लगता है: यह डैनियल के विचार की मूल खरीद को हरा देता है, जो सभी समर्थित की कोशिश करना है समानांतर में तरीके। और कॉलबैक का कोई जोखिम नहीं है क्योंकि दो बार कॉल किया जा रहा है क्योंकि फोकस () और अनफोकस्ड () अतिरिक्त कॉल को दबा देता है जब कुछ भी नहीं बदल रहा है। वास्तव में ऐसा लगता है कि हमें पहले संशोधन में वापस आना चाहिए।
लुई सेमप्रिनि

@LouisSemprini यह एक शानदार कैच है। मैं कोड के मूल इरादे भूल गया था! मैंने मूल को बहाल कर दिया है और एक स्पष्टीकरण जोड़ा है!
डैनियल बकमास्टर

आज की जाँच के अनुसार, यह कम से कम क्रोम 78 + मैकोस पर ऑल्ट + टैब का पता नहीं लगाता है
ह्यूगो ग्रिस

7

यह वास्तव में मुश्किल है। ऐसा लगता है कि निम्नलिखित आवश्यकताओं को देखते हुए कोई समाधान नहीं है।

  • पृष्ठ में iframes शामिल हैं जिनका आपके पास कोई नियंत्रण नहीं है
  • TAB परिवर्तन (ctrl + टैब) या विंडो परिवर्तन (alt + टैब) द्वारा ट्रिगर किए जा रहे परिवर्तन की परवाह किए बिना आप दृश्यता स्थिति परिवर्तन को ट्रैक करना चाहते हैं

ऐसा होता है क्योंकि:

  • पृष्ठ दृश्यता API विश्वसनीय रूप से आपको टैब परिवर्तन (यहां तक ​​कि iframes के साथ) के बारे में बता सकता है, लेकिन उपयोगकर्ता द्वारा विंडो बदलने पर यह आपको नहीं बता सकता है।
  • विंडो ब्लर / फ़ोकस इवेंट्स को सुनने से ऑल्ट + टैब और सीटीएल + टैब का पता लगाया जा सकता है, जब तक कि आइफ्रेम में फोकस न हो।

इन प्रतिबंधों को देखते हुए, एक समाधान को लागू करना संभव है जो जोड़ती है - पृष्ठ दृश्यता API - विंडो ब्लर / फ़ोकस - document.activeElement

यह करने में सक्षम है:

  • 1) ctrl + टैब जब पैरेंट पेज पर फोकस होता है: YES
  • 2) ctrl + टैब जब iframe में फोकस होता है: YES
  • 3) ऑल्ट + टैब जब पैरेंट पेज पर फोकस होता है: YES
  • 4) alt + टैब जब iframe में फोकस होता है: NO <- bummer

जब iframe में फ़ोकस होता है, तो आपके ब्लर / फ़ोकस इवेंट्स को बिल्कुल भी आमंत्रित नहीं किया जाता है, और पेज विजिबिलिटी API alt + टैब पर ट्रिगर नहीं होगा।

मैंने @ एंडी के समाधान पर निर्माण किया और इसे (लगभग अच्छा) समाधान यहां लागू किया: https://dl.dropboxusercontent.com/u/2683925/estante-compenders/visibility_test1.html (क्षमा करें, मुझे JSFiddle से कुछ परेशानी थी)।

यह Github: https://github.com/qmagico/estante-compenders पर भी उपलब्ध है

यह क्रोम / क्रोमियम पर काम करता है। यह फ़ायरफ़ॉक्स पर काम करता है, सिवाय इसके कि यह iframe कंटेंट लोड नहीं करता है (किसी भी विचार क्यों?)

वैसे भी, पिछली समस्या को हल करने के लिए (4), एकमात्र तरीका जो आप कर सकते हैं वह है इफ्रे पर धब्बा / फोकस घटनाओं के लिए सुनना। यदि आपका iframes पर कुछ नियंत्रण है, तो आप ऐसा करने के लिए PostMessage API का उपयोग कर सकते हैं।

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

मैंने अभी भी पर्याप्त ब्राउज़रों के साथ इसका परीक्षण नहीं किया है। यदि आप इस बारे में अधिक जानकारी प्राप्त कर सकते हैं कि यह कहाँ काम नहीं करता है, तो कृपया मुझे नीचे टिप्पणी में बताएं।


मेरे परीक्षणों में इसने IE9, IE10 और Android पर क्रोम पर भी काम किया।
टोनी लम्पापा

1
ऐसा लगता है कि IPAD को पूरी तरह से अलग समाधान की आवश्यकता है - stackoverflow.com/questions/4940657/…
टोनी लम्पापा

3
ये सभी लिंक 404s हैं :(
डैनियल बकमास्टर

6
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/


5

यह क्रोम 67 पर मेरे लिए काम करता है, फ़ायरफ़ॉक्स 67,

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

3

आप उपयोग कर सकते हैं:

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

})();

3

HTML 5 में आप भी इस्तेमाल कर सकते हैं:

  • onpageshow: खिड़की दिखाई देने पर स्क्रिप्ट को चलाया जाना
  • onpagehide: खिड़की के छिपे होने पर चलाने के लिए स्क्रिप्ट

देख:


2
मुझे लगता है कि यह BFCache से संबंधित है: जब उपयोगकर्ता क्लिक या फॉरवर्ड पर क्लिक करता है - यह कंप्यूटर डेस्कटॉप के शीर्ष पर स्थित पृष्ठ से संबंधित नहीं है।
गैरबराबरी

2

यह एंडी ई से उत्तर का एक अनुकूलन है।

यह एक कार्य करेगा जैसे हर 30 सेकंड में पृष्ठ को ताज़ा करें, लेकिन केवल तभी जब पृष्ठ दिखाई और केंद्रित हो।

यदि दृश्यता का पता नहीं लगाया जा सकता है, तो केवल फोकस का उपयोग किया जाएगा।

यदि उपयोगकर्ता पृष्ठ पर ध्यान केंद्रित करता है, तो यह तुरंत अपडेट हो जाएगा

किसी भी अजाक्स कॉल के 30 सेकंड बाद तक पेज फिर से अपडेट नहीं होगा

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

फोकस / ब्लर विधियों पर भरोसा करने से काम नहीं चलता (यह आपको बहुत कुछ सकारात्मक देता है), देखें stackoverflow.com/a/9502074/698168
जूलियन क्रोनग

2

JQuery के बिना एक समाधान के लिए Visibility.js की जांच करें जो तीन पेज राज्यों के बारे में जानकारी प्रदान करता है

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

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

पुराने ब्राउज़र (IE <10; iOS <7) के लिए एक वापसी भी उपलब्ध है


ब्राउज़र समर्थन के बारे में क्या? क्रोम, सफारी, और फ़ायरफ़ॉक्स में अच्छा forking के लिए अब।
सेलवा गणपति

1

उपयोग करने के लिए थोड़ा अधिक जटिल तरीका होगा setInterval() माउस स्थिति की जांच करने और अंतिम जांच की तुलना करने के किया । यदि माउस समय की एक निर्धारित राशि में स्थानांतरित नहीं हुआ है, तो उपयोगकर्ता शायद निष्क्रिय है।

यह कह रही है, तो उपयोगकर्ता के प्रयोग में है का जोड़ा लाभ है बजाय सिर्फ अगर विंडो सक्रिय नहीं है की जाँच।

जैसा कि कई लोगों ने बताया है, यह हमेशा यह जांचने का एक अच्छा तरीका नहीं है कि उपयोगकर्ता या ब्राउज़र विंडो बेकार है, क्योंकि उपयोगकर्ता शायद माउस का उपयोग भी नहीं कर रहा है या वीडियो, या समान देख रहा है। मैं केवल निष्क्रिय-रास के लिए एक संभव तरीका सुझा रहा हूं।


30
जब तक उपयोगकर्ता के पास माउस नहीं होगा।
user1686

@ अस्नान: यह कोडिंगहोरर है। blog/2007/03/ अब।
चिबॉर्ग

यदि उपयोगकर्ता एक वीडियो देख रहा है, तो यह पासा भी नहीं खेलता है
jamiew

आप टाइमर को रीसेट करने और नॉन-माउस समस्या को हल करने के लिए ऑनकीप्रेस या अन्य समान घटनाओं का उपयोग कर सकते हैं। बेशक, यह अभी भी उपयोगकर्ताओं को सक्रिय रूप से वीडियो देखने, छवि का अध्ययन करने, आदि के लिए पेज देखने के लिए काम नहीं करेगा
joshuahedlund

1

Angular.js के लिए, यहां एक निर्देश (स्वीकृत उत्तर के आधार पर) है जो आपके नियंत्रक को दृश्यता में बदलाव पर प्रतिक्रिया करने की अनुमति देगा:

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

});

आप इसे इस उदाहरण की तरह उपयोग कर सकते हैं: <div react-on-window-focus="refresh()">जहाँ refresh()नियंत्रक के दायरे में है, वहाँ एक स्कोप फ़ंक्शन है।


0

यहाँ एक ठोस, आधुनिक समाधान है। (लघु एक मीठा 👌🏽)

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

यह एक श्रोता को ट्रिगर करने के लिए सेटअप करेगा जब कोई दृश्यता घटना को निकाल दिया जाता है जो एक फोकस या धुंधला हो सकता है।


0

यदि आप संपूर्ण ब्राउज़र कलंक पर कार्य करना चाहते हैं : जैसा कि मैंने टिप्पणी की थी, यदि ब्राउज़र ने खोई हुई घटनाओं में से किसी एक पर ध्यान केंद्रित नहीं किया तो आग लग जाएगी। मेरा विचार एक लूप में गिनने और काउंटर को रीसेट करने के लिए है, अगर एक घटना आग। यदि काउंटर एक सीमा तक पहुंचता है तो मैं एक स्थान पर कर देता हूं। दूसरे पृष्ठ पर जाएं। यदि आप देव-औजारों पर काम करते हैं तो भी यह आग लगती है।

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

यह एफएफ पर सफल परीक्षण का मसौदा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.