फ़ायरफ़ॉक्स में काम नहीं कर रहा चेतन स्क्रॉल


164

यह फ़ंक्शन ठीक काम करता है। यह शरीर को एक वांछित कंटेनर के ऑफसेट तक स्क्रॉल करता है

function scrolear(destino){
    var stop = $(destino).offset().top;
    var delay = 1000;
    $('body').animate({scrollTop: stop}, delay);
    return false;
}

लेकिन फ़ायरफ़ॉक्स में नहीं। क्यों?

-EDIT-

स्वीकृत उत्तर में डी डबल ट्रिगर को संभालने के लिए, मेरा सुझाव है कि एनीमेशन से पहले तत्व को रोकना:

$('body,html').stop(true,true).animate({scrollTop: stop}, delay);

2
आपका अंतिम कोड यहां के सभी सामानों में सबसे सुरुचिपूर्ण है।
छिपकली

जवाबों:


331

फ़ायरफ़ॉक्स htmlस्तर पर अतिप्रवाह रखता है, जब तक कि विशेष रूप से अलग तरह से व्यवहार करने के लिए स्टाइल नहीं किया जाता है।

इसे फ़ायरफ़ॉक्स में काम करने के लिए, उपयोग करें

$('body,html').animate( ... );

काम करने का उदाहरण

CSS समाधान निम्नलिखित शैलियों को सेट करने के लिए होगा:

html { overflow: hidden; height: 100%; }
body { overflow: auto; height: 100%; }

मुझे लगता है कि जेएस समाधान कम से कम आक्रामक होगा।


अपडेट करें

नीचे बहुत सारी चर्चा इस तथ्य पर केंद्रित है कि scrollTopदो तत्वों के एनिमेशन से कॉलबैक को दो बार लागू किया जा सकता है। ब्राउज़र-डिटेक्शन सुविधाओं का सुझाव दिया गया है और बाद में हटा दिया गया है, और कुछ यकीनन दूर की कौड़ी हैं।

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

function runOnce(fn) { 
    var count = 0; 
    return function() { 
        if(++count == 1)
            fn.apply(this, arguments);
    };
};

$('body, html').animate({ scrollTop: stop }, delay, runOnce(function() {
   console.log('scroll complete');
}));

51
जेएस समाधान में एक दोष है! चेतन फ़ंक्शन को दो बार क्रमशः html एलिमेंट और बॉडी एलिमेंट के लिए निष्पादित किया जाता है। ऐसा लगता है कि वेबकिट ब्राउज़र शरीर का उपयोग करते हैं और शेष HTML का उपयोग करता है । यह फिक्स काम करना चाहिए$(jQuery.browser.webkit ? "body": "html").animate(...);
आंद्रेइको डि

2
मैंने पाया कि आंद्रेको से समाधान jQuery <1.4 में काम नहीं किया था जो मैं उपयोग कर रहा था। मैं इसे इस तरह से ठीक करने में सक्षम था $(jQuery.browser.mozilla ? "html" : "body").animate(...);:। यह ब्राउज़ सूँघने, लेकिन सुविधा का पता लगाने का उपयोग नहीं करने के लिए बहुत अच्छा होगा। सीएसएस पर फीचर डिटेक्शन कैसे करें, यह सुनिश्चित नहीं है
रुस्तवोर

23
ध्यान दें, jQuery.browserनवीनतम jQuery संस्करण से हटा दिया गया है और गायब है
spiderplant0

2
4 साल, और यह जवाब अभी भी उपयोगी साबित हो रहा है। बहुत बहुत धन्यवाद!
मैट

1
@ डफ: मुख्य रूप से, क्योंकि window.scrollचेतन नहीं है। आप निश्चित रूप से अपनी खुद की चीज़ को अंतराल के साथ रोल कर सकते हैं और scrollBy। यदि आप उस में आसानी जोड़ना चाहते हैं, तो आपके पास अपने उत्पाद के बजाय मामूली पहलू के लिए लिखने के लिए अचानक बहुत सारे कोड हैं।
डेविड हेडलंड

19

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

$('html, body')
    .animate({ scrollTop: 100 })
    .promise()
    .then(function(){
        // callback code here
    })
});

अद्यतन: यहाँ आप इसके बजाय सुविधा का उपयोग कैसे कर सकते हैं। कोड का यह हिस्सा आपके एनीमेशन कॉल से पहले मूल्यांकन करने की आवश्यकता है:

// Note that the DOM needs to be loaded first, 
// or else document.body will be undefined
function getScrollTopElement() {

    // if missing doctype (quirks mode) then will always use 'body'
    if ( document.compatMode !== 'CSS1Compat' ) return 'body';

    // if there's a doctype (and your page should)
    // most browsers will support the scrollTop property on EITHER html OR body
    // we'll have to do a quick test to detect which one...

    var html = document.documentElement;
    var body = document.body;

    // get our starting position. 
    // pageYOffset works for all browsers except IE8 and below
    var startingY = window.pageYOffset || body.scrollTop || html.scrollTop;

    // scroll the window down by 1px (scrollTo works in all browsers)
    var newY = startingY + 1;
    window.scrollTo(0, newY);

    // And check which property changed
    // FF and IE use only html. Safari uses only body.
    // Chrome has values for both, but says 
    // body.scrollTop is deprecated when in Strict mode.,
    // so let's check for html first.
    var element = ( html.scrollTop === newY ) ? 'html' : 'body';

    // now reset back to the starting position
    window.scrollTo(0, startingY);

    return element;
}

// store the element selector name in a global var -
// we'll use this as the selector for our page scrolling animation.
scrollTopElement = getScrollTopElement();

अब उस संस्करण का उपयोग करें जिसे हमने पृष्ठ स्क्रॉलिंग एनीमेशन के चयनकर्ता के रूप में परिभाषित किया है, और नियमित सिंटैक्स का उपयोग करें:

$(scrollTopElement).animate({ scrollTop: 100 }, 500, function() {
    // normal callback
});

सामान्य परिस्थितियों में महान काम करता है, धन्यवाद! हालाँकि, इसके बारे में जागरूक होने के लिए कुछ जोड़े हैं। (1) यदि फीचर टेस्ट चलने पर विंडो ओवरफ्लो करने के लिए शरीर के पास पर्याप्त सामग्री नहीं है, तो विंडो स्क्रॉल नहीं होगी और परीक्षण एक फर्जी "बॉडी" परिणाम देता है। (2) यदि परीक्षण iOS में एक iframe के अंदर चलता है, तो यह उसी कारण से विफल हो जाता है। IOS में iframes तब तक लंबवत (क्षैतिज रूप से नहीं) तक विस्तारित होते हैं, जब तक कि सामग्री स्क्रॉल किए बिना अंदर फिट न हो जाए। (3) क्योंकि परीक्षण मुख्य विंडो में निष्पादित किया जाता है, यह स्क्रॉल हैंडलर्स को ट्रिगर करता है जो पहले से ही जगह में हैं। ... (जारी)
hashchange

... इन कारणों से, बुलेटप्रूफ टेस्ट को एक समर्पित iframe (सॉल्वेस (3)) के साथ बड़े-पर्याप्त सामग्री (सॉल्व्स (1)) के साथ चलाना होगा, जिसे क्षैतिज स्क्रॉल (सॉल्व्स (2)) के लिए परीक्षण किया गया है।
hashchange

मुझे वास्तव में इस फ़ंक्शन को सुसंगत परिणाम देने के लिए टाइमआउट स्क्रिप्ट में चलाना था, अन्यथा यह कभी-कभी वापसी htmlऔर कभी- कभी वापसी करने के लिए लगता था body। फ़ंक्शन घोषित करने के बाद यहां मेरा कोड है var scrollTopElement; setTimeout( function() { scrollTopElement = getScrollTopElement(); console.log(scrollTopElement); }, 1000); हालांकि इसके लिए धन्यवाद, इसने मेरी समस्या हल कर दी है।
टोनी एम

कोई बात नहीं, मुझे पता चला कि वास्तविक मुद्दा क्या है। यदि आप पुनः लोड होने (f5) के पहले से ही पृष्ठ के निचले भाग में हैं, तो यह स्क्रिप्ट पसंद आने के htmlबजाय वापस आ जाएगी body। यह केवल तभी है जब आप वेबपेज को सभी तरह से स्क्रॉल करते हैं और आप पुनः लोड करते हैं, अन्यथा यह काम करता है।
टोनी एम

पृष्ठ के निचले भाग में खुलने के बाद मैंने उसके लिए एक चेक जोड़ा तो मेरे लिए यह काम किया।
स्कॉट

6

मैंने उम्र बिताने की कोशिश की कि मेरा कोड काम क्यों नहीं करेगा -

$('body,html').animate({scrollTop: 50}, 500);

समस्या मेरे सीएसएस में थी -

body { height: 100%};

मैंने इसे autoइसके बजाय सेट किया (और इस बात की चिंता छोड़ दी गई कि इसे 100%पहली जगह में क्यों सेट किया गया था )। उसने मेरे लिए इसे हल कर दिया।


2

तुम एक प्लगइन का उपयोग करके इस मुद्दे को चकमा देना चाहते हो सकता है - विशेष रूप से, मेरे प्लगइन :)

गंभीरता से, भले ही मूल समस्या लंबे समय से संबोधित की गई है (विभिन्न ब्राउज़र विंडो स्क्रॉलिंग के लिए अलग-अलग तत्वों का उपयोग करते हैं), लाइन के नीचे कुछ गैर-तुच्छ मुद्दे हैं जो आपको यात्रा कर सकते हैं:

मैं स्पष्ट रूप से पक्षपाती हूं, लेकिन jQuery.scrollable वास्तव में इन मुद्दों को संबोधित करने के लिए एक अच्छा विकल्प है। (वास्तव में, मुझे किसी अन्य प्लगइन का पता नहीं है जो उन सभी को संभालता है।)

एक है जो आप के लिए स्क्रॉल - - के साथ एक बुलेट प्रूफ तरह से इसके अलावा, आप लक्षित स्थिति पर गणना कर सकते हैं इस सार में समारोहgetScrollTargetPosition()

जिससे सभी आपका साथ छोड़ दें

function scrolear ( destino ) {
    var $window = $( window ),
        targetPosition = getScrollTargetPosition ( $( destino ), $window );

    $window.scrollTo( targetPosition, { duration: 1000 } );

    return false;
}

1

इससे सावधान रहें। मुझे एक ही समस्या थी, न तो फ़ायरफ़ॉक्स या एक्सप्लोरर स्क्रॉलिंग के साथ

$('body').animate({scrollTop:pos_},1500,function(){do X});

तो मैंने इस्तेमाल किया जैसे डेविड ने कहा

$('body, html').animate({scrollTop:pos_},1500,function(){do X});

महान यह काम किया, लेकिन नई समस्या है, क्योंकि दो तत्व हैं, शरीर और HTML, फ़ंक्शन को दो बार निष्पादित किया जाता है, यह है, एक्स दो बार चलाता है।

केवल 'html' और फ़ायरफ़ॉक्स और एक्सप्लोरर के साथ काम करने की कोशिश की गई, लेकिन अब क्रोम इसका समर्थन नहीं करता है।

इसलिए क्रोम और फ़ायरफ़ॉक्स और एक्सप्लोरर के लिए HTML की आवश्यकता है। क्या यह एक jQuery बग है? नहीं पता।

बस अपने फ़ंक्शन से सावधान रहें, क्योंकि यह दो बार चलेगा।


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

2
.stop (सच्चा, सच्चा) .animate के बारे में क्या?
टोनी मिशेल Caubet

0

मैं सिफारिश करेंगे नहीं पर भरोसा bodyहै और न ही htmlएक अधिक पोर्टेबल समाधान के रूप में। बस शरीर में एक div जोड़ें जो स्क्रॉल किए गए तत्वों को समाहित करता है और इसे पूर्ण आकार के स्क्रॉलिंग को सक्षम करने के लिए स्टाइल करना है:

#my-scroll {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: auto;
}

(यह मानते हुए display:block;और top:0;left:0;आपके लक्ष्य से मेल खाने वाली चूक हैं), तो $('#my-scroll')अपने एनिमेशन के लिए उपयोग करें।


0

यह एक वास्तविक डील है। यह क्रोम और फ़ायरफ़ॉक्स पर त्रुटिपूर्ण रूप से काम करता है। यह और भी दुखद है कि कुछ अज्ञानी मुझे वोट देते हैं। यह कोड वस्तुतः सभी ब्राउज़रों पर पूरी तरह से काम करता है। आपको केवल एक लिंक जोड़ना होगा और उस तत्व की आईडी डालनी होगी जिसे आप href में स्क्रॉल करना चाहते हैं और यह किसी भी चीज़ को निर्दिष्ट किए बिना काम करता है। शुद्ध पुन: प्रयोज्य और विश्वसनीय कोड।

$(document).ready(function() {
  function filterPath(string) {
    return string
    .replace(/^\//,'')
    .replace(/(index|default).[a-zA-Z]{3,4}$/,'')
    .replace(/\/$/,'');
  }
  var locationPath = filterPath(location.pathname);
  var scrollElem = scrollableElement('html', 'body');

  $('a[href*=#]').each(function() {
    var thisPath = filterPath(this.pathname) || locationPath;
    if (locationPath == thisPath
    && (location.hostname == this.hostname || !this.hostname)
    && this.hash.replace(/#/,'') ) {
      var $target = $(this.hash), target = this.hash;
      if (target) {
        var targetOffset = $target.offset().top;
        $(this).click(function(event) {
          event.preventDefault();
          $(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
            location.hash = target;
          });
        });
      }
    }
  });

  // use the first element that is "scrollable"
  function scrollableElement(els) {
    for (var i = 0, argLength = arguments.length; i <argLength; i++) {
      var el = arguments[i],
          $scrollElement = $(el);
      if ($scrollElement.scrollTop()> 0) {
        return el;
      } else {
        $scrollElement.scrollTop(1);
        var isScrollable = $scrollElement.scrollTop()> 0;
        $scrollElement.scrollTop(0);
        if (isScrollable) {
          return el;
        }
      }
    }
    return [];
  }
});

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

0

मुझे हाल ही में एक ही समस्या का सामना करना पड़ा और मैंने ऐसा करके इसे हल किया:

$ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top}, 'fast'});

और youpi !!! यह सभी ब्राउज़रों पर काम करता है।

यदि स्थिति सही नहीं है, तो आप ऐसा करके ऑफसेट () .top से एक मूल्य घटा सकते हैं

$ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top-desired_value}, 'fast'});

यह समाधान पहले से ही मौजूदा जवाबों में वर्णित है, लेकिन साझा करने के लिए धन्यवाद
टोनी मिशेल क्यूबेट

यह विधि अभी भी फ़ायरफ़ॉक्स में एक गड़बड़ का सामना करती है, जैसा कि मैंने अभी पोस्ट किए गए प्रश्न में उल्लेख किया है: stackoverflow.com/q/58617731/1056713
Chaya कूपर

-3

मेरे लिए समस्या यह थी कि फ़ायरफ़ॉक्स स्वचालित रूप से नाम-विशेषता के साथ एंकर के लिए कूद गया, जैसा कि मैंने URL में डाल दिया हैश नाम। हालांकि मैं इसे रोकने के लिए .preventDefault () लगाता हूं। इसलिए नाम की विशेषताओं को बदलने के बाद, फ़ायरफ़ॉक्स स्वचालित रूप से एंकरों के लिए नहीं कूदता है, लेकिन एनीमेशन सही प्रदर्शन करता है।

@ टोनी क्षमा करें यदि यह समझ में नहीं आता था। बात यह है कि मैंने www.someurl.com/#hashname जैसे URL में हैश को बदल दिया है। उदाहरण के लिए मेरे पास एक एंकर था, <a name="hashname" ...></a>जिसे jQuery को स्वचालित रूप से स्क्रॉल करना चाहिए। लेकिन ऐसा नहीं था क्योंकि यह बिना किसी स्क्रॉल एनीमेशन के फ़ायरफ़ॉक्स में मिलान नाम विशेषता के साथ एंकर के दाईं ओर कूद गया। एक बार मैंने नाम विशेषता को हैश नाम से कुछ अलग करने के लिए बदल दिया, उदाहरण के लिए name="hashname-anchor", स्क्रॉलिंग ने काम किया।


-5

मेरे लिए, यह एनीमेशन के बिंदु पर आईडी को जोड़ने से बच रहा था:

बचना:

 scrollTop: $('#' + id).offset().top

पहले से आईडी तैयार करना और इसके बजाय यह करना:

 scrollTop: $(id).offset().top

एफएफ में तय किया गया। (सीएसएस अतिरिक्त मेरे लिए कोई फर्क नहीं पड़ा)


-8
setTimeout(function(){                               
                   $('html,body').animate({ scrollTop: top }, 400);
                 },0);

आशा है कि यह काम करेगा।


4
सेटटाइम कैसे मदद करता है, यहाँ?
टोनी मिशेल कैबेट

2
@ToniMichelCaubet संभवत: लक्ष्य को एनीमेशन को अतुल्यकालिक बनाना है। jQuery के एनिमेशन पहले से ही अतुल्यकालिक हैं, हालाँकि, यह कुछ भी नहीं पूरा करता है।
mwcz

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