JQuery: केवल आकार बदलने के बाद ही RESIZE इवेंट को कैसे कॉल करें?


109

ब्राउज़र विंडो के आकार बदलने के बाद मैं किसी फ़ंक्शन को कैसे कॉल कर सकता हूं?

मैं ऐसा करने की कोशिश कर रहा हूं, लेकिन मुझे समस्या हो रही है। मैं JQuery के आकार परिवर्तन समारोह का उपयोग कर रहा हूँ:

$(window).resize(function() {
  ... // how to call only once the browser has FINISHED resizing?
});

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

मैं केवल एक बार (एक बार ब्राउज़र विंडो के आकार बदलने के बाद) आकार बदलने वाले फ़ंक्शन को कैसे कॉल कर सकता हूं ?

अपडेट करें

इसके अलावा एक वैश्विक चर का उपयोग करने के लिए बिना।


@Berrerren, यदि आप मुझे दिखा सकते हैं कि कैसे jsfiddle.net/Zevan/c9UE5/1 बिना वैश्विक परिवर्तन के, मैं निश्चित रूप से करूंगा :)
निक नेम

उपरोक्त क्लीयरआउट / सेसमेटआउट विधि अद्भुत रूप से अच्छी तरह से काम करती है।
क्रि-ओ .3

जवाबों:


129

यहाँ ajh के निर्देशों का उपयोग करके एक उदाहरण दिया गया है

आप किसी भी setInterval या setTimeout में संदर्भ आईडी स्टोर कर सकते हैं। ऐशे ही:

var loop = setInterval(func, 30);

// some time later clear the interval
clearInterval(loop);

मुझे यह पसंद है कि यह कोड बस इतना है। वैश्विक चर का उपयोग किए बिना इस काम को करने का कोई तरीका ?
निक नेम

अगर मैं यह देखता हूं कि वैश्विक चर के बिना यह कैसे किया जाए, तो मैं "स्वीकृत उत्तर"
बनाऊंगा

कोई दिक्कत नहीं है। कुछ तरीके हैं। मैंने जो सबसे आसान सोचा था, उसे प्रतिबिंबित करने के लिए मैंने उत्तर को संपादित किया है।
ज़ीवन

अद्यतन के लिए धन्यवाद, लेकिन यह अभी भी एक वैश्विक चर का उपयोग करने के लिए प्रतीत होता है। क्या आप इसे एक वैश्विक चर (var id) की आवश्यकता के लिए अपडेट कर सकते हैं। धन्यवाद
nickb

4
मुझे लगता है कि आपने पोस्ट के अंत में लिंक को याद किया ... इसे देखें: jsfiddle.net/Zevan/c9UE5/5
ज़ेवन

85

वाद-विवाद

function debouncer( func , timeout ) {
   var timeoutID , timeout = timeout || 200;
   return function () {
      var scope = this , args = arguments;
      clearTimeout( timeoutID );
      timeoutID = setTimeout( function () {
          func.apply( scope , Array.prototype.slice.call( args ) );
      } , timeout );
   }
}


$( window ).resize( debouncer( function ( e ) {
    // do stuff 
} ) );

ध्यान दें, आप इस विधि का उपयोग उस चीज के लिए कर सकते हैं जिसे आप चाहते हैं (प्रमुख घटनाओं आदि)।

इष्टतम वांछित प्रभाव के लिए टाइमआउट पैरामीटर को घुमाएं।


1
मैंने इसे चलाने की कोशिश की और यह TWICE चलाने के लिए प्रतीत होता है । मैंने "// do सामान" को "$ (" बॉडी ") से बदल दिया। एपेंड (" <br/> पूरा! ");" और यह इसे दो बार एक ब्राउज़र आकार पर TWICE कहता है
निकब

उफ़ ... मैं एक महत्वपूर्ण हिस्सा भूल गया (वास्तव में टाइमआउट की स्थापना) ... निश्चित अब, कृपया फिर से कोशिश करें;)
19

3
@ user43493: यह सिंटियन कहता है func, आंतरिक thisसूचक को इंगित करने के scopeसाथ, और Array.prototype.slice.call(args)(जो एक मानक सरणी उत्पन्न करता है args) तर्कों के रूप में
एरिक

4
यह एक पुन: प्रयोज्य अमूर्तता है, इसलिए आपको टाइमआउट को नियंत्रित करने या वैश्विक टाइमआउट के बारे में जानकारी रखने की आवश्यकता नहीं है। आप इसे और अधिक के लिए उपयोग कर सकते हैं, तो बस आकार बदलने खिड़की;) उदाहरण के लिए एक उच्च टाइमआउट पैरामीटर पारित करके सबमिट बटन की आलोचना करें। आप कम कोड समाधान का विकल्प चुन सकते हैं, लेकिन मैं आपको सलाह देता हूं कि आप इस स्निपेट को अपनी किट में रखें, आप इसे बाद में
सराहेंगे

2
यदि आप पहले से ही उस परिश्रम का उपयोग कर रहे हैं तो अंडरस्कोर.जेएस का अच्छा कार्यान्वयन है। underscorejs.org/#debounce
twmulloy

22

आप के साथ setTimeout()और उपयोग कर सकते हैं :clearTimeout()jQuery.data

$(window).resize(function() {
    clearTimeout($.data(this, 'resizeTimer'));
    $.data(this, 'resizeTimer', setTimeout(function() {
        //do something
        alert("Haven't resized in 200ms!");
    }, 200));
});

अपडेट करें

मैंने jQuery के डिफ़ॉल्ट (और ) -वेंट-हैंडलर को बढ़ाने के लिए एक एक्सटेंशन लिखा था । यह चयनित तत्वों के लिए एक या एक से अधिक घटनाओं के लिए एक ईवेंट हैंडलर फ़ंक्शन देता है यदि ईवेंट किसी दिए गए अंतराल के लिए ट्रिगर नहीं किया गया था। यह उपयोगी है यदि आप एक देरी के बाद ही कॉलबैक को फायर करना चाहते हैं, जैसे कि आकार बदलने की घटना, या फिर। https://github.com/yckart/jquery.unevent.jsonbind

;(function ($) {
    var methods = { on: $.fn.on, bind: $.fn.bind };
    $.each(methods, function(k){
        $.fn[k] = function () {
            var args = [].slice.call(arguments),
                delay = args.pop(),
                fn = args.pop(),
                timer;

            args.push(function () {
                var self = this,
                    arg = arguments;
                clearTimeout(timer);
                timer = setTimeout(function(){
                    fn.apply(self, [].slice.call(arg));
                }, delay);
            });

            return methods[k].apply(this, isNaN(delay) ? arguments : args);
        };
    });
}(jQuery));

इसे किसी अन्य onया bind-वेंट हैंडलर की तरह उपयोग करें , सिवाय इसके कि आप अंतिम के रूप में एक अतिरिक्त पैरामीटर पास कर सकते हैं:

$(window).on('resize', function(e) {
    console.log(e.type + '-event was 200ms not triggered');
}, 200);

http://jsfiddle.net/ARTsinn/EqqHx/


1
सचमुच हर दिन एक ही Google खोज करें। और कोड के इस टुकड़े के लिए उसी पृष्ठ पर आएं। काश मैं इसे याद कर पाती।
डस्टिन सिल्क

7
var lightbox_resize = false;
$(window).resize(function() {
    console.log(true);
    if (lightbox_resize)
        clearTimeout(lightbox_resize);
    lightbox_resize = setTimeout(function() {
        console.log('resize');
    }, 500);
});

मुझे यह सबसे अधिक पसंद है लेकिन अपने सशर्त बयानों पर घुंघराले कोष्ठक का उपयोग क्यों नहीं करते हैं? मुझे पता है कि यह उनके बिना काम करता है, लेकिन यह अन्य
देवों

7

बस ऊपर जोड़ने के लिए, स्क्रॉल बारों में और बाहर पॉपिंग के कारण अवांछित आकार बदलना घटनाओं के लिए आम है, यहाँ कुछ कोड है जिससे बचने के लिए:

function registerResize(f) {
    $(window).resize(function() {
        clearTimeout(this.resizeTimeout);
        this.resizeTimeout = setTimeout(function() {
            var oldOverflow = document.body.style.overflow;
            document.body.style.overflow = "hidden";
            var currHeight = $(window).height(),
                currWidth = $(window).width();
            document.body.style.overflow = oldOverflow;

            var prevUndefined = (typeof this.prevHeight === 'undefined' || typeof this.prevWidth === 'undefined');
            if (prevUndefined || this.prevHeight !== currHeight || this.prevWidth !== currWidth) {
                //console.log('Window size ' + (prevUndefined ? '' : this.prevHeight + "," + this.prevWidth) + " -> " + currHeight + "," + currWidth);
                this.prevHeight = currHeight;
                this.prevWidth = currWidth;

                f(currHeight, currWidth);
            }
        }, 200);
    });
    $(window).resize(); // initialize
}

registerResize(function(height, width) {
    // this will be called only once per resize regardless of scrollbars changes
});

jsfiddle देखें


5

Underscore.js के पास इस कार्य के लिए कुछ बेहतरीन तरीके हैं: throttleऔर debounce। यहां तक ​​कि अगर आप अंडरस्कोर का उपयोग नहीं कर रहे हैं, तो इन कार्यों के स्रोत पर एक नज़र डालें। यहाँ एक उदाहरण है:

var redraw = function() {'redraw logic here'};
var debouncedRedraw = _.debounce(redraw, 750);
$(window).on('resize', debouncedRedraw);

2

यह मेरा दृष्टिकोण है:

document.addEventListener('DOMContentLoaded', function(){
    var tos = {};
    var idi = 0;
    var fn  = function(id)
    {
        var len = Object.keys(tos).length;

        if(len == 0)
            return;

        to = tos[id];
        delete tos[id];

        if(len-1 == 0)
            console.log('Resize finished trigger');
    };

    window.addEventListener('resize', function(){
        idi++;
        var id = 'id-'+idi;
        tos[id] = window.setTimeout(function(){fn(id)}, 500);
    });
});

रिसाइज़-इवेंट-श्रोता सभी इनकमिंग रिसाइज़ कॉल को पकड़ता है, प्रत्येक के लिए एक टाइमआउट-फंक्शन बनाता है और टाइम-आइडेंटिफ़ायर 'id-'को एक tos-रियर में पूर्ववर्ती (सरणी सरणी कुंजी के रूप में उपयोग करने योग्य होने के लिए) पुनरावृत्त संख्या के साथ बचाता है ।

हर बार, टाइमआउट ट्रिगर होता है, यह -function fn, उस चेक को कॉल करता है, अगर वह आखिरी बार tosएरे में था (fn-function हर निष्पादित टाइमआउट को हटा देता है)। यदि सही (= if(len-1 == 0)) है, तो आकार बदलना समाप्त हो गया है।


यह अच्छा होगा यदि आपके पास कुछ टिप्पणियां या एक स्पष्टीकरण है जैसा कि आप यहां कर रहे हैं
ब्रेट ग्रेगसन

1

jQuery offईवेंट हैंडलर को निकालने के लिए एक विधि प्रदान करता है

$(window).resize(function(){
    if(magic == true) {
        $(window).off('resize', arguments.callee);
    }
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.