पता लगाएँ कि क्या स्क्रॉल इवेंट उपयोगकर्ता द्वारा बनाया गया था


84

क्या यह बताना संभव है कि एक स्क्रॉल घटना ब्राउज़र द्वारा या उपयोगकर्ता द्वारा की गई थी? विशेष रूप से, बैक बटन का उपयोग करते समय ब्राउज़र अंतिम ज्ञात स्क्रॉल स्थिति पर जा सकता है। यदि मैं ईवेंट स्क्रॉल करने के लिए बाध्य हूं तो मैं कैसे बता सकता हूं कि यह उपयोगकर्ता या ब्राउज़र के कारण हुआ था?

$(document).scroll( function(){ 
    //who did this?!
});

मैं तीन प्रकार की स्थितियों को देखता हूं जो एक ब्राउज़र में स्क्रॉलिंग का कारण बनती हैं।

  1. उपयोगकर्ता कुछ कार्रवाई करता है। उदाहरण के लिए, मूसवेल, एरो कीज़, पेज अप / डाउन कीज़, होम / एंड कीज़ का उपयोग करता है।
  2. ब्राउज़र स्वचालित रूप से स्क्रॉल करता है। उदाहरण के लिए, अपने ब्राउज़र में बैक बटन का उपयोग करते समय यह अंतिम ज्ञात स्क्रॉल स्थिति पर स्वचालित रूप से कूद जाएगा।
  3. जावास्क्रिप्ट स्क्रॉल। उदाहरण के लिए, element.scrollTo(x,y)

1
यदि आप बैक बॉटन का उपयोग करते हुए मुझे ब्राउजर या उपयोगकर्ता के स्क्रॉल ईवेंट का उपयोग करने पर विचार करते हैं, तो मुझे आपके प्रश्न पर यकीन नहीं है। आम तौर पर: आप "ब्राउज़र द्वारा स्क्रॉलिंग" पर क्या विचार करते हैं? यदि आपका मतलब है कि आपकी स्क्रिप्ट द्वारा शुरू की गई स्क्रॉलिंग, तो आपको बस इतना करना होगा, जब आपकी स्क्रिप्ट स्क्रॉल करती है, या तो ईवेंट हैंडलर को निष्क्रिय करने के लिए या एक फ्लैग सेट करने के लिए ताकि इवेंट हैंडलर इसे अनदेखा करना जानता हो।
RoToRa

मैंने बैक बटन के माध्यम से स्क्रॉल करने को "ब्राउज़र स्क्रॉल" माना। कुछ भी - मूसली, ऊपर / नीचे तीर, केंद्र बटन क्लिक, आदि एक उपयोगकर्ता स्क्रॉल होगा। मुझे लगता है कि मेरा असली सवाल हो सकता है - क्या कोई अंतर करने का कोई तरीका है जहां एक घटना आई है? मैंने इवेंट ऑब्जेक्ट पर गुणों को देखा, लेकिन कुछ भी नहीं खोज सका। मैं जिन तीन परिदृश्यों की कल्पना कर सकता हूं, वे हैं ब्राउज़र ने स्क्रॉल करना शुरू किया, जावास्क्रिप्ट ने स्क्रॉलिंग शुरू की और उपयोगकर्ता ने स्क्रॉलिंग शुरू की। आशा है कि चीजों को स्पष्ट करता है।
मृत्ष्मन

@mrshherman मुझे इनमें से कुछ समान आउटपुट हासिल करते हुए मिले: stackoverflow.com/questions/2834667/…
AlphaMale

जवाबों:


30

दुर्भाग्य से, यह बताने का कोई सीधा तरीका नहीं है।

मैं कहूंगा कि यदि आप अपने ऐप को फिर से डिज़ाइन कर सकते हैं ताकि यह इस प्रकार के प्रवाह पर निर्भर न हो, तो इसके लिए जाएं।

यदि नहीं, तो एक वैकल्पिक हल मैं के बारे में सोच सकते हैं उपयोगकर्ता द्वारा आरंभ किए स्क्रॉल का ट्रैक रखने और जाँच लें कि देखने के लिए कि पुस्तक ब्राउज़र द्वारा या उपयोगकर्ता द्वारा ट्रिगर किया गया है।

यहाँ एक उदाहरण है जो मैंने एक साथ रखा है जो इसे बहुत अच्छी तरह से करता है (उन ब्राउज़रों को छोड़कर जहां jQuery के इतिहास में समस्याएं हैं)।

आपको इसे पूरी तरह से परखने में सक्षम होने के लिए इसे स्थानीय रूप से चलाने की आवश्यकता है (jsFiddle / jsbin अच्छा फिट नहीं है क्योंकि वे सामग्री को iFrame करते हैं)।

यहाँ परीक्षण के मामले हैं जिन्हें मैंने सत्यापित किया है:

  • पेज लोड - userScrollहैfalse
  • माउस / कीबोर्ड का उपयोग करते हुए स्क्रॉल करें - userScrollबन जाता हैtrue
  • पेज बॉटम पर जाने के लिए लिंक पर क्लिक करें - userScrollबन जाता हैfalse
  • क्लिक बैक / फॉरवर्ड - userScrollबन जाता है false;

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="utf-8" /> 
    <script src="http://code.jquery.com/jquery-1.6.1.min.js"></script> 
    <script type="text/javascript" src="https://raw.github.com/tkyk/jquery-history-plugin/master/jquery.history.js"></script> 
</head> 
<body> 
    <span> hello there </span><br/> 
    <a href="#bottom"> click here to go down </a> 
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 
    <a name="bottom"> just sitting </a> 
</body> 
<script type="text/javascript"> 

var userScroll = false;     

function mouseEvent(e) { 
    userScroll = true; 
} 


$(function() { 

    // reset flag on back/forward 
    $.history.init(function(hash){ 
        userScroll = false; 
    }); 

    $(document).keydown(function(e) { 
        if(e.which == 33        // page up 
           || e.which == 34     // page dn 
           || e.which == 32     // spacebar
           || e.which == 38     // up 
           || e.which == 40     // down 
           || (e.ctrlKey && e.which == 36)     // ctrl + home 
           || (e.ctrlKey && e.which == 35)     // ctrl + end 
          ) { 
            userScroll = true; 
        } 
    }); 

    // detect user scroll through mouse
    // Mozilla/Webkit 
    if(window.addEventListener) {
        document.addEventListener('DOMMouseScroll', mouseEvent, false); 
    }

    //for IE/OPERA etc 
    document.onmousewheel = mouseEvent; 


    // to reset flag when named anchors are clicked
    $('a[href*=#]').click(function() { 
        userScroll = false;
    }); 

      // detect browser/user scroll
    $(document).scroll( function(){  
        console.log('Scroll initiated by ' + (userScroll == true ? "user" : "browser"));
    });
}); 
</script> 
</html>

टिप्पणियाँ:

  • जब उपयोगकर्ता माउस के साथ स्क्रॉलबार खींचता है तो यह स्क्रॉलिंग को ट्रैक नहीं करता है। इसे कुछ और कोड के साथ जोड़ा जा सकता है, जिसे मैंने आपके लिए एक अभ्यास के रूप में छोड़ दिया है।
  • event.keyCodes ओएस द्वारा भिन्न हो सकता है, इसलिए आपको उचित रूप से बदलना पड़ सकता है।

उम्मीद है की यह मदद करेगा!


धन्यवाद श्रीमान। मुझे लगता है कि यह सबसे अच्छा जवाब है, हालांकि यह वह नहीं है जो मैं उम्मीद कर रहा था कि यह होगा (क्या? कोई event.throwerसंपत्ति नहीं है?)।
mrtsherman

स्क्रॉल करते समय आपको घर और अंत कुंजियों का उपयोग करते हुए नियंत्रण को दबाने की आवश्यकता नहीं है।
कर्टिस

DOMMouseScroll मैक पर नवीनतम क्रोम पर काम नहीं करता है। दस्तावेज़ का उपयोग करने के लिए सबसे अच्छा है। OndewventListener ('mousewheel' onmousewel सेट करने के बजाय
Curtis

9

सभी उपयोगकर्ता घटनाओं को पकड़ने की कोशिश करने के बजाय, यह विपरीत करना आसान है और केवल प्रोग्रामेटिक घटनाओं को संभालना है - और उन पर ध्यान न दें।

उदाहरण के लिए, इस तरह का कोड काम करेगा:

// Element that needs to be scrolled
var myElement = document.getElementById('my-container');

// Flag to tell if the change was programmatic or by the user
var ignoreNextScrollEvent = false;

function setScrollTop(scrollTop) {
    ignoreNextScrollEvent = true;
    myElement.scrollTop = scrollTop
}

myElement.addEventListener('scroll', function() {
    if (ignoreNextScrollEvent) {
        // Ignore this event because it was done programmatically
        ignoreNextScrollEvent = false;
        return;
    }

    // Process user-initiated event here
});

फिर जब आप कॉल करते हैं setScrollTop(), तो स्क्रॉल ईवेंट को अनदेखा कर दिया जाएगा, जबकि यदि उपयोगकर्ता माउस, कीबोर्ड या किसी अन्य तरीके से स्क्रॉल करता है, तो ईवेंट संसाधित हो जाएगा।


2
यह ब्राउजर द्वारा ट्रिगर की गई स्क्रॉल घटनाओं का पता नहीं लगाता / अनदेखा नहीं करता है।
मफल्यूहर

मैं कुछ इसी तरह के बारे में सोच रहा हूँ - यह ध्यान में नहीं आता है कि स्क्रॉल व्यवहार 'सुचारू' पर सेट किया जा सकता है
कामिल बोबेन

8

जहां तक ​​मुझे पता है कि "उपयोगकर्ता" या अन्य माध्यमों से जब भी स्क्रॉल इवेंट जारी किया गया है, यह बताना असंभव है (किसी भी काम के बिना)।

आप कोशिश कर सकते हैं (जैसा कि दूसरों ने उल्लेख किया है) मौसमी घटनाओं को पकड़ते हैं, तो संभवतः किसी भी कुंजी पर कीडाउन घटना को पकड़ने की कोशिश कर रहे हैं जो स्क्रॉल (तीर, स्थान आदि) को ट्रिगर कर सकता है, जबकि वर्तमान में ध्यान केंद्रित करने वाले तत्व की जांच कर रहा है, क्योंकि आप उदाहरण के लिए स्क्रॉल नहीं कर सकते हैं। तीर कुंजी एक इनपुट क्षेत्र में टाइप करते समय। सामान्य तौर पर यह जटिल और गड़बड़ स्क्रिप्ट होगी।

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


धन्यवाद WTK। थोड़ी देर के लिए यह सबसे अच्छा जवाब था, लेकिन दुर्भाग्य से आपके लिए मिर्चिफ़ ने कुछ कोड उदाहरणों के साथ आपके जवाब पर खुलासा किया, इसलिए मैंने उसे इनाम दिया। अगर मैं इसे विभाजित कर सकता था तो मेरे पास होगा!
mrtsherman

4
ठीक है। यह इनाम के बारे में नहीं है बल्कि ज्ञान फैलाने और हासिल करने के बारे में है :)
WTK

3

हां, यह 100% संभव है। मैं एक ऐसे अनुप्रयोग में इसका उपयोग कर रहा हूं जहां IE एक आवश्यकता नहीं है - केवल क्लाइंट का सामना करना पड़ रहा है। जब मेरा बैकबोन ऐप एक एनीमेशन शुरू करता है जहां स्क्रॉल बदल जाता है - स्क्रॉल होता है लेकिन इन ईवेंट कैप्चर को ट्रिगर नहीं करता है। यह एफएफ, सफारी और क्रोम नवीनतम में परीक्षण किया गया है।

$('html, body').bind('scroll mousedown wheel DOMMouseScroll mousewheel keyup', function(evt) {
  // detect only user initiated, not by an .animate though
    if (evt.type === 'DOMMouseScroll' || evt.type === 'keyup' || evt.type === 'mousewheel') {
    // up
    if (evt.originalEvent.detail < 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta > 0)) { 
    // down.
    } else if (evt.originalEvent.detail > 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta < 0)) { 
  }
}
}); 

1
सलाह के लिये धन्यवाद। हालाँकि, यह एक द्विआधारी समाधान है - जावास्क्रिप्ट बनाम स्क्रॉल किए गए गैर-जेएस स्क्रॉल का पता लगाता है। मुझे वास्तव में एक टर्नरी समाधान की आवश्यकता है। (जावास्क्रिप्ट, उपयोगकर्ता, ब्राउज़र)।
म्रतशर्मन

2

इसके बजाय Mousewheel और DOMMouseScroll घटनाओं का उपयोग करने का प्रयास करें। Http://www.quirksmode.org/dom/events/scroll.html देखें


इस सुझाव के लिए धन्यवाद। हालाँकि मुझे नहीं लगता कि मेरे पास यही है। मुझे वास्तव में ब्राउज़र और उपयोगकर्ता स्क्रॉल के बीच अंतर करने की आवश्यकता है। सिर्फ मूसवेल पर निशाना मत लगाओ।
मृत्श्मान

मुझे लगता है कि ऑनस्क्रीन इवेंट से पहले मूसवेल इवेंट को निकाल दिया जाता है। तो आप var userscroll = true को mousewheel पर सेट कर सकते हैं, और onscroll में इसका पता लगा सकते हैं (और इसे गलत पर रीसेट करें)।
गेरबेन

3
बड़ी संख्या में उपयोगकर्ता द्वारा स्क्रॉल किए गए ईवेंट शुरू किए गए हैं, जो हालांकि कवर नहीं किए जाएंगे। तीर कुंजी, विंडो आकार, आदि। इस घटना के प्रेषक को "X" कहना ज्यादा सुरक्षित है क्योंकि इस घटना के बाहर सब कुछ "X" होना चाहिए। यह मेरे लिए भी काम नहीं करता है, क्योंकि मैं ब्राउज़र द्वारा शुरू किए गए स्क्रॉल की पहचान करना चाहता हूं, न कि उपयोगकर्ता द्वारा। इसलिए इस उपयोग के मामले को बनाने के लिए मुझे सभी मेस्यूअल स्क्रॉल को ट्रैक करना होगा और फिर यह जानने की कोशिश करनी होगी कि उसके बाद का स्क्रॉल इवेंट यूजर था या नहीं। मुझे डर है कि यह सिर्फ असाध्य है।
म्रतशर्मन

2

आप तैयार पर स्क्रॉल स्थिति की जांच कर सकते हैं। जब आप स्क्रॉल इवेंट पर आग लगाते हैं, तो यह सुनिश्चित करने के लिए कि पेज लोड होने के समय स्क्रॉल की स्थिति अलग है। पेज स्क्रॉल होने के बाद अंतिम रूप से संग्रहीत मूल्य को साफ करना सुनिश्चित करें।

$(function () {
    var loadScrollTop = ($(document).scrollTop() > 0 ? $(document).scrollTop() : null);
    $(document).scroll(function (e) {
        if ( $(document).scrollTop() !== loadScrollTop) {
            // scroll code here!
        }
        loadScrollTop = null;
    });
});

इस विचार के लिए धन्यवाद। कुछ परिदृश्य हैं कि यह मेरे लिए काफी कवर नहीं करता है। हालांकि यह एक अच्छा विचार है और अगर मुझे कभी जरूरत पड़े तो मैं इसे अपनी पिछली जेब में रखूंगा।
mrtsherman 3

सरल और ज्यादातर मामलों में प्रभावी।
हारून

0

के बारे में:

विशेष रूप से, बैक बटन का उपयोग करते समय ब्राउज़र अंतिम ज्ञात स्क्रॉल स्थिति पर जा सकता है।

पृष्ठ के रेंडर होने के बाद यह बहुत जल्द ही फायर हो जाता है। आप स्क्रॉल इवेंट में सूची को 1 सेकंड या तो विलंबित कर सकते हैं।


2
यह एक मजबूत समाधान नहीं होगा। कूदने का समय पृष्ठ लोड समय पर निर्भर है। जब तक पेज पूरी तरह से लोड नहीं हो जाता तब तक ब्राउजर कूदने में देरी करता है। यह पृष्ठ तत्वों को रोकता है जो पृष्ठ ऊंचाई (छवियों की तरह) को दृश्य से बाहर स्क्रॉल करने से लोड और बदलते हैं।
म्रतशर्मन

0

उपयोगकर्ता द्वारा बनाई गई स्क्रॉल को अलग करने का एक और तरीका है: आप वैकल्पिक ईवेंट हैंडलर का उपयोग कर सकते हैं, उदाहरण के लिए 'मूसवेल', 'टचमूव', 'कीडड' कोड 38 और 40 के साथ तीर स्क्रॉलिंग के लिए, स्क्रॉल बार के साथ स्क्रॉल करने के लिए - यदि 'माउसअप' इवेंट तक 'स्क्रॉल' इवेंट को 'मूसडाउन' के साथ एक साथ निकाल दिया जाता है।


-1

यह बहुत उपयोगी पाया। यहाँ उन इच्छुक लोगों के लिए एक कॉफ़ीस्क्रिप्ट संस्करण है।

$ ->
  S.userScroll = false

  # reset flag on back/forward
  if $.history?
    $.history.init (hash) ->
      S.userScroll = false

  mouseEvent = (e)->
    S.userScroll = true

  $(document).keydown (e) ->
    importantKey =  (e.which == 33 or        # page up
      e.which == 34 or    # page dn
      e.which == 32 or    # spacebar
      e.which == 38 or    # up
      e.which == 40 or    # down
      (e.ctrlKey and e.which == 36) or    # ctrl + home
      (e.ctrlKey and e.which == 35)    # ctrl + end
    )
    if importantKey
      S.userScroll = true;

  # Detect user scroll through mouse
  # Mozilla/Webkit
  if window.addEventListener
      document.addEventListener('DOMMouseScroll', mouseEvent, false);

  # for IE/OPERA etc
  document.onmousewheel = mouseEvent;

-1

अगर आप JQuery का उपयोग कर रहे हैं तो इसका बेहतर जवाब है, जाहिरा तौर पर - मैं सिर्फ इसे खुद से आज़मा रहा हूं।

देखें: उपयोगकर्ता द्वारा jquery ईवेंट ट्रिगर का पता लगाना या कोड द्वारा कॉल करना


सलाह के लिये धन्यवाद। हालाँकि, यह एक द्विआधारी समाधान है - जावास्क्रिप्ट बनाम स्क्रॉल किए गए गैर-जेएस स्क्रॉल का पता लगाता है। मुझे वास्तव में एक टर्नरी समाधान की आवश्यकता है। (जावास्क्रिप्ट, उपयोगकर्ता, ब्राउज़र)। Sidenote, jQuery आपके प्रॉप्स किए गए समाधान के लिए एक आवश्यकता नहीं है।
म्रतशर्मन

-1

यह आपके एप्लिकेशन के साथ मदद नहीं कर सकता है, लेकिन मुझे उपयोगकर्ता स्क्रॉल पर एक घटना को आग लगाने की ज़रूरत थी लेकिन प्रोग्रामिक स्क्रॉल और पोस्टिंग इंसेज़ नहीं है जो किसी और की मदद करता है।

wheelइसके बजाय घटना को सुनें scroll,

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

https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event


element.addEventListener('wheel', (event) => {
       //do user scroll stuff here
})

एक चेतावनी यह है कि wheelमोबाइल पर स्क्रॉल करने से आग नहीं लगती है, इसलिए मैंने जांच की कि क्या डिवाइस मोबाइल था और इसी तरह के फ़ंक्शन का उपयोग किया गया था

if(this.mobile){
  element.addEventListener('scroll', (event) => {
       //do mobile scroll stuff here
  })
}

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