Chrome में पृष्ठ के लोड पर पॉपस्टेट करें


94

मैं अपने वेब ऐप के लिए इतिहास एपीआई का उपयोग कर रहा हूं और एक मुद्दा है। मैं पृष्ठ पर कुछ परिणामों को अपडेट करने के लिए Ajax कॉल करता हूं और पृष्ठ के लोड के बिना ब्राउज़र के स्थान बार को अपडेट करने के लिए history.pushState () का उपयोग करता हूं । फिर, बैक-बटन पर क्लिक करने पर मैं पिछली स्थिति को पुनर्स्थापित करने के लिए window.popstate का उपयोग करता हूं ।

समस्या अच्छी तरह से ज्ञात है - क्रोम और फ़ायरफ़ॉक्स उस पॉपस्टेट घटना को अलग तरीके से मानते हैं। जबकि फ़ायरफ़ॉक्स इसे पहले लोड पर फायर नहीं करता है, क्रोम करता है। मैं फ़ायरफ़ॉक्स शैली रखना चाहता हूँ और लोड पर घटना को आग नहीं देना चाहता क्योंकि यह सिर्फ लोड पर समान लोगों के साथ परिणामों को अपडेट करता है। क्या History.js का उपयोग करने के अलावा कोई वर्कअराउंड है ? इसका उपयोग करने में मेरा मन नहीं लग रहा है - इसके लिए बहुत सारे JS पुस्तकालयों की आवश्यकता है, और चूंकि मुझे इसे पहले से बहुत अधिक JS के साथ CMS में लागू करने की आवश्यकता है, मैं JS को कम से कम करना चाहूंगा। ।

इसलिए, यह जानना चाहते हैं कि क्या क्रोम को लोड करने पर 'पॉपस्टैट' को फायर न करने का कोई तरीका है या हो सकता है कि, किसी ने History.js का उपयोग करने का प्रयास किया क्योंकि सभी लाइब्रेरी एक फ़ाइल में एक साथ मैश हो गईं।


3
जोड़ने के लिए, फ़ायरफ़ॉक्स का व्यवहार विशिष्ट और सही व्यवहार है। Chrome 34 के रूप में, यह अब ठीक हो गया है! ओपेरा देवों के लिए याय!
हेनरी चैन

जवाबों:


49

संस्करण 19 में Google Chrome में @spliter के समाधान ने काम करना बंद कर दिया। जैसा कि @johnnymire ने बताया, Chrome 19 में history.state मौजूद है, लेकिन यह अशक्त है।

मेरा काम विंडो window.history.state! == को जाँचने में है कि क्या विंडो window.history में मौजूद है:

var popped = ('state' in window.history && window.history.state !== null), initialURL = location.href;

मैंने इसे सभी प्रमुख ब्राउज़रों और क्रोम संस्करणों में 19 और 18 में परीक्षण किया। ऐसा लगता है कि यह काम करता है।


5
सर उठाने के लिए धन्यवाद; मुझे लगता है कि आप इसे सरल बना सकते हैं inऔर nullजांच कर सकते हैं != nullक्योंकि यह भी ध्यान रखेगा undefined
pimvdb

5
इसका उपयोग केवल तभी काम करेगा जब आप हमेशा nullअपने history.pushState()तरीकों का उपयोग करें history.pushState(null,null,'http//example.com/)। दी, कि शायद सबसे usages (कि यह कैसे jquery.pjax.js और सबसे अन्य डेमो में स्थापित किया गया है)। लेकिन अगर ब्राउज़र लागू होते हैं window.history.state(जैसे FF और Chrome 19+), तो window.history.state एक रिफ्रेश पर या ब्राउज़र रीस्टार्ट होने के बाद नॉन-नल हो सकता है
unexplainedBacn

19
यह मेरे लिए क्रोम 21 में अब काम नहीं कर रहा है। मैं पेज लोड पर झूठे को पॉपअप करने और फिर किसी भी पुश या पॉप पर सही करने के लिए पॉपअप सेट करने के लिए घाव करता हूं। यह पहले लोड पर क्रोम का पॉप अप करता है। इसे यहाँ थोड़ा बेहतर बताया गया है: github.com/defunkt/jquery-pjax/issues/143#issuecomment-6194330
चाड वॉन नौ

1
@ChadvonNau उत्कृष्ट विचार है, और यह एक इलाज काम करता है - बहुत बहुत धन्यवाद!
sowasred2012

मैं इसी समस्या के साथ आया था और सरल @ChadvonNau समाधान का उपयोग कर रहा था।
फेरेमासन

30

यदि आप प्रत्येक हैंडलर के लिए विशेष उपाय नहीं करना चाहते हैं, जो आपके द्वारा onpopstate में जोड़ा जाता है, तो मेरा समाधान आपके लिए दिलचस्प हो सकता है। इस समाधान का एक बड़ा प्लस यह भी है कि पृष्ठ लोडिंग समाप्त होने से पहले onpopstate घटनाओं को संभाला जा सकता है।

बस इस कोड को चलाने से पहले एक बार किसी भी onpopstate हैंडलर को जोड़ने और सब कुछ अपेक्षित रूप से काम करना चाहिए (मोज़िला ^ ^ की तरह उर्फ)

(function() {
    // There's nothing to do for older browsers ;)
    if (!window.addEventListener)
        return;
    var blockPopstateEvent = document.readyState!="complete";
    window.addEventListener("load", function() {
        // The timeout ensures that popstate-events will be unblocked right
        // after the load event occured, but not in the same event-loop cycle.
        setTimeout(function(){ blockPopstateEvent = false; }, 0);
    }, false);
    window.addEventListener("popstate", function(evt) {
        if (blockPopstateEvent && document.readyState=="complete") {
            evt.preventDefault();
            evt.stopImmediatePropagation();
        }
    }, false);
})();

यह काम किस प्रकार करता है:

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

हालाँकि, जब क्रोम तैयार हो जाता है, तब दस्तावेज़ के रेडीस्टेट पहले से ही "पूर्ण" पर होता है, हम गलत तरीके से चालू करते हैं, जिससे दस्तावेज़ लोड होने से पहले दस्तावेज़ लोड होने की अनुमति देने से पहले दस्तावेज़ लोडिंग समाप्त कर दिया गया है।

अपडेट 2014-04-23: एक बग फिक्स्ड जहां पेज लोड होने के बाद स्क्रिप्ट निष्पादित होने पर पॉपस्टैट इवेंट को ब्लॉक कर दिया गया है।


4
मेरे लिए अब तक का सबसे अच्छा समाधान। मैं वर्षों से setTimeout पद्धति का उपयोग कर रहा हूं, लेकिन जब पृष्ठ धीरे-धीरे लोड हो रहा होता है, तो उपयोगकर्ता को बहुत जल्दी पुश करने पर यह बगिया व्यवहार का कारण बनता है। window.history.stateयदि कोई राज्य सेट किया गया था, तो पुनः लोड करने में विफल रहता है। पुशस्टेट क्लुटर्स कोड से पहले वेरिएबल सेट करना। आपका समाधान सुरुचिपूर्ण है और बाकी कोडबस को प्रभावित किए बिना अन्य लिपियों के शीर्ष पर गिराया जा सकता है। धन्यवाद।
किक

4
यह समाधान है! यदि केवल इस समस्या को हल करने का प्रयास करते समय मैंने इसे बहुत पहले ही पढ़ लिया था। यह एकमात्र ऐसा काम है जिसने निर्दोष रूप से काम किया है। धन्यवाद!
बेन फ्लेमिंग

1
उत्कृष्ट व्याख्या और एक कोशिश के लायक एकमात्र समाधान।
सनी आर गुप्ता

यह एक बेहतरीन उपाय है। लेखन के समय, नवीनतम क्रोम और एफएफ ठीक है, मुद्दा सफारी (मैक और आईफोन) के साथ है। यह समाधान एक आकर्षण की तरह काम करता है।
विन

1
यहाँ प्रारंभ करें यदि सफारी आपके दिन को बर्बाद कर रही है, तो ये वे कोड हैं जिनकी आप तलाश कर रहे हैं!
डैनो

28

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

यहाँ मेरा समाधान है: https://gist.github.com/3551566

/*
* Necessary hack because WebKit fires a popstate event on document load
* https://code.google.com/p/chromium/issues/detail?id=63040
* https://bugs.webkit.org/process_bug.cgi
*/
window.addEventListener('load', function() {
  setTimeout(function() {
    window.addEventListener('popstate', function() {
      ...
    });
  }, 0);
});

यह एकमात्र समाधान है जिसने मेरे लिए काम किया। धन्यवाद!
जस्टिन

3
मिठाई! सबसे उत्थान और / या स्वीकृत उत्तर से बेहतर काम करता है!
ProblemsOfSumit

किसी को भी इस समाधान के लिए सक्रिय लिंक है, मैं दिए गए लिंक नहीं पहुँच सकते हैं gist.github.com/3551566
हरबीर

1
आपको जिस्ट की आवश्यकता क्यों है?
बजे ओलेग वासकेविच

एकदम सही जवाब। धन्यवाद।
साइडरोक्सिलोन

25

समाधान jquery.pjax.js लाइनों में पाया गया है 195-225:

// Used to detect initial (useless) popstate.
// If history.state exists, assume browser isn't going to fire initial popstate.
var popped = ('state' in window.history), initialURL = location.href


// popstate handler takes care of the back and forward buttons
//
// You probably shouldn't use pjax on pages with other pushState
// stuff yet.
$(window).bind('popstate', function(event){
  // Ignore inital popstate that some browsers fire on page load
  var initialPop = !popped && location.href == initialURL
  popped = true
  if ( initialPop ) return

  var state = event.state

  if ( state && state.pjax ) {
    var container = state.pjax
    if ( $(container+'').length )
      $.pjax({
        url: state.url || location.href,
        fragment: state.fragment,
        container: container,
        push: false,
        timeout: state.timeout
      })
    else
      window.location = location.href
  }
})

8
इस समाधान ने मेरे लिए विंडोज (क्रोम 19) पर काम करना बंद कर दिया, फिर भी मैक (क्रोम 18) पर काम कर रहा है। इतिहास की तरह लगता है
.स्टेट

1
@johnnymire मैंने Chrome 19 लोअर के लिए अपना समाधान पोस्ट किया: stackoverflow.com/a/10651028/291500
Pavel Linkesch

इस पोस्ट-क्रोम 19 व्यवहार को प्रतिबिंबित करने के लिए किसी को इस उत्तर को संपादित करना चाहिए।
जॉर्ज सुआरेज़ डे लिस

5
समाधान की तलाश में किसी के लिए, टोरेन का जवाब आज के वर्तमान क्रोम और फ़ायरफ़ॉक्स संस्करणों पर एक आकर्षण की तरह काम करता है
जोर्ज सुआरेज़ डे लिस

1
अब अप्रैल 2015 में, मैंने सफारी के साथ एक मुद्दे को हल करने के लिए इस समाधान का उपयोग किया। कॉर्डोवा का उपयोग करते हुए हाइब्रिड आईओएस / एंड्रॉइड ऐप पर बैक बटन दबाने से निपटने के लिए मुझे ऑनपॉपस्टेट इवेंट का उपयोग करना पड़ा। सफारी एक रीलोड के बाद भी अपने onpopstate को आग लगाती है, जिसे मैंने प्रोग्रामेटिक रूप से कॉल किया। जिस तरह से मेरा कोड सेटअप था, वह पुनः लोड () कहे जाने के बाद एक अनंत लूप में चला गया। इसने इसे ठीक कर दिया। मुझे केवल घोषणा के बाद पहली 3 पंक्तियों की आवश्यकता थी (प्लस शीर्ष पर असाइनमेंट)।
मार्तविस पी।

14

Pjax को फिर से लागू करने की तुलना में अधिक प्रत्यक्ष समाधान पुशस्टैट पर एक चर सेट किया गया है, और popState पर चर की जांच करें, इसलिए प्रारंभिक popState लोड पर असंगत रूप से आग नहीं लगाता है (न कि jquery- विशिष्ट समाधान, बस घटनाओं के लिए):

$(window).bind('popstate', function (ev){
  if (!window.history.ready && !ev.originalEvent.state)
    return; // workaround for popstate on load
});

// ... later ...

function doNavigation(nextPageId) {
  window.history.ready = true;

  history.pushState(state, null, 'content.php?id='+ nextPageId); 
  // ajax in content instead of loading server-side
}

हमेशा झूठे का मूल्यांकन करने पर ऐसा नहीं होगा? मेरा मतलब है, window.history.readyहमेशा सच है।
एंड्री Drozdyuk

उदाहरण को थोड़ा और स्पष्ट होने के लिए अद्यतन करें। मूल रूप से, आप केवल ऑल-क्लीयर देने के लिए केवल पॉपस्टेट घटनाओं को संभालना चाहते हैं। आप लोड के बाद एक सेटटाइमआउट 500ms के साथ एक ही प्रभाव प्राप्त कर सकते हैं, लेकिन ईमानदार होने के लिए यह थोड़ा सस्ता है।
टॉम मैकेंजी

3
यह उत्तर IMO होना चाहिए, मैंने पावेल्स समाधान की कोशिश की और यह फ़ायरफ़ॉक्स में ठीक से काम नहीं किया
पोर्को

इस कष्टप्रद समस्या के आसान समाधान के रूप में इसने मेरे लिए काम किया। आपका बहुत बहुत धन्यवाद!
नीरजुल

!window.history.ready && !ev.originalEvent.state- पृष्ठ को रीफ्रेश करने पर वे दो चीजें कभी परिभाषित नहीं होती हैं । इसलिए कोई कोड निष्पादित नहीं करता है।
चॉवी 27'13

4

वेबकिट के प्रारंभिक onpopstate ईवेंट को कोई राज्य असाइन नहीं किया गया है, इसलिए आप अवांछित व्यवहार की जांच के लिए इसका उपयोग कर सकते हैं:

window.onpopstate = function(e){
    if(e.state)
        //do something
};

एक व्यापक समाधान, मूल पृष्ठ पर नेविगेशन के लिए अनुमति देता है, इस विचार पर निर्माण करेगा:

<body onload="init()">
    <a href="page1" onclick="doClick(this); return false;">page 1</a>
    <a href="page2" onclick="doClick(this); return false;">page 2</a>
    <div id="content"></div>
</body>

<script>
function init(){
   openURL(window.location.href);
}
function doClick(e){
    if(window.history.pushState)
        openURL(e.getAttribute('href'), true);
    else
        window.open(e.getAttribute('href'), '_self');
}
function openURL(href, push){
    document.getElementById('content').innerHTML = href + ': ' + (push ? 'user' : 'browser'); 
    if(window.history.pushState){
        if(push)
            window.history.pushState({href: href}, 'your page title', href);
        else
            window.history.replaceState({href: href}, 'your page title', href);
    }
}
window.onpopstate = function(e){
    if(e.state)
        openURL(e.state.href);
};
</script>

हालांकि यह अभी भी दो बार (कुछ निफ्टी नेविगेशन के साथ) आग लगा सकता है , इसे पिछले href के खिलाफ एक चेक के साथ ही हैंडल किया जा सकता है।


1
धन्यवाद। Pjax समाधान ने iOS 5.0 पर काम करना बंद कर दिया है क्योंकि window.history.stateयह iOS में भी अशक्त है। बस जाँच अगर e.state संपत्ति शून्य है पर्याप्त है।
हुस्की

क्या इस समाधान के साथ कोई ज्ञात समस्याएं हैं? यह मेरे द्वारा परीक्षण किए गए किसी भी ब्राउज़र पर पूरी तरह से काम करता है।
याकूब

3

यह मेरा काम है।

window.setTimeout(function() {
  window.addEventListener('popstate', function() {
    // ...
  });
}, 1000);

Ubuntu पर क्रोमियम 28 पर मेरे लिए नहीं। कभी-कभी, घटना अभी भी निकाल दी जाती है।
जॉर्ज सुआरेज़ डे लिस

खुद की कोशिश की, हमेशा काम नहीं करता है। कभी-कभी पॉपस्टैट प्रारंभिक पृष्ठ लोड के आधार पर टाइमआउट की तुलना में बाद में आग लगाता है
एंड्रयू बर्गेस

1

यहाँ मेरा समाधान है:

var _firstload = true;
$(function(){
    window.onpopstate = function(event){
        var state = event.state;

        if(_firstload && !state){ 
            _firstload = false; 
        }
        else if(state){
            _firstload = false;
            // you should pass state.some_data to another function here
            alert('state was changed! back/forward button was pressed!');
        }
        else{
            _firstload = false;
            // you should inform some function that the original state returned
            alert('you returned back to the original state (the home state)');
        }
    }
})   

0

पृष्ठ लोड पर क्रोम को आग न लगाने के लिए Chrome प्राप्त करने का सबसे अच्छा तरीका https://code.google.com/p/chromium/issues/detail?id=63040 है । वे जानते हैं कि Chrome अभी दो पूर्ण वर्षों के लिए HTML5 कल्पना के अनुपालन में नहीं है और अभी भी इसे ठीक नहीं किया है!


2
यह क्रोम 34 के बाद से तय किया गया है।
matys84pl

0

event.state !== nullइतिहास में पहले लोड किए गए पृष्ठ पर वापस लौटने के उपयोग के मामले में, गैर मोबाइल ब्राउज़रों में काम नहीं करेगा। जब अजाक्स नेविगेशन वास्तव में शुरू होता है, तो मैं सत्रस्टेजेज का उपयोग करता हूं।

history.pushState(url, null, url);
sessionStorage.ajNavStarted = true;

window.addEventListener('popstate', function(e) {
    if (sessionStorage.ajNavStarted) {
        location.href = (e.state === null) ? location.href : e.state;
    }
}, false);


window.onload = function () {if (history.state === null) {history.replaceState (location.pathname + location.search + location.hash, null, location.pathname + location.sath + location.hash); }}; window.addEventListener ('popstate', function (e) {if (e.state! == null) {location.href = e.state;}}, false);
इल्यूजनिस्ट

-1

प्रस्तुत समाधान में पृष्ठ पुनः लोड करने में समस्या है। निम्नलिखित बेहतर काम करने लगता है, लेकिन मैंने केवल फ़ायरफ़ॉक्स और क्रोम का परीक्षण किया है। यह वास्तविकता का उपयोग करता है, कि इसमें e.event.stateऔर के बीच अंतर प्रतीत होता है window.history.state

window.addEvent('popstate', function(e) {
    if(e.event.state) {
        window.location.reload(); // Event code
    }
});

e.eventअपरिभाषित है
chovy

-1

मुझे पता है कि आपने इसके खिलाफ पूछा था, लेकिन आपको वास्तव में History.js का उपयोग करना चाहिए क्योंकि यह एक लाख ब्राउज़र असंगतता को साफ़ करता है। मैं केवल बाद में खोजने के लिए मैनुअल फिक्स मार्ग पर गया था और अधिक से अधिक समस्याएं थीं कि आप केवल सड़क के नीचे का रास्ता खोज लेंगे। यह वास्तव में आजकल उतना कठिन नहीं है:

<script src="//cdnjs.cloudflare.com/ajax/libs/history.js/1.8/native.history.min.js" type="text/javascript"></script>

और https://github.com/browserstate/history.js पर एपीआई पढ़ें


-1

इससे मेरे लिए समस्या हल हो गई। मैंने किया था एक टाइमआउट फ़ंक्शन सेट किया गया था जो पगेलोड पर निकाल दी गई पॉपस्टेट घटना को याद करने के लिए फ़ंक्शन के निष्पादन में देरी करता है

if (history && history.pushState) {
  setTimeout(function(){
    $(window).bind("popstate", function() {
      $.getScript(location.href);
    });
  },3000);
}

-2

आप एक ईवेंट बना सकते हैं और इसे अपने ऑनलोड हैंडलर के बाद फायर कर सकते हैं।

var evt = document.createEvent("PopStateEvent");
evt.initPopStateEvent("popstate", false, false, { .. state object  ..});
window.dispatchEvent(evt);

ध्यान दें, यह क्रोम / सफारी में थोड़ा टूट गया है, लेकिन मैंने पैच को WebKit में जमा कर दिया है और यह जल्द ही उपलब्ध होना चाहिए, लेकिन यह "सबसे सही" तरीका है।


-2

इसने मेरे लिए फ़ायरफ़ॉक्स और क्रोम में काम किया

window.onpopstate = function(event) { //back button click
    console.log("onpopstate");
    if (event.state) {
        window.location.reload();
    }
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.