एचटीएमएल 5 इतिहास पॉपस्टेट पर ब्राउज़र स्क्रॉल को रोकें


83

क्या एक पॉपस्टेट घटना होने पर दस्तावेज़ को स्क्रॉल करने के डिफ़ॉल्ट व्यवहार को रोकना संभव है?

हमारी साइट jQuery के एनिमेटेड स्क्रॉलिंग और History.js का उपयोग करती है, और राज्य के परिवर्तनों को उपयोगकर्ता को पेज के विभिन्न क्षेत्रों में पुशस्टेट या पॉपस्टेट के माध्यम से स्क्रॉल करना चाहिए। मुसीबत यह है कि ब्राउज़र जब एक पॉपस्टैट घटना होती है तो पिछली स्थिति की स्क्रॉल स्थिति को स्वचालित रूप से पुनर्स्थापित करता है।

मैंने एक कंटेनर तत्व का उपयोग करके दस्तावेज़ की 100% चौड़ाई और ऊंचाई पर सेट करने की कोशिश की है और उस कंटेनर के अंदर की सामग्री को स्क्रॉल किया है। समस्या यह है कि मैंने पाया है कि यह दस्तावेज़ को स्क्रॉल करने जितना आसान नहीं है; खासकर अगर बॉक्स-शैडो और ग्रेडिएंट जैसे बहुत सारे सीएसएस 3 का उपयोग कर रहे हैं।

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

फ़ायरफ़ॉक्स पृष्ठ को स्क्रॉल करता है (और स्क्रॉल घटना को आग लगाता है) पहले पॉपस्टैट फायर और क्रोम आग को पहले पॉपस्टैट करता है फिर दस्तावेज़ को स्क्रॉल करता है।

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

क्या यह संभव है कि दस्तावेज़ को पॉपस्टेट घटनाओं पर स्क्रॉल किया जाए?


आपको स्क्रॉल स्थिति सेट करने के बाद एक तत्व आयाम (पृष्ठ रीफ़्लो के लिए बाध्य करने) को पढ़ने के साथ कुछ सफलता मिल सकती है। उदाहरण के लिए, document.body.clientHeightलेकिन मैंने इसे सभी ब्राउज़रों में काम करते नहीं देखा।
सीन होगन

क्या होगा अगर आपने दस्तावेज़ के स्क्रॉल फ़ंक्शन में हेरफेर किया, तो वह वह है जहां मैं कम से कम शुरू करूंगा। यहाँ इसके लिए एक समाधान है: stackoverflow.com/questions/7035331/…
जेफ़ वुडेन

जवाबों:


67
if ('scrollRestoration' in history) {
  history.scrollRestoration = 'manual';
}

( 2 सितंबर 2015 को Google द्वारा घोषित )

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

क्रोम: समर्थित (46 के बाद से)

फ़ायरफ़ॉक्स: समर्थित (46 के बाद से)

IE / एज: समर्थित नहीं है, समर्थन के लिए पूछें (तब टिप्पणी में लिंक छोड़ दें)

ओपेरा: समर्थित (33 के बाद से)

सफ़ारी: समर्थित

अधिक जानकारी के लिए, MDN पर ब्राउज़र संगतता देखें ।


1
कम: history.scrollRestoration && history.scrollRestoration = 'manual';या यहाँ तक किvar sr = 'scrollRestoration'; history[sr] && history[sr] = 'manual';
भरत

31

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

भविष्य के लिए आशा है, हालांकि, यदि आप HTML5 इतिहास युक्ति को देखते हैं , जो स्पष्ट रूप से स्क्रॉल स्थिति के लिए राज्य वस्तु पर प्रतिनिधित्व करने की इच्छा रखता है:

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

यह, और यदि आप ऊपर उल्लिखित मोज़िला टिकट पर टिप्पणियों को पढ़ते हैं, तो कुछ संकेत देता है कि यह संभव है कि निकट भविष्य में स्क्रॉल स्थिति को अब बहाल नहीं किया जाएगा onpopstate, कम से कम उपयोग करने वाले लोगों के लिए pushState

दुर्भाग्य से, तब तक, स्क्रॉल स्थिति संग्रहीत हो जाती है जब pushStateउपयोग किया जाता है, और replaceStateस्क्रॉल स्थिति को प्रतिस्थापित नहीं करता है। अन्यथा, यह काफी आसान होगा, और आप replaceStateवर्तमान स्क्रॉल स्थिति को सेट करने के लिए उपयोग कर सकते हैं उपयोगकर्ता ने हर बार पृष्ठ को स्क्रॉल किया है (कुछ सतर्क onscroll हैंडलर के साथ)।

दुर्भाग्य से, HTML5 कल्पना निर्दिष्ट नहीं करती है जब वास्तव में popstateघटना को निकाल दिया जाना है, यह सिर्फ कहता है: «कुछ मामलों में निकाल दिया जाता है जब सत्र इतिहास प्रविष्टि» पर नेविगेट करते हुए, जो स्पष्ट रूप से यह नहीं कहता है कि यह पहले या बाद में है; यदि यह हमेशा से पहले था, तो पॉपस्टैट के बाद होने वाले स्क्रॉलिंग इवेंट को संभालने के साथ एक समाधान संभव होगा।

स्क्रॉल ईवेंट रद्द करें?

इसके अलावा, यह भी आसान होगा, अगर स्क्रॉल घटना जहां रद्द करने योग्य है, जो यह नहीं है। यदि ऐसा होता है, तो आप किसी श्रृंखला की पहली स्क्रॉल घटना को रद्द कर सकते हैं (उपयोगकर्ता स्क्रॉल इवेंट लेमिंग्स की तरह हैं, वे दर्जनों में आते हैं, जबकि इतिहास के रिप्रोड्यूसिंग द्वारा चलाई गई स्क्रॉल घटना एक ही है), और आप ठीक होंगे।

अब कोई समाधान नहीं है

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


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

4

आप यहाँ पर किसी प्रकार के भयानक ब्राउज़र को सूँघने जा रहे हैं। फ़ायरफ़ॉक्स के लिए, मैं स्क्रॉल स्थिति को संग्रहीत करने और इसे पुनर्स्थापित करने के आपके समाधान के साथ जाऊंगा।

मुझे लगा कि आपके विवरण के आधार पर मेरे पास एक अच्छा वेबकिट समाधान है, लेकिन मैंने अभी क्रोम 21 में कोशिश की थी, और ऐसा लगता है कि क्रोम पहले स्क्रॉल करता है, फिर पॉपस्टैट इवेंट को फायर करता है, फिर स्क्रॉल इवेंट को फायर करता है। लेकिन संदर्भ के लिए, मैं यहाँ आया हूँ:

function noScrollOnce(event) {
    event.preventDefault();
    document.removeEventListener('scroll', noScrollOnce);
}
window.onpopstate = function () {
    document.addEventListener('scroll', noScrollOnce);
};​

काला जादू जैसे कि पेज को दिखाते हुए पोस्ट किए गए absoluteतत्व को आगे बढ़ाकर स्क्रॉल किया जाता है, स्क्रीन को पुन: गति से भी खारिज किया जाता है।

तो मैं 99% यकीन है कि जवाब है कि आप नहीं कर सकते हैं, और आप सवाल में उल्लेख किया है समझौता का उपयोग करने के लिए जा रहे हैं। जावास्क्रिप्ट के बारे में कुछ भी जानने से पहले दोनों ब्राउज़र स्क्रॉल करते हैं, इसलिए जावास्क्रिप्ट केवल घटना के बाद ही प्रतिक्रिया कर सकता है। अंतर केवल इतना है कि जावास्क्रिप्ट को निकाल देने के बाद फ़ायरफ़ॉक्स स्क्रीन को पेंट नहीं करता है, यही वजह है कि फ़ायरफ़ॉक्स में एक व्यावहारिक समाधान है, लेकिन वेबकिट में नहीं।


3

अब आप कर सकते हैं

history.scrollRestoration = 'manual';

और यह ब्राउज़र स्क्रॉल को रोकना चाहिए। यह अभी केवल क्रोम 46 और इसके बाद के संस्करण में काम करता है, लेकिन ऐसा लगता है कि फ़ायरफ़ॉक्स इसे भी समर्थन देने की योजना बना रहा है


2

समाधान पेज की स्क्रॉल स्थिति के बराबर उपयोग position: fixedऔर निर्दिष्ट topकरना है।

यहाँ एक उदाहरण है:

$(window).on('popstate', function()
{
   $('.yourWrapAroundAllContent').css({
      position: 'fixed',
      top: -window.scrollY
   });

   requestAnimationFrame(function()
   {
      $('.yourWrapAroundAllContent').css({
         position: 'static',
         top: 0
      });          
   });
});

हां, आप इसके बजाय फ़्लिकरिंग स्क्रॉलबार प्राप्त करते हैं, लेकिन यह कम बुराई है।


1

सभी ब्राउज़र में निम्नलिखित फिक्स काम करना चाहिए।

आप अनलोड घटना पर स्क्रॉल स्थिति को 0 पर सेट कर सकते हैं। आप यहां इस ईवेंट के बारे में पढ़ सकते हैं: https://developer.mozilla.org/en-US/docs/Web/Events/nload । पेज को छोड़ने से पहले अनिवार्य रूप से, अनलोड घटना ठीक हो जाती है।

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

//Listen for unload event. This is triggered when leaving the page.
//Reference: https://developer.mozilla.org/en-US/docs/Web/Events/unload
window.addEventListener('unload', function(e) {
    //set scroll position to the top of the page.
    window.scrollTo(0, 0);
});

1

मेरे लिए काम नहीं करने के लिए स्क्रॉलरैस्टिलेशन सेट करना, यहाँ मेरा समाधान है।

window.addEventListener('popstate', function(e) {
    var scrollTop = document.body.scrollTop;
    window.addEventListener('scroll', function(e) {
        document.body.scrollTop = scrollTop;
    });
});

0

पृष्ठ के शीर्ष पर कहीं एक 'स्पैन' तत्व बनाएं और लोड पर इस पर ध्यान केंद्रित करें। ब्राउजर फोकस्ड एलिमेंट पर स्क्रॉल करेगा। मैं समझता हूं कि यह एक वर्कअराउंड है और सभी ब्राउज़र (uhmmm .. Safari) में 'स्पैन' काम नहीं करता है। उम्मीद है की यह मदद करेगा।


0

यहां मैंने एक साइट पर लागू किया है जो पोस्टस्टेट को निकाल दिए जाने पर एक विशिष्ट तत्व पर ध्यान केंद्रित करने के लिए स्क्रॉल स्थिति चाहता था (बैक बटन):

$(document).ready(function () {

     if (window.history.pushState) {
        //if push supported - push current page onto stack:
        window.history.pushState(null, document.title, document.location.href);
    }

    //add handler:
    $(window).on('popstate', PopStateHandler);
}

//fires when the back button is pressed:
function PopStateHandler(e) {
    emnt= $('#elementID');
    window.scrollTo(0, emnt.position().top);
    alert('scrolling to position');
}

परीक्षण किया और फ़ायरफ़ॉक्स में काम करता है।

Chrome स्थिति में स्क्रॉल करेगा लेकिन फिर मूल स्थान पर वापस जाएगा।


0

जैसे दूसरों ने कहा, ऐसा करने का कोई वास्तविक तरीका नहीं है, केवल बदसूरत हैकी तरीका है। स्क्रॉल ईवेंट श्रोता को हटाने से मेरे लिए काम नहीं किया गया, इसलिए यह करने के लिए मेरा बदसूरत तरीका है:

/// GLOBAL VARS ////////////////////////
var saveScrollPos = false;
var scrollPosSaved = window.pageYOffset;
////////////////////////////////////////

jQuery(document).ready(function($){

    //// Go back with keyboard shortcuts ////
    $(window).keydown(function(e){
        var key = e.keyCode || e.charCode;

        if((e.altKey && key == 37) || (e.altKey && key == 39) || key == 8)
        saveScrollPos = false;
    });
    /////////////////////////////////////////

    //// Go back with back button ////
    $("html").bind("mouseout",  function(){ saveScrollPos = false; });
    //////////////////////////////////

    $("html").bind("mousemove", function(){ saveScrollPos = true; });

    $(window).scroll(function(){
        if(saveScrollPos)
        scrollPosSaved = window.pageYOffset;
        else
        window.scrollTo(0, scrollPosSaved);
    });

});

यह Chrome, FF और IE में काम करता है (यह पहली बार जब आप IE में वापस जाता है)। किसी भी सुधार सुझाव का स्वागत है! उम्मीद है की यह मदद करेगा।


-5

यह कोशिश करना चाहते हो सकता है?

window.onpopstate = function(event) {
  return false;
};

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